Annotation of truecrypt/service/ntservice.c, revision 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.