- Prepare to delete marked services upon startup.
[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 = RpcServerUseProtseqEpW(L"ncacn_np",
111 10,
112 L"\\pipe\\ntsvcs",
113 NULL);
114 if (Status != RPC_S_OK)
115 {
116 DPRINT1("RpcServerUseProtseqEpW() 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 ACCESS_MASK DesiredAccess;
284 DWORD dwError = ERROR_SUCCESS;
285
286 DPRINT("ScmrControlService() called\n");
287
288 if (ScmShutdown)
289 return ERROR_SHUTDOWN_IN_PROGRESS;
290
291 /* Check the service handle */
292 hSvc = (PSERVICE_HANDLE)hService;
293 if (hSvc->Handle.Tag != SERVICE_TAG)
294 {
295 DPRINT1("Invalid handle tag!\n");
296 return ERROR_INVALID_HANDLE;
297 }
298
299 /* Check access rights */
300 switch (dwControl)
301 {
302 case SERVICE_CONTROL_STOP:
303 DesiredAccess = SERVICE_STOP;
304 break;
305
306 case SERVICE_CONTROL_PAUSE:
307 case SERVICE_CONTROL_CONTINUE:
308 DesiredAccess = SERVICE_PAUSE_CONTINUE;
309 break;
310
311 case SERVICE_INTERROGATE:
312 DesiredAccess = SERVICE_INTERROGATE;
313 break;
314
315 default:
316 if (dwControl >= 128 && dwControl <= 255)
317 DesiredAccess = SERVICE_USER_DEFINED_CONTROL;
318 else
319 DesiredAccess = SERVICE_QUERY_CONFIG |
320 SERVICE_CHANGE_CONFIG |
321 SERVICE_QUERY_STATUS |
322 SERVICE_START |
323 SERVICE_PAUSE_CONTINUE;
324 break;
325 }
326
327 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
328 DesiredAccess))
329 return ERROR_ACCESS_DENIED;
330
331 /* Check the service entry point */
332 lpService = hSvc->ServiceEntry;
333 if (lpService == NULL)
334 {
335 DPRINT1("lpService == NULL!\n");
336 return ERROR_INVALID_HANDLE;
337 }
338
339 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
340 {
341 /* Send control code to the driver */
342 dwError = ScmControlDriver(lpService,
343 dwControl,
344 lpServiceStatus);
345 }
346 else
347 {
348 /* FIXME: Send control code to the service */
349 #if 0
350 dwError = ScmControlService(lpService,
351 dwControl,
352 lpServiceStatus);
353 #endif
354 dwError = ERROR_INVALID_SERVICE_CONTROL;
355 }
356
357 /* Return service status information */
358 RtlCopyMemory(lpServiceStatus,
359 &lpService->Status,
360 sizeof(SERVICE_STATUS));
361
362 return dwError;
363 }
364
365
366 /* Function 2 */
367 unsigned long
368 ScmrDeleteService(handle_t BindingHandle,
369 unsigned int hService)
370 {
371 PSERVICE_HANDLE hSvc;
372 PSERVICE lpService;
373 DWORD dwError;
374
375 DPRINT("ScmrDeleteService() called\n");
376
377 if (ScmShutdown)
378 return ERROR_SHUTDOWN_IN_PROGRESS;
379
380 hSvc = (PSERVICE_HANDLE)hService;
381 if (hSvc->Handle.Tag != SERVICE_TAG)
382 return ERROR_INVALID_HANDLE;
383
384 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
385 STANDARD_RIGHTS_REQUIRED))
386 return ERROR_ACCESS_DENIED;
387
388 lpService = hSvc->ServiceEntry;
389 if (lpService == NULL)
390 {
391 DPRINT1("lpService == NULL!\n");
392 return ERROR_INVALID_HANDLE;
393 }
394
395 /* FIXME: Acquire service database lock exclusively */
396
397 if (lpService->bDeleted)
398 {
399 DPRINT1("The service has already been marked for delete!\n");
400 return ERROR_SERVICE_MARKED_FOR_DELETE;
401 }
402
403 /* Mark service for delete */
404 lpService->bDeleted = TRUE;
405
406 dwError = ScmMarkServiceForDelete(lpService);
407
408 /* FIXME: Release service database lock */
409
410 DPRINT("ScmrDeleteService() done\n");
411
412 return dwError;
413 }
414
415
416 /* Function 3 */
417 unsigned long
418 ScmrLockServiceDatabase(handle_t BindingHandle,
419 unsigned int hSCManager,
420 unsigned int *hLock)
421 {
422 PMANAGER_HANDLE hMgr;
423
424 DPRINT("ScmrLockServiceDatabase() called\n");
425
426 *hLock = 0;
427
428 hMgr = (PMANAGER_HANDLE)hSCManager;
429 if (hMgr->Handle.Tag != MANAGER_TAG)
430 return ERROR_INVALID_HANDLE;
431
432 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
433 SC_MANAGER_LOCK))
434 return ERROR_ACCESS_DENIED;
435
436 /* FIXME: Lock the database */
437 *hLock = 0x12345678; /* Dummy! */
438
439 return ERROR_SUCCESS;
440 }
441
442
443 /* Function 4 */
444 unsigned long
445 ScmrQueryServiceObjectSecurity(handle_t BindingHandle)
446 {
447 DPRINT1("ScmrQueryServiceSecurity() is unimplemented\n");
448 return ERROR_CALL_NOT_IMPLEMENTED;
449 }
450
451
452 /* Function 5 */
453 unsigned long
454 ScmrSetServiceObjectSecurity(handle_t BindingHandle)
455 {
456 DPRINT1("ScmrSetServiceSecurity() is unimplemented\n");
457 return ERROR_CALL_NOT_IMPLEMENTED;
458 }
459
460
461 /* Function 6 */
462 unsigned long
463 ScmrQueryServiceStatus(handle_t BindingHandle,
464 unsigned int hService,
465 LPSERVICE_STATUS lpServiceStatus)
466 {
467 PSERVICE_HANDLE hSvc;
468 PSERVICE lpService;
469
470 DPRINT("ScmrQueryServiceStatus() called\n");
471
472 if (ScmShutdown)
473 return ERROR_SHUTDOWN_IN_PROGRESS;
474
475 hSvc = (PSERVICE_HANDLE)hService;
476 if (hSvc->Handle.Tag != SERVICE_TAG)
477 {
478 DPRINT1("Invalid handle tag!\n");
479 return ERROR_INVALID_HANDLE;
480 }
481
482 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
483 SERVICE_QUERY_STATUS))
484 {
485 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
486 return ERROR_ACCESS_DENIED;
487 }
488
489 lpService = hSvc->ServiceEntry;
490 if (lpService == NULL)
491 {
492 DPRINT1("lpService == NULL!\n");
493 return ERROR_INVALID_HANDLE;
494 }
495
496 /* Return service status information */
497 RtlCopyMemory(lpServiceStatus,
498 &lpService->Status,
499 sizeof(SERVICE_STATUS));
500
501 return ERROR_SUCCESS;
502 }
503
504
505 /* Function 7 */
506 unsigned long
507 ScmrSetServiceStatus(handle_t BindingHandle)
508 {
509 DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
510 /* FIXME */
511 return ERROR_CALL_NOT_IMPLEMENTED;
512 }
513
514
515 /* Function 8 */
516 unsigned long
517 ScmrUnlockServiceDatabase(handle_t BindingHandle,
518 unsigned int hLock)
519 {
520 DPRINT1("ScmrUnlockServiceDatabase() called\n");
521 /* FIXME */
522 return ERROR_SUCCESS;
523 }
524
525
526 /* Function 9 */
527 unsigned long
528 ScmrNotifyBootConfigStatus(handle_t BindingHandle,
529 unsigned long BootAcceptable)
530 {
531 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
532 /* FIXME */
533 return ERROR_SUCCESS;
534 }
535
536
537 /* Function 11 */
538 unsigned long
539 ScmrChangeServiceConfigW(handle_t BiningHandle,
540 unsigned int hService,
541 unsigned long dwServiceType,
542 unsigned long dwStartType,
543 unsigned long dwErrorControl,
544 wchar_t *lpBinaryPathName,
545 wchar_t *lpLoadOrderGroup,
546 unsigned long *lpdwTagId, /* in, out, unique */
547 wchar_t *lpDependencies,
548 unsigned long dwDependenciesLength,
549 wchar_t *lpServiceStartName,
550 wchar_t *lpPassword,
551 unsigned long dwPasswordLength,
552 wchar_t *lpDisplayName)
553 {
554 DWORD dwError = ERROR_SUCCESS;
555 PSERVICE_HANDLE hSvc;
556 PSERVICE lpService = NULL;
557 HKEY hServiceKey = NULL;
558
559 DPRINT("ScmrChangeServiceConfigW() called\n");
560 DPRINT("dwServiceType = %lu\n", dwServiceType);
561 DPRINT("dwStartType = %lu\n", dwStartType);
562 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
563 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
564 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
565 DPRINT("lpDisplayName = %S\n", lpDisplayName);
566
567 if (ScmShutdown)
568 return ERROR_SHUTDOWN_IN_PROGRESS;
569
570 hSvc = (PSERVICE_HANDLE)hService;
571 if (hSvc->Handle.Tag != SERVICE_TAG)
572 {
573 DPRINT1("Invalid handle tag!\n");
574 return ERROR_INVALID_HANDLE;
575 }
576
577 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
578 SERVICE_CHANGE_CONFIG))
579 {
580 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
581 return ERROR_ACCESS_DENIED;
582 }
583
584 lpService = hSvc->ServiceEntry;
585 if (lpService == NULL)
586 {
587 DPRINT1("lpService == NULL!\n");
588 return ERROR_INVALID_HANDLE;
589 }
590
591 /* FIXME: Lock database exclusively */
592
593 if (lpService->bDeleted)
594 {
595 /* FIXME: Unlock database */
596 DPRINT1("The service has already been marked for delete!\n");
597 return ERROR_SERVICE_MARKED_FOR_DELETE;
598 }
599
600 /* Open the service key */
601 dwError = ScmOpenServiceKey(lpService->szServiceName,
602 KEY_WRITE,
603 &hServiceKey);
604 if (dwError != ERROR_SUCCESS)
605 goto done;
606
607 /* Write service data to the registry */
608 /* Set the display name */
609 if (lpDisplayName != NULL && *lpDisplayName != 0)
610 {
611 RegSetValueExW(hServiceKey,
612 L"DisplayName",
613 0,
614 REG_SZ,
615 (LPBYTE)lpDisplayName,
616 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
617 }
618
619 if (dwServiceType != SERVICE_NO_CHANGE)
620 {
621 /* Set the service type */
622 dwError = RegSetValueExW(hServiceKey,
623 L"Type",
624 0,
625 REG_DWORD,
626 (LPBYTE)&dwServiceType,
627 sizeof(DWORD));
628 if (dwError != ERROR_SUCCESS)
629 goto done;
630 }
631
632 if (dwStartType != SERVICE_NO_CHANGE)
633 {
634 /* Set the start value */
635 dwError = RegSetValueExW(hServiceKey,
636 L"Start",
637 0,
638 REG_DWORD,
639 (LPBYTE)&dwStartType,
640 sizeof(DWORD));
641 if (dwError != ERROR_SUCCESS)
642 goto done;
643 }
644
645 if (dwErrorControl != SERVICE_NO_CHANGE)
646 {
647 /* Set the error control value */
648 dwError = RegSetValueExW(hServiceKey,
649 L"ErrorControl",
650 0,
651 REG_DWORD,
652 (LPBYTE)&dwErrorControl,
653 sizeof(DWORD));
654 if (dwError != ERROR_SUCCESS)
655 goto done;
656 }
657
658 #if 0
659 /* FIXME: set the new ImagePath value */
660
661 /* Set the image path */
662 if (dwServiceType & SERVICE_WIN32)
663 {
664 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
665 {
666 dwError = RegSetValueExW(hServiceKey,
667 L"ImagePath",
668 0,
669 REG_EXPAND_SZ,
670 (LPBYTE)lpBinaryPathName,
671 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
672 if (dwError != ERROR_SUCCESS)
673 goto done;
674 }
675 }
676 else if (dwServiceType & SERVICE_DRIVER)
677 {
678 if (lpImagePath != NULL && *lpImagePath != 0)
679 {
680 dwError = RegSetValueExW(hServiceKey,
681 L"ImagePath",
682 0,
683 REG_EXPAND_SZ,
684 (LPBYTE)lpImagePath,
685 (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
686 if (dwError != ERROR_SUCCESS)
687 goto done;
688 }
689 }
690 #endif
691
692 /* Set the group name */
693 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
694 {
695 dwError = RegSetValueExW(hServiceKey,
696 L"Group",
697 0,
698 REG_SZ,
699 (LPBYTE)lpLoadOrderGroup,
700 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
701 if (dwError != ERROR_SUCCESS)
702 goto done;
703 }
704
705 if (lpdwTagId != NULL)
706 {
707 /* FIXME: Write tag */
708 }
709
710 /* Write dependencies */
711 if (lpDependencies != NULL && *lpDependencies != 0)
712 {
713 dwError = ScmWriteDependencies(hServiceKey,
714 lpDependencies,
715 dwDependenciesLength);
716 if (dwError != ERROR_SUCCESS)
717 goto done;
718 }
719
720 if (lpPassword != NULL)
721 {
722 /* FIXME: Write password */
723 }
724
725 /* FIXME: Unlock database */
726
727 done:
728 if (hServiceKey != NULL)
729 RegCloseKey(hServiceKey);
730
731 DPRINT("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError);
732
733 return dwError;
734 }
735
736
737 /* Function 12 */
738 unsigned long
739 ScmrCreateServiceW(handle_t BindingHandle,
740 unsigned int hSCManager,
741 wchar_t *lpServiceName,
742 wchar_t *lpDisplayName,
743 unsigned long dwDesiredAccess,
744 unsigned long dwServiceType,
745 unsigned long dwStartType,
746 unsigned long dwErrorControl,
747 wchar_t *lpBinaryPathName,
748 wchar_t *lpLoadOrderGroup,
749 unsigned long *lpdwTagId, /* in, out */
750 wchar_t *lpDependencies,
751 unsigned long dwDependenciesLength,
752 wchar_t *lpServiceStartName,
753 wchar_t *lpPassword,
754 unsigned long dwPasswordLength,
755 unsigned int *hService) /* out */
756 {
757 PMANAGER_HANDLE hManager;
758 DWORD dwError = ERROR_SUCCESS;
759 PSERVICE lpService = NULL;
760 SC_HANDLE hServiceHandle = NULL;
761 LPWSTR lpImagePath = NULL;
762 HKEY hServiceKey = NULL;
763
764 DPRINT("ScmrCreateServiceW() called\n");
765 DPRINT("lpServiceName = %S\n", lpServiceName);
766 DPRINT("lpDisplayName = %S\n", lpDisplayName);
767 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
768 DPRINT("dwServiceType = %lu\n", dwServiceType);
769 DPRINT("dwStartType = %lu\n", dwStartType);
770 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
771 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
772 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
773
774 if (ScmShutdown)
775 return ERROR_SHUTDOWN_IN_PROGRESS;
776
777 hManager = (PMANAGER_HANDLE)hSCManager;
778 if (hManager->Handle.Tag != MANAGER_TAG)
779 {
780 DPRINT1("Invalid manager handle!\n");
781 return ERROR_INVALID_HANDLE;
782 }
783
784 /* Check access rights */
785 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
786 SC_MANAGER_CREATE_SERVICE))
787 {
788 DPRINT1("Insufficient access rights! 0x%lx\n",
789 hManager->Handle.DesiredAccess);
790 return ERROR_ACCESS_DENIED;
791 }
792
793 /* Fail if the service already exists! */
794 if (ScmGetServiceEntryByName(lpServiceName) != NULL)
795 return ERROR_SERVICE_EXISTS;
796
797 if (dwServiceType & SERVICE_DRIVER)
798 {
799 /* FIXME: Adjust the image path
800 * Following line is VERY BAD, because it assumes that the
801 * first part of full file name is the OS directory */
802 if (lpBinaryPathName[1] == ':') lpBinaryPathName += GetWindowsDirectoryW(NULL, 0);
803
804 lpImagePath = HeapAlloc(GetProcessHeap(),
805 HEAP_ZERO_MEMORY,
806 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
807 if (lpImagePath == NULL)
808 {
809 dwError = ERROR_NOT_ENOUGH_MEMORY;
810 goto done;
811 }
812 wcscpy(lpImagePath, lpBinaryPathName);
813 }
814
815 /* Allocate a new service entry */
816 dwError = ScmCreateNewServiceRecord(lpServiceName,
817 &lpService);
818 if (dwError != ERROR_SUCCESS)
819 goto done;
820
821 /* Fill the new service entry */
822 lpService->Status.dwServiceType = dwServiceType;
823 lpService->dwStartType = dwStartType;
824 lpService->dwErrorControl = dwErrorControl;
825
826 /* Fill the display name */
827 if (lpDisplayName != NULL &&
828 *lpDisplayName != 0 &&
829 wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
830 {
831 lpService->lpDisplayName = HeapAlloc(GetProcessHeap, 0,
832 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
833 if (lpService->lpDisplayName == NULL)
834 {
835 dwError = ERROR_NOT_ENOUGH_MEMORY;
836 goto done;
837 }
838 wcscpy(lpService->lpDisplayName, lpDisplayName);
839 }
840
841 /* Write service data to the registry */
842 /* Create the service key */
843 dwError = ScmCreateServiceKey(lpServiceName,
844 KEY_WRITE,
845 &hServiceKey);
846 if (dwError != ERROR_SUCCESS)
847 goto done;
848
849 /* Set the display name */
850 if (lpDisplayName != NULL && *lpDisplayName != 0)
851 {
852 RegSetValueExW(hServiceKey,
853 L"DisplayName",
854 0,
855 REG_SZ,
856 (LPBYTE)lpDisplayName,
857 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
858 }
859
860 /* Set the service type */
861 dwError = RegSetValueExW(hServiceKey,
862 L"Type",
863 0,
864 REG_DWORD,
865 (LPBYTE)&dwServiceType,
866 sizeof(DWORD));
867 if (dwError != ERROR_SUCCESS)
868 goto done;
869
870 /* Set the start value */
871 dwError = RegSetValueExW(hServiceKey,
872 L"Start",
873 0,
874 REG_DWORD,
875 (LPBYTE)&dwStartType,
876 sizeof(DWORD));
877 if (dwError != ERROR_SUCCESS)
878 goto done;
879
880 /* Set the error control value */
881 dwError = RegSetValueExW(hServiceKey,
882 L"ErrorControl",
883 0,
884 REG_DWORD,
885 (LPBYTE)&dwErrorControl,
886 sizeof(DWORD));
887 if (dwError != ERROR_SUCCESS)
888 goto done;
889
890 /* Set the image path */
891 if (dwServiceType & SERVICE_WIN32)
892 {
893 dwError = RegSetValueExW(hServiceKey,
894 L"ImagePath",
895 0,
896 REG_EXPAND_SZ,
897 (LPBYTE)lpBinaryPathName,
898 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
899 if (dwError != ERROR_SUCCESS)
900 goto done;
901 }
902 else if (dwServiceType & SERVICE_DRIVER)
903 {
904 dwError = RegSetValueExW(hServiceKey,
905 L"ImagePath",
906 0,
907 REG_EXPAND_SZ,
908 (LPBYTE)lpImagePath,
909 (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
910 if (dwError != ERROR_SUCCESS)
911 goto done;
912 }
913
914 /* Set the group name */
915 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
916 {
917 dwError = RegSetValueExW(hServiceKey,
918 L"Group",
919 0,
920 REG_SZ,
921 (LPBYTE)lpLoadOrderGroup,
922 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
923 if (dwError != ERROR_SUCCESS)
924 goto done;
925 }
926
927 if (lpdwTagId != NULL)
928 {
929 /* FIXME: Write tag */
930 }
931
932 /* Write dependencies */
933 if (lpDependencies != NULL && *lpDependencies != 0)
934 {
935 dwError = ScmWriteDependencies(hServiceKey,
936 lpDependencies,
937 dwDependenciesLength);
938 if (dwError != ERROR_SUCCESS)
939 goto done;
940 }
941
942 if (lpPassword != NULL)
943 {
944 /* FIXME: Write password */
945 }
946
947 dwError = ScmCreateServiceHandle(lpService,
948 &hServiceHandle);
949 if (dwError != ERROR_SUCCESS)
950 goto done;
951
952 dwError = ScmCheckAccess(hServiceHandle,
953 dwDesiredAccess);
954 if (dwError != ERROR_SUCCESS)
955 goto done;
956
957 done:;
958 if (hServiceKey != NULL)
959 RegCloseKey(hServiceKey);
960
961 if (dwError == ERROR_SUCCESS)
962 {
963 DPRINT("hService %lx\n", hServiceHandle);
964 *hService = (unsigned int)hServiceHandle;
965
966 if (lpdwTagId != NULL)
967 *lpdwTagId = 0; /* FIXME */
968 }
969 else
970 {
971 /* Release the display name buffer */
972 if (lpService->lpServiceName != lpService->lpDisplayName)
973 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
974
975 if (hServiceHandle != NULL)
976 {
977 /* Remove the service handle */
978 HeapFree(GetProcessHeap(), 0, hServiceHandle);
979 }
980
981 if (lpService != NULL)
982 {
983 /* FIXME: remove the service entry */
984 }
985 }
986
987 if (lpImagePath != NULL)
988 HeapFree(GetProcessHeap(), 0, lpImagePath);
989
990 DPRINT("ScmrCreateServiceW() done (Error %lu)\n", dwError);
991
992 return dwError;
993 }
994
995
996 /* Function 15 */
997 unsigned long
998 ScmrOpenSCManagerW(handle_t BindingHandle,
999 wchar_t *lpMachineName,
1000 wchar_t *lpDatabaseName,
1001 unsigned long dwDesiredAccess,
1002 unsigned int *hScm)
1003 {
1004 DWORD dwError;
1005 SC_HANDLE hHandle;
1006
1007 DPRINT("ScmrOpenSCManagerW() called\n");
1008 DPRINT("lpMachineName = %p\n", lpMachineName);
1009 DPRINT("lpMachineName: %S\n", lpMachineName);
1010 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
1011 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
1012 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1013
1014 if (ScmShutdown)
1015 return ERROR_SHUTDOWN_IN_PROGRESS;
1016
1017 dwError = ScmCreateManagerHandle(lpDatabaseName,
1018 &hHandle);
1019 if (dwError != ERROR_SUCCESS)
1020 {
1021 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
1022 return dwError;
1023 }
1024
1025 /* Check the desired access */
1026 dwError = ScmCheckAccess(hHandle,
1027 dwDesiredAccess | SC_MANAGER_CONNECT);
1028 if (dwError != ERROR_SUCCESS)
1029 {
1030 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1031 HeapFree(GetProcessHeap(), 0, hHandle);
1032 return dwError;
1033 }
1034
1035 *hScm = (unsigned int)hHandle;
1036 DPRINT("*hScm = %x\n", *hScm);
1037
1038 DPRINT("ScmrOpenSCManagerW() done\n");
1039
1040 return ERROR_SUCCESS;
1041 }
1042
1043
1044 /* Function 16 */
1045 unsigned int
1046 ScmrOpenServiceW(handle_t BindingHandle,
1047 unsigned int hSCManager,
1048 wchar_t *lpServiceName,
1049 unsigned long dwDesiredAccess,
1050 unsigned int *hService)
1051 {
1052 PSERVICE lpService;
1053 PMANAGER_HANDLE hManager;
1054 SC_HANDLE hHandle;
1055 DWORD dwError;
1056
1057 DPRINT("ScmrOpenServiceW() called\n");
1058 DPRINT("hSCManager = %x\n", hSCManager);
1059 DPRINT("lpServiceName = %p\n", lpServiceName);
1060 DPRINT("lpServiceName: %S\n", lpServiceName);
1061 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1062
1063 if (ScmShutdown)
1064 return ERROR_SHUTDOWN_IN_PROGRESS;
1065
1066 hManager = (PMANAGER_HANDLE)hSCManager;
1067 if (hManager->Handle.Tag != MANAGER_TAG)
1068 {
1069 DPRINT1("Invalid manager handle!\n");
1070 return ERROR_INVALID_HANDLE;
1071 }
1072
1073 /* FIXME: Lock the service list */
1074
1075 /* Get service database entry */
1076 lpService = ScmGetServiceEntryByName(lpServiceName);
1077 if (lpService == NULL)
1078 {
1079 DPRINT("Could not find a service!\n");
1080 return ERROR_SERVICE_DOES_NOT_EXIST;
1081 }
1082
1083 /* Create a service handle */
1084 dwError = ScmCreateServiceHandle(lpService,
1085 &hHandle);
1086 if (dwError != ERROR_SUCCESS)
1087 {
1088 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
1089 return dwError;
1090 }
1091
1092 /* Check the desired access */
1093 dwError = ScmCheckAccess(hHandle,
1094 dwDesiredAccess);
1095 if (dwError != ERROR_SUCCESS)
1096 {
1097 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1098 HeapFree(GetProcessHeap(), 0, hHandle);
1099 return dwError;
1100 }
1101
1102 *hService = (unsigned int)hHandle;
1103 DPRINT("*hService = %x\n", *hService);
1104
1105 DPRINT("ScmrOpenServiceW() done\n");
1106
1107 return ERROR_SUCCESS;
1108 }
1109
1110
1111 /* Function 20 */
1112 unsigned long
1113 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
1114 unsigned int hSCManager,
1115 wchar_t *lpServiceName,
1116 wchar_t *lpDisplayName, /* [out, unique] */
1117 unsigned long *lpcchBuffer)
1118 {
1119 // PMANAGER_HANDLE hManager;
1120 PSERVICE lpService;
1121 DWORD dwLength;
1122 DWORD dwError;
1123
1124 DPRINT1("ScmrGetServiceDisplayNameW() called\n");
1125 DPRINT1("hSCManager = %x\n", hSCManager);
1126 DPRINT1("lpServiceName: %S\n", lpServiceName);
1127 DPRINT1("lpDisplayName: %p\n", lpDisplayName);
1128 DPRINT1("*lpcchBuffer: %lu\n", *lpcchBuffer);
1129
1130 // hManager = (PMANAGER_HANDLE)hSCManager;
1131 // if (hManager->Handle.Tag != MANAGER_TAG)
1132 // {
1133 // DPRINT1("Invalid manager handle!\n");
1134 // return ERROR_INVALID_HANDLE;
1135 // }
1136
1137 /* Get service database entry */
1138 lpService = ScmGetServiceEntryByName(lpServiceName);
1139 if (lpService == NULL)
1140 {
1141 DPRINT1("Could not find a service!\n");
1142 return ERROR_SERVICE_DOES_NOT_EXIST;
1143 }
1144
1145 dwLength = wcslen(lpService->lpDisplayName) + 1;
1146
1147 if (lpDisplayName != NULL &&
1148 *lpcchBuffer >= dwLength)
1149 {
1150 wcscpy(lpDisplayName, lpService->lpDisplayName);
1151 }
1152
1153 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1154
1155 *lpcchBuffer = dwLength;
1156
1157 return dwError;
1158 }
1159
1160
1161 /* Function 21 */
1162 unsigned long
1163 ScmrGetServiceKeyNameW(handle_t BindingHandle,
1164 unsigned int hSCManager,
1165 wchar_t *lpDisplayName,
1166 wchar_t *lpServiceName, /* [out, unique] */
1167 unsigned long *lpcchBuffer)
1168 {
1169 // PMANAGER_HANDLE hManager;
1170 PSERVICE lpService;
1171 DWORD dwLength;
1172 DWORD dwError;
1173
1174 DPRINT1("ScmrGetServiceKeyNameW() called\n");
1175 DPRINT1("hSCManager = %x\n", hSCManager);
1176 DPRINT1("lpDisplayName: %S\n", lpDisplayName);
1177 DPRINT1("lpServiceName: %p\n", lpServiceName);
1178 DPRINT1("*lpcchBuffer: %lu\n", *lpcchBuffer);
1179
1180 // hManager = (PMANAGER_HANDLE)hSCManager;
1181 // if (hManager->Handle.Tag != MANAGER_TAG)
1182 // {
1183 // DPRINT1("Invalid manager handle!\n");
1184 // return ERROR_INVALID_HANDLE;
1185 // }
1186
1187 /* Get service database entry */
1188 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
1189 if (lpService == NULL)
1190 {
1191 DPRINT1("Could not find a service!\n");
1192 return ERROR_SERVICE_DOES_NOT_EXIST;
1193 }
1194
1195 dwLength = wcslen(lpService->lpServiceName) + 1;
1196
1197 if (lpServiceName != NULL &&
1198 *lpcchBuffer >= dwLength)
1199 {
1200 wcscpy(lpServiceName, lpService->lpServiceName);
1201 }
1202
1203 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1204
1205 *lpcchBuffer = dwLength;
1206
1207 return dwError;
1208 }
1209
1210
1211 /* Function 27 */
1212 unsigned long
1213 ScmrOpenSCManagerA(handle_t BindingHandle,
1214 char *lpMachineName,
1215 char *lpDatabaseName,
1216 unsigned long dwDesiredAccess,
1217 unsigned int *hScm)
1218 {
1219 UNICODE_STRING MachineName;
1220 UNICODE_STRING DatabaseName;
1221 DWORD dwError;
1222
1223 DPRINT("ScmrOpenSCManagerA() called\n");
1224
1225 if (lpMachineName)
1226 RtlCreateUnicodeStringFromAsciiz(&MachineName,
1227 lpMachineName);
1228
1229 if (lpDatabaseName)
1230 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
1231 lpDatabaseName);
1232
1233 dwError = ScmrOpenSCManagerW(BindingHandle,
1234 lpMachineName ? MachineName.Buffer : NULL,
1235 lpDatabaseName ? DatabaseName.Buffer : NULL,
1236 dwDesiredAccess,
1237 hScm);
1238
1239 if (lpMachineName)
1240 RtlFreeUnicodeString(&MachineName);
1241
1242 if (lpDatabaseName)
1243 RtlFreeUnicodeString(&DatabaseName);
1244
1245 return dwError;
1246 }
1247
1248
1249 /* Function 28 */
1250 unsigned int
1251 ScmrOpenServiceA(handle_t BindingHandle,
1252 unsigned int hSCManager,
1253 char *lpServiceName,
1254 unsigned long dwDesiredAccess,
1255 unsigned int *hService)
1256 {
1257 UNICODE_STRING ServiceName;
1258 DWORD dwError;
1259
1260 DPRINT("ScmrOpenServiceA() called\n");
1261
1262 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
1263 lpServiceName);
1264
1265 dwError = ScmrOpenServiceW(BindingHandle,
1266 hSCManager,
1267 ServiceName.Buffer,
1268 dwDesiredAccess,
1269 hService);
1270
1271 RtlFreeUnicodeString(&ServiceName);
1272
1273 return dwError;
1274 }
1275
1276
1277
1278 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
1279 {
1280 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
1281 }
1282
1283
1284 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
1285 {
1286 HeapFree(GetProcessHeap(), 0, ptr);
1287 }
1288
1289 /* EOF */