home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / winnt / service / simple.c < prev   
C/C++ Source or Header  |  1997-10-05  |  10KB  |  326 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1997  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   simple.c
  9. //
  10. //  PURPOSE:  Implements the body of the service.
  11. //            The default behavior is to open a
  12. //            named pipe, \\.\pipe\simple, and read
  13. //            from it.  It the modifies the data and
  14. //            writes it back to the pipe.
  15. //
  16. //  FUNCTIONS:
  17. //            ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
  18. //            ServiceStop( );
  19. //
  20. //  COMMENTS: The functions implemented in simple.c are
  21. //            prototyped in service.h
  22. //              
  23. //
  24. //  AUTHOR: Craig Link - Microsoft Developer Support
  25. //
  26.  
  27.  
  28. #include <windows.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <process.h>
  32. #include <tchar.h>
  33. #include "service.h"
  34.  
  35. // this event is signalled when the
  36. // service should end
  37. //
  38. HANDLE  hServerStopEvent = NULL;
  39.  
  40.  
  41. //
  42. //  FUNCTION: ServiceStart
  43. //
  44. //  PURPOSE: Actual code of the service
  45. //           that does the work.
  46. //
  47. //  PARAMETERS:
  48. //    dwArgc   - number of command line arguments
  49. //    lpszArgv - array of command line arguments
  50. //
  51. //  RETURN VALUE:
  52. //    none
  53. //
  54. //  COMMENTS:
  55. //    The default behavior is to open a
  56. //    named pipe, \\.\pipe\simple, and read
  57. //    from it.  It the modifies the data and
  58. //    writes it back to the pipe.  The service
  59. //    stops when hServerStopEvent is signalled
  60. //
  61. VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
  62. {
  63.     HANDLE                  hPipe = INVALID_HANDLE_VALUE;
  64.     HANDLE                  hEvents[2] = {NULL, NULL};
  65.     OVERLAPPED              os;
  66.     PSECURITY_DESCRIPTOR    pSD = NULL;
  67.     SECURITY_ATTRIBUTES     sa;
  68.     TCHAR                   szIn[80];
  69.     TCHAR                   szOut[80];
  70.     LPTSTR                  lpszPipeName = TEXT("\\\\.\\pipe\\simple");
  71.     BOOL                    bRet;
  72.     DWORD                   cbRead;
  73.     DWORD                   cbWritten;
  74.     DWORD                   dwWait;
  75.     UINT                    ndx;
  76.  
  77.     ///////////////////////////////////////////////////
  78.     //
  79.     // Service initialization
  80.     //
  81.  
  82.     // report the status to the service control manager.
  83.     //
  84.     if (!ReportStatusToSCMgr(
  85.         SERVICE_START_PENDING, // service state
  86.         NO_ERROR,              // exit code
  87.         3000))                 // wait hint
  88.         goto cleanup;
  89.  
  90.     // create the event object. The control handler function signals
  91.     // this event when it receives the "stop" control code.
  92.     //
  93.     hServerStopEvent = CreateEvent(
  94.         NULL,    // no security attributes
  95.         TRUE,    // manual reset event
  96.         FALSE,   // not-signalled
  97.         NULL);   // no name
  98.  
  99.     if ( hServerStopEvent == NULL)
  100.         goto cleanup;
  101.  
  102.     hEvents[0] = hServerStopEvent;
  103.  
  104.     // report the status to the service control manager.
  105.     //
  106.     if (!ReportStatusToSCMgr(
  107.         SERVICE_START_PENDING, // service state
  108.         NO_ERROR,              // exit code
  109.         3000))                 // wait hint
  110.         goto cleanup;
  111.  
  112.     // create the event object object use in overlapped i/o
  113.     //
  114.     hEvents[1] = CreateEvent(
  115.         NULL,    // no security attributes
  116.         TRUE,    // manual reset event
  117.         FALSE,   // not-signalled
  118.         NULL);   // no name
  119.  
  120.     if ( hEvents[1] == NULL)
  121.         goto cleanup;
  122.  
  123.     // report the status to the service control manager.
  124.     //
  125.     if (!ReportStatusToSCMgr(
  126.         SERVICE_START_PENDING, // service state
  127.         NO_ERROR,              // exit code
  128.         3000))                 // wait hint
  129.         goto cleanup;
  130.  
  131.     // create a security descriptor that allows anyone to write to
  132.     //  the pipe...
  133.     //
  134.     pSD = (PSECURITY_DESCRIPTOR) malloc( SECURITY_DESCRIPTOR_MIN_LENGTH );
  135.  
  136.     if (pSD == NULL)
  137.         goto cleanup;
  138.  
  139.     if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
  140.         goto cleanup;
  141.  
  142.     // add a NULL disc. ACL to the security descriptor.
  143.     //
  144.     if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE))
  145.         goto cleanup;
  146.  
  147.     sa.nLength = sizeof(sa);
  148.     sa.lpSecurityDescriptor = pSD;
  149.     sa.bInheritHandle = TRUE;
  150.  
  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.         3000))                 // wait hint
  158.         goto cleanup;
  159.  
  160.  
  161.     // allow user tp define pipe name
  162.     for ( ndx = 1; ndx < dwArgc-1; ndx++ )
  163.     {
  164.  
  165.         if ( ( (*(lpszArgv[ndx]) == TEXT('-')) ||
  166.                (*(lpszArgv[ndx]) == TEXT('/')) ) &&
  167.              _tcsicmp( TEXT("pipe"), lpszArgv[ndx]+1 ) == 0 )
  168.         {
  169.             lpszPipeName = lpszArgv[++ndx];
  170.         }
  171.  
  172.     }
  173.  
  174.     // open our named pipe...
  175.     //
  176.     hPipe = CreateNamedPipe(
  177.                     lpszPipeName         ,  // name of pipe
  178.                     FILE_FLAG_OVERLAPPED |
  179.                     PIPE_ACCESS_DUPLEX,     // pipe open mode
  180.                     PIPE_TYPE_MESSAGE |
  181.                     PIPE_READMODE_MESSAGE |
  182.                     PIPE_WAIT,              // pipe IO type
  183.                     1,                      // number of instances
  184.                     0,                      // size of outbuf (0 == allocate as necessary)
  185.                     0,                      // size of inbuf
  186.                     1000,                   // default time-out value
  187.                     &sa);                   // security attributes
  188.  
  189.     if (hPipe == INVALID_HANDLE_VALUE) {
  190.         AddToMessageLog(TEXT("Unable to create named pipe"));
  191.         goto cleanup;
  192.     }
  193.  
  194.  
  195.     // report the status to the service control manager.
  196.     //
  197.     if (!ReportStatusToSCMgr(
  198.         SERVICE_RUNNING,       // service state
  199.         NO_ERROR,              // exit code
  200.         0))                    // wait hint
  201.         goto cleanup;
  202.  
  203.     //
  204.     // End of initialization
  205.     //
  206.     ////////////////////////////////////////////////////////
  207.  
  208.     ////////////////////////////////////////////////////////
  209.     //
  210.     // Service is now running, perform work until shutdown
  211.     //
  212.  
  213.     while ( 1 )
  214.     {
  215.         // init the overlapped structure
  216.         //
  217.         memset( &os, 0, sizeof(OVERLAPPED) );
  218.         os.hEvent = hEvents[1];
  219.         ResetEvent( hEvents[1] );
  220.  
  221.         // wait for a connection...
  222.         //
  223.         ConnectNamedPipe(hPipe, &os);
  224.  
  225.         if ( GetLastError() == ERROR_IO_PENDING )
  226.         {
  227.             dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE );
  228.             if ( dwWait != WAIT_OBJECT_0+1 )     // not overlapped i/o event - error occurred,
  229.                 break;                           // or server stop signaled
  230.         }
  231.  
  232.         // init the overlapped structure
  233.         //
  234.         memset( &os, 0, sizeof(OVERLAPPED) );
  235.         os.hEvent = hEvents[1];
  236.         ResetEvent( hEvents[1] );
  237.  
  238.         // grab whatever's coming through the pipe...
  239.         //
  240.         bRet = ReadFile(
  241.                     hPipe,          // file to read from
  242.                     szIn,           // address of input buffer
  243.                     sizeof(szIn),   // number of bytes to read
  244.                     &cbRead,        // number of bytes read
  245.                     &os);           // overlapped stuff, not needed
  246.  
  247.         if ( !bRet && ( GetLastError() == ERROR_IO_PENDING ) )
  248.         {
  249.             dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE );
  250.             if ( dwWait != WAIT_OBJECT_0+1 )     // not overlapped i/o event - error occurred,
  251.                 break;                           // or server stop signaled
  252.         }
  253.  
  254.         // munge the string
  255.         //
  256.         _stprintf(szOut, TEXT("Hello! [%s]"), szIn);
  257.  
  258.         // init the overlapped structure
  259.         //
  260.         memset( &os, 0, sizeof(OVERLAPPED) );
  261.         os.hEvent = hEvents[1];
  262.         ResetEvent( hEvents[1] );
  263.  
  264.         // send it back out...
  265.         //
  266.         bRet = WriteFile(
  267.                     hPipe,          // file to write to
  268.                     szOut,          // address of output buffer
  269.                     sizeof(szOut),  // number of bytes to write
  270.                     &cbWritten,     // number of bytes written
  271.                     &os);           // overlapped stuff, not needed
  272.  
  273.         if ( !bRet && ( GetLastError() == ERROR_IO_PENDING ) )
  274.         {
  275.             dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE );
  276.             if ( dwWait != WAIT_OBJECT_0+1 )     // not overlapped i/o event - error occurred,
  277.                 break;                           // or server stop signaled
  278.         }
  279.  
  280.         // drop the connection...
  281.         //
  282.         DisconnectNamedPipe(hPipe);
  283.     }
  284.  
  285.   cleanup:
  286.  
  287.     if (hPipe != INVALID_HANDLE_VALUE )
  288.         CloseHandle(hPipe);
  289.  
  290.     if (hServerStopEvent)
  291.         CloseHandle(hServerStopEvent);
  292.  
  293.     if (hEvents[1]) // overlapped i/o event
  294.         CloseHandle(hEvents[1]);
  295.  
  296.     if ( pSD )
  297.         free( pSD );
  298.  
  299. }
  300.  
  301.  
  302. //
  303. //  FUNCTION: ServiceStop
  304. //
  305. //  PURPOSE: Stops the service
  306. //
  307. //  PARAMETERS:
  308. //    none
  309. //
  310. //  RETURN VALUE:
  311. //    none
  312. //
  313. //  COMMENTS:
  314. //    If a ServiceStop procedure is going to
  315. //    take longer than 3 seconds to execute,
  316. //    it should spawn a thread to execute the
  317. //    stop code, and return.  Otherwise, the
  318. //    ServiceControlManager will believe that
  319. //    the service has stopped responding.
  320. //    
  321. VOID ServiceStop()
  322. {
  323.     if ( hServerStopEvent )
  324.         SetEvent(hServerStopEvent);
  325. }
  326.