[ARMLLB]: Make DbgPrint compatible so we can use debug.h.
[reactos.git] / rosapps / templates / skel_service / ServiceMain.c
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%lu, 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 VOID 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 break;
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 break;
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 break;
134
135 case SERVICE_CONTROL_INTERROGATE:
136 break;
137
138 default:
139 if (dwControl > 127 && dwControl < 256) /* user defined */
140 LogEvent(_T("User defined control code"), 0, 0, LOG_FILE);
141 else
142 LogEvent(_T("ERROR: Bad control code"), 0, 0, LOG_FILE);
143 break;
144 }
145 }
146
147
148 VOID WINAPI
149 ServiceMain(DWORD argc, LPTSTR argv[])
150 {
151 SERVICEINFO servInfo;
152
153 LogEvent(_T("Entering ServiceMain"), 0, 0, LOG_FILE);
154
155 servInfo.servStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
156 servInfo.servStatus.dwCurrentState = SERVICE_STOPPED;
157 servInfo.servStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
158 servInfo.servStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
159 servInfo.servStatus.dwServiceSpecificExitCode = 0;
160 servInfo.servStatus.dwCheckPoint = 0;
161 servInfo.servStatus.dwWaitHint = 1000;
162
163 LogEvent(_T("Registering service control handler"), 0, 0, LOG_FILE);
164 servInfo.hStatus = RegisterServiceCtrlHandlerEx(ServiceName, ServerCtrlHandler, &servInfo);
165 if (!servInfo.hStatus)
166 LogEvent(_T("Failed to register service"), GetLastError(), 100, LOG_ALL);
167
168 UpdateStatus(&servInfo, SERVICE_START_PENDING, 1);
169
170 if (!CreateServiceThread(&servInfo))
171 {
172 servInfo.servStatus.dwServiceSpecificExitCode = 1;
173 UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
174 return;
175 }
176
177 LogEvent(_T("Service thread shut down. Set SERVICE_STOPPED status"), 0, 0, LOG_FILE);
178 UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
179
180 LogEvent(_T("Leaving ServiceMain"), 0, 0, LOG_FILE);
181 }
182
183
184 int _tmain(int argc, LPTSTR argv[])
185 {
186 SERVICE_TABLE_ENTRY ServiceTable[] =
187 {
188 {ServiceName, ServiceMain},
189 {NULL, NULL }
190 };
191
192 InitLogging();
193
194 if (!StartServiceCtrlDispatcher(ServiceTable))
195 LogEvent(_T("failed to start the service control dispatcher"), GetLastError(), 101, LOG_ALL);
196
197 return 0;
198 }