mirror of
https://github.com/bobranten/Ext4Fsd.git
synced 2025-10-29 21:18:30 -05:00
525 lines
12 KiB
C++
525 lines
12 KiB
C++
#include <Ext2Srv.h>
|
|
#include <Sddl.h>
|
|
#include <Ext2Pipe.h>
|
|
|
|
|
|
/*
|
|
* global defintions
|
|
*/
|
|
|
|
#define CL_ASSERT(cond) do {switch('x') {case (cond): case 0: break;}} while (0)
|
|
|
|
#define DEBUG(...) do {} while(0)
|
|
|
|
/*
|
|
* glboal variables
|
|
*/
|
|
|
|
BOOLEAN g_stop = FALSE;
|
|
HANDLE g_wait;
|
|
|
|
/* pipe handles */
|
|
|
|
PEXT2_PIPE g_hep = NULL;
|
|
|
|
/*
|
|
* function prototypes
|
|
*/
|
|
|
|
BOOLEAN Ext2QueryDrive (PPIPE_REQ *pr, ULONG len);
|
|
BOOLEAN Ext2DefineDrive(PPIPE_REQ *pr, ULONG len);
|
|
BOOLEAN Ext2RemoveDrive(PPIPE_REQ *pr, ULONG len);
|
|
|
|
|
|
/*
|
|
* function body
|
|
*/
|
|
|
|
BOOL Ext2ReadPipe(HANDLE p, PVOID b, DWORD c, PDWORD r)
|
|
{
|
|
DWORD bytes = 0, total = 0;
|
|
BOOL rc = FALSE;
|
|
|
|
while (total < c) {
|
|
rc = ReadFile(p,(PCHAR)b + total, c - total, &bytes, NULL);
|
|
if (rc) {
|
|
total += bytes;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (r)
|
|
*r = total;
|
|
return rc;
|
|
}
|
|
|
|
|
|
BOOL Ext2WritePipe(HANDLE p, PVOID b, DWORD c, PDWORD w)
|
|
{
|
|
DWORD bytes = 0, total = 0;
|
|
BOOL rc = FALSE;
|
|
|
|
while (total < c) {
|
|
rc = WriteFile(p, (PCHAR)b + total, c - total, &bytes, NULL);
|
|
if (rc) {
|
|
total += bytes;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (w)
|
|
*w = total;
|
|
return rc;
|
|
}
|
|
|
|
|
|
PSECURITY_ATTRIBUTES Ext2CreateSA()
|
|
{
|
|
PSECURITY_ATTRIBUTES sa = NULL;
|
|
BOOL rc = FALSE;
|
|
|
|
PSECURITY_DESCRIPTOR SD = NULL;
|
|
LPCTSTR SACL = // ("S:(ML;;NW;;;LW)")
|
|
_T("D:") // Discretionary ACL
|
|
_T("A;OICI;GA;;;BG") // Allow access to
|
|
// built-in guests
|
|
_T("A;OICI;GA;;;AN") // Allow access to
|
|
// anonymous logon
|
|
_T("A;OICI;GA;;;AU") // Allow
|
|
// read/write/execute
|
|
// to authenticated
|
|
// users
|
|
_T("A;OICI;GA;;;BA"); // Allow full control
|
|
// to administrators
|
|
|
|
// _T("S:(ML;;NW;;;LW)D:(A;OICI;GA;;;S-1-1-0)");
|
|
// _T("S:(ML;;NW;;;LW)D:(A;;0x12019f;;;WD)");
|
|
|
|
/* convert */
|
|
rc = ConvertStringSecurityDescriptorToSecurityDescriptor(
|
|
SACL, SDDL_REVISION_1, &SD, NULL);
|
|
if (!rc) {
|
|
goto errorout;
|
|
}
|
|
|
|
// Initialize a security attributes structure.
|
|
sa = (PSECURITY_ATTRIBUTES) LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES));
|
|
if (NULL == sa) {
|
|
goto errorout;
|
|
}
|
|
sa->nLength = sizeof (SECURITY_ATTRIBUTES);
|
|
sa->lpSecurityDescriptor = SD;
|
|
sa->bInheritHandle = TRUE;
|
|
|
|
errorout:
|
|
|
|
if (!sa) {
|
|
if (SD)
|
|
LocalFree(SD);
|
|
}
|
|
|
|
return sa;
|
|
}
|
|
|
|
VOID Ext2FreeSA(PSECURITY_ATTRIBUTES sa)
|
|
{
|
|
PACL ACL = NULL;
|
|
|
|
if (NULL == sa)
|
|
return;
|
|
|
|
if (sa->lpSecurityDescriptor) {
|
|
LocalFree(sa->lpSecurityDescriptor);
|
|
}
|
|
|
|
LocalFree(sa);
|
|
}
|
|
|
|
PEXT2_PIPE
|
|
Ext2CreatePipe()
|
|
{
|
|
PEXT2_PIPE ap = NULL;
|
|
LPSECURITY_ATTRIBUTES sa = NULL;
|
|
|
|
ap = new EXT2_PIPE;
|
|
if (!ap) {
|
|
return NULL;
|
|
}
|
|
memset(ap, 0, sizeof(EXT2_PIPE));
|
|
|
|
sa = Ext2CreateSA();
|
|
|
|
ap->p = CreateNamedPipe( _T(EXT2_MGR_SRV), PIPE_ACCESS_DUPLEX |
|
|
FILE_FLAG_WRITE_THROUGH /* | ACCESS_SYSTEM_SECURITY */,
|
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
|
|
PIPE_WAIT /* PIPE_REJECT_REMOTE_CLIENTS */ ,
|
|
PIPE_UNLIMITED_INSTANCES,
|
|
REQ_BODY_SIZE, REQ_BODY_SIZE,
|
|
6000, sa);
|
|
if (INVALID_HANDLE_VALUE == ap->p) {
|
|
DWORD le = GetLastError();
|
|
if (le == ERROR_PIPE_BUSY) {
|
|
WaitNamedPipe(_T(EXT2_MGR_SRV), 1000);
|
|
} else {
|
|
}
|
|
delete ap;
|
|
ap = NULL;
|
|
goto errorout;
|
|
}
|
|
|
|
/* create new sync event */
|
|
ap->q = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
ap->e = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if (INVALID_HANDLE_VALUE == ap->e ||
|
|
INVALID_HANDLE_VALUE == ap->q) {
|
|
if (ap->e && INVALID_HANDLE_VALUE != ap->e)
|
|
CloseHandle(ap->e);
|
|
if (ap->q && INVALID_HANDLE_VALUE != ap->q)
|
|
CloseHandle(ap->q);
|
|
CloseHandle(ap->p);
|
|
delete ap;
|
|
ap = NULL;
|
|
goto errorout;
|
|
}
|
|
|
|
errorout:
|
|
|
|
if (sa)
|
|
Ext2FreeSA(sa);
|
|
|
|
return ap;
|
|
}
|
|
|
|
|
|
VOID Ext2DestroyPipe(PEXT2_PIPE ap)
|
|
{
|
|
if (ap->p && ap->p != INVALID_HANDLE_VALUE)
|
|
CloseHandle(ap->p);
|
|
|
|
if (ap->e && ap->e != INVALID_HANDLE_VALUE)
|
|
CloseHandle(ap->e);
|
|
|
|
if (ap->q && INVALID_HANDLE_VALUE != ap->q)
|
|
CloseHandle(ap->q);
|
|
|
|
delete ap;
|
|
}
|
|
|
|
|
|
BOOLEAN Ext2QueryDrive(PPIPE_REQ *pr, ULONG len)
|
|
{
|
|
PPIPE_REQ p;
|
|
PREQ_QUERY_DRV q;
|
|
|
|
CHAR devPath[] = "A:";
|
|
DWORD rc = FALSE;
|
|
|
|
if (!pr || !*pr)
|
|
goto errorout;
|
|
|
|
p = *pr;
|
|
q = (PREQ_QUERY_DRV)&p->data[0];
|
|
|
|
devPath[0] = q->drive;
|
|
q->type = GetDriveTypeA(devPath);
|
|
|
|
if (q->type != DRIVE_NO_ROOT_DIR) {
|
|
CHAR *s = &q->name[0];
|
|
ULONG l = len - sizeof(PIPE_REQ) - sizeof(REQ_QUERY_DRV);
|
|
rc = QueryDosDeviceA(devPath, s, l);
|
|
if (rc) {
|
|
q->result = 1;
|
|
p->len = (int)(sizeof(PIPE_REQ) + sizeof(REQ_QUERY_DRV) + strlen(s) + 1);
|
|
} else {
|
|
q->result = 0;
|
|
}
|
|
} else {
|
|
q->result = 1;
|
|
}
|
|
|
|
|
|
errorout:
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOLEAN Ext2DefineDrive(PPIPE_REQ *pr, ULONG len)
|
|
{
|
|
PPIPE_REQ p;
|
|
PREQ_DEFINE_DRV q;
|
|
BOOLEAN rc = 0;
|
|
|
|
CHAR dosPath[] = "A:\0";
|
|
|
|
if (!pr || !*pr)
|
|
goto errorout;
|
|
|
|
p = *pr;
|
|
q = (PREQ_DEFINE_DRV)&p->data[0];
|
|
|
|
dosPath[0] = q->drive;
|
|
q->result = (UCHAR)DefineDosDeviceA(q->flags, dosPath, &q->name[0]);
|
|
rc = (BOOLEAN) q->result;
|
|
|
|
errorout:
|
|
|
|
return rc;
|
|
}
|
|
|
|
VOID Ext2NotifyDefineDrive(PPIPE_REQ pr)
|
|
{
|
|
TCHAR task[60];
|
|
PREQ_DEFINE_DRV q;
|
|
|
|
if (!pr)
|
|
return;
|
|
|
|
q = (PREQ_DEFINE_DRV)&pr->data[0];
|
|
|
|
if (q->result) {
|
|
_stprintf_s(task, 59, _T("/add %C"), q->drive);
|
|
Ext2NotifyUser(task, q->pid);
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN Ext2RemoveDrive(PPIPE_REQ *pr, ULONG len)
|
|
{
|
|
PPIPE_REQ p;
|
|
PREQ_REMOVE_DRV q;
|
|
BOOLEAN rc = 0;
|
|
|
|
CHAR dosPath[] = "A:\0";
|
|
|
|
if (!pr || !*pr)
|
|
goto errorout;
|
|
|
|
p = *pr;
|
|
q = (PREQ_REMOVE_DRV)&p->data[0];
|
|
|
|
dosPath[0] = q->drive;
|
|
q->result = (UCHAR)DefineDosDeviceA(q->flags, dosPath, &q->name[0]);
|
|
rc = (BOOLEAN)q->result;
|
|
|
|
errorout:
|
|
|
|
return rc;
|
|
}
|
|
|
|
VOID Ext2NotifyRemoveDrive(PPIPE_REQ pr)
|
|
{
|
|
TCHAR task[60];
|
|
PREQ_REMOVE_DRV q;
|
|
|
|
if (!pr)
|
|
return;
|
|
|
|
q = (PREQ_REMOVE_DRV)&pr->data[0];
|
|
|
|
if (q->result) {
|
|
_stprintf_s(task, 59, _T("/del %C"), q->drive);
|
|
Ext2NotifyUser(task, q->pid);
|
|
}
|
|
}
|
|
|
|
VOID __cdecl
|
|
Ext2ClientEngine(VOID *arg)
|
|
{
|
|
PEXT2_PIPE ap = (PEXT2_PIPE)arg;
|
|
PPIPE_REQ pr = NULL;
|
|
PIPE_REQ ac;
|
|
ULONG len = 0;
|
|
BOOL rc;
|
|
|
|
len = REQ_BODY_SIZE;
|
|
pr = (PIPE_REQ *) new CHAR[len];
|
|
if (!pr) {
|
|
goto errorout;
|
|
}
|
|
|
|
while (!g_stop) {
|
|
|
|
//wait for a command
|
|
DWORD bytes=0;
|
|
|
|
memset(&ac, 0, sizeof(ac));
|
|
if (!Ext2ReadPipe(ap->p, &ac, sizeof(ac), &bytes)) {
|
|
break;
|
|
}
|
|
|
|
if (ac.magic != PIPE_REQ_MAGIC || ac.len <= sizeof(ac)) {
|
|
break;
|
|
}
|
|
|
|
if (ac.len > len) {
|
|
if (pr)
|
|
delete [] pr;
|
|
pr = (PPIPE_REQ) new CHAR[ac.len + 4];
|
|
if (!pr) {
|
|
break;
|
|
}
|
|
len = ac.len + 4;
|
|
}
|
|
|
|
memset(pr, 0, len);
|
|
memcpy(pr, &ac, sizeof(ac));
|
|
if (!Ext2ReadPipe(ap->p, &pr->data[0],
|
|
ac.len - sizeof(ac), &bytes)) {
|
|
break;
|
|
}
|
|
|
|
if (pr->cmd == CMD_QUERY_DRV) {
|
|
DEBUG("got CMD_QUERY_DRV.\n");
|
|
rc = Ext2QueryDrive(&pr, len);
|
|
} else if (pr->cmd == CMD_DEFINE_DRV) {
|
|
DEBUG("got CMD_DEFINE_DRV.\n");
|
|
rc = Ext2DefineDrive(&pr, len);
|
|
} else if (pr->cmd == CMD_REMOVE_DRV) {
|
|
DEBUG("got CMD_REMOVE_DRV.\n");
|
|
rc = Ext2RemoveDrive(&pr, len);
|
|
} else {
|
|
rc = FALSE;
|
|
DEBUG("got unknown CMD.\n");
|
|
break;
|
|
}
|
|
|
|
if (!Ext2WritePipe(ap->p, pr, pr->len, &bytes)) {
|
|
break;
|
|
}
|
|
|
|
if (rc) {
|
|
if (pr->cmd == CMD_REMOVE_DRV) {
|
|
Ext2NotifyRemoveDrive(pr);
|
|
} else if (pr->cmd == CMD_DEFINE_DRV) {
|
|
Ext2NotifyDefineDrive(pr);
|
|
}
|
|
}
|
|
}
|
|
|
|
DEBUG("client disconnected.\n");
|
|
|
|
errorout:
|
|
|
|
if (ap && ap->q)
|
|
SetEvent(ap->q);
|
|
|
|
_endthread();
|
|
}
|
|
|
|
VOID __cdecl
|
|
Ext2PipeEngine(VOID *arg)
|
|
{
|
|
PEXT2_PIPE ap = NULL, *cu;
|
|
DWORD le;
|
|
BOOL rc;
|
|
|
|
DEBUG("server mode is to start...\n");
|
|
|
|
SetEvent(g_wait);
|
|
|
|
while (!g_stop) {
|
|
|
|
int times = 0;
|
|
|
|
retry:
|
|
|
|
/* create named pipe */
|
|
ap = Ext2CreatePipe();
|
|
if (NULL == ap) {
|
|
if (times++ < 10) {
|
|
Sleep(250 * times);
|
|
goto retry;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/* ASSD_PIPE is valid or not */
|
|
if (!ap->p || ap->p == INVALID_HANDLE_VALUE ||
|
|
!ap->e || ap->e == INVALID_HANDLE_VALUE) {
|
|
Ext2DestroyPipe(ap);
|
|
if (times++ < 10) {
|
|
Sleep(500);
|
|
goto retry;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/* wait connection request from client */
|
|
memset(&ap->o, 0, sizeof(OVERLAPPED));
|
|
ap->o.hEvent = ap->e;
|
|
rc = ConnectNamedPipe(ap->p, &ap->o);
|
|
le = GetLastError();
|
|
if (rc != 0 || le == ERROR_PIPE_CONNECTED) {
|
|
DEBUG("got client connected.\n");
|
|
ap->l = g_hep;
|
|
g_hep = ap;
|
|
_beginthread(Ext2ClientEngine, 0, (PVOID)ap);
|
|
} else {
|
|
Ext2DestroyPipe(ap);
|
|
}
|
|
|
|
if (g_stop)
|
|
goto errorout;
|
|
|
|
/* do cleanup of closed pipes */
|
|
cu = &g_hep;
|
|
while (ap = *cu) {
|
|
if (ap->s) {
|
|
*cu = ap->l;
|
|
Ext2DestroyPipe(ap);
|
|
} else {
|
|
cu = &ap->l;
|
|
}
|
|
}
|
|
|
|
DEBUG("Waiting for next client.\n");
|
|
}
|
|
|
|
errorout:
|
|
|
|
SetEvent(g_wait);
|
|
_endthread();
|
|
}
|
|
|
|
DWORD Ext2StartPipeSrv()
|
|
{
|
|
DWORD rc;
|
|
|
|
do {
|
|
g_wait = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
} while (!g_wait || g_wait == INVALID_HANDLE_VALUE);
|
|
|
|
|
|
do {
|
|
_beginthread(Ext2PipeEngine, 0, NULL);
|
|
rc = WaitForSingleObject(g_wait, 1000*1);
|
|
} while (rc == WAIT_TIMEOUT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID Ext2StopPipeSrv()
|
|
{
|
|
PEXT2_PIPE *cu = &g_hep, ap;
|
|
DWORD rc = 0;
|
|
|
|
g_stop = TRUE;
|
|
|
|
/* do cleanup of all remained pipes */
|
|
cu = &g_hep;
|
|
while (ap = *cu) {
|
|
SetEvent(ap->e);
|
|
rc = WaitForSingleObject(ap->q, INFINITE);
|
|
if (rc != WAIT_TIMEOUT) {
|
|
*cu = ap->l;
|
|
Ext2DestroyPipe(ap);
|
|
} else {
|
|
cu = &ap->l;
|
|
}
|
|
}
|
|
WaitForSingleObject(g_wait, 1000);
|
|
}
|