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