home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / security / winnt / sd_flppy / floplock.c < prev    next >
C/C++ Source or Header  |  1996-04-18  |  24KB  |  723 lines

  1. /****************************************************************************\
  2. *  INCLUDES, DEFINES
  3. \****************************************************************************/
  4. #define STRICT
  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. #define PERR(api) printf("\n%s: Error %d from %s on line %d",  \
  10.     __FILE__, GetLastError(), api, __LINE__);
  11. #define PMSG(msg) printf("\n%s line %d: %s",  \
  12.     __FILE__, __LINE__, msg);
  13.  
  14. // this event is signalled when the
  15. //  worker thread ends
  16. //
  17. HANDLE                  hServDoneEvent = NULL;
  18. SERVICE_STATUS          ssStatus;       // current status of the service
  19.  
  20. SERVICE_STATUS_HANDLE   sshStatusHandle;
  21. DWORD                   dwGlobalErr;
  22. DWORD                   TID = 0;
  23. HANDLE                  threadHandle = NULL;
  24. HANDLE                  pipeHandle;
  25.  
  26.  
  27. /****************************************************************************\
  28. * FUNCTION PROTOTYPES
  29. \****************************************************************************/
  30.  
  31. VOID    WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
  32. VOID    WINAPI service_ctrl(DWORD dwCtrlCode);
  33. BOOL    ReportStatusToSCMgr(DWORD dwCurrentState,
  34.                             DWORD dwWin32ExitCode,
  35.                             DWORD dwCheckPoint,
  36.                             DWORD dwWaitHint);
  37. VOID    die(char *reason);
  38. VOID    worker_thread(VOID *notUsed);
  39. VOID    StopSimpleService(LPTSTR lpszMsg);
  40. BOOL    WriteSD_ToA_File(PSECURITY_DESCRIPTOR psdAbsoluteSD, LPTSTR lpszFileName);
  41.  
  42.  
  43. /****************************************************************************\
  44. * GLOBAL VARIABLES AND TYPEDEFS
  45. \****************************************************************************/
  46.  
  47. #define                               SZ_SD_BUF   100
  48. #define                               SZ_SID_BUF   75
  49. #define                               SZ_ACL_BUF  150
  50.  
  51. UCHAR                ucAbsSDBuf      [SZ_SD_BUF]  = "";
  52. UCHAR                ucEvrSDBuf      [SZ_SD_BUF]  = "";
  53. UCHAR                ucSIDBuf        [SZ_SID_BUF] = "";
  54. UCHAR                ucPwrUsrsSIDBuf [SZ_SID_BUF] = "";
  55. UCHAR                ucACLBuf        [SZ_ACL_BUF] = "";
  56.  
  57. DWORD                dwSID          = SZ_SID_BUF;
  58. DWORD                dwDACL         = SZ_ACL_BUF;
  59. BOOL                 bFloppiesAreLocked;
  60.  
  61. PSECURITY_DESCRIPTOR psdAbsoluteSD      = (PSECURITY_DESCRIPTOR)&ucAbsSDBuf;
  62. PSECURITY_DESCRIPTOR psdEveryoneSD      = (PSECURITY_DESCRIPTOR)&ucEvrSDBuf;
  63. PSID                 psidAdministrators = (PSID)&ucSIDBuf;
  64. PSID                 psidPowerUsers     = (PSID)&ucPwrUsrsSIDBuf;
  65. PACL                 pNewDACL           = (PACL)&ucACLBuf;
  66.  
  67.  
  68.  
  69. //  main() --
  70. //      all main does is call StartServiceCtrlDispatcher
  71. //      to register the main service thread.  When the
  72. //      API returns, the service has stopped, so exit.
  73. //
  74. int
  75. main()
  76. {
  77.  
  78.     SERVICE_TABLE_ENTRY dispatchTable[] = {
  79.         { TEXT("SimpleService"), (LPSERVICE_MAIN_FUNCTION)service_main },
  80.         { NULL, NULL }
  81.     };
  82.  
  83.   // check if Win32s, if so, display notice and terminate
  84.         if( GetVersion() & 0x80000000 )
  85.         {
  86.           MessageBox( NULL,
  87.              "This application cannot run on Windows 3.1 or Windows 95.\n"
  88.              "This application will now terminate.",
  89.              "SD_FLPPY",
  90.              MB_OK | MB_ICONSTOP | MB_SETFOREGROUND );
  91.           return( 1 );
  92.         }
  93.  
  94.     #define FILE_TO_REDIRECT_STDOUT_TO "c:\\floplock.out"
  95. //  freopen(FILE_TO_REDIRECT_STDOUT_TO,"w+",stdout);
  96.  
  97.     if (!StartServiceCtrlDispatcher(dispatchTable)) {
  98.         StopSimpleService("StartServiceCtrlDispatcher failed.");
  99.     }
  100. }
  101.  
  102.  
  103.  
  104. //  service_main() --
  105. //      this function takes care of actually starting the service,
  106. //      informing the service controller at each step along the way.
  107. //      After launching the worker thread, it waits on the event
  108. //      that the worker thread will signal at its termination.
  109. //
  110. VOID WINAPI
  111. service_main(DWORD dwArgc, LPTSTR *lpszArgv)
  112. {
  113.     DWORD                   dwWait;
  114.     SECURITY_ATTRIBUTES     sa;
  115.  
  116.     // register our service control handler:
  117.     //
  118.     sshStatusHandle = RegisterServiceCtrlHandler(
  119.                                     TEXT("SimpleService"),
  120.                                     service_ctrl);
  121.  
  122.     if (!sshStatusHandle)
  123.         goto cleanup;
  124.  
  125.     // SERVICE_STATUS members that don't change in example
  126.     //
  127.     ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  128.     ssStatus.dwServiceSpecificExitCode = 0;
  129.  
  130.  
  131.     // report the status to Service Control Manager.
  132.     //
  133.     if (!ReportStatusToSCMgr(
  134.         SERVICE_START_PENDING, // service state
  135.         NO_ERROR,              // exit code
  136.         1,                     // checkpoint
  137.         3000))                 // wait hint
  138.         goto cleanup;
  139.  
  140.     // create the event object. The control handler function signals
  141.     // this event when it receives the "stop" control code.
  142.     //
  143.     hServDoneEvent = CreateEvent(
  144.         NULL,    // no security attributes
  145.         TRUE,    // manual reset event
  146.         FALSE,   // not-signalled
  147.         NULL);   // no name
  148.  
  149.     if (hServDoneEvent == (HANDLE)NULL)
  150.         goto cleanup;
  151.  
  152.     // report the status to the service control manager.
  153.     //
  154.     if (!ReportStatusToSCMgr(
  155.         SERVICE_START_PENDING, // service state
  156.         NO_ERROR,              // exit code
  157.         2,                     // checkpoint
  158.         3000))                 // wait hint
  159.         goto cleanup;
  160.  
  161.     // Create a security descriptor that allows only local Administrators
  162.     //   to do anything with the pipe.  Since Domain administrators are
  163.     //   normally also local Administrators, this will serve most needs
  164.  
  165.     /************************************************************************\
  166.     *
  167.     * Build SIDs of local Administrators and Power Users.  Note that the Power
  168.     *   Users group is defined on Windows NT machines, but not on Advanced
  169.     *   Server machines.  This means that we will on Advanced Server machines
  170.     *   have a DACL that has an ACE (for Power Users) that will never be used
  171.     *
  172.     \************************************************************************/
  173.  
  174.     {
  175.       SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  176.  
  177.       InitializeSid(        psidAdministrators, &siaNtAuthority, 2 );
  178.       InitializeSid(        psidPowerUsers,     &siaNtAuthority, 2 );
  179.  
  180.       *(GetSidSubAuthority( psidAdministrators, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  181.       *(GetSidSubAuthority( psidPowerUsers,     0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  182.  
  183.       *(GetSidSubAuthority( psidAdministrators, 1 )) = DOMAIN_ALIAS_RID_ADMINS;
  184.       *(GetSidSubAuthority( psidPowerUsers,     1 )) = DOMAIN_ALIAS_RID_POWER_USERS;
  185.     }
  186.  
  187.  
  188.     /************************************************************************\
  189.     *
  190.     * Initialize new DACL
  191.     *
  192.     \************************************************************************/
  193.  
  194.     if (!InitializeAcl(pNewDACL,
  195.                        dwDACL,
  196.                        ACL_REVISION))
  197.     { StopSimpleService("InitializeAcl");
  198.     }
  199.  
  200.     /************************************************************************\
  201.     *
  202.     * Allow All access for local Administrators only
  203.     *
  204.     \************************************************************************/
  205.  
  206.     if (!AddAccessAllowedAce(pNewDACL,
  207.                              ACL_REVISION,
  208.                              FILE_ALL_ACCESS,
  209.                              psidAdministrators))
  210.     { StopSimpleService("AddAccessAllowedAce");
  211.     }
  212.  
  213.     /************************************************************************\
  214.     *
  215.     * If we unlock the floppies when the service stops, then for the sake of
  216.     *   consistency, we have to also allow Power Users on the Admin-only DACL,
  217.     *   since Power Users can stop services.  It would be inconsistent to try
  218.     *   to lock Power Users away from their floppies if Power Users could get
  219.     *   to the floppies simply by stopping the service
  220.     *
  221.     * It's still OK to use the same DACL for the pipe as for the floppies,
  222.     *   that is, it's OK to let Power Users on the DACL for the pipe too.  The
  223.     *   reason is that it is not generally (and certainly not by default) the
  224.     *   case that an account is a member of Power Users on more than their own
  225.     *   machines.  So, putting Power Users on the pipe let's Power Users admin
  226.     *   the floppies via the pipe only on the machines on which they are
  227.     *   actually Power Users, and again, on those machines they can stop the
  228.     *   floppy-locking service as well
  229.     *
  230.     \************************************************************************/
  231.  
  232.     #define UNLOCK_AT_SERVICE_STOP (0==0)
  233.     if     (UNLOCK_AT_SERVICE_STOP)
  234.     { if (!AddAccessAllowedAce(pNewDACL,
  235.                                ACL_REVISION,
  236.                                FILE_ALL_ACCESS,
  237.                                psidPowerUsers))
  238.       { StopSimpleService("AddAccessAllowedAce");
  239.       }
  240.     }
  241.  
  242.     /************************************************************************\
  243.     *
  244.     * Build SD in absolute format - first the Admins-only then the Everyone SD
  245.     *
  246.     \************************************************************************/
  247.  
  248.     if (!InitializeSecurityDescriptor(psdAbsoluteSD,
  249.                                       SECURITY_DESCRIPTOR_REVISION))
  250.     { StopSimpleService("InitializeSecurityDescriptor");
  251.     }
  252.  
  253.     if (!InitializeSecurityDescriptor(psdEveryoneSD,
  254.                                       SECURITY_DESCRIPTOR_REVISION))
  255.     { StopSimpleService("InitializeSecurityDescriptor");
  256.     }
  257.  
  258.     /************************************************************************\
  259.     *
  260.     * Set DACL into SD - first the Admins-only then the Everyone SD
  261.     *
  262.     \************************************************************************/
  263.  
  264.     if (!SetSecurityDescriptorDacl(psdAbsoluteSD,
  265.                                    TRUE,      // fDaclPresent flag
  266.                                    pNewDACL,
  267.                                    FALSE))    // not a default DACL
  268.     { StopSimpleService("SetSecurityDescriptorDacl");
  269.     }
  270.  
  271.     if (!SetSecurityDescriptorDacl(psdEveryoneSD,
  272.                                    TRUE,      // fDaclPresent flag
  273.                                    (PACL)NULL,
  274.                                    FALSE))    // not a default DACL
  275.     { StopSimpleService("SetSecurityDescriptorDacl");
  276.     }
  277.  
  278.     /************************************************************************\
  279.     *
  280.     * Check to see that SD is valid before attempting to write it to the file
  281.     *
  282.     \************************************************************************/
  283.  
  284.     if (!IsValidSecurityDescriptor(psdAbsoluteSD))
  285.     { StopSimpleService("IsValidSecurityDescriptor");
  286.     }
  287.  
  288.     sa.nLength = sizeof(sa);
  289.     sa.lpSecurityDescriptor = psdAbsoluteSD;
  290.     sa.bInheritHandle = TRUE;  // why not... we spawn no processes
  291.  
  292.     // open our named pipe...
  293.     //
  294.     pipeHandle = CreateNamedPipe(
  295.                     "\\\\.\\pipe\\sd_flppy",  // name of pipe
  296.                     PIPE_ACCESS_DUPLEX,     // pipe open mode
  297.                     PIPE_TYPE_MESSAGE |
  298.                     PIPE_READMODE_MESSAGE |
  299.                     PIPE_WAIT,              // pipe IO type
  300.                     1,                      // number of instances
  301.                     0,                      // size of outbuf (0 == allocate as necessary)
  302.                     0,                      // size of inbuf
  303.                     1000,                   // default time-out value
  304.                     &sa);                   // security attributes
  305.  
  306.     if (!pipeHandle) {
  307.         StopSimpleService("CreateNamedPipe");
  308.         return;
  309.     }
  310.  
  311.     // Set the same DACL onto the floppies
  312.     //
  313.  
  314.     /************************************************************************\
  315.     *
  316.     * Write SD to file system - first for A: then B:
  317.     *
  318.     \************************************************************************/
  319.  
  320.     if (!WriteSD_ToA_File(psdAbsoluteSD,"\\\\.\\A:"))
  321.     { StopSimpleService("Write of DACL to A: failed");
  322.     }
  323.  
  324.     if (!WriteSD_ToA_File(psdAbsoluteSD,"\\\\.\\B:"))
  325.     { StopSimpleService("Write of DACL to B: failed");
  326.     }
  327.  
  328.     bFloppiesAreLocked = TRUE;
  329.  
  330.     /************************************************************************\
  331.     *
  332.     * only works for CDROM drives if you revoke the SeChangeNotify privilege
  333.     * from Everyone in user manager
  334.     *
  335.     \************************************************************************/
  336.   /*
  337.     if (!WriteSD_ToA_File(psdAbsoluteSD,"\\\\.\\E:"))
  338.     { StopSimpleService("Write of DACL to E: failed");
  339.     }
  340.   */
  341.     /************************************************************************\
  342.     *
  343.     * Works for COM ports as well - commented out as this samples is floppy only
  344.     *
  345.     \************************************************************************/
  346.   /*
  347.     if (!WriteSD_ToA_File(psdAbsoluteSD,"COM1:"))
  348.     { StopSimpleService("Write of DACL to COM1: failed");
  349.     }
  350.   */
  351.  
  352.     // start the thread that performs the work of the service.
  353.     //
  354.     threadHandle = CreateThread(
  355.                     NULL,       // security attributes
  356.                     0,          // stack size (0 means inherit parent's stack size)
  357.                     (LPTHREAD_START_ROUTINE)worker_thread,
  358.                     NULL,       // argument to thread
  359.                     0,          // thread creation flags
  360.                     &TID);      // pointer to thread ID
  361.  
  362.     if (!threadHandle)
  363.         goto cleanup;
  364.  
  365.     // report the status to the service control manager.
  366.     //
  367.     if (!ReportStatusToSCMgr(
  368.         SERVICE_RUNNING, // service state
  369.         NO_ERROR,        // exit code
  370.         0,               // checkpoint
  371.         0))              // wait hint
  372.         goto cleanup;
  373.  
  374.     // wait indefinitely until hServDoneEvent is signaled.
  375.     //
  376.     dwWait = WaitForSingleObject(
  377.         hServDoneEvent,  // event object
  378.         INFINITE);       // wait indefinitely
  379.  
  380. cleanup:
  381.  
  382.     if (hServDoneEvent != NULL)
  383.         CloseHandle(hServDoneEvent);
  384.  
  385.  
  386.     // try to report the stopped status to the service control manager.
  387.     //
  388.     if (sshStatusHandle != 0)
  389.         (VOID)ReportStatusToSCMgr(
  390.                             SERVICE_STOPPED,
  391.                             dwGlobalErr,
  392.                             0,
  393.                             0);
  394.  
  395.     // When SERVICE MAIN FUNCTION returns in a single service
  396.     // process, the StartServiceCtrlDispatcher function in
  397.     // the main thread returns, terminating the process.
  398.     //
  399.     return;
  400. }
  401.  
  402.  
  403.  
  404. //  service_ctrl() --
  405. //      this function is called by the Service Controller whenever
  406. //      someone calls ControlService in reference to our service.
  407. //
  408. VOID WINAPI
  409. service_ctrl(DWORD dwCtrlCode)
  410. {
  411.     DWORD  dwState = SERVICE_RUNNING;
  412.  
  413.     // Handle the requested control code.
  414.     //
  415.     switch(dwCtrlCode) {
  416.  
  417.         // Pause the service if it is running.
  418.         //
  419.         case SERVICE_CONTROL_PAUSE:
  420.  
  421.             if (ssStatus.dwCurrentState == SERVICE_RUNNING) {
  422.                 SuspendThread(threadHandle);
  423.                 dwState = SERVICE_PAUSED;
  424.             }
  425.             break;
  426.  
  427.         // Resume the paused service.
  428.         //
  429.         case SERVICE_CONTROL_CONTINUE:
  430.  
  431.             if (ssStatus.dwCurrentState == SERVICE_PAUSED) {
  432.                 ResumeThread(threadHandle);
  433.                 dwState = SERVICE_RUNNING;
  434.             }
  435.             break;
  436.  
  437.         // Stop the service.
  438.         //
  439.         case SERVICE_CONTROL_STOP:
  440.  
  441.             dwState = SERVICE_STOP_PENDING;
  442.  
  443.             // Report the status, specifying the checkpoint and waithint,
  444.             //  before setting the termination event.
  445.             //
  446.             ReportStatusToSCMgr(
  447.                     SERVICE_STOP_PENDING, // current state
  448.                     NO_ERROR,             // exit code
  449.                     1,                    // checkpoint
  450.                     3000);                // waithint
  451.  
  452.             if     (UNLOCK_AT_SERVICE_STOP)
  453.             { if (!WriteSD_ToA_File(psdEveryoneSD,"\\\\.\\A:"))
  454.               { StopSimpleService("Unlock of A: failed, see log file");
  455.               }
  456.               if (!WriteSD_ToA_File(psdEveryoneSD,"\\\\.\\B:"))
  457.               { StopSimpleService("Unlock of B: failed, see log file");
  458.               }
  459.  
  460.               bFloppiesAreLocked = FALSE;
  461.             }
  462.  
  463.             SetEvent(hServDoneEvent);
  464.             return;
  465.  
  466.         // Update the service status.
  467.         //
  468.         case SERVICE_CONTROL_INTERROGATE:
  469.             break;
  470.  
  471.         // invalid control code
  472.         //
  473.         default:
  474.             break;
  475.  
  476.     }
  477.  
  478.     // send a status response.
  479.     //
  480.     ReportStatusToSCMgr(dwState, NO_ERROR, 0, 0);
  481. }
  482.  
  483.  
  484.  
  485. //  worker_thread() --
  486. //      this function does the actual nuts and bolts work that
  487. //      the service requires.  It will also Pause or Stop when
  488. //      asked by the service_ctrl function.
  489. //
  490. VOID
  491. worker_thread(VOID *notUsed)
  492. {
  493.     char                 inbuf[180];
  494.     char                 outbuf[180];
  495.     BOOL                 ret;
  496.     DWORD                bytesRead;
  497.     DWORD                bytesWritten;
  498.     DWORD                dwLen;
  499.  
  500.     // okay, our pipe has been created, let's enter the simple
  501.     //  processing loop...
  502.     //
  503.     while (1) {
  504.  
  505.         // wait for a connection...
  506.         //
  507.         ConnectNamedPipe(pipeHandle, NULL);
  508.  
  509.         // grab whatever's coming through the pipe...
  510.         //
  511.         ret = ReadFile(
  512.                     pipeHandle,     // file to read from
  513.                     inbuf,          // address of input buffer
  514.                     sizeof(inbuf),  // number of bytes to read
  515.                     &bytesRead,     // number of bytes read
  516.                     NULL);          // overlapped stuff, not needed
  517.  
  518.         if (!ret)
  519.             // pipe's broken... go back and reconnect
  520.             //
  521.             continue;
  522.  
  523.         switch (inbuf[0])
  524.         { case 'U':
  525.             dwLen = sprintf(outbuf,"Floppies were unlocked");
  526.  
  527.             if (!WriteSD_ToA_File(psdEveryoneSD,"\\\\.\\A:"))
  528.             { dwLen += sprintf(outbuf+dwLen,", unlock of A: failed, see log file");
  529.             }
  530.             if (!WriteSD_ToA_File(psdEveryoneSD,"\\\\.\\B:"))
  531.             { dwLen += sprintf(outbuf+dwLen,", unlock of B: failed, see log file");
  532.             }
  533.  
  534.             bFloppiesAreLocked = FALSE;
  535.             break;
  536.  
  537.           case 'L':
  538.             dwLen = sprintf(outbuf,"Floppies were locked");
  539.  
  540.             if (!WriteSD_ToA_File(psdAbsoluteSD,"\\\\.\\A:"))
  541.             { dwLen += sprintf(outbuf+dwLen,", lock of A: failed, see log file");
  542.             }
  543.             if (!WriteSD_ToA_File(psdAbsoluteSD,"\\\\.\\B:"))
  544.             { dwLen += sprintf(outbuf+dwLen,", lock of B: failed, see log file");
  545.             }
  546.  
  547.             bFloppiesAreLocked = TRUE;
  548.             break;
  549.  
  550.           case 'Q':
  551.             if (bFloppiesAreLocked)
  552.             { sprintf(outbuf,"Floppy status is: Locked");
  553.             }
  554.             else
  555.             { sprintf(outbuf,"Floppy status is: Unlocked");
  556.             }
  557.             break;
  558.  
  559.           default :
  560.             sprintf(outbuf,"Bad operation passed in");
  561.         }
  562.  
  563.         // send it back out...
  564.         //
  565.         ret = WriteFile(
  566.                     pipeHandle,     // file to write to
  567.                     outbuf,         // address of output buffer
  568.                     sizeof(outbuf), // number of bytes to write
  569.                     &bytesWritten,  // number of bytes written
  570.                     NULL);          // overlapped stuff, not needed
  571.  
  572.         if (!ret)
  573.             // pipe's broken... go back and reconnect
  574.             //
  575.             continue;
  576.  
  577.         // drop the connection...
  578.         //
  579.         DisconnectNamedPipe(pipeHandle);
  580.     }
  581. }
  582.  
  583.  
  584.  
  585. // utility functions...
  586.  
  587.  
  588.  
  589. // ReportStatusToSCMgr() --
  590. //      This function is called by the ServMainFunc() and
  591. //      ServCtrlHandler() functions to update the service's status
  592. //      to the service control manager.
  593. //
  594. BOOL
  595. ReportStatusToSCMgr(DWORD dwCurrentState,
  596.                     DWORD dwWin32ExitCode,
  597.                     DWORD dwCheckPoint,
  598.                     DWORD dwWaitHint)
  599. {
  600.     BOOL fResult;
  601.  
  602.     // Disable control requests until the service is started.
  603.     //
  604.     if (dwCurrentState == SERVICE_START_PENDING)
  605.         ssStatus.dwControlsAccepted = 0;
  606.     else
  607.         ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  608.             SERVICE_ACCEPT_PAUSE_CONTINUE;
  609.  
  610.     // These SERVICE_STATUS members are set from parameters.
  611.     //
  612.     ssStatus.dwCurrentState = dwCurrentState;
  613.     ssStatus.dwWin32ExitCode = dwWin32ExitCode;
  614.     ssStatus.dwCheckPoint = dwCheckPoint;
  615.  
  616.     ssStatus.dwWaitHint = dwWaitHint;
  617.  
  618.     // Report the status of the service to the service control manager.
  619.     //
  620.     if (!(fResult = SetServiceStatus(
  621.                 sshStatusHandle,    // service reference handle
  622.                 &ssStatus))) {      // SERVICE_STATUS structure
  623.  
  624.         // If an error occurs, stop the service.
  625.         //
  626.         StopSimpleService("SetServiceStatus");
  627.     }
  628.     return fResult;
  629. }
  630.  
  631.  
  632.  
  633. // The StopSimpleService function can be used by any thread to report an
  634. //  error, or stop the service.
  635. //
  636. VOID
  637. StopSimpleService(LPTSTR lpszMsg)
  638. {
  639.     CHAR    chMsg[256];
  640.     HANDLE  hEventSource;
  641.     LPTSTR  lpszStrings[2];
  642.  
  643.     dwGlobalErr = GetLastError();
  644.  
  645.     // Use event logging to log the error.
  646.     //
  647.     hEventSource = RegisterEventSource(NULL,
  648.                             TEXT("SimpleService"));
  649.  
  650.     sprintf(chMsg, "SimpleService error: %d", dwGlobalErr);
  651.     lpszStrings[0] = chMsg;
  652.     lpszStrings[1] = lpszMsg;
  653.  
  654.     if (hEventSource != NULL) {
  655.         ReportEvent(hEventSource, // handle of event source
  656.             EVENTLOG_ERROR_TYPE,  // event type
  657.             0,                    // event category
  658.             0,                    // event ID
  659.             NULL,                 // current user's SID
  660.             2,                    // strings in lpszStrings
  661.             0,                    // no bytes of raw data
  662.             lpszStrings,          // array of error strings
  663.             NULL);                // no raw data
  664.  
  665.         (VOID) DeregisterEventSource(hEventSource);
  666.     }
  667.  
  668.     // Set a termination event to stop SERVICE MAIN FUNCTION.
  669.     //
  670.     SetEvent(hServDoneEvent);
  671. }
  672.  
  673. /****************************************************************************\
  674. *
  675. * FUNCTION: WriteSD_ToA_File
  676. *
  677. \****************************************************************************/
  678.  
  679. BOOL WriteSD_ToA_File(PSECURITY_DESCRIPTOR psdAbsoluteSD, LPTSTR lpszFileName)
  680. {
  681.   DWORD dwErrorMode;
  682.   BOOL  bStatus;
  683.  
  684.   /**************************************************************************\
  685.   *
  686.   * SetErrorMode so we don't get the error due to no floppy disk in the floppy
  687.   *   drive
  688.   *
  689.   \**************************************************************************/
  690.  
  691.   dwErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  692.  
  693.   /**************************************************************************\
  694.   *
  695.   * Write SD to file system
  696.   *
  697.   \**************************************************************************/
  698.  
  699.   bStatus = SetFileSecurity(lpszFileName,
  700.                             (SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION),
  701.                             psdAbsoluteSD);
  702.  
  703.   /**************************************************************************\
  704.   *
  705.   * SetErrorMode back to its previous value
  706.   *
  707.   \**************************************************************************/
  708.  
  709.   SetErrorMode(dwErrorMode);
  710.  
  711.   if (!bStatus)
  712.   { if (ERROR_FILE_NOT_FOUND == GetLastError())
  713.     { printf("\nAttempted to lock %s, but it was not found",lpszFileName);
  714.     }
  715.     else
  716.     { PERR("SetFileSecurity");
  717.       return(FALSE);
  718.     }
  719.   }
  720.  
  721.   return(TRUE);
  722. }
  723.