|
|
1.1.1.2 ! root 1: /* Copyright (C) 2004 TrueCrypt Foundation 1.1 root 2: This product uses components written by Paul Le Roux <[email protected]> */ 3: 4: #include "TCdefs.h" 5: #include <process.h> 6: 7: #include "ntservice.h" 8: 9: #include "crypto.h" 10: #include "apidrvr.h" 11: 12: #include "dismount.h" 13: #include <mountdev.h> 14: 15: /* current status of the service */ 16: SERVICE_STATUS ssStatus; 17: 18: /* handle for reporting back to the SCM */ 19: SERVICE_STATUS_HANDLE sshStatusHandle = 0; 20: 21: /* stop event; used at shutdown */ 22: HANDLE hServerStopEvent = NULL; 23: 24: /* Handle to the device driver */ 25: HANDLE hDriver = INVALID_HANDLE_VALUE; 26: 27: /* main() calls StartServiceCtrlDispatcher to register the main service 28: thread. When the this call returns, the service has stopped, so exit. */ 29: 30: int main (int argc, char **argv) 31: { 32: SERVICE_TABLE_ENTRY dispatchTable[]= 33: { 34: {SZSERVICENAME, (LPSERVICE_MAIN_FUNCTION) service_main}, 35: {NULL, NULL} 36: }; 37: 38: if (StartServiceCtrlDispatcher (dispatchTable) == 0) 39: AddToMessageLog ("StartServiceCtrlDispatcher failed."); 40: } 41: 42: /* service_main, this routine performs the service initialization and then 43: calls the user defined ServiceStart() routine to perform majority of the 44: work. */ 45: 46: void WINAPI 47: service_main (DWORD dwArgc, LPSTR * lpszArgv) 48: { 49: /* register our service control handler: */ 50: sshStatusHandle = RegisterServiceCtrlHandler (SZSERVICENAME, service_ctrl); 51: if (sshStatusHandle == 0) 52: return; 53: 54: ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 55: ssStatus.dwServiceSpecificExitCode = 0; 56: 57: /* report the status to the service control manager. */ 58: if (!ReportStatusToSCMgr ( 59: SERVICE_START_PENDING, /* service state */ 60: NO_ERROR, /* exit code */ 61: 3000)) /* wait hint */ 62: return; 63: 64: ServiceStart (dwArgc, lpszArgv); 65: } 66: 67: /* service_ctrl, this function is called by the SCM whenever ControlService() 68: is called on this service. */ 69: 70: void WINAPI 71: service_ctrl (DWORD dwCtrlCode) 72: { 73: /* Handle the requested control code. */ 74: switch (dwCtrlCode) 75: { 76: case SERVICE_CONTROL_STOP: 77: { 78: DWORD os_error; 79: int err; 80: UnmountAllVolumes (NULL, &os_error, &err); 81: 82: /* Stop the service. SERVICE_STOP_PENDING should be reported 83: before setting the Stop Event - hServerStopEvent - in 84: ServiceStop(). This avoids a race condition which may 85: result in a 1053 - The Service did not respond... error. */ 86: ReportStatusToSCMgr (SERVICE_STOP_PENDING, NO_ERROR, 0); 87: ServiceStop (); 88: } 89: return; 90: 91: case SERVICE_CONTROL_SHUTDOWN: 92: { 93: DWORD os_error; 94: int err; 95: UnmountAllVolumes (NULL, &os_error, &err); 96: } 97: break; 98: 99: case SERVICE_CONTROL_INTERROGATE: 100: /* Update the service status. */ 101: break; 102: 103: default: 104: /* invalid control code */ 105: break; 106: 107: } 108: 109: ReportStatusToSCMgr (ssStatus.dwCurrentState, NO_ERROR, 0); 110: } 111: 112: /* ReportStatusToSCMgr, sets the current status of the service and reports it 113: to the Service Control Manager */ 114: 115: BOOL 116: ReportStatusToSCMgr (DWORD dwCurrentState, /* the state of the service */ 117: DWORD dwWin32ExitCode, /* error code to report */ 118: DWORD dwWaitHint) /* worst case estimate to next 119: checkpoint */ 120: { 121: static DWORD dwCheckPoint = 1; 122: BOOL fResult = TRUE; 123: 124: if (dwCurrentState == SERVICE_START_PENDING) 125: ssStatus.dwControlsAccepted = 0; 126: else 127: ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; 128: 129: ssStatus.dwCurrentState = dwCurrentState; 130: ssStatus.dwWin32ExitCode = dwWin32ExitCode; 131: ssStatus.dwWaitHint = dwWaitHint; 132: 133: if ((dwCurrentState == SERVICE_RUNNING) || 134: (dwCurrentState == SERVICE_STOPPED)) 135: ssStatus.dwCheckPoint = 0; 136: else 137: ssStatus.dwCheckPoint = dwCheckPoint++; 138: 139: /* Report the status of the service to the service control manager. */ 140: 141: if (!(fResult = SetServiceStatus (sshStatusHandle, &ssStatus))) 142: { 143: AddToMessageLog ("SetServiceStatus"); 144: } 145: 146: return fResult; 147: } 148: 149: 150: /* AddToMessageLog, allows any thread to log an error message */ 151: 152: void 153: AddToMessageLog (LPSTR lpszMsg) 154: { 155: char szMsg[256]; 156: HANDLE hEventSource; 157: LPSTR lpszStrings[2]; 158: DWORD dwErr = GetLastError (); 159: 160: /* Use event logging to log the error */ 161: 162: hEventSource = RegisterEventSource (NULL, SZSERVICENAME); 163: 164: sprintf (szMsg, "%s error: %d", SZSERVICENAME, dwErr); 165: lpszStrings[0] = szMsg; 166: lpszStrings[1] = lpszMsg; 167: 168: if (hEventSource != NULL) 169: { 170: ReportEvent (hEventSource, /* handle of event source */ 171: EVENTLOG_ERROR_TYPE, /* event type */ 172: 0, /* event category */ 173: 0, /* event ID */ 174: NULL, /* current user 's SID */ 175: 2, /* strings in lpszStrings */ 176: 0, /* no bytes of raw data */ 177: lpszStrings, /* array of error strings */ 178: NULL); /* no raw data */ 179: 180: DeregisterEventSource (hEventSource); 181: } 182: } 183: 184: /* GetLastErrorText, copies error message text to string */ 185: 186: LPSTR 187: GetLastErrorText (LPSTR lpszBuf, DWORD dwSize) 188: { 189: DWORD dwRet; 190: LPSTR lpszTemp = NULL; 191: 192: dwRet = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, 193: NULL, 194: GetLastError (), 195: LANG_NEUTRAL, 196: (LPSTR) & lpszTemp, 197: 0, 198: NULL); 199: 200: /* supplied buffer is not long enough */ 201: if (dwRet == 0 || ((long) dwSize < (long) dwRet + 14)) 202: lpszBuf[0] = '\0'; 203: else 204: { 205: lpszTemp[lstrlen (lpszTemp) - 2] = '\0'; /* remove cr and newline 206: character */ 207: sprintf (lpszBuf, "%s (0x%x)", lpszTemp, GetLastError ()); 208: } 209: 210: if (lpszTemp != NULL) 211: LocalFree ((HLOCAL) lpszTemp); 212: 213: return lpszBuf; 214: } 215: 216: void 217: ServiceStart (DWORD dwArgc, LPTSTR * lpszArgv) 218: { 219: DWORD dwWait, dwResult = ERROR_GEN_FAILURE; 220: HANDLE hPipe = INVALID_HANDLE_VALUE; 221: HANDLE hEvents[2] = {NULL, NULL}; 222: OVERLAPPED os; 223: PSECURITY_DESCRIPTOR pSD = NULL; 224: SECURITY_ATTRIBUTES sa; 225: TCHAR szIn[80]; 226: TCHAR szOut[80]; 227: LPTSTR lpszPipeName = "\\\\.\\pipe\\truecryptservice"; 228: BOOL bRet; 229: DWORD cbRead; 230: DWORD cbWritten; 231: 232: if (!ReportStatusToSCMgr ( 233: SERVICE_START_PENDING, /* service state */ 234: NO_ERROR, /* exit code */ 235: 3000)) /* wait hint */ 236: goto error; 237: 238: hServerStopEvent = CreateEvent ( 239: NULL, /* no security 240: attributes */ 241: TRUE, /* manual reset event */ 242: FALSE, /* not-signalled */ 243: NULL); /* no name */ 244: 245: if (hServerStopEvent == NULL) 246: goto error; 247: 248: if (!ReportStatusToSCMgr ( 249: SERVICE_START_PENDING, /* service state */ 250: NO_ERROR, /* exit code */ 251: 3000)) /* wait hint */ 252: goto error; 253: 254: /* Try to open a handle to the device driver. It will be closed 255: later. */ 256: hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); 257: if (hDriver == INVALID_HANDLE_VALUE) 258: { 259: handleWin32Error (NULL); 260: goto error; 261: } 262: 263: if (!ReportStatusToSCMgr ( 264: SERVICE_START_PENDING, /* service state */ 265: NO_ERROR, /* exit code */ 266: 3000)) /* wait hint */ 267: goto error; 268: 269: /* create the event object object use in overlapped i/o */ 270: hEvents[1] = CreateEvent ( 271: NULL, /* no security attributes */ 272: TRUE, /* manual reset event */ 273: FALSE, /* not-signalled */ 274: NULL); /* no name */ 275: 276: if (hEvents[1] == NULL) 277: goto error; 278: 279: if (!ReportStatusToSCMgr ( 280: SERVICE_START_PENDING, /* service state */ 281: NO_ERROR, /* exit code */ 282: 3000)) /* wait hint */ 283: goto error; 284: 285: /* create a security descriptor that allows anyone to write to the 286: pipe */ 287: pSD = (PSECURITY_DESCRIPTOR) malloc (SECURITY_DESCRIPTOR_MIN_LENGTH); 288: 289: if (pSD == NULL) 290: goto error; 291: 292: if (InitializeSecurityDescriptor (pSD, SECURITY_DESCRIPTOR_REVISION) == 0) 293: goto error; 294: 295: /* add a NULL disc.ACL to the security descriptor. */ 296: if (SetSecurityDescriptorDacl (pSD, TRUE, (PACL) NULL, FALSE) == 0) 297: goto error; 298: 299: sa.nLength = sizeof (sa); 300: sa.lpSecurityDescriptor = pSD; 301: sa.bInheritHandle = TRUE; 302: 303: if (!ReportStatusToSCMgr ( 304: SERVICE_START_PENDING, /* service state */ 305: NO_ERROR, /* exit code */ 306: 3000)) /* wait hint */ 307: goto error; 308: 309: hPipe = CreateNamedPipe ( 310: lpszPipeName, /* name of pipe */ 311: FILE_FLAG_OVERLAPPED | 312: PIPE_ACCESS_DUPLEX, /* pipe open mode */ 313: PIPE_TYPE_MESSAGE | 314: PIPE_READMODE_MESSAGE | 315: PIPE_WAIT, /* pipe IO type */ 316: 1, /* number of instances */ 317: 0, /* size of outbuf (0 == 318: allocate as necessary) */ 319: 0, /* size of inbuf */ 320: 1000, /* default time-out value */ 321: &sa); /* security attributes */ 322: 323: if (hPipe == INVALID_HANDLE_VALUE) 324: { 325: AddToMessageLog (TEXT ("Unable to create named pipe")); 326: goto error; 327: } 328: 329: hEvents[0] = hServerStopEvent; 330: 331: if (!ReportStatusToSCMgr ( 332: SERVICE_RUNNING, /* service state */ 333: NO_ERROR, /* exit code */ 334: 0)) /* wait hint */ 335: goto error; 336: 337: for (;;) 338: { 339: int nDosDriveNo = -1, err; 340: DWORD os_error; 341: 342: /* init the overlapped structure */ 343: memset (&os, 0, sizeof (OVERLAPPED)); 344: os.hEvent = hEvents[1]; 345: ResetEvent (hEvents[1]); 346: 347: /* wait for a connection... */ 348: ConnectNamedPipe (hPipe, &os); 349: 350: if (GetLastError ()== ERROR_IO_PENDING) 351: { 352: dwWait = WaitForMultipleObjects (2, hEvents, FALSE, INFINITE); 353: if (dwWait != WAIT_OBJECT_0 + 1) /* not overlapped i/o 354: event - error 355: occurred, */ 356: break; /* or server stop signaled */ 357: } 358: 359: /* init the overlapped structure */ 360: memset (&os, 0, sizeof (OVERLAPPED)); 361: os.hEvent = hEvents[1]; 362: ResetEvent (hEvents[1]); 363: 364: /* grab whatever's coming through the pipe... */ 365: bRet = ReadFile ( 366: hPipe, /* file to read from */ 367: szIn, /* address of input buffer */ 368: sizeof (szIn), /* number of bytes to 369: read */ 370: &cbRead, /* number of bytes read */ 371: &os); /* overlapped stuff, not 372: needed */ 373: 374: if (bRet == FALSE && (GetLastError ()== ERROR_IO_PENDING)) 375: { 376: dwWait = WaitForMultipleObjects (2, hEvents, FALSE, INFINITE); 377: if (dwWait != WAIT_OBJECT_0 + 1) /* not overlapped i/o 378: event - error 379: occurred, */ 380: break; /* or server stop signaled */ 381: } 382: 383: sscanf (szIn, "%s %d", szOut, &nDosDriveNo); 384: 385: if (strcmp (szOut, "mount") == 0) 386: { 387: BOOL bResult; 388: HANDLE mountManager; 389: char dosName[3] = {0,':',0}, szDevice[64]; 390: 391: dosName[0] = (char) (nDosDriveNo + 'A'); 392: sprintf (szDevice, "%s%c", NT_MOUNT_PREFIX, dosName[0]); 393: 394: // Notify Mount Manager of volume arrival 395: mountManager = CreateFileW (MOUNTMGR_DOS_DEVICE_NAME, FILE_READ_DATA|FILE_WRITE_DATA, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 396: if(mountManager != INVALID_HANDLE_VALUE) 397: { 1.1.1.2 ! root 398: // W2k MMGR support disabled for now to prevent remount bug ! 399: OSVERSIONINFO os; ! 400: os.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); ! 401: GetVersionEx (&os); ! 402: if (!(os.dwPlatformId == VER_PLATFORM_WIN32_NT ! 403: && os.dwMajorVersion == 5 && os.dwMinorVersion == 0)) ! 404: { ! 405: ! 406: WCHAR arrVolume[64], tmp[] = {0,0}; ! 407: char buf[200]; ! 408: PMOUNTMGR_TARGET_NAME in = (PMOUNTMGR_TARGET_NAME) buf; ! 409: ! 410: tmp[0] = (WCHAR)dosName[0]; ! 411: wcscpy (arrVolume, TC_MOUNT_PREFIX); ! 412: wcscat (arrVolume, tmp); ! 413: ! 414: in->DeviceNameLength = (USHORT) wcslen(arrVolume) * 2; ! 415: wcscpy(in->DeviceName, arrVolume); ! 416: ! 417: bResult = DeviceIoControl (mountManager, IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION, in, ! 418: sizeof (in->DeviceNameLength) + wcslen(arrVolume) * 2, 0, 0, &dwResult, NULL); ! 419: } 1.1 root 420: 421: CloseHandle (mountManager); 422: } 423: 424: // Create drive letter link 425: if(!DefineDosDevice (DDD_RAW_TARGET_PATH, dosName, szDevice)) 426: sprintf (szOut, "-ERR 1 %d", GetLastError()); 427: else 428: sprintf (szOut, "+OK mounted"); 429: 430: } 431: else if (strcmp (szOut, "unmount") == 0) 432: { 433: if (UnmountVolume (nDosDriveNo, &os_error, &err) == FALSE) 434: { 435: sprintf (szOut, "-ERR %d %lu", err, os_error); 436: } 437: else 438: { 439: sprintf (szOut, "+OK unmounted"); 440: } 441: } 442: else if (strcmp (szOut, "unmountall") == 0) 443: { 444: if (UnmountAllVolumes (NULL, &os_error, &err) == FALSE) 445: { 446: sprintf (szOut, "-ERR %d %lu", err, os_error); 447: } 448: else 449: { 450: sprintf (szOut, "+OK unmounted"); 451: } 452: } 453: else 454: { 455: sprintf (szOut, "-ERR invalid command"); 456: } 457: 458: /* init the overlapped structure */ 459: memset (&os, 0, sizeof (OVERLAPPED)); 460: os.hEvent = hEvents[1]; 461: ResetEvent (hEvents[1]); 462: 463: /* send it back out... */ 464: bRet = WriteFile ( 465: hPipe, /* file to write to */ 466: szOut, /* address of output buffer */ 467: sizeof (szOut), /* number of bytes to 468: write */ 469: &cbWritten, /* number of bytes 470: written */ 471: &os); /* overlapped stuff, not 472: needed */ 473: 474: if (bRet == FALSE && (GetLastError ()== ERROR_IO_PENDING)) 475: { 476: dwWait = WaitForMultipleObjects (2, hEvents, FALSE, INFINITE); 477: if (dwWait != WAIT_OBJECT_0 + 1) /* not overlapped i/o 478: event - error 479: occurred, */ 480: break; /* or server stop signaled */ 481: } 482: 483: /* drop the connection... */ 484: DisconnectNamedPipe (hPipe); 485: } 486: 487: 488: dwResult = NO_ERROR; 489: 490: error: 491: if (hServerStopEvent != NULL) 492: CloseHandle (hServerStopEvent); 493: 494: if (hEvents[1] != NULL) 495: CloseHandle (hEvents[1]); 496: 497: if (hDriver != INVALID_HANDLE_VALUE) 498: CloseHandle (hDriver); 499: 500: if (hPipe != INVALID_HANDLE_VALUE) 501: CloseHandle (hPipe); 502: 503: if (pSD != NULL) 504: free (pSD); 505: 506: ReportStatusToSCMgr (SERVICE_STOPPED, dwResult, 0); 507: } 508: 509: void 510: ServiceStop () 511: { 512: if (hServerStopEvent != NULL) 513: SetEvent (hServerStopEvent); 514: } 515: 516: void 517: handleWin32Error (HWND dummy) 518: { 519: char tmp[256] = 520: {0}; 521: 522: if (dummy); /* Remove warning */ 523: 524: GetLastErrorText (tmp, sizeof (tmp)); 525: 526: AddToMessageLog (tmp); 527: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.