1 /* 2 * PROJECT: ReactOS services 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: 5 * PURPOSE: skeleton service 6 * COPYRIGHT: Copyright 2008 Ged Murphy <gedmurphy@reactos.org> 7 * 8 */ 9 10 #include "myservice.h" 11 12 volatile BOOL bShutDown = FALSE; 13 volatile BOOL bPause = FALSE; 14 15 LPTSTR ServiceName = _T("skel_service"); 16 17 typedef struct _ServiceInfo 18 { 19 SERVICE_STATUS servStatus; 20 SERVICE_STATUS_HANDLE hStatus; 21 } SERVICEINFO, *PSERVICEINFO; 22 23 /********* To be moved to new file **********/ 24 typedef struct _ServiceData 25 { 26 INT val1; 27 INT val2; 28 } SERVICEDATA, *PSERVICEDATA; 29 30 DWORD WINAPI ThreadProc(LPVOID lpParam) 31 { 32 while (!bShutDown) 33 Sleep(1000); 34 35 return 0; 36 } 37 /*******************************************/ 38 39 40 static VOID 41 UpdateStatus(PSERVICEINFO pServInfo, 42 DWORD NewStatus, 43 DWORD Check) 44 { 45 TCHAR szSet[50]; 46 47 if (Check > 0) 48 pServInfo->servStatus.dwCheckPoint += Check; 49 else 50 pServInfo->servStatus.dwCheckPoint = Check; 51 52 if (NewStatus > 0) 53 pServInfo->servStatus.dwCurrentState = NewStatus; 54 55 _sntprintf(szSet, 56 49, 57 _T("Service state 0x%lx, CheckPoint %lu"), 58 pServInfo->servStatus.dwCurrentState, 59 pServInfo->servStatus.dwCheckPoint); 60 LogEvent(szSet, 0, 0, LOG_FILE); 61 62 if (!SetServiceStatus(pServInfo->hStatus, &pServInfo->servStatus)) 63 LogEvent(_T("Cannot set service status"), GetLastError(), 0, LOG_ALL); 64 } 65 66 static BOOL 67 CreateServiceThread(PSERVICEINFO pServInfo) 68 { 69 HANDLE hThread; 70 PSERVICEDATA servData; 71 72 UpdateStatus(pServInfo, 0, 1); 73 74 LogEvent(_T("Creating service thread"), 0, 0, LOG_FILE); 75 76 hThread = CreateThread(NULL, 77 0, 78 ThreadProc, 79 &servData, 80 0, 81 NULL); 82 83 if (!hThread) 84 { 85 LogEvent(_T("Failed to start service thread"), GetLastError(), 101, LOG_ALL); 86 return FALSE; 87 } 88 89 UpdateStatus(pServInfo, 0, 1); 90 91 LogEvent(_T("setting service status to running"), 0, 0, LOG_FILE); 92 UpdateStatus(pServInfo, SERVICE_RUNNING, 0); 93 94 WaitForSingleObject(hThread, INFINITE); 95 96 if (hThread) 97 CloseHandle(hThread); 98 99 return TRUE; 100 } 101 102 103 DWORD WINAPI 104 ServerCtrlHandler(DWORD dwControl, 105 DWORD dwEventType, 106 LPVOID lpEventData, 107 LPVOID lpContext) 108 109 { 110 PSERVICEINFO pServInfo = (PSERVICEINFO)lpContext; 111 112 switch (dwControl) 113 { 114 case SERVICE_CONTROL_SHUTDOWN: 115 case SERVICE_CONTROL_STOP: 116 LogEvent(_T("\nSetting the service to SERVICE_STOP_PENDING"), 0, 0, LOG_FILE); 117 InterlockedExchange((LONG *)&bShutDown, TRUE); 118 pServInfo->servStatus.dwWin32ExitCode = 0; 119 pServInfo->servStatus.dwWaitHint = 0; 120 UpdateStatus(pServInfo, SERVICE_STOP_PENDING, 1); 121 return ERROR_SUCCESS; 122 123 case SERVICE_CONTROL_PAUSE: 124 LogEvent(_T("Setting the service to SERVICE_PAUSED"), 0, 0, LOG_FILE); 125 InterlockedExchange((LONG *)&bPause, TRUE); 126 UpdateStatus(pServInfo, SERVICE_PAUSED, 0); 127 return ERROR_SUCCESS; 128 129 case SERVICE_CONTROL_CONTINUE: 130 LogEvent(_T("Setting the service to SERVICE_RUNNING"), 0, 0, LOG_FILE); 131 InterlockedExchange((LONG *)&bPause, FALSE); 132 UpdateStatus(pServInfo, SERVICE_RUNNING, 0); 133 return ERROR_SUCCESS; 134 135 case SERVICE_CONTROL_INTERROGATE: 136 return ERROR_SUCCESS; 137 138 default: 139 if (dwControl >= 128 && dwControl <= 255) /* User defined */ 140 { 141 LogEvent(_T("User defined control code"), 0, 0, LOG_FILE); 142 return ERROR_SUCCESS; 143 } 144 else 145 { 146 LogEvent(_T("ERROR: Bad control code"), 0, 0, LOG_FILE); 147 return ERROR_INVALID_SERVICE_CONTROL; 148 } 149 } 150 } 151 152 153 VOID WINAPI 154 ServiceMain(DWORD argc, LPTSTR argv[]) 155 { 156 SERVICEINFO servInfo; 157 158 LogEvent(_T("Entering ServiceMain"), 0, 0, LOG_FILE); 159 160 servInfo.servStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 161 servInfo.servStatus.dwCurrentState = SERVICE_STOPPED; 162 servInfo.servStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE; 163 servInfo.servStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; 164 servInfo.servStatus.dwServiceSpecificExitCode = 0; 165 servInfo.servStatus.dwCheckPoint = 0; 166 servInfo.servStatus.dwWaitHint = 1000; 167 168 LogEvent(_T("Registering service control handler"), 0, 0, LOG_FILE); 169 servInfo.hStatus = RegisterServiceCtrlHandlerEx(ServiceName, ServerCtrlHandler, &servInfo); 170 if (!servInfo.hStatus) 171 LogEvent(_T("Failed to register service"), GetLastError(), 100, LOG_ALL); 172 173 UpdateStatus(&servInfo, SERVICE_START_PENDING, 1); 174 175 if (!CreateServiceThread(&servInfo)) 176 { 177 servInfo.servStatus.dwServiceSpecificExitCode = 1; 178 UpdateStatus(&servInfo, SERVICE_STOPPED, 0); 179 return; 180 } 181 182 LogEvent(_T("Service thread shut down. Set SERVICE_STOPPED status"), 0, 0, LOG_FILE); 183 UpdateStatus(&servInfo, SERVICE_STOPPED, 0); 184 185 LogEvent(_T("Leaving ServiceMain"), 0, 0, LOG_FILE); 186 } 187 188 189 int _tmain(int argc, LPTSTR argv[]) 190 { 191 SERVICE_TABLE_ENTRY ServiceTable[] = 192 { 193 {ServiceName, ServiceMain}, 194 {NULL, NULL } 195 }; 196 197 InitLogging(); 198 199 if (!StartServiceCtrlDispatcher(ServiceTable)) 200 LogEvent(_T("failed to start the service control dispatcher"), GetLastError(), 101, LOG_ALL); 201 202 return 0; 203 } 204