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