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 *****************************************************************/
17 /* FUNCTIONS ****************************************************************/
19 static DWORD
EnablePrivilege(LPCWSTR lpszPrivilegeName
, BOOL bEnablePrivilege
)
21 DWORD dwRet
= ERROR_SUCCESS
;
24 if (OpenProcessToken(GetCurrentProcess(),
25 TOKEN_ADJUST_PRIVILEGES
,
30 tp
.PrivilegeCount
= 1;
31 tp
.Privileges
[0].Attributes
= (bEnablePrivilege
? SE_PRIVILEGE_ENABLED
: 0);
33 if (LookupPrivilegeValueW(NULL
,
35 &tp
.Privileges
[0].Luid
))
37 if (AdjustTokenPrivileges(hToken
, FALSE
, &tp
, 0, NULL
, NULL
))
39 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED
)
40 dwRet
= ERROR_NOT_ALL_ASSIGNED
;
44 dwRet
= GetLastError();
49 dwRet
= GetLastError();
56 dwRet
= GetLastError();
64 ScmLoadDriver(PSERVICE lpService
)
67 UNICODE_STRING DriverPath
;
69 DWORD dwError
= ERROR_SUCCESS
;
71 /* Build the driver path */
72 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
73 pszDriverPath
= HeapAlloc(GetProcessHeap(),
75 (52 + wcslen(lpService
->lpServiceName
) + 1) * sizeof(WCHAR
));
76 if (pszDriverPath
== NULL
)
77 return ERROR_NOT_ENOUGH_MEMORY
;
80 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
82 lpService
->lpServiceName
);
84 RtlInitUnicodeString(&DriverPath
,
87 DPRINT(" Path: %wZ\n", &DriverPath
);
89 /* Acquire driver-loading privilege */
90 dwError
= EnablePrivilege(SE_LOAD_DRIVER_NAME
, TRUE
);
91 if (dwError
!= ERROR_SUCCESS
)
93 /* We encountered a failure, exit properly */
94 DPRINT1("SERVICES: Cannot acquire driver-loading privilege, error = %lu\n", dwError
);
98 Status
= NtLoadDriver(&DriverPath
);
100 /* Release driver-loading privilege */
101 EnablePrivilege(SE_LOAD_DRIVER_NAME
, FALSE
);
103 if (!NT_SUCCESS(Status
))
105 dwError
= RtlNtStatusToDosError(Status
);
109 HeapFree(GetProcessHeap(), 0, pszDriverPath
);
116 ScmUnloadDriver(PSERVICE lpService
)
119 UNICODE_STRING DriverPath
;
121 DWORD dwError
= ERROR_SUCCESS
;
123 /* Build the driver path */
124 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
125 pszDriverPath
= HeapAlloc(GetProcessHeap(),
127 (52 + wcslen(lpService
->lpServiceName
) + 1) * sizeof(WCHAR
));
128 if (pszDriverPath
== NULL
)
129 return ERROR_NOT_ENOUGH_MEMORY
;
131 wcscpy(pszDriverPath
,
132 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
133 wcscat(pszDriverPath
,
134 lpService
->lpServiceName
);
136 RtlInitUnicodeString(&DriverPath
,
139 /* Acquire driver-unloading privilege */
140 dwError
= EnablePrivilege(SE_LOAD_DRIVER_NAME
, TRUE
);
141 if (dwError
!= ERROR_SUCCESS
)
143 /* We encountered a failure, exit properly */
144 DPRINT1("SERVICES: Cannot acquire driver-unloading privilege, error = %lu\n", dwError
);
148 Status
= NtUnloadDriver(&DriverPath
);
150 /* Release driver-unloading privilege */
151 EnablePrivilege(SE_LOAD_DRIVER_NAME
, FALSE
);
153 if (!NT_SUCCESS(Status
))
155 dwError
= RtlNtStatusToDosError(Status
);
159 HeapFree(GetProcessHeap(), 0, pszDriverPath
);
166 ScmGetDriverStatus(PSERVICE lpService
,
167 LPSERVICE_STATUS lpServiceStatus
)
169 OBJECT_ATTRIBUTES ObjectAttributes
;
170 UNICODE_STRING DirName
;
172 NTSTATUS Status
= STATUS_SUCCESS
;
173 POBJECT_DIRECTORY_INFORMATION DirInfo
;
177 DWORD dwError
= ERROR_SUCCESS
;
178 BOOLEAN bFound
= FALSE
;
180 DPRINT1("ScmGetDriverStatus() called\n");
182 memset(lpServiceStatus
, 0, sizeof(SERVICE_STATUS
));
184 if (lpService
->Status
.dwServiceType
== SERVICE_KERNEL_DRIVER
)
186 RtlInitUnicodeString(&DirName
,
191 RtlInitUnicodeString(&DirName
,
195 InitializeObjectAttributes(&ObjectAttributes
,
201 Status
= NtOpenDirectoryObject(&DirHandle
,
202 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
204 if (!NT_SUCCESS(Status
))
206 DPRINT1("NtOpenDirectoryObject() failed!\n");
207 return RtlNtStatusToDosError(Status
);
210 BufferLength
= sizeof(OBJECT_DIRECTORY_INFORMATION
) +
211 2 * MAX_PATH
* sizeof(WCHAR
);
212 DirInfo
= (OBJECT_DIRECTORY_INFORMATION
*) HeapAlloc(GetProcessHeap(),
219 Status
= NtQueryDirectoryObject(DirHandle
,
226 if (Status
== STATUS_NO_MORE_ENTRIES
)
228 DPRINT("No more services\n");
232 if (!NT_SUCCESS(Status
))
235 DPRINT("Comparing: '%S' '%wZ'\n", lpService
->lpServiceName
, &DirInfo
->Name
);
237 if (_wcsicmp(lpService
->lpServiceName
, DirInfo
->Name
.Buffer
) == 0)
239 DPRINT1("Found: '%S' '%wZ'\n",
240 lpService
->lpServiceName
, &DirInfo
->Name
);
247 HeapFree(GetProcessHeap(),
252 if (!NT_SUCCESS(Status
))
254 DPRINT1("Status: %lx\n", Status
);
255 return RtlNtStatusToDosError(Status
);
258 if ((bFound
== TRUE
) &&
259 (lpService
->Status
.dwCurrentState
!= SERVICE_STOP_PENDING
))
261 if (lpService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
263 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
264 lpService
->Status
.dwServiceSpecificExitCode
= ERROR_SUCCESS
;
265 lpService
->Status
.dwCheckPoint
= 0;
266 lpService
->Status
.dwWaitHint
= 0;
267 lpService
->Status
.dwControlsAccepted
= 0;
271 lpService
->Status
.dwCurrentState
= SERVICE_RUNNING
;
272 lpService
->Status
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
;
274 if (lpService
->Status
.dwWin32ExitCode
== ERROR_SERVICE_NEVER_STARTED
)
275 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
280 lpService
->Status
.dwCurrentState
= SERVICE_STOPPED
;
281 lpService
->Status
.dwControlsAccepted
= 0;
282 lpService
->Status
.dwCheckPoint
= 0;
283 lpService
->Status
.dwWaitHint
= 0;
285 if (lpService
->Status
.dwCurrentState
== SERVICE_STOP_PENDING
)
286 lpService
->Status
.dwWin32ExitCode
= ERROR_SUCCESS
;
288 lpService
->Status
.dwWin32ExitCode
= ERROR_GEN_FAILURE
;
291 if (lpServiceStatus
!= NULL
)
293 memcpy(lpServiceStatus
,
295 sizeof(SERVICE_STATUS
));
298 DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError
);
300 return ERROR_SUCCESS
;
305 ScmControlDriver(PSERVICE lpService
,
307 LPSERVICE_STATUS lpServiceStatus
)
311 DPRINT("ScmControlDriver() called\n");
315 case SERVICE_CONTROL_STOP
:
316 if (lpService
->Status
.dwCurrentState
!= SERVICE_RUNNING
)
318 dwError
= ERROR_INVALID_SERVICE_CONTROL
;
322 dwError
= ScmUnloadDriver(lpService
);
323 if (dwError
== ERROR_SUCCESS
)
325 lpService
->Status
.dwControlsAccepted
= 0;
326 lpService
->Status
.dwCurrentState
= SERVICE_STOPPED
;
330 case SERVICE_CONTROL_INTERROGATE
:
331 dwError
= ScmGetDriverStatus(lpService
,
336 dwError
= ERROR_INVALID_SERVICE_CONTROL
;
340 DPRINT("ScmControlDriver() done (Erorr: %lu)\n", dwError
);