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