[SHELL32] -Expand the name of the cpl file because CreateActCtx needs a full path.
[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%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 }