mirror of
				https://github.com/bobranten/Ext4Fsd.git
				synced 2025-10-30 21:38:31 -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);
 | |
| }
 |