#include #include #include /* * 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); }