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