À©µµ¿ì ÇÁ·Î±×·¡¹Ö ÀÚ·á |
---|
Á¦¸ñ | 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 ///////////////////////////////// |