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