Synchronize up to trunk's revision r57689.
[reactos.git] / base / system / services / driver.c
1 /*
2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/driver.c
5 * PURPOSE: Driver control interface
6 * COPYRIGHT: Copyright 2005-2006 Eric Kohl
7 *
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "services.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS ****************************************************************/
18
19 DWORD
20 ScmLoadDriver(PSERVICE lpService)
21 {
22 PWSTR pszDriverPath;
23 UNICODE_STRING DriverPath;
24 NTSTATUS Status;
25 DWORD dwError = ERROR_SUCCESS;
26
27 /* Build the driver path */
28 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
29 pszDriverPath = HeapAlloc(GetProcessHeap(),
30 HEAP_ZERO_MEMORY,
31 (52 + wcslen(lpService->lpServiceName) + 1) * sizeof(WCHAR));
32 if (pszDriverPath == NULL)
33 return ERROR_NOT_ENOUGH_MEMORY;
34
35 wcscpy(pszDriverPath,
36 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
37 wcscat(pszDriverPath,
38 lpService->lpServiceName);
39
40 RtlInitUnicodeString(&DriverPath,
41 pszDriverPath);
42
43 /* FIXME: Acquire privilege */
44
45 DPRINT(" Path: %wZ\n", &DriverPath);
46 Status = NtLoadDriver(&DriverPath);
47
48 /* FIXME: Release privilege */
49
50 if (!NT_SUCCESS(Status))
51 {
52 dwError = RtlNtStatusToDosError(Status);
53 }
54
55 HeapFree(GetProcessHeap(), 0, pszDriverPath);
56
57 return dwError;
58 }
59
60
61 DWORD
62 ScmUnloadDriver(PSERVICE lpService)
63 {
64 PWSTR pszDriverPath;
65 UNICODE_STRING DriverPath;
66 NTSTATUS Status;
67 DWORD dwError = ERROR_SUCCESS;
68
69 /* Build the driver path */
70 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
71 pszDriverPath = HeapAlloc(GetProcessHeap(),
72 HEAP_ZERO_MEMORY,
73 (52 + wcslen(lpService->lpServiceName) + 1) * sizeof(WCHAR));
74 if (pszDriverPath == NULL)
75 return ERROR_NOT_ENOUGH_MEMORY;
76
77 wcscpy(pszDriverPath,
78 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
79 wcscat(pszDriverPath,
80 lpService->lpServiceName);
81
82 RtlInitUnicodeString(&DriverPath,
83 pszDriverPath);
84
85 /* FIXME: Acquire privilege */
86
87 Status = NtUnloadDriver(&DriverPath);
88
89 /* FIXME: Release privilege */
90
91 if (!NT_SUCCESS(Status))
92 {
93 dwError = RtlNtStatusToDosError(Status);
94 }
95
96 HeapFree(GetProcessHeap(), 0, pszDriverPath);
97
98 return dwError;
99 }
100
101
102 DWORD
103 ScmGetDriverStatus(PSERVICE lpService,
104 LPSERVICE_STATUS lpServiceStatus)
105 {
106 OBJECT_ATTRIBUTES ObjectAttributes;
107 UNICODE_STRING DirName;
108 HANDLE DirHandle;
109 NTSTATUS Status = STATUS_SUCCESS;
110 POBJECT_DIRECTORY_INFORMATION DirInfo;
111 ULONG BufferLength;
112 ULONG DataLength;
113 ULONG Index;
114 DWORD dwError = ERROR_SUCCESS;
115 BOOLEAN bFound = FALSE;
116
117 DPRINT1("ScmGetDriverStatus() called\n");
118
119 memset(lpServiceStatus, 0, sizeof(SERVICE_STATUS));
120
121 if (lpService->Status.dwServiceType == SERVICE_KERNEL_DRIVER)
122 {
123 RtlInitUnicodeString(&DirName,
124 L"\\Driver");
125 }
126 else
127 {
128 RtlInitUnicodeString(&DirName,
129 L"\\FileSystem");
130 }
131
132 InitializeObjectAttributes(&ObjectAttributes,
133 &DirName,
134 0,
135 NULL,
136 NULL);
137
138 Status = NtOpenDirectoryObject(&DirHandle,
139 DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
140 &ObjectAttributes);
141 if (!NT_SUCCESS(Status))
142 {
143 DPRINT1("NtOpenDirectoryObject() failed!\n");
144 return RtlNtStatusToDosError(Status);
145 }
146
147 BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) +
148 2 * MAX_PATH * sizeof(WCHAR);
149 DirInfo = (OBJECT_DIRECTORY_INFORMATION*) HeapAlloc(GetProcessHeap(),
150 HEAP_ZERO_MEMORY,
151 BufferLength);
152
153 Index = 0;
154 while (TRUE)
155 {
156 Status = NtQueryDirectoryObject(DirHandle,
157 DirInfo,
158 BufferLength,
159 TRUE,
160 FALSE,
161 &Index,
162 &DataLength);
163 if (Status == STATUS_NO_MORE_ENTRIES)
164 {
165 DPRINT("No more services\n");
166 break;
167 }
168
169 if (!NT_SUCCESS(Status))
170 break;
171
172 DPRINT("Comparing: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->Name);
173
174 if (_wcsicmp(lpService->lpServiceName, DirInfo->Name.Buffer) == 0)
175 {
176 DPRINT1("Found: '%S' '%wZ'\n",
177 lpService->lpServiceName, &DirInfo->Name);
178 bFound = TRUE;
179
180 break;
181 }
182 }
183
184 HeapFree(GetProcessHeap(),
185 0,
186 DirInfo);
187 NtClose(DirHandle);
188
189 if (!NT_SUCCESS(Status))
190 {
191 DPRINT1("Status: %lx\n", Status);
192 return RtlNtStatusToDosError(Status);
193 }
194
195 if ((bFound == TRUE) &&
196 (lpService->Status.dwCurrentState != SERVICE_STOP_PENDING))
197 {
198 if (lpService->Status.dwCurrentState == SERVICE_STOPPED)
199 {
200 lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
201 lpService->Status.dwServiceSpecificExitCode = ERROR_SUCCESS;
202 lpService->Status.dwCheckPoint = 0;
203 lpService->Status.dwWaitHint = 0;
204 lpService->Status.dwControlsAccepted = 0;
205 }
206 else
207 {
208 lpService->Status.dwCurrentState = SERVICE_RUNNING;
209 lpService->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
210
211 if (lpService->Status.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED)
212 lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
213 }
214 }
215 else
216 {
217 lpService->Status.dwCurrentState = SERVICE_STOPPED;
218 lpService->Status.dwControlsAccepted = 0;
219 lpService->Status.dwCheckPoint = 0;
220 lpService->Status.dwWaitHint = 0;
221
222 if (lpService->Status.dwCurrentState == SERVICE_STOP_PENDING)
223 lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
224 else
225 lpService->Status.dwWin32ExitCode = ERROR_GEN_FAILURE;
226 }
227
228 if (lpServiceStatus != NULL)
229 {
230 memcpy(lpServiceStatus,
231 &lpService->Status,
232 sizeof(SERVICE_STATUS));
233 }
234
235 DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError);
236
237 return ERROR_SUCCESS;
238 }
239
240
241 DWORD
242 ScmControlDriver(PSERVICE lpService,
243 DWORD dwControl,
244 LPSERVICE_STATUS lpServiceStatus)
245 {
246 DWORD dwError;
247
248 DPRINT("ScmControlDriver() called\n");
249
250 switch (dwControl)
251 {
252 case SERVICE_CONTROL_STOP:
253 if (lpService->Status.dwCurrentState != SERVICE_RUNNING)
254 {
255 dwError = ERROR_INVALID_SERVICE_CONTROL;
256 goto done;
257 }
258
259 dwError = ScmUnloadDriver(lpService);
260 if (dwError == ERROR_SUCCESS)
261 {
262 lpService->Status.dwControlsAccepted = 0;
263 lpService->Status.dwCurrentState = SERVICE_STOPPED;
264 }
265 break;
266
267 case SERVICE_CONTROL_INTERROGATE:
268 dwError = ScmGetDriverStatus(lpService,
269 lpServiceStatus);
270 break;
271
272 default:
273 dwError = ERROR_INVALID_SERVICE_CONTROL;
274 }
275
276 done:;
277 DPRINT("ScmControlDriver() done (Erorr: %lu)\n", dwError);
278
279 return dwError;
280 }
281
282 /* EOF */