À©µµ¿ì ÇÁ·Î±×·¡¹Ö ÀÚ·á

HomePage Backward Forward Post Reply List
Delete Modify
  Á¦¸ñ   Time Server 1998/07/20 (21:22)
À̸§ ±èÈ¿¿ø
¹øÈ£ 33
Á¶È¸ 414
º»¹®
     /*****************************************************************************
     Module :     MSJTimeSrv.c
     Description: Minimal Service Template
     *****************************************************************************/


     #define STRICT
     #define UNICODE
     #include <Windows.h>


     //////////////////////////////////////////////////////////////////////////////


     #define dimof(A)  (sizeof(A) / sizeof(A[0]))


     //////////////////////////////////////////////////////////////////////////////


     WCHAR g_szAppName[] = L"MSJ Time Service";


     //////////////////////////////////////////////////////////////////////////////


     HANDLE g_hIOCP = NULL;


     // The completion port wakes for 1 of 2 reasons:
     enum COMPKEY {
       CK_SERVICECONTROL,   // A service control code
       CK_PIPE              // A client connects to our pipe
     };


     //////////////////////////////////////////////////////////////////////////////


     void WINAPI TimeServiceHandler(DWORD fdwControl) {
       // The Handler thread is very simple and executes very quickly because
       // it just passes the control code off to the ServiceMain thread.
       PostQueuedCompletionStatus(g_hIOCP, fdwControl, CK_SERVICECONTROL,
     NULL);
     }


     //////////////////////////////////////////////////////////////////////////////


     #define SERVICE_CONTROL_RUN            0x00000000


     DWORD dwSrvCtrlToPend[256] = {   // 255 is max user-defined code
       /* 0: SERVICE_CONTROL_RUN         */ SERVICE_START_PENDING,
       /* 1: SERVICE_CONTROL_STOP        */ SERVICE_STOP_PENDING,
       /* 2: SERVICE_CONTROL_PAUSE       */ SERVICE_PAUSE_PENDING,
       /* 3: SERVICE_CONTROL_CONTINUE    */ SERVICE_CONTINUE_PENDING,
       /* 4: SERVICE_CONTROL_INTERROGATE */ 0,
       /* 5: SERVICE_CONTROL_SHUTDOWN    */ SERVICE_STOP_PENDING,
       /* 6 - 255: User-defined codes    */ 0
     };


     DWORD dwSrvPendToState[] = {
       /* 0: Undefined                */ 0,
       /* 1: SERVICE_STOPPED          */ 0,
       /* 2: SERVICE_START_PENDING    */ SERVICE_RUNNING,
       /* 3: SERVICE_STOP_PENDING     */ SERVICE_STOPPED,
       /* 4: SERVICE_RUNNING          */ 0,
       /* 5: SERVICE_CONTINUE_PENDING */ SERVICE_RUNNING,
       /* 6: SERVICE_PAUSE_PENDING    */ SERVICE_PAUSED,
       /* 7: SERVICE_PAUSED           */ 0
     };


     //////////////////////////////////////////////////////////////////////////////


     void WINAPI TimeServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
       DWORD dwCompKey  = CK_SERVICECONTROL;
       DWORD fdwControl = SERVICE_CONTROL_RUN;
       DWORD dwBytesTransferred;
       SYSTEMTIME st;
       HANDLE hpipe;
       OVERLAPPED o, *po;
       SERVICE_STATUS ss;
       SERVICE_STATUS_HANDLE hSS;

       // Create the completion port and save its handle in a global
       // variable so that the Handler function can access it.
       g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,
     CK_PIPE, 0);

       // Give SCM the address of this service's Handler
       // NOTE: hSS does not have to be closed.
       hSS = RegisterServiceCtrlHandler(g_szAppName, TimeServiceHandler);

       // Do what the service should do.
       // Initialize the members that never change
       ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
       ss.dwControlsAccepted = SERVICE_ACCEPT_STOP |
          SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
       
       do {
          switch (dwCompKey) {
          case CK_SERVICECONTROL:
             // We got a new control code
             ss.dwWin32ExitCode = NO_ERROR;
             ss.dwServiceSpecificExitCode = 0;
             ss.dwCheckPoint = 0;
             ss.dwWaitHint = 0;

             if (fdwControl == SERVICE_CONTROL_INTERROGATE) {
                SetServiceStatus(hSS, &ss);
                break;
             }

             // Determine which PENDING state to return
             if (dwSrvCtrlToPend[fdwControl] != 0) {
                ss.dwCurrentState = dwSrvCtrlToPend[fdwControl];
                ss.dwCheckPoint = 0;
                ss.dwWaitHint = 500;   // half a second
                SetServiceStatus(hSS, &ss);
             }

             switch (fdwControl) {
                case SERVICE_CONTROL_RUN:
                case SERVICE_CONTROL_CONTINUE:
                   // While running, create a pipe that clients can connect to.
                   hpipe = CreateNamedPipe(L"\\\\.\\pipe\\MSJTime",
                      PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
                      PIPE_TYPE_BYTE, 1, sizeof(st), sizeof(st), 1000, NULL);

                   // Associate the pipe with the completion port
                   CreateIoCompletionPort(hpipe, g_hIOCP, CK_PIPE, 0);

                   // Pend an asynchronous connect against the pipe
                   ZeroMemory(&o, sizeof(o));
                   ConnectNamedPipe(hpipe, &o);
                   break;

                case SERVICE_CONTROL_PAUSE:
                case SERVICE_CONTROL_STOP:
                case SERVICE_CONTROL_SHUTDOWN:
                   // When not running, close the pipe so clients can't connect
                   CloseHandle(hpipe);
                   break;

                case 128:   // User-defined control (demonstration purposes)
                   MessageBox(NULL, L"Got control code 128", g_szAppName, MB_OK);
                   break;
             }

             // Determine which complete state to return
             if (dwSrvPendToState[ss.dwCurrentState] != 0) {
                ss.dwCurrentState = dwSrvPendToState[ss.dwCurrentState];
                ss.dwCheckPoint = ss.dwWaitHint = 0;
                SetServiceStatus(hSS, &ss);
             }
             break;

          case CK_PIPE:
             // We got a client request: Send our current time to the client
             GetSystemTime(&st);
             WriteFile(hpipe, &st, sizeof(st), &dwBytesTransferred, NULL);
             FlushFileBuffers(hpipe);
             DisconnectNamedPipe(hpipe);

             // Allow another client to connect
             ZeroMemory(&o, sizeof(o));
             ConnectNamedPipe(hpipe, &o);
          }

          if (ss.dwCurrentState != SERVICE_STOPPED) {
             // Sleep until a control code comes in or a client connects
             GetQueuedCompletionStatus(g_hIOCP, &dwBytesTransferred,
                &dwCompKey, &po, INFINITE);
             fdwControl = dwBytesTransferred;
          }
       } while (ss.dwCurrentState != SERVICE_STOPPED);

       // Cleanup and stop this service
       CloseHandle(g_hIOCP);   
     }


     //////////////////////////////////////////////////////////////////////////////


     void InstallService() {
       TCHAR szModulePathname[_MAX_PATH];
       SC_HANDLE hService;

       // Open the SCM on this machine.
       SC_HANDLE hSCM = OpenSCManager(NULL, NULL,
     SC_MANAGER_CREATE_SERVICE);

       // Get our full pathname
       GetModuleFileName(NULL, szModulePathname, dimof(szModulePathname));

       // Add this service to the SCM's database.
       hService = CreateService(hSCM, g_szAppName, g_szAppName, 0,
          SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
     SERVICE_ERROR_IGNORE,
          szModulePathname, NULL, NULL, NULL, NULL, NULL);

       // Close the service and the SCM
       CloseServiceHandle(hService);
       CloseServiceHandle(hSCM);
     }


     //////////////////////////////////////////////////////////////////////////////


     void RemoveService() {
       // Open the SCM on this machine.
       SC_HANDLE hSCM = OpenSCManager(NULL, NULL,
     SC_MANAGER_CONNECT);

       // Open this service for DELETE access
       SC_HANDLE hService = OpenService(hSCM, g_szAppName, DELETE);

       // Remove this service from the SCM's database.
       DeleteService(hService);

       // Close the service and the SCM
       CloseServiceHandle(hService);
       CloseServiceHandle(hSCM);
     }


     //////////////////////////////////////////////////////////////////////////////


     int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstExePrev,
       LPSTR pszCmdLine, int nCmdShow) {

       int nArgc = __argc;
     #ifdef UNICODE
       LPCTSTR *ppArgv = (LPCTSTR*) CommandLineToArgvW(GetCommandLine(),
     &nArgc);
     #else
       LPCTSTR *ppArgv = (LPCTSTR*) __argv;
     #endif

       BOOL fStartService = (nArgc < 2), fDebug = FALSE;
       int i;

       for (i = 1; i < nArgc; i++) {
          if ((ppArgv[i][0] == __TEXT('-')) || (ppArgv[i][0] == __TEXT('/'))) {
             // Command line switch
             if (lstrcmpi(&ppArgv[i][1], __TEXT("install")) == 0)
                InstallService();

             if (lstrcmpi(&ppArgv[i][1], __TEXT("remove"))  == 0)
                RemoveService();

             if (lstrcmpi(&ppArgv[i][1], __TEXT("debug"))   == 0)
                fDebug = TRUE;
          }
       }

     #ifdef UNICODE
       HeapFree(GetProcessHeap(), 0, (PVOID) ppArgv);
     #endif

       if (fDebug) {
          // Running as EXE not as service, just run the service for debugging
          TimeServiceMain(0, NULL);
       }

       if (fStartService) {
          SERVICE_TABLE_ENTRY ServiceTable[] = {
             { g_szAppName, TimeServiceMain },
             { NULL,        NULL }   // End of list
          };
          StartServiceCtrlDispatcher(ServiceTable);
       }

       return(0);
     }


     //////////////////////////////// End Of File /////////////////////////////////
     

HomePage Backward Forward Post Reply List
1998 by swindler