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
10 /* INCLUDES *****************************************************************/
14 #include <ndk/iofuncs.h>
15 #include <ndk/setypes.h>
20 /* FUNCTIONS ****************************************************************/
23 ScmLoadDriver(PSERVICE lpService
)
25 NTSTATUS Status
= STATUS_SUCCESS
;
26 BOOLEAN WasPrivilegeEnabled
= FALSE
;
28 UNICODE_STRING DriverPath
;
30 /* Build the driver path */
31 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
32 pszDriverPath
= HeapAlloc(GetProcessHeap(),
34 (52 + wcslen(lpService
->lpServiceName
) + 1) * sizeof(WCHAR
));
35 if (pszDriverPath
== NULL
)
36 return ERROR_NOT_ENOUGH_MEMORY
;
39 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
41 lpService
->lpServiceName
);
43 RtlInitUnicodeString(&DriverPath
,
46 DPRINT(" Path: %wZ\n", &DriverPath
);
48 /* Acquire driver-loading privilege */
49 Status
= RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE
,
52 &WasPrivilegeEnabled
);
53 if (!NT_SUCCESS(Status
))
55 /* We encountered a failure, exit properly */
56 DPRINT1("SERVICES: Cannot acquire driver-loading privilege, Status = 0x%08lx\n", Status
);
60 Status
= NtLoadDriver(&DriverPath
);
62 /* Release driver-loading privilege */
63 RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE
,
66 &WasPrivilegeEnabled
);
69 HeapFree(GetProcessHeap(), 0, pszDriverPath
);
70 return RtlNtStatusToDosError(Status
);
75 ScmUnloadDriver(PSERVICE lpService
)
77 NTSTATUS Status
= STATUS_SUCCESS
;
78 BOOLEAN WasPrivilegeEnabled
= FALSE
;
80 UNICODE_STRING DriverPath
;
82 /* Build the driver path */
83 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
84 pszDriverPath
= HeapAlloc(GetProcessHeap(),
86 (52 + wcslen(lpService
->lpServiceName
) + 1) * sizeof(WCHAR
));
87 if (pszDriverPath
== NULL
)
88 return ERROR_NOT_ENOUGH_MEMORY
;
91 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
93 lpService
->lpServiceName
);
95 RtlInitUnicodeString(&DriverPath
,
98 DPRINT(" Path: %wZ\n", &DriverPath
);
100 /* Acquire driver-unloading privilege */
101 Status
= RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE
,
104 &WasPrivilegeEnabled
);
105 if (!NT_SUCCESS(Status
))
107 /* We encountered a failure, exit properly */
108 DPRINT1("SERVICES: Cannot acquire driver-unloading privilege, Status = 0x%08lx\n", Status
);
112 Status
= NtUnloadDriver(&DriverPath
);
114 /* Release driver-unloading privilege */
115 RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE
,
118 &WasPrivilegeEnabled
);
121 HeapFree(GetProcessHeap(), 0, pszDriverPath
);
122 return RtlNtStatusToDosError(Status
);
127 ScmGetDriverStatus(PSERVICE lpService
,
128 LPSERVICE_STATUS lpServiceStatus
)
130 OBJECT_ATTRIBUTES ObjectAttributes
;
131 UNICODE_STRING DirName
;
133 NTSTATUS Status
= STATUS_SUCCESS
;
134 POBJECT_DIRECTORY_INFORMATION DirInfo
;
138 DWORD dwError
= ERROR_SUCCESS
;
139 BOOLEAN bFound
= FALSE
;
141 DPRINT1("ScmGetDriverStatus() called\n");
143 /* Zero output buffer if any */
144 if (lpServiceStatus
!= NULL
)
146 memset(lpServiceStatus
, 0, sizeof(SERVICE_STATUS
));
149 /* Select the appropriate object directory based on driver type */
150 if (lpService
->Status
.dwServiceType
== SERVICE_KERNEL_DRIVER
)
152 RtlInitUnicodeString(&DirName
, L
"\\Driver");
154 else // if (lpService->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER)
156 ASSERT(lpService
->Status
.dwServiceType
== SERVICE_FILE_SYSTEM_DRIVER
);
157 RtlInitUnicodeString(&DirName
, L
"\\FileSystem");
160 InitializeObjectAttributes(&ObjectAttributes
,
166 /* Open the object directory where loaded drivers are */
167 Status
= NtOpenDirectoryObject(&DirHandle
,
168 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
170 if (!NT_SUCCESS(Status
))
172 DPRINT1("NtOpenDirectoryObject() failed!\n");
173 return RtlNtStatusToDosError(Status
);
176 /* Allocate a buffer big enough for querying the object */
177 BufferLength
= sizeof(OBJECT_DIRECTORY_INFORMATION
) +
178 2 * MAX_PATH
* sizeof(WCHAR
);
179 DirInfo
= (OBJECT_DIRECTORY_INFORMATION
*) HeapAlloc(GetProcessHeap(),
183 /* Now, start browsing entry by entry */
187 Status
= NtQueryDirectoryObject(DirHandle
,
194 /* End of enumeration, the driver was not found */
195 if (Status
== STATUS_NO_MORE_ENTRIES
)
197 DPRINT("No more services\n");
201 /* Other error, fail */
202 if (!NT_SUCCESS(Status
))
205 DPRINT("Comparing: '%S' '%wZ'\n", lpService
->lpServiceName
, &DirInfo
->Name
);
207 /* Compare names to check whether it matches our driver */
208 if (_wcsicmp(lpService
->lpServiceName
, DirInfo
->Name
.Buffer
) == 0)
210 /* That's our driver, bail out! */
211 DPRINT1("Found: '%S' '%wZ'\n",
212 lpService
->lpServiceName
, &DirInfo
->Name
);
219 /* Release resources we don't need */
220 HeapFree(GetProcessHeap(),
225 /* Only quit if there's a failure
226 * Not having found the driver is legit!
227 * It means the driver was registered as a service, but not loaded
228 * We have not to fail in that situation, but to return proper status
230 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NO_MORE_ENTRIES
)
232 DPRINT1("Status: %lx\n", Status
);
233 return RtlNtStatusToDosError(Status
);
236 /* Now, we have two cases:
237 * We found the driver: it means it's running
238 * We didn't find the driver: it wasn't running
240 if ((bFound
!= FALSE
) &&
241 (lpService
->Status
.dwCurrentState
!= SERVICE_STOP_PENDING
))
243 if (lpService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
245 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
246 lpService
->Status
.dwServiceSpecificExitCode
= ERROR_SUCCESS
;
247 lpService
->Status
.dwCheckPoint
= 0;
248 lpService
->Status
.dwWaitHint
= 0;
249 lpService
->Status
.dwControlsAccepted
= 0;
253 lpService
->Status
.dwCurrentState
= SERVICE_RUNNING
;
254 lpService
->Status
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
;
256 if (lpService
->Status
.dwWin32ExitCode
== ERROR_SERVICE_NEVER_STARTED
)
257 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
260 /* Not found, return it's stopped */
263 lpService
->Status
.dwCurrentState
= SERVICE_STOPPED
;
264 lpService
->Status
.dwControlsAccepted
= 0;
265 lpService
->Status
.dwCheckPoint
= 0;
266 lpService
->Status
.dwWaitHint
= 0;
268 if (lpService
->Status
.dwCurrentState
== SERVICE_STOP_PENDING
)
269 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
271 lpService
->Status
.dwWin32ExitCode
= ERROR_GEN_FAILURE
;
274 /* Copy service status if required */
275 if (lpServiceStatus
!= NULL
)
277 memcpy(lpServiceStatus
,
279 sizeof(SERVICE_STATUS
));
282 DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError
);
284 return ERROR_SUCCESS
;
289 ScmControlDriver(PSERVICE lpService
,
291 LPSERVICE_STATUS lpServiceStatus
)
295 DPRINT("ScmControlDriver() called\n");
299 case SERVICE_CONTROL_STOP
:
300 if (lpService
->Status
.dwCurrentState
!= SERVICE_RUNNING
)
302 dwError
= ERROR_INVALID_SERVICE_CONTROL
;
306 dwError
= ScmUnloadDriver(lpService
);
307 if (dwError
== ERROR_SUCCESS
)
309 lpService
->Status
.dwControlsAccepted
= 0;
310 lpService
->Status
.dwCurrentState
= SERVICE_STOPPED
;
314 case SERVICE_CONTROL_INTERROGATE
:
315 dwError
= ScmGetDriverStatus(lpService
,
320 dwError
= ERROR_INVALID_SERVICE_CONTROL
;
324 DPRINT("ScmControlDriver() done (Erorr: %lu)\n", dwError
);