Annotation of truecrypt/service/ntservice.c, revision 1.1.1.3

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.