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

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

unix.superglobalmegacorp.com

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