ReactOS 0.4.16-dev-303-g11d5cb8
driver.c
Go to the documentation of this file.
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#include <ndk/iofuncs.h>
15#include <ndk/setypes.h>
16
17#define NDEBUG
18#include <debug.h>
19
20/* FUNCTIONS ****************************************************************/
21
22static
25{
27 BOOLEAN WasPrivilegeEnabled = FALSE;
28 PWSTR pszDriverPath;
29 UNICODE_STRING DriverPath;
30
31 /* Build the driver path */
32 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
33 pszDriverPath = HeapAlloc(GetProcessHeap(),
35 (52 + wcslen(lpService->lpServiceName) + 1) * sizeof(WCHAR));
36 if (pszDriverPath == NULL)
38
39 wcscpy(pszDriverPath,
40 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
41 wcscat(pszDriverPath,
42 lpService->lpServiceName);
43
44 RtlInitUnicodeString(&DriverPath,
45 pszDriverPath);
46
47 DPRINT(" Path: %wZ\n", &DriverPath);
48
49 /* Acquire driver-loading privilege */
51 TRUE,
52 FALSE,
53 &WasPrivilegeEnabled);
54 if (!NT_SUCCESS(Status))
55 {
56 /* We encountered a failure, exit properly */
57 DPRINT1("SERVICES: Cannot acquire driver-loading privilege, Status = 0x%08lx\n", Status);
58 goto done;
59 }
60
61 Status = NtLoadDriver(&DriverPath);
62
63 /* Release driver-loading privilege */
65 WasPrivilegeEnabled,
66 FALSE,
67 &WasPrivilegeEnabled);
68
69done:
70 HeapFree(GetProcessHeap(), 0, pszDriverPath);
72}
73
74
75static
78{
80 BOOLEAN WasPrivilegeEnabled = FALSE;
81 PWSTR pszDriverPath;
82 UNICODE_STRING DriverPath;
83 DWORD dwError;
84
85 /* Build the driver path */
86 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
87 pszDriverPath = HeapAlloc(GetProcessHeap(),
89 (52 + wcslen(lpService->lpServiceName) + 1) * sizeof(WCHAR));
90 if (pszDriverPath == NULL)
92
93 wcscpy(pszDriverPath,
94 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
95 wcscat(pszDriverPath,
96 lpService->lpServiceName);
97
98 RtlInitUnicodeString(&DriverPath,
99 pszDriverPath);
100
101 DPRINT(" Path: %wZ\n", &DriverPath);
102
103 /* Acquire driver-unloading privilege */
105 TRUE,
106 FALSE,
107 &WasPrivilegeEnabled);
108 if (!NT_SUCCESS(Status))
109 {
110 /* We encountered a failure, exit properly */
111 DPRINT1("SERVICES: Cannot acquire driver-unloading privilege, Status = 0x%08lx\n", Status);
112 dwError = RtlNtStatusToDosError(Status);
113 goto done;
114 }
115
116 Status = NtUnloadDriver(&DriverPath);
119 else
120 dwError = RtlNtStatusToDosError(Status);
121
122 /* Release driver-unloading privilege */
124 WasPrivilegeEnabled,
125 FALSE,
126 &WasPrivilegeEnabled);
127
128done:
129 HeapFree(GetProcessHeap(), 0, pszDriverPath);
130 return dwError;
131}
132
133
134static
135DWORD
137 LPSERVICE_STATUS lpServiceStatus)
138{
141 HANDLE DirHandle;
146 ULONG Index;
147 DWORD dwError = ERROR_SUCCESS;
148 BOOLEAN bFound = FALSE;
149 DWORD dwPreviousState;
150
151 DPRINT1("ScmGetDriverStatus() called\n");
152
153 /* Zero output buffer if any */
154 if (lpServiceStatus != NULL)
155 {
156 memset(lpServiceStatus, 0, sizeof(SERVICE_STATUS));
157 }
158
159 /* Select the appropriate object directory based on driver type */
161 {
162 RtlInitUnicodeString(&DirName, L"\\Driver");
163 }
164 else // if (lpService->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER)
165 {
167 RtlInitUnicodeString(&DirName, L"\\FileSystem");
168 }
169
171 &DirName,
172 0,
173 NULL,
174 NULL);
175
176 /* Open the object directory where loaded drivers are */
177 Status = NtOpenDirectoryObject(&DirHandle,
180 if (!NT_SUCCESS(Status))
181 {
182 DPRINT1("NtOpenDirectoryObject() failed\n");
184 }
185
186 /* Allocate a buffer big enough for querying the object */
188 2 * MAX_PATH * sizeof(WCHAR);
192
193 /* Now, start browsing entry by entry */
194 Index = 0;
195 while (TRUE)
196 {
197 Status = NtQueryDirectoryObject(DirHandle,
198 DirInfo,
200 TRUE,
201 FALSE,
202 &Index,
203 &DataLength);
204 /* End of enumeration, the driver was not found */
206 {
207 DPRINT("No more services\n");
208 break;
209 }
210
211 /* Other error, fail */
212 if (!NT_SUCCESS(Status))
213 break;
214
215 DPRINT("Comparing: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->Name);
216
217 /* Compare names to check whether it matches our driver */
218 if (_wcsicmp(lpService->lpServiceName, DirInfo->Name.Buffer) == 0)
219 {
220 /* That's our driver, bail out! */
221 DPRINT1("Found: '%S' '%wZ'\n",
222 lpService->lpServiceName, &DirInfo->Name);
223 bFound = TRUE;
224
225 break;
226 }
227 }
228
229 /* Release resources we don't need */
231 0,
232 DirInfo);
233 NtClose(DirHandle);
234
235 /* Only quit if there's a failure
236 * Not having found the driver is legit!
237 * It means the driver was registered as a service, but not loaded
238 * We have not to fail in that situation, but to return proper status
239 */
241 {
242 DPRINT1("Status: %lx\n", Status);
244 }
245
246 /* Now, we have two cases:
247 * We found the driver: it means it's running
248 * We didn't find the driver: it wasn't running
249 */
250 if (bFound)
251 {
252 /* Found, return it's running */
253
254 dwPreviousState = lpService->Status.dwCurrentState;
255
256 /* It is running */
258
259 if (dwPreviousState == SERVICE_STOPPED)
260 {
261 /* Make it run if it was stopped before */
265 lpService->Status.dwCheckPoint = 0;
266 lpService->Status.dwWaitHint = 0;
267 }
268
271 }
272 else
273 {
274 /* Not found, return it's stopped */
275
277 {
278 /* Stopped successfully */
281 lpService->Status.dwControlsAccepted = 0;
282 lpService->Status.dwCheckPoint = 0;
283 lpService->Status.dwWaitHint = 0;
284 }
285 else if (lpService->Status.dwCurrentState == SERVICE_STOPPED)
286 {
287 /* Don't change the current status */
288 }
289 else
290 {
293 lpService->Status.dwControlsAccepted = 0;
294 lpService->Status.dwCheckPoint = 0;
295 lpService->Status.dwWaitHint = 0;
296 }
297 }
298
299 /* Copy service status if required */
300 if (lpServiceStatus != NULL)
301 {
302 RtlCopyMemory(lpServiceStatus,
303 &lpService->Status,
304 sizeof(SERVICE_STATUS));
305 }
306
307 DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError);
308
309 return ERROR_SUCCESS;
310}
311
312
313DWORD
315{
316 DWORD dwError;
317
318 DPRINT("ScmStartDriver(%p)\n", pService);
319
320 dwError = ScmLoadDriver(pService);
321 if (dwError == ERROR_SUCCESS)
322 {
326 }
327
328 DPRINT("ScmStartDriver returns %lu\n", dwError);
329
330 return dwError;
331}
332
333
334DWORD
336 DWORD dwControl,
337 LPSERVICE_STATUS lpServiceStatus)
338{
339 DWORD dwError;
340
341 DPRINT("ScmControlDriver() called\n");
342
343 switch (dwControl)
344 {
346 /* Check the drivers status */
347 dwError = ScmGetDriverStatus(lpService,
348 lpServiceStatus);
349 if (dwError != ERROR_SUCCESS)
350 goto done;
351
352 /* Fail, if it is not running */
353 if (lpService->Status.dwCurrentState != SERVICE_RUNNING)
354 {
356 goto done;
357 }
358
359 /* Unload the driver */
360 dwError = ScmUnloadDriver(lpService);
361 if (dwError == ERROR_INVALID_SERVICE_CONTROL)
362 {
363 /* The driver cannot be stopped, mark it non-stoppable */
364 lpService->Status.dwControlsAccepted = 0;
365 goto done;
366 }
367
368 /* Make the driver 'stop pending' */
370
371 /* Check the drivers status again */
372 dwError = ScmGetDriverStatus(lpService,
373 lpServiceStatus);
374 break;
375
377 dwError = ScmGetDriverStatus(lpService,
378 lpServiceStatus);
379 break;
380
381 default:
383 }
384
385done:
386 DPRINT("ScmControlDriver() done (Erorr: %lu)\n", dwError);
387
388 return dwError;
389}
390
391/* EOF */
NTSTATUS NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
Definition: driver.c:2208
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
static DWORD ScmGetDriverStatus(PSERVICE lpService, LPSERVICE_STATUS lpServiceStatus)
Definition: driver.c:136
DWORD ScmStartDriver(PSERVICE pService)
Definition: driver.c:314
static DWORD ScmUnloadDriver(PSERVICE lpService)
Definition: driver.c:77
static DWORD ScmLoadDriver(PSERVICE lpService)
Definition: driver.c:24
DWORD ScmControlDriver(PSERVICE lpService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: driver.c:335
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:737
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:25
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define ASSERT(a)
Definition: mode.c:44
#define SE_LOAD_DRIVER_PRIVILEGE
Definition: security.c:664
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
struct _OBJECT_DIRECTORY_INFORMATION OBJECT_DIRECTORY_INFORMATION
NTSYSAPI NTSTATUS NTAPI RtlAdjustPrivilege(_In_ ULONG Privilege, _In_ BOOLEAN NewValue, _In_ BOOLEAN ForThread, _Out_ PBOOLEAN OldValue)
#define DIRECTORY_QUERY
Definition: nt_native.h:1254
#define DIRECTORY_TRAVERSE
Definition: nt_native.h:1255
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSTATUS NTAPI NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
Definition: driver.c:2147
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: obdir.c:393
NTSTATUS NTAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PVOID Buffer, IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
Definition: obdir.c:490
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
DWORD dwServiceType
Definition: winsvc.h:99
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwControlsAccepted
Definition: winsvc.h:101
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwCurrentState
Definition: winsvc.h:100
DWORD dwCheckPoint
Definition: winsvc.h:104
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
SERVICE_STATUS Status
Definition: services.h:72
LPWSTR lpServiceName
Definition: services.h:64
uint16_t * PWSTR
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
#define ERROR_SERVICE_NEVER_STARTED
Definition: winerror.h:628
#define ERROR_GEN_FAILURE
Definition: winerror.h:134
#define ERROR_INVALID_SERVICE_CONTROL
Definition: winerror.h:603
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define SERVICE_CONTROL_INTERROGATE
Definition: winsvc.h:39
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:953
#define SERVICE_FILE_SYSTEM_DRIVER
Definition: cmtypes.h:954
__wchar_t WCHAR
Definition: xmlstorage.h:180