|
|
1.1 ! root 1: /* Copyright (C) 2004 TrueCrypt Team, truecrypt.org ! 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: { ! 398: WCHAR arrVolume[64], tmp[] = {0,0}; ! 399: char buf[200]; ! 400: PMOUNTMGR_TARGET_NAME in = (PMOUNTMGR_TARGET_NAME) buf; ! 401: ! 402: tmp[0] = (WCHAR)dosName[0]; ! 403: wcscpy (arrVolume, TC_MOUNT_PREFIX); ! 404: wcscat (arrVolume, tmp); ! 405: ! 406: in->DeviceNameLength = (USHORT) wcslen(arrVolume) * 2; ! 407: wcscpy(in->DeviceName, arrVolume); ! 408: ! 409: bResult = DeviceIoControl (mountManager, IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION, in, ! 410: sizeof (in->DeviceNameLength) + wcslen(arrVolume) * 2, 0, 0, &dwResult, NULL); ! 411: ! 412: CloseHandle (mountManager); ! 413: } ! 414: ! 415: // Create drive letter link ! 416: if(!DefineDosDevice (DDD_RAW_TARGET_PATH, dosName, szDevice)) ! 417: sprintf (szOut, "-ERR 1 %d", GetLastError()); ! 418: else ! 419: sprintf (szOut, "+OK mounted"); ! 420: ! 421: } ! 422: else if (strcmp (szOut, "unmount") == 0) ! 423: { ! 424: if (UnmountVolume (nDosDriveNo, &os_error, &err) == FALSE) ! 425: { ! 426: sprintf (szOut, "-ERR %d %lu", err, os_error); ! 427: } ! 428: else ! 429: { ! 430: sprintf (szOut, "+OK unmounted"); ! 431: } ! 432: } ! 433: else if (strcmp (szOut, "unmountall") == 0) ! 434: { ! 435: if (UnmountAllVolumes (NULL, &os_error, &err) == FALSE) ! 436: { ! 437: sprintf (szOut, "-ERR %d %lu", err, os_error); ! 438: } ! 439: else ! 440: { ! 441: sprintf (szOut, "+OK unmounted"); ! 442: } ! 443: } ! 444: else ! 445: { ! 446: sprintf (szOut, "-ERR invalid command"); ! 447: } ! 448: ! 449: /* init the overlapped structure */ ! 450: memset (&os, 0, sizeof (OVERLAPPED)); ! 451: os.hEvent = hEvents[1]; ! 452: ResetEvent (hEvents[1]); ! 453: ! 454: /* send it back out... */ ! 455: bRet = WriteFile ( ! 456: hPipe, /* file to write to */ ! 457: szOut, /* address of output buffer */ ! 458: sizeof (szOut), /* number of bytes to ! 459: write */ ! 460: &cbWritten, /* number of bytes ! 461: written */ ! 462: &os); /* overlapped stuff, not ! 463: needed */ ! 464: ! 465: if (bRet == FALSE && (GetLastError ()== ERROR_IO_PENDING)) ! 466: { ! 467: dwWait = WaitForMultipleObjects (2, hEvents, FALSE, INFINITE); ! 468: if (dwWait != WAIT_OBJECT_0 + 1) /* not overlapped i/o ! 469: event - error ! 470: occurred, */ ! 471: break; /* or server stop signaled */ ! 472: } ! 473: ! 474: /* drop the connection... */ ! 475: DisconnectNamedPipe (hPipe); ! 476: } ! 477: ! 478: ! 479: dwResult = NO_ERROR; ! 480: ! 481: error: ! 482: if (hServerStopEvent != NULL) ! 483: CloseHandle (hServerStopEvent); ! 484: ! 485: if (hEvents[1] != NULL) ! 486: CloseHandle (hEvents[1]); ! 487: ! 488: if (hDriver != INVALID_HANDLE_VALUE) ! 489: CloseHandle (hDriver); ! 490: ! 491: if (hPipe != INVALID_HANDLE_VALUE) ! 492: CloseHandle (hPipe); ! 493: ! 494: if (pSD != NULL) ! 495: free (pSD); ! 496: ! 497: ReportStatusToSCMgr (SERVICE_STOPPED, dwResult, 0); ! 498: } ! 499: ! 500: void ! 501: ServiceStop () ! 502: { ! 503: if (hServerStopEvent != NULL) ! 504: SetEvent (hServerStopEvent); ! 505: } ! 506: ! 507: void ! 508: handleWin32Error (HWND dummy) ! 509: { ! 510: char tmp[256] = ! 511: {0}; ! 512: ! 513: if (dummy); /* Remove warning */ ! 514: ! 515: GetLastErrorText (tmp, sizeof (tmp)); ! 516: ! 517: AddToMessageLog (tmp); ! 518: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.