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 memset(lpServiceStatus
, 0, sizeof(SERVICE_STATUS
));
145 if (lpService
->Status
.dwServiceType
== SERVICE_KERNEL_DRIVER
)
147 RtlInitUnicodeString(&DirName
, L
"\\Driver");
149 else // if (lpService->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER)
151 ASSERT(lpService
->Status
.dwServiceType
== SERVICE_FILE_SYSTEM_DRIVER
);
152 RtlInitUnicodeString(&DirName
, L
"\\FileSystem");
155 InitializeObjectAttributes(&ObjectAttributes
,
161 Status
= NtOpenDirectoryObject(&DirHandle
,
162 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
164 if (!NT_SUCCESS(Status
))
166 DPRINT1("NtOpenDirectoryObject() failed!\n");
167 return RtlNtStatusToDosError(Status
);
170 BufferLength
= sizeof(OBJECT_DIRECTORY_INFORMATION
) +
171 2 * MAX_PATH
* sizeof(WCHAR
);
172 DirInfo
= (OBJECT_DIRECTORY_INFORMATION
*) HeapAlloc(GetProcessHeap(),
179 Status
= NtQueryDirectoryObject(DirHandle
,
186 if (Status
== STATUS_NO_MORE_ENTRIES
)
188 DPRINT("No more services\n");
192 if (!NT_SUCCESS(Status
))
195 DPRINT("Comparing: '%S' '%wZ'\n", lpService
->lpServiceName
, &DirInfo
->Name
);
197 if (_wcsicmp(lpService
->lpServiceName
, DirInfo
->Name
.Buffer
) == 0)
199 DPRINT1("Found: '%S' '%wZ'\n",
200 lpService
->lpServiceName
, &DirInfo
->Name
);
207 HeapFree(GetProcessHeap(),
212 if (!NT_SUCCESS(Status
))
214 DPRINT1("Status: %lx\n", Status
);
215 return RtlNtStatusToDosError(Status
);
218 if ((bFound
== TRUE
) &&
219 (lpService
->Status
.dwCurrentState
!= SERVICE_STOP_PENDING
))
221 if (lpService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
223 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
224 lpService
->Status
.dwServiceSpecificExitCode
= ERROR_SUCCESS
;
225 lpService
->Status
.dwCheckPoint
= 0;
226 lpService
->Status
.dwWaitHint
= 0;
227 lpService
->Status
.dwControlsAccepted
= 0;
231 lpService
->Status
.dwCurrentState
= SERVICE_RUNNING
;
232 lpService
->Status
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
;
234 if (lpService
->Status
.dwWin32ExitCode
== ERROR_SERVICE_NEVER_STARTED
)
235 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
240 lpService
->Status
.dwCurrentState
= SERVICE_STOPPED
;
241 lpService
->Status
.dwControlsAccepted
= 0;
242 lpService
->Status
.dwCheckPoint
= 0;
243 lpService
->Status
.dwWaitHint
= 0;
245 if (lpService
->Status
.dwCurrentState
== SERVICE_STOP_PENDING
)
246 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
248 lpService
->Status
.dwWin32ExitCode
= ERROR_GEN_FAILURE
;
251 if (lpServiceStatus
!= NULL
)
253 memcpy(lpServiceStatus
,
255 sizeof(SERVICE_STATUS
));
258 DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError
);
260 return ERROR_SUCCESS
;
265 ScmControlDriver(PSERVICE lpService
,
267 LPSERVICE_STATUS lpServiceStatus
)
271 DPRINT("ScmControlDriver() called\n");
275 case SERVICE_CONTROL_STOP
:
276 if (lpService
->Status
.dwCurrentState
!= SERVICE_RUNNING
)
278 dwError
= ERROR_INVALID_SERVICE_CONTROL
;
282 dwError
= ScmUnloadDriver(lpService
);
283 if (dwError
== ERROR_SUCCESS
)
285 lpService
->Status
.dwControlsAccepted
= 0;
286 lpService
->Status
.dwCurrentState
= SERVICE_STOPPED
;
290 case SERVICE_CONTROL_INTERROGATE
:
291 dwError
= ScmGetDriverStatus(lpService
,
296 dwError
= ERROR_INVALID_SERVICE_CONTROL
;
300 DPRINT("ScmControlDriver() done (Erorr: %lu)\n", dwError
);