1
0
mirror of https://github.com/bobranten/Ext4Fsd.git synced 2025-10-29 13:18:30 -05:00
Files
Ext4Fsd/Ext2Srv/Ext2Pipe.cpp
2020-08-14 23:04:55 +02:00

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);
}