Make sure that FileList is not empty. fixes bug #884.
[reactos.git] / reactos / subsys / system / services / rpcserver.c
1 /*
2
3 */
4
5 /* INCLUDES ****************************************************************/
6
7 #include "services.h"
8 #include "svcctl_s.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13
14 /* GLOBALS *****************************************************************/
15
16 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
17 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
18
19 typedef struct _SCMGR_HANDLE
20 {
21 DWORD Tag;
22 DWORD RefCount;
23 DWORD DesiredAccess;
24 } SCMGR_HANDLE;
25
26
27 typedef struct _MANAGER_HANDLE
28 {
29 SCMGR_HANDLE Handle;
30
31 /* FIXME: Insert more data here */
32
33 WCHAR DatabaseName[1];
34 } MANAGER_HANDLE, *PMANAGER_HANDLE;
35
36
37 typedef struct _SERVICE_HANDLE
38 {
39 SCMGR_HANDLE Handle;
40
41 DWORD DesiredAccess;
42 PSERVICE ServiceEntry;
43
44 /* FIXME: Insert more data here */
45
46 } SERVICE_HANDLE, *PSERVICE_HANDLE;
47
48
49 #define SC_MANAGER_READ \
50 (STANDARD_RIGHTS_READ | \
51 SC_MANAGER_QUERY_LOCK_STATUS | \
52 SC_MANAGER_ENUMERATE_SERVICE)
53
54 #define SC_MANAGER_WRITE \
55 (STANDARD_RIGHTS_WRITE | \
56 SC_MANAGER_MODIFY_BOOT_CONFIG | \
57 SC_MANAGER_CREATE_SERVICE)
58
59 #define SC_MANAGER_EXECUTE \
60 (STANDARD_RIGHTS_EXECUTE | \
61 SC_MANAGER_LOCK | \
62 SC_MANAGER_ENUMERATE_SERVICE | \
63 SC_MANAGER_CONNECT | \
64 SC_MANAGER_CREATE_SERVICE)
65
66
67 #define SERVICE_READ \
68 (STANDARD_RIGHTS_READ | \
69 SERVICE_INTERROGATE | \
70 SERVICE_ENUMERATE_DEPENDENTS | \
71 SERVICE_QUERY_STATUS | \
72 SERVICE_QUERY_CONFIG)
73
74 #define SERVICE_WRITE \
75 (STANDARD_RIGHTS_WRITE | \
76 SERVICE_CHANGE_CONFIG)
77
78 #define SERVICE_EXECUTE \
79 (STANDARD_RIGHTS_EXECUTE | \
80 SERVICE_USER_DEFINED_CONTROL | \
81 SERVICE_PAUSE_CONTINUE | \
82 SERVICE_STOP | \
83 SERVICE_START)
84
85
86 /* VARIABLES ***************************************************************/
87
88 static GENERIC_MAPPING
89 ScmManagerMapping = {SC_MANAGER_READ,
90 SC_MANAGER_WRITE,
91 SC_MANAGER_EXECUTE,
92 SC_MANAGER_ALL_ACCESS};
93
94 static GENERIC_MAPPING
95 ScmServiceMapping = {SERVICE_READ,
96 SERVICE_WRITE,
97 SERVICE_EXECUTE,
98 SC_MANAGER_ALL_ACCESS};
99
100
101 /* FUNCTIONS ***************************************************************/
102
103 VOID
104 ScmStartRpcServer(VOID)
105 {
106 RPC_STATUS Status;
107
108 DPRINT("ScmStartRpcServer() called");
109
110 Status = RpcServerUseProtseqEp(L"ncacn_np",
111 10,
112 L"\\pipe\\ntsvcs",
113 NULL);
114 if (Status != RPC_S_OK)
115 {
116 DPRINT1("RpcServerUseProtseqEp() failed (Status %lx)\n", Status);
117 return;
118 }
119
120 Status = RpcServerRegisterIf(svcctl_ServerIfHandle,
121 NULL,
122 NULL);
123 if (Status != RPC_S_OK)
124 {
125 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
126 return;
127 }
128
129 Status = RpcServerListen(1, 20, TRUE);
130 if (Status != RPC_S_OK)
131 {
132 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
133 return;
134 }
135
136 DPRINT("ScmStartRpcServer() done");
137 }
138
139
140 static DWORD
141 ScmCreateManagerHandle(LPWSTR lpDatabaseName,
142 SC_HANDLE *Handle)
143 {
144 PMANAGER_HANDLE Ptr;
145
146 if (lpDatabaseName == NULL)
147 lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
148
149 Ptr = HeapAlloc(GetProcessHeap(),
150 HEAP_ZERO_MEMORY,
151 sizeof(MANAGER_HANDLE) + wcslen(lpDatabaseName) * sizeof(WCHAR));
152 if (Ptr == NULL)
153 return ERROR_NOT_ENOUGH_MEMORY;
154
155 Ptr->Handle.Tag = MANAGER_TAG;
156 Ptr->Handle.RefCount = 1;
157
158 /* FIXME: initialize more data here */
159
160 wcscpy(Ptr->DatabaseName, lpDatabaseName);
161
162 *Handle = (SC_HANDLE)Ptr;
163
164 return ERROR_SUCCESS;
165 }
166
167
168 static DWORD
169 ScmCreateServiceHandle(PSERVICE lpServiceEntry,
170 SC_HANDLE *Handle)
171 {
172 PSERVICE_HANDLE Ptr;
173
174 Ptr = HeapAlloc(GetProcessHeap(),
175 HEAP_ZERO_MEMORY,
176 sizeof(SERVICE_HANDLE));
177 if (Ptr == NULL)
178 return ERROR_NOT_ENOUGH_MEMORY;
179
180 Ptr->Handle.Tag = SERVICE_TAG;
181 Ptr->Handle.RefCount = 1;
182
183 /* FIXME: initialize more data here */
184 Ptr->ServiceEntry = lpServiceEntry;
185
186 *Handle = (SC_HANDLE)Ptr;
187
188 return ERROR_SUCCESS;
189 }
190
191
192 static DWORD
193 ScmCheckAccess(SC_HANDLE Handle,
194 DWORD dwDesiredAccess)
195 {
196 PMANAGER_HANDLE hMgr;
197
198 hMgr = (PMANAGER_HANDLE)Handle;
199 if (hMgr->Handle.Tag == MANAGER_TAG)
200 {
201 RtlMapGenericMask(&dwDesiredAccess,
202 &ScmManagerMapping);
203
204 hMgr->Handle.DesiredAccess = dwDesiredAccess;
205
206 return ERROR_SUCCESS;
207 }
208 else if (hMgr->Handle.Tag == SERVICE_TAG)
209 {
210 RtlMapGenericMask(&dwDesiredAccess,
211 &ScmServiceMapping);
212
213 hMgr->Handle.DesiredAccess = dwDesiredAccess;
214
215 return ERROR_SUCCESS;
216 }
217
218 return ERROR_INVALID_HANDLE;
219 }
220
221
222 /* Function 0 */
223 unsigned long
224 ScmrCloseServiceHandle(handle_t BindingHandle,
225 unsigned int hScObject)
226 {
227 PMANAGER_HANDLE hManager;
228
229 DPRINT("ScmrCloseServiceHandle() called\n");
230
231 DPRINT("hScObject = %X\n", hScObject);
232
233 if (hScObject == 0)
234 return ERROR_INVALID_HANDLE;
235
236 hManager = (PMANAGER_HANDLE)hScObject;
237 if (hManager->Handle.Tag == MANAGER_TAG)
238 {
239 DPRINT("Found manager handle\n");
240
241 hManager->Handle.RefCount--;
242 if (hManager->Handle.RefCount == 0)
243 {
244 /* FIXME: add cleanup code */
245
246 HeapFree(GetProcessHeap(), 0, hManager);
247 }
248
249 DPRINT("ScmrCloseServiceHandle() done\n");
250 return ERROR_SUCCESS;
251 }
252 else if (hManager->Handle.Tag == SERVICE_TAG)
253 {
254 DPRINT("Found service handle\n");
255
256 hManager->Handle.RefCount--;
257 if (hManager->Handle.RefCount == 0)
258 {
259 /* FIXME: add cleanup code */
260
261 HeapFree(GetProcessHeap(), 0, hManager);
262 }
263
264 DPRINT("ScmrCloseServiceHandle() done\n");
265 return ERROR_SUCCESS;
266 }
267
268 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
269
270 return ERROR_INVALID_HANDLE;
271 }
272
273
274 /* Function 1 */
275 unsigned long
276 ScmrControlService(handle_t BindingHandle,
277 unsigned int hService,
278 unsigned long dwControl,
279 LPSERVICE_STATUS lpServiceStatus)
280 {
281 PSERVICE_HANDLE hSvc;
282 PSERVICE lpService;
283
284 DPRINT1("ScmrControlService() called\n");
285
286 hSvc = (PSERVICE_HANDLE)hService;
287 if (hSvc->Handle.Tag != SERVICE_TAG)
288 {
289 DPRINT1("Invalid handle tag!\n");
290 return ERROR_INVALID_HANDLE;
291 }
292
293
294 /* FIXME: Check access rights */
295
296
297 lpService = hSvc->ServiceEntry;
298 if (lpService == NULL)
299 {
300 DPRINT1("lpService == NULL!\n");
301 return ERROR_INVALID_HANDLE;
302 }
303
304
305 /* FIXME: Send control code to the service */
306
307
308 /* Return service status information */
309 lpServiceStatus->dwServiceType = lpService->Type;
310 lpServiceStatus->dwCurrentState = lpService->CurrentState;
311 lpServiceStatus->dwControlsAccepted = lpService->ControlsAccepted;
312 lpServiceStatus->dwWin32ExitCode = lpService->Win32ExitCode;
313 lpServiceStatus->dwServiceSpecificExitCode = lpService->ServiceSpecificExitCode;
314 lpServiceStatus->dwCheckPoint = lpService->CheckPoint;
315 lpServiceStatus->dwWaitHint = lpService->WaitHint;
316
317 return ERROR_SUCCESS;
318 }
319
320
321 /* Function 2 */
322 unsigned long
323 ScmrDeleteService(handle_t BindingHandle,
324 unsigned int hService)
325 {
326 PSERVICE_HANDLE hSvc;
327 PSERVICE lpService;
328
329 DPRINT1("ScmrDeleteService() called\n");
330
331 hSvc = (PSERVICE_HANDLE)hService;
332 if (hSvc->Handle.Tag != SERVICE_TAG)
333 return ERROR_INVALID_HANDLE;
334
335 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
336 STANDARD_RIGHTS_REQUIRED))
337 return ERROR_ACCESS_DENIED;
338
339 lpService = hSvc->ServiceEntry;
340 if (lpService == NULL)
341 {
342 DPRINT1("lpService == NULL!\n");
343 return ERROR_INVALID_HANDLE;
344 }
345
346 /* FIXME: Mark service for delete */
347
348 return ERROR_SUCCESS;
349 }
350
351
352 /* Function 3 */
353 unsigned long
354 ScmrLockServiceDatabase(handle_t BindingHandle,
355 unsigned int hSCManager,
356 unsigned int *hLock)
357 {
358 PMANAGER_HANDLE hMgr;
359
360 DPRINT("ScmrLockServiceDatabase() called\n");
361
362 *hLock = 0;
363
364 hMgr = (PMANAGER_HANDLE)hSCManager;
365 if (hMgr->Handle.Tag != MANAGER_TAG)
366 return ERROR_INVALID_HANDLE;
367
368 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
369 SC_MANAGER_LOCK))
370 return ERROR_ACCESS_DENIED;
371
372 /* FIXME: Lock the database */
373 *hLock = 0x12345678; /* Dummy! */
374
375 return ERROR_SUCCESS;
376 }
377
378
379 /* Function 4 */
380 unsigned long
381 ScmrQueryServiceObjectSecurity(handle_t BindingHandle)
382 {
383 DPRINT1("ScmrQueryServiceSecurity() is unimplemented\n");
384 return ERROR_CALL_NOT_IMPLEMENTED;
385 }
386
387
388 /* Function 5 */
389 unsigned long
390 ScmrSetServiceObjectSecurity(handle_t BindingHandle)
391 {
392 DPRINT1("ScmrSetServiceSecurity() is unimplemented\n");
393 return ERROR_CALL_NOT_IMPLEMENTED;
394 }
395
396
397 /* Function 6 */
398 unsigned long
399 ScmrQueryServiceStatus(handle_t BindingHandle,
400 unsigned int hService,
401 LPSERVICE_STATUS lpServiceStatus)
402 {
403 PSERVICE_HANDLE hSvc;
404 PSERVICE lpService;
405
406 DPRINT("ScmrQueryServiceStatus() called\n");
407
408 hSvc = (PSERVICE_HANDLE)hService;
409 if (hSvc->Handle.Tag != SERVICE_TAG)
410 {
411 DPRINT1("Invalid handle tag!\n");
412 return ERROR_INVALID_HANDLE;
413 }
414
415 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
416 SERVICE_QUERY_STATUS))
417 {
418 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
419 return ERROR_ACCESS_DENIED;
420 }
421
422 lpService = hSvc->ServiceEntry;
423 if (lpService == NULL)
424 {
425 DPRINT1("lpService == NULL!\n");
426 return ERROR_INVALID_HANDLE;
427 }
428
429 /* Return service status information */
430 lpServiceStatus->dwServiceType = lpService->Type;
431 lpServiceStatus->dwCurrentState = lpService->CurrentState;
432 lpServiceStatus->dwControlsAccepted = lpService->ControlsAccepted;
433 lpServiceStatus->dwWin32ExitCode = lpService->Win32ExitCode;
434 lpServiceStatus->dwServiceSpecificExitCode = lpService->ServiceSpecificExitCode;
435 lpServiceStatus->dwCheckPoint = lpService->CheckPoint;
436 lpServiceStatus->dwWaitHint = lpService->WaitHint;
437
438 return ERROR_SUCCESS;
439 }
440
441
442 /* Function 7 */
443 unsigned long
444 ScmrSetServiceStatus(handle_t BindingHandle)
445 {
446 DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
447 /* FIXME */
448 return ERROR_CALL_NOT_IMPLEMENTED;
449 }
450
451
452 /* Function 8 */
453 unsigned long
454 ScmrUnlockServiceDatabase(handle_t BindingHandle,
455 unsigned int hLock)
456 {
457 DPRINT1("ScmrUnlockServiceDatabase() called\n");
458 /* FIXME */
459 return ERROR_SUCCESS;
460 }
461
462
463 /* Function 9 */
464 unsigned long
465 ScmrNotifyBootConfigStatus(handle_t BindingHandle,
466 unsigned long BootAcceptable)
467 {
468 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
469 /* FIXME */
470 return ERROR_SUCCESS;
471 }
472
473
474
475 /* Function 12 */
476 #if 0
477 unsigned long
478 ScmrCreateServiceW(handle_t BindingHandle,
479 unsigned int hSCManager,
480 wchar_t *lpServiceName,
481 wchar_t *lpDisplayName,
482 unsigned long dwDesiredAccess,
483 unsigned long dwServiceType,
484 unsigned long dwStartType,
485 unsigned long dwErrorControl,
486 wchar_t *lpBinaryPathName,
487 wchar_t *lpLoadOrderGroup,
488 unsigned long *lpdwTagId,
489 wchar_t *lpDependencies,
490 wchar_t *lpServiceStartName,
491 wchar_t *lpPassword)
492 {
493 DPRINT1("ScmrCreateServiceW() called\n");
494 if (lpdwTagId != NULL)
495 *lpdwTagId = 0;
496 return ERROR_SUCCESS;
497 }
498 #endif
499
500
501 /* Function 15 */
502 unsigned long
503 ScmrOpenSCManagerW(handle_t BindingHandle,
504 wchar_t *lpMachineName,
505 wchar_t *lpDatabaseName,
506 unsigned long dwDesiredAccess,
507 unsigned int *hScm)
508 {
509 DWORD dwError;
510 SC_HANDLE hHandle;
511
512 DPRINT("ScmrOpenSCManagerW() called\n");
513 DPRINT("lpMachineName = %p\n", lpMachineName);
514 DPRINT("lpMachineName: %S\n", lpMachineName);
515 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
516 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
517 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
518
519 dwError = ScmCreateManagerHandle(lpDatabaseName,
520 &hHandle);
521 if (dwError != ERROR_SUCCESS)
522 {
523 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
524 return dwError;
525 }
526
527 /* Check the desired access */
528 dwError = ScmCheckAccess(hHandle,
529 dwDesiredAccess | SC_MANAGER_CONNECT);
530 if (dwError != ERROR_SUCCESS)
531 {
532 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
533 HeapFree(GetProcessHeap(), 0, hHandle);
534 return dwError;
535 }
536
537 *hScm = (unsigned int)hHandle;
538 DPRINT("*hScm = %x\n", *hScm);
539
540 DPRINT("ScmrOpenSCManagerW() done\n");
541
542 return ERROR_SUCCESS;
543 }
544
545
546 /* Function 16 */
547 unsigned int
548 ScmrOpenServiceW(handle_t BindingHandle,
549 unsigned int hSCManager,
550 wchar_t *lpServiceName,
551 unsigned long dwDesiredAccess,
552 unsigned int *hService)
553 {
554 UNICODE_STRING ServiceName;
555 PSERVICE lpService;
556 PMANAGER_HANDLE hManager;
557 SC_HANDLE hHandle;
558 DWORD dwError;
559
560 DPRINT("ScmrOpenServiceW() called\n");
561 DPRINT("hSCManager = %x\n", hSCManager);
562 DPRINT("lpServiceName = %p\n", lpServiceName);
563 DPRINT("lpServiceName: %S\n", lpServiceName);
564 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
565
566 hManager = (PMANAGER_HANDLE)hSCManager;
567 if (hManager->Handle.Tag != MANAGER_TAG)
568 {
569 DPRINT1("Invalid manager handle!\n");
570 return ERROR_INVALID_HANDLE;
571 }
572
573 /* FIXME: Lock the service list */
574
575 /* Get service database entry */
576 RtlInitUnicodeString(&ServiceName,
577 lpServiceName);
578
579 lpService = ScmGetServiceEntryByName(&ServiceName);
580 if (lpService == NULL)
581 {
582 DPRINT1("Could not find a service!\n");
583 return ERROR_SERVICE_DOES_NOT_EXIST;
584 }
585
586 /* Create a service handle */
587 dwError = ScmCreateServiceHandle(lpService,
588 &hHandle);
589 if (dwError != ERROR_SUCCESS)
590 {
591 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
592 return dwError;
593 }
594
595 /* Check the desired access */
596 dwError = ScmCheckAccess(hHandle,
597 dwDesiredAccess);
598 if (dwError != ERROR_SUCCESS)
599 {
600 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
601 HeapFree(GetProcessHeap(), 0, hHandle);
602 return dwError;
603 }
604
605 *hService = (unsigned int)hHandle;
606 DPRINT("*hService = %x\n", *hService);
607
608 DPRINT("ScmrOpenServiceW() done\n");
609
610 return ERROR_SUCCESS;
611 }
612
613
614
615 /* Function 27 */
616 unsigned long
617 ScmrOpenSCManagerA(handle_t BindingHandle,
618 char *lpMachineName,
619 char *lpDatabaseName,
620 unsigned long dwDesiredAccess,
621 unsigned int *hScm)
622 {
623 UNICODE_STRING MachineName;
624 UNICODE_STRING DatabaseName;
625 DWORD dwError;
626
627 DPRINT("ScmrOpenSCManagerA() called\n");
628
629 if (lpMachineName)
630 RtlCreateUnicodeStringFromAsciiz(&MachineName,
631 lpMachineName);
632
633 if (lpDatabaseName)
634 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
635 lpDatabaseName);
636
637 dwError = ScmrOpenSCManagerW(BindingHandle,
638 lpMachineName ? MachineName.Buffer : NULL,
639 lpDatabaseName ? DatabaseName.Buffer : NULL,
640 dwDesiredAccess,
641 hScm);
642
643 if (lpMachineName)
644 RtlFreeUnicodeString(&MachineName);
645
646 if (lpDatabaseName)
647 RtlFreeUnicodeString(&DatabaseName);
648
649 return dwError;
650 }
651
652
653 /* Function 28 */
654 unsigned int
655 ScmrOpenServiceA(handle_t BindingHandle,
656 unsigned int hSCManager,
657 char *lpServiceName,
658 unsigned long dwDesiredAccess,
659 unsigned int *hService)
660 {
661 UNICODE_STRING ServiceName;
662 DWORD dwError;
663
664 DPRINT("ScmrOpenServiceA() called\n");
665
666 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
667 lpServiceName);
668
669 dwError = ScmrOpenServiceW(BindingHandle,
670 hSCManager,
671 ServiceName.Buffer,
672 dwDesiredAccess,
673 hService);
674
675 RtlFreeUnicodeString(&ServiceName);
676
677 return dwError;
678 }
679
680
681
682 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
683 {
684 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
685 }
686
687
688 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
689 {
690 HeapFree(GetProcessHeap(), 0, ptr);
691 }
692
693 /* EOF */