mirror of
				https://github.com/bobranten/Ext4Fsd.git
				synced 2025-10-30 21:38:31 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			864 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			864 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| #include "stdafx.h"
 | |
| #include <dbt.h>
 | |
| #include <tchar.h>
 | |
| #include < tlhelp32.h>
 | |
| #include "..\Ext2Srv\Ext2Pipe.h"
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * global defintions
 | |
|  */
 | |
| 
 | |
| #define CL_ASSERT(cond) do {switch('x') {case (cond): case 0: break;}} while (0)
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * glboal variables
 | |
|  */
 | |
| 
 | |
| /* pipe handles */
 | |
| 
 | |
| HANDLE g_hPipe = NULL;
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * function body
 | |
|  */
 | |
| 
 | |
| int Ext2StartSrv();
 | |
| 
 | |
| HANDLE Ext2OpenPipe(CHAR *PipeName)
 | |
| {
 | |
|     DWORD   rc;
 | |
| 
 | |
|     if (g_hPipe != NULL && g_hPipe != INVALID_HANDLE_VALUE) {
 | |
|         return g_hPipe;
 | |
|     }
 | |
| 
 | |
| retry:
 | |
| 
 | |
|     // open pipe (created by Ext2Srv)
 | |
|     g_hPipe = CreateFile(PipeName,
 | |
|                          GENERIC_READ | GENERIC_WRITE, 
 | |
|                          0, NULL, OPEN_EXISTING, 0, NULL);
 | |
|  
 | |
|     // exit if the pipe handle is valid. 
 | |
|     if (g_hPipe == INVALID_HANDLE_VALUE) {
 | |
| 
 | |
|          // exit if an error other than ERROR_PIPE_BUSY occurs. 
 | |
|         rc = GetLastError(); 
 | |
|         if (rc != ERROR_PIPE_BUSY) {
 | |
|             return NULL;
 | |
|         }
 | |
|  
 | |
|         // all pipe instances are busy, so wait for 20 seconds. 
 | |
|         if (!WaitNamedPipe(PipeName, 20000)) { 
 | |
|             return NULL;
 | |
|         }
 | |
| 
 | |
|         Ext2StartSrv();
 | |
| 
 | |
|         goto retry;
 | |
|     }
 | |
| 
 | |
|     return g_hPipe;
 | |
| }
 | |
| 
 | |
| void Ext2ClosePipe()
 | |
| {
 | |
|     if (g_hPipe != NULL && g_hPipe != INVALID_HANDLE_VALUE) {
 | |
|         CloseHandle(g_hPipe);
 | |
|         g_hPipe = NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 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;
 | |
| }
 | |
| 
 | |
| 
 | |
| DWORD Ext2PipeControl(PPIPE_REQ *pr, ULONG *len)
 | |
| {
 | |
|     PPIPE_REQ       p;
 | |
|     PREQ_QUERY_DRV  q;
 | |
|     PIPE_REQ        ac;
 | |
|     DWORD           le;
 | |
|     DWORD           bytes = 0;
 | |
|     DWORD           rc = 0;
 | |
|     int             tries = 0;
 | |
| 
 | |
|     p = *pr;
 | |
|     q = (PREQ_QUERY_DRV)p->data;
 | |
| 
 | |
| Reopen_try:
 | |
| 
 | |
|     /* just try to connect pipe anyway */
 | |
|     if (NULL == Ext2OpenPipe(EXT2_MGR_SRV)) {
 | |
|         printf("failed to connect to server.\n");
 | |
|         if (Ext2StartExt2Srv()) {
 | |
| 			goto Reopen_try;
 | |
|         }
 | |
|         goto errorout;
 | |
|     }
 | |
|     
 | |
|     // send a message to srv
 | |
|     rc = Ext2WritePipe(g_hPipe, p, p->len, &bytes);
 | |
|     if (!rc || bytes != p->len) {
 | |
|         le = GetLastError();
 | |
| 		if (le == ERROR_NO_DATA && tries++ < 10) {
 | |
| 			Ext2ClosePipe();
 | |
| 			Sleep(500 * tries);
 | |
| 			goto Reopen_try;
 | |
| 		}
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     bytes = 0;
 | |
|     memset(&ac, 0, sizeof(ac));
 | |
|     rc = Ext2ReadPipe(g_hPipe, &ac, sizeof(ac), &bytes);
 | |
|     if (!rc || bytes != sizeof(ac)) {
 | |
|         le = GetLastError();
 | |
|         goto errorout;
 | |
|     }
 | |
|     if (*len < ac.len) {
 | |
|         if (p) {
 | |
|             delete [] p;
 | |
|         }
 | |
|         *len = ac.len;
 | |
|         p = (PIPE_REQ *) new CHAR[*len];
 | |
|         *pr = p;
 | |
|         if (!p) {
 | |
|             goto errorout;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     memset(p, 0, *len);
 | |
|     memcpy(p, &ac, sizeof(ac));
 | |
|     rc = Ext2ReadPipe(g_hPipe, &p->data[0],
 | |
|                       ac.len - bytes, &bytes);
 | |
|     if (!rc || bytes != (ac.len - sizeof(ac))) {
 | |
|         le = GetLastError();
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL Ext2DefineDosDevicePipe(DWORD flags,  CHAR *dos,  CHAR *symlink)
 | |
| {
 | |
|     PPIPE_REQ       p = NULL;
 | |
|     ULONG           len = REQ_BODY_SIZE;
 | |
|     BOOL            rc = 0;
 | |
|  
 | |
|     p = (PPIPE_REQ) new CHAR[len];
 | |
|     if (NULL == p)
 | |
|         goto errorout;
 | |
| 
 | |
|     if (flags & DDD_REMOVE_DEFINITION) {
 | |
| 
 | |
|         /* do dismount */
 | |
|         PREQ_REMOVE_DRV  q;
 | |
|         memset(p, 0, len);
 | |
|         p->magic = PIPE_REQ_MAGIC;
 | |
|         p->len = sizeof(PIPE_REQ) + sizeof(REQ_REMOVE_DRV);
 | |
|         p->cmd = CMD_REMOVE_DRV;
 | |
|         q = (PREQ_REMOVE_DRV)&p->data[0];
 | |
|         q->pid = GetCurrentProcessId();
 | |
|         q->drive = (UCHAR)toupper(dos[0]);
 | |
|         q->flags = flags;
 | |
|         strcpy(&q->name[0], symlink);
 | |
|         p->len += strlen(symlink) + 1;
 | |
| 
 | |
|         rc = Ext2PipeControl(&p, &len);
 | |
|         if (!rc) {
 | |
|             printf("pipe communication failed.\n");
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|         if (q->result) {
 | |
|             printf("%C: removed.\n", q->drive);
 | |
|             rc = TRUE;
 | |
|         } else {
 | |
|             printf("failed to remove %C:.\n", q->drive);
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|     } else {
 | |
| 
 | |
|         /* do mount */
 | |
|         PREQ_DEFINE_DRV q;
 | |
|         memset(p, 0, len);
 | |
|         p->magic = PIPE_REQ_MAGIC;
 | |
|         p->len = sizeof(PIPE_REQ) + sizeof(REQ_DEFINE_DRV);
 | |
|         p->cmd = CMD_DEFINE_DRV;
 | |
|         q = (PREQ_DEFINE_DRV)&p->data[0];
 | |
|         q->pid = GetCurrentProcessId();
 | |
|         q->drive = (UCHAR)toupper(dos[0]);
 | |
|         q->flags = flags;
 | |
|         strcpy(&q->name[0], symlink);
 | |
|         p->len += strlen(symlink) + 1;
 | |
| 
 | |
|         rc = Ext2PipeControl(&p, &len);
 | |
|         if ( !rc) {
 | |
|             printf("pipe communication failed.\n");
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|         if (q->result) {
 | |
|             rc = TRUE;
 | |
|             printf("%C: assigned to %s\n", q->drive, &q->name[0]);
 | |
|         } else {
 | |
|             printf("failed to assign %C: to %s.\n", q->drive, &q->name[0]);
 | |
|             goto errorout;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (p)
 | |
|         delete []p;
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL Ext2DefineDosDeviceLocal(DWORD flags,  CHAR *dos,  CHAR *symlink)
 | |
| {
 | |
|     CHAR dosPath[] = "A:\0";
 | |
|     BOOL rc;
 | |
| 
 | |
|     dosPath[0] = (CHAR)toupper(dos[0]);
 | |
|     rc = DefineDosDevice(flags, dosPath, symlink);
 | |
|     if (rc) {
 | |
|         if (flags & DDD_REMOVE_DEFINITION) {
 | |
|             Ext2DrvNotify(dosPath[0], FALSE);
 | |
|         } else {
 | |
|             Ext2DrvNotify(dosPath[0], TRUE);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL Ext2DefineDosDevice(DWORD flags,  CHAR *dos,  CHAR *symlink)
 | |
| {
 | |
|     if (CanDoLocalMount()) {
 | |
|         return Ext2DefineDosDeviceLocal(flags, dos, symlink);
 | |
|     }
 | |
| 
 | |
|     return Ext2DefineDosDevicePipe(flags, dos, symlink);
 | |
| }
 | |
| 
 | |
| 
 | |
| DWORD Ext2QueryDrivePipe(CHAR drive, CHAR *symlink)
 | |
| {
 | |
|     PPIPE_REQ       p = NULL;
 | |
|     PREQ_QUERY_DRV  q;
 | |
|     ULONG           len = REQ_BODY_SIZE;
 | |
|     DWORD           rc = 0;
 | |
|  
 | |
|     p = (PPIPE_REQ) new CHAR[len];
 | |
|     if (NULL == p)
 | |
|         goto errorout;
 | |
| 
 | |
|      /* do query */
 | |
|     memset(p, 0, len);
 | |
|     p->magic = PIPE_REQ_MAGIC;
 | |
|     p->len = sizeof(PIPE_REQ) + sizeof(REQ_QUERY_DRV);
 | |
|     p->cmd = CMD_QUERY_DRV;
 | |
|     q = (PREQ_QUERY_DRV)&p->data[0];
 | |
|     q->drive = (UCHAR)toupper(drive);
 | |
|     rc = Ext2PipeControl(&p, &len);
 | |
|     if ( !rc) {
 | |
|         printf("pipe communication failed.\n");
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     rc = q->type;
 | |
|     if (q->result) {
 | |
|         printf("%C: -> %s\n", q->drive, &q->name[0]);
 | |
|         strcpy(symlink, &q->name[0]);
 | |
|     } else {
 | |
|         printf("failed to queyr %C:\n", q->drive);
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (p)
 | |
|         delete []p;
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| DWORD Ext2QueryDriveLocal(CHAR drive, CHAR *symlink)
 | |
| {
 | |
|     DWORD           type;
 | |
|     CHAR            devPath[] = "A:";
 | |
| 
 | |
|     devPath[0] = drive;
 | |
|     type = GetDriveType(devPath);
 | |
|     if (type != DRIVE_NO_ROOT_DIR) {
 | |
|         QueryDosDevice(devPath, symlink, MAX_PATH);
 | |
|     }
 | |
| 
 | |
|     return type;
 | |
| }
 | |
| 
 | |
| DWORD Ext2QueryDrive(CHAR drive, CHAR *symlink)
 | |
| {
 | |
|     if (CanDoLocalMount()) {
 | |
|         return Ext2QueryDriveLocal(drive, symlink);
 | |
|     }
 | |
| 
 | |
|     return Ext2QueryDrivePipe(drive, symlink);
 | |
| }
 | |
| 
 | |
| int Ext2CreateToken(DWORD pid, DWORD *sid, HANDLE *token)
 | |
| {
 | |
|     HANDLE  h = NULL, token_user = NULL;
 | |
|     DWORD dwTokenRights;
 | |
|     PSID IntegrityLevelSid = NULL;
 | |
|     CString SIDvalue;
 | |
|     TOKEN_MANDATORY_LABEL IntegrityLevelToken = {0};
 | |
| 
 | |
|     int     rc = -1;
 | |
| 
 | |
|     rc = ProcessIdToSessionId(pid, sid);
 | |
|     if (!rc) {
 | |
|         rc = -1 * GetLastError();
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
 | |
|     if (h == NULL || h == INVALID_HANDLE_VALUE) {
 | |
|         rc = -1 * GetLastError();
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     rc = OpenProcessToken(h, TOKEN_DUPLICATE, &token_user);
 | |
|     if(!rc) {
 | |
|         rc = -1 * GetLastError();
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     dwTokenRights = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY |
 | |
|                     TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT |
 | |
|                     TOKEN_ADJUST_SESSIONID;
 | |
|     rc = DuplicateTokenEx(token_user, dwTokenRights, NULL,
 | |
|                           SecurityImpersonation /*SecurityIdentification*/,
 | |
|                           TokenPrimary, token);
 | |
|     if (!rc) {
 | |
|         rc = -1 * GetLastError();
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     //  S-revision-authority-rid
 | |
|     //  S-1-16-?
 | |
|     //  16 represents
 | |
|     //     SECURITY_MANDATORY_LABEL_AUTHORITY
 | |
| 
 | |
|     SIDvalue.Format("S-1-16-%d", SECURITY_MANDATORY_MEDIUM_RID);
 | |
|     if(!ConvertStringSidToSidA(SIDvalue, &IntegrityLevelSid)) {
 | |
|         /* not critical, ignore this error */
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     IntegrityLevelToken.Label.Attributes = SE_GROUP_INTEGRITY;
 | |
|     IntegrityLevelToken.Label.Sid = IntegrityLevelSid;
 | |
| 
 | |
|     SetTokenInformation(*token,
 | |
|                         TokenIntegrityLevel,
 | |
|                         &IntegrityLevelToken,
 | |
|                         sizeof(TOKEN_MANDATORY_LABEL) +
 | |
|                         GetLengthSid(IntegrityLevelSid));
 | |
|     LocalFree(IntegrityLevelSid);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (token_user && token_user != INVALID_HANDLE_VALUE)
 | |
|         CloseHandle(token_user);
 | |
| 
 | |
|     if (h && h != INVALID_HANDLE_VALUE)
 | |
|         CloseHandle(h);
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| 
 | |
| DWORD Ext2QuerySrv(TCHAR *srv, DWORD *pids, DWORD as)
 | |
| {
 | |
|     DWORD  total = 0;
 | |
|     HANDLE p = NULL;
 | |
|     PROCESSENTRY32 r = {0};
 | |
| 
 | |
|     p = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 | |
|     if (INVALID_HANDLE_VALUE == p)
 | |
|         return 0;
 | |
| 
 | |
|     r.dwSize=sizeof(PROCESSENTRY32);
 | |
|     if (!Process32First(p, &r)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     do {
 | |
|         TCHAR *n = _tcsrchr(&r.szExeFile[0], _T('\\'));
 | |
|         if (!n)
 | |
|             n = &r.szExeFile[0];
 | |
|         if (_tcsicmp(n, srv) == 0) {
 | |
|             pids[total++] = r.th32ProcessID;
 | |
|             if (total >= as)
 | |
|                 break;
 | |
|         }
 | |
|         
 | |
|     } while(Process32Next(p, &r));
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     CloseHandle(p);
 | |
| 
 | |
|     return total;
 | |
| }
 | |
| 
 | |
| TCHAR *Ext2StrLastA(TCHAR *t, TCHAR *s)
 | |
| {
 | |
|     int lt = strlen(t), ls = strlen(s), i;
 | |
| 
 | |
|     for (i = lt - ls; i >= 0; i--) {
 | |
|         if (0 == _strnicmp(&t[i], s, ls))
 | |
|             return &t[i];
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| TCHAR * Ext2BuildCMDA()
 | |
| {
 | |
|     TCHAR  cmd[512] = {0}, *p,  *refresh = NULL;
 | |
|     int    len = 0;
 | |
| 
 | |
|     if (GetModuleFileName(NULL, cmd, 510)) {
 | |
|     } else { 
 | |
|         strcpy(cmd, GetCommandLine());
 | |
|     }
 | |
| 
 | |
|     len = (int)_tcslen(cmd) + 2;
 | |
|     refresh = new TCHAR[len];
 | |
|     if (!refresh)
 | |
|         goto errorout;
 | |
|     memset(refresh, 0, sizeof(TCHAR)*len);
 | |
|     _tcscpy(refresh, cmd);
 | |
|     p = _tcsstr(refresh, _T("/"));
 | |
|     if (p)
 | |
|         *p = 0;
 | |
| 
 | |
|     p = Ext2StrLastA(refresh, "Ext2Mgr");
 | |
|     if (p) {
 | |
|         p[4] = 'S';
 | |
|         p[5] = 'r';
 | |
|         p[6] = 'v';
 | |
|     } else {
 | |
|         delete [] refresh;
 | |
|         refresh = NULL;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
|     return refresh;
 | |
| }
 | |
| 
 | |
| WCHAR *Ext2StrLastW(WCHAR *t, WCHAR *s)
 | |
| {
 | |
|     int lt = wcslen(t), ls = wcslen(s), i;
 | |
| 
 | |
|     for (i = lt - ls; i >= 0; i--) {
 | |
|         if (0 == _wcsnicmp(&t[i], s, ls))
 | |
|             return &t[i];
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| WCHAR *Ext2BuildCMDW()
 | |
| {
 | |
|     WCHAR  cmd[512] = {0}, *p, *refresh = NULL;
 | |
|     int    len = 0;
 | |
| 
 | |
|     if (GetModuleFileNameW(NULL, cmd, 510)) {
 | |
|     } else { 
 | |
|         wcscpy(cmd, GetCommandLineW());
 | |
|     }
 | |
| 
 | |
|     len = (int)wcslen(cmd) + 2;
 | |
|     refresh = new WCHAR[len];
 | |
|     if (!refresh)
 | |
|         goto errorout;
 | |
|     memset(refresh, 0, sizeof(WCHAR)*len);
 | |
|     wcscpy(refresh, cmd);
 | |
|     p = wcsstr(refresh, L"/");
 | |
|     if (p)
 | |
|         *p = 0;
 | |
| 
 | |
|     p = Ext2StrLastW(refresh, L"Ext2Mgr");
 | |
|     if (p) {
 | |
|         p[4] = 'S';
 | |
|         p[5] = 'r';
 | |
|         p[6] = 'v';
 | |
|     } else {
 | |
|         delete [] refresh;
 | |
|         refresh = NULL;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
|     return refresh;
 | |
| }
 | |
| 
 | |
| PROCESS_INFORMATION g_Ext2Srv;
 | |
| 
 | |
| 
 | |
| typedef BOOL
 | |
| (WINAPI *lpfnCreateProcessWithTokenW)(
 | |
|     HANDLE hToken,
 | |
|     DWORD dwLogonFlags,
 | |
|     LPCWSTR lpApplicationName,
 | |
|     LPWSTR lpCommandLine,
 | |
|     DWORD dwCreationFlags,
 | |
|     LPVOID lpEnvironment,
 | |
|     LPCWSTR lpCurrentDirectory,
 | |
|     LPSTARTUPINFOW lpStartupInfo,
 | |
|     LPPROCESS_INFORMATION lpProcessInformation
 | |
|     );
 | |
| 
 | |
| lpfnCreateProcessWithTokenW g_CreateProcessWithTokenW;
 | |
| 
 | |
| int Ext2StartSrvAsUser(HANDLE token)
 | |
| {
 | |
|     LPWSTR  cmd = NULL;
 | |
|     STARTUPINFOW si = {0};
 | |
|     PROCESS_INFORMATION pi = {0};
 | |
|     int     rc = -1;
 | |
| 
 | |
|     cmd = Ext2BuildCMDW();
 | |
|     if (!cmd) {
 | |
|         rc = -1;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     si.cb = sizeof( STARTUPINFO );
 | |
|     if (token && g_CreateProcessWithTokenW) {
 | |
|         rc = g_CreateProcessWithTokenW(
 | |
|                              token, 0, NULL, cmd,
 | |
|                              NORMAL_PRIORITY_CLASS |
 | |
|                              CREATE_NO_WINDOW, 
 | |
|                              NULL, NULL,
 | |
|                              &si, &pi );
 | |
|     } else {
 | |
|         rc = CreateProcessW(  NULL, cmd, NULL, NULL,
 | |
|                              FALSE, NORMAL_PRIORITY_CLASS |
 | |
|                              CREATE_NO_WINDOW, NULL, NULL,
 | |
|                              &si, &pi );
 | |
|     }
 | |
| 
 | |
|     if (!rc) {
 | |
|         rc = -1 * GetLastError();
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     g_Ext2Srv = pi;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (cmd)
 | |
|         delete []cmd;
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| int Ext2StartSrvAsElevated()
 | |
| {
 | |
|     LPTSTR  cmd = NULL;
 | |
|     STARTUPINFO si = {0};
 | |
|     PROCESS_INFORMATION pi = {0};
 | |
|     int     rc = -1;
 | |
| 
 | |
|     cmd = Ext2BuildCMDA();
 | |
|     if (!cmd) {
 | |
|         rc = -1;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     si.cb = sizeof( STARTUPINFO );
 | |
|     rc = CreateProcess(  NULL, cmd, NULL, NULL,
 | |
|                          FALSE, NORMAL_PRIORITY_CLASS |
 | |
|                          CREATE_NO_WINDOW, NULL, NULL,
 | |
|                          &si, &pi );
 | |
| 
 | |
|     if (!rc) {
 | |
|         rc = -1 * GetLastError();
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     g_Ext2Srv = pi;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (cmd)
 | |
|         delete []cmd;
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| int Ext2StartSrv()
 | |
| {
 | |
|     DWORD   pid[12] = {0}, num;
 | |
|     int     rc = -1;
 | |
| 
 | |
|     num = Ext2QuerySrv(_T("Ext2Srv.exe"), pid, 10);
 | |
|     if (num) {
 | |
|         /* already started */
 | |
|         rc = num;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     if (IsVistaOrAbove()) {
 | |
| 
 | |
|         DWORD   sid = 0, mysid = 0;
 | |
|         HANDLE  token = 0;
 | |
| 
 | |
|         num = Ext2QuerySrv(_T("Explorer.exe"), &pid[0], 10);
 | |
|         if (!num) {
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|         pid[num] = GetCurrentProcessId();
 | |
|         num++;
 | |
| 
 | |
|         rc = ProcessIdToSessionId(GetCurrentProcessId(), &mysid);
 | |
|         if (!rc) {
 | |
|             rc = -1 * GetLastError();
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|         while (num > 0 && pid[num - 1]) {
 | |
| 
 | |
|             rc = Ext2CreateToken(pid[--num], &sid, &token);
 | |
|             if (rc > 0) {
 | |
|                 if (sid == mysid)  {
 | |
|                     rc = Ext2StartSrvAsUser(token);
 | |
|                 } else {
 | |
|                     rc = 0;
 | |
|                 }
 | |
|                 if (token && token != INVALID_HANDLE_VALUE) {
 | |
|                     CloseHandle(token);
 | |
|                     token = NULL;
 | |
|                 }
 | |
|                 if (rc == 1) {
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|     } else {
 | |
| 
 | |
|         Ext2StartSrvAsElevated();
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| void Ext2StopSrv()
 | |
| {
 | |
|     PROCESS_INFORMATION pi = g_Ext2Srv;
 | |
| 
 | |
|     memset(&g_Ext2Srv, 0, sizeof(pi));
 | |
| 
 | |
|     /* wait until process exits or timeouts */
 | |
| 
 | |
|     if (pi.hProcess != INVALID_HANDLE_VALUE) { 
 | |
|         TerminateProcess(pi.hProcess, -1);
 | |
|         CloseHandle(pi.hProcess); 
 | |
|     } 
 | |
|     if (pi.hThread != INVALID_HANDLE_VALUE) {
 | |
|         CloseHandle(pi.hThread); 
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* Ext2EnablePrivilege(SE_TCB_NAME) */
 | |
| 
 | |
| BOOL Ext2EnablePrivilege(LPCTSTR lpszPrivilegeName)
 | |
| {
 | |
|     TOKEN_PRIVILEGES tp = {0};
 | |
|     HANDLE  token;
 | |
|     LUID    luid;
 | |
|     BOOL    rc;
 | |
| 
 | |
|     rc = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES |
 | |
|                           TOKEN_QUERY | TOKEN_READ, &token);
 | |
|     if(!rc)
 | |
|         goto errorout;
 | |
| 
 | |
|     rc = LookupPrivilegeValue(NULL, lpszPrivilegeName, &luid);
 | |
|     if(!rc)
 | |
|         goto errorout;
 | |
| 
 | |
|     /* initialize token privilege */
 | |
|     tp.PrivilegeCount = 1;
 | |
|     tp.Privileges[0].Luid = luid;
 | |
|     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 | |
|     rc = AdjustTokenPrivileges(token, FALSE, &tp, NULL, NULL, NULL);
 | |
|     CloseHandle(token);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| #define KEY_WOW64_64KEY         (0x0100)
 | |
| 
 | |
| BOOL KdpQueryRegDWORD(CHAR *service, CHAR *value, DWORD *data)
 | |
| {
 | |
|     int     rc = TRUE;
 | |
|     HKEY    key;
 | |
|     CHAR   keyPath[MAX_PATH] = "SYSTEM\\CurrentControlSet\\Services\\";
 | |
|     LONG    status, type, len = 0;
 | |
| 
 | |
|     strcat(keyPath, service);
 | |
|     status = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS | KEY_WOW64_64KEY,
 | |
|                             &key) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     len = sizeof(DWORD);
 | |
|     status = RegQueryValueEx( key,
 | |
|                               value,
 | |
|                               0,
 | |
|                               (LPDWORD)&type,
 | |
|                               (BYTE *)data,
 | |
|                               (LPDWORD)&len);
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|     }
 | |
|     RegCloseKey(key);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL KdpSetRegDWORD(CHAR *service, CHAR *value, DWORD data)
 | |
| {
 | |
|     int     rc = TRUE;
 | |
|     HKEY    key;
 | |
|     CHAR   keyPath[MAX_PATH] = "SYSTEM\\CurrentControlSet\\Services\\";
 | |
|     LONG    status;
 | |
| 
 | |
|     strcat(keyPath, service);
 | |
|     status = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS | KEY_WOW64_64KEY,
 | |
|                             &key) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = RegSetValueEx( key,
 | |
|                               value,
 | |
|                               0,
 | |
|                               REG_DWORD,
 | |
|                               (BYTE *)&data,
 | |
|                               sizeof(DWORD));
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|     }
 | |
|     RegCloseKey(key);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL Ext2StartPipeSrv()
 | |
| {
 | |
|     HMODULE hAdvapi32;
 | |
|     BOOL rc = FALSE;
 | |
| 
 | |
|     if (CanDoLocalMount()) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     /* query advapi32!CreateProcessWithToken */
 | |
|     hAdvapi32 = GetModuleHandle("Advapi32.DLL");
 | |
|     g_CreateProcessWithTokenW = (lpfnCreateProcessWithTokenW)
 | |
|         GetProcAddress(hAdvapi32, "CreateProcessWithTokenW");
 | |
| 
 | |
|     if (!g_CreateProcessWithTokenW) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* add more privilege for toke duplication */
 | |
|     Ext2EnablePrivilege(SE_INCREASE_QUOTA_NAME);
 | |
|     Ext2EnablePrivilege(SE_TCB_NAME);
 | |
| 
 | |
|     /* start Ext2Srv.exe */
 | |
|     rc = Ext2StartSrv();
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| VOID Ext2StopPipeSrv()
 | |
| {
 | |
|     /* close pipe handles */
 | |
|     Ext2ClosePipe();
 | |
| 
 | |
|     /* terminate process: Ext2Srv */
 | |
|     Ext2StopSrv();
 | |
| } |