8198709becb34b9c42131c0bb097849d9e668aa1
[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 DWORD
223 ScmAssignNewTag(LPWSTR lpServiceGroup,
224 LPDWORD lpdwTagId)
225 {
226 /* FIXME */
227 DPRINT("Assigning new tag in group %S\n", lpServiceGroup);
228 *lpdwTagId = 0;
229 return ERROR_SUCCESS;
230 }
231
232
233 /* Function 0 */
234 unsigned long
235 ScmrCloseServiceHandle(handle_t BindingHandle,
236 unsigned int hScObject)
237 {
238 PMANAGER_HANDLE hManager;
239
240 DPRINT("ScmrCloseServiceHandle() called\n");
241
242 DPRINT("hScObject = %X\n", hScObject);
243
244 if (hScObject == 0)
245 return ERROR_INVALID_HANDLE;
246
247 hManager = (PMANAGER_HANDLE)hScObject;
248 if (hManager->Handle.Tag == MANAGER_TAG)
249 {
250 DPRINT("Found manager handle\n");
251
252 hManager->Handle.RefCount--;
253 if (hManager->Handle.RefCount == 0)
254 {
255 /* FIXME: add cleanup code */
256
257 HeapFree(GetProcessHeap(), 0, hManager);
258 }
259
260 DPRINT("ScmrCloseServiceHandle() done\n");
261 return ERROR_SUCCESS;
262 }
263 else if (hManager->Handle.Tag == SERVICE_TAG)
264 {
265 DPRINT("Found service handle\n");
266
267 hManager->Handle.RefCount--;
268 if (hManager->Handle.RefCount == 0)
269 {
270 /* FIXME: add cleanup code */
271
272 HeapFree(GetProcessHeap(), 0, hManager);
273 }
274
275 DPRINT("ScmrCloseServiceHandle() done\n");
276 return ERROR_SUCCESS;
277 }
278
279 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
280
281 return ERROR_INVALID_HANDLE;
282 }
283
284
285 /* Function 1 */
286 unsigned long
287 ScmrControlService(handle_t BindingHandle,
288 unsigned int hService,
289 unsigned long dwControl,
290 LPSERVICE_STATUS lpServiceStatus)
291 {
292 PSERVICE_HANDLE hSvc;
293 PSERVICE lpService;
294 ACCESS_MASK DesiredAccess;
295 DWORD dwError = ERROR_SUCCESS;
296
297 DPRINT("ScmrControlService() called\n");
298
299 if (ScmShutdown)
300 return ERROR_SHUTDOWN_IN_PROGRESS;
301
302 /* Check the service handle */
303 hSvc = (PSERVICE_HANDLE)hService;
304 if (hSvc->Handle.Tag != SERVICE_TAG)
305 {
306 DPRINT1("Invalid handle tag!\n");
307 return ERROR_INVALID_HANDLE;
308 }
309
310 /* Check access rights */
311 switch (dwControl)
312 {
313 case SERVICE_CONTROL_STOP:
314 DesiredAccess = SERVICE_STOP;
315 break;
316
317 case SERVICE_CONTROL_PAUSE:
318 case SERVICE_CONTROL_CONTINUE:
319 DesiredAccess = SERVICE_PAUSE_CONTINUE;
320 break;
321
322 case SERVICE_INTERROGATE:
323 DesiredAccess = SERVICE_INTERROGATE;
324 break;
325
326 default:
327 if (dwControl >= 128 && dwControl <= 255)
328 DesiredAccess = SERVICE_USER_DEFINED_CONTROL;
329 else
330 DesiredAccess = SERVICE_QUERY_CONFIG |
331 SERVICE_CHANGE_CONFIG |
332 SERVICE_QUERY_STATUS |
333 SERVICE_START |
334 SERVICE_PAUSE_CONTINUE;
335 break;
336 }
337
338 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
339 DesiredAccess))
340 return ERROR_ACCESS_DENIED;
341
342 /* Check the service entry point */
343 lpService = hSvc->ServiceEntry;
344 if (lpService == NULL)
345 {
346 DPRINT1("lpService == NULL!\n");
347 return ERROR_INVALID_HANDLE;
348 }
349
350 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
351 {
352 /* Send control code to the driver */
353 dwError = ScmControlDriver(lpService,
354 dwControl,
355 lpServiceStatus);
356 }
357 else
358 {
359 /* FIXME: Send control code to the service */
360 #if 0
361 dwError = ScmControlService(lpService,
362 dwControl,
363 lpServiceStatus);
364 #endif
365 dwError = ERROR_INVALID_SERVICE_CONTROL;
366 }
367
368 /* Return service status information */
369 RtlCopyMemory(lpServiceStatus,
370 &lpService->Status,
371 sizeof(SERVICE_STATUS));
372
373 return dwError;
374 }
375
376
377 /* Function 2 */
378 unsigned long
379 ScmrDeleteService(handle_t BindingHandle,
380 unsigned int hService)
381 {
382 PSERVICE_HANDLE hSvc;
383 PSERVICE lpService;
384 DWORD dwError;
385
386 DPRINT("ScmrDeleteService() called\n");
387
388 if (ScmShutdown)
389 return ERROR_SHUTDOWN_IN_PROGRESS;
390
391 hSvc = (PSERVICE_HANDLE)hService;
392 if (hSvc->Handle.Tag != SERVICE_TAG)
393 return ERROR_INVALID_HANDLE;
394
395 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
396 STANDARD_RIGHTS_REQUIRED))
397 return ERROR_ACCESS_DENIED;
398
399 lpService = hSvc->ServiceEntry;
400 if (lpService == NULL)
401 {
402 DPRINT1("lpService == NULL!\n");
403 return ERROR_INVALID_HANDLE;
404 }
405
406 /* FIXME: Acquire service database lock exclusively */
407
408 if (lpService->bDeleted)
409 {
410 DPRINT1("The service has already been marked for delete!\n");
411 return ERROR_SERVICE_MARKED_FOR_DELETE;
412 }
413
414 /* Mark service for delete */
415 lpService->bDeleted = TRUE;
416
417 dwError = ScmMarkServiceForDelete(lpService);
418
419 /* FIXME: Release service database lock */
420
421 DPRINT("ScmrDeleteService() done\n");
422
423 return dwError;
424 }
425
426
427 /* Function 3 */
428 unsigned long
429 ScmrLockServiceDatabase(handle_t BindingHandle,
430 unsigned int hSCManager,
431 unsigned int *hLock)
432 {
433 PMANAGER_HANDLE hMgr;
434
435 DPRINT("ScmrLockServiceDatabase() called\n");
436
437 *hLock = 0;
438
439 hMgr = (PMANAGER_HANDLE)hSCManager;
440 if (hMgr->Handle.Tag != MANAGER_TAG)
441 return ERROR_INVALID_HANDLE;
442
443 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
444 SC_MANAGER_LOCK))
445 return ERROR_ACCESS_DENIED;
446
447 /* FIXME: Lock the database */
448 *hLock = 0x12345678; /* Dummy! */
449
450 return ERROR_SUCCESS;
451 }
452
453
454 /* Function 4 */
455 unsigned long
456 ScmrQueryServiceObjectSecurity(handle_t BindingHandle,
457 unsigned int hService,
458 unsigned long dwSecurityInformation,
459 unsigned char *lpSecurityDescriptor,
460 unsigned long dwSecuityDescriptorSize,
461 unsigned long *pcbBytesNeeded)
462 {
463 PSERVICE_HANDLE hSvc;
464 PSERVICE lpService;
465 ULONG DesiredAccess = 0;
466 NTSTATUS Status;
467 DWORD dwBytesNeeded;
468 DWORD dwError;
469
470 DPRINT("ScmrQueryServiceSecurity() called\n");
471
472 hSvc = (PSERVICE_HANDLE)hService;
473 if (hSvc->Handle.Tag != SERVICE_TAG)
474 {
475 DPRINT1("Invalid handle tag!\n");
476 return ERROR_INVALID_HANDLE;
477 }
478
479 if (dwSecurityInformation & (DACL_SECURITY_INFORMATION ||
480 GROUP_SECURITY_INFORMATION ||
481 OWNER_SECURITY_INFORMATION))
482 DesiredAccess |= READ_CONTROL;
483
484 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
485 DesiredAccess |= ACCESS_SYSTEM_SECURITY;
486
487 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
488 DesiredAccess))
489 {
490 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
491 return ERROR_ACCESS_DENIED;
492 }
493
494 lpService = hSvc->ServiceEntry;
495 if (lpService == NULL)
496 {
497 DPRINT1("lpService == NULL!\n");
498 return ERROR_INVALID_HANDLE;
499 }
500
501 /* FIXME: Lock the service list */
502
503 Status = RtlQuerySecurityObject(lpService->lpSecurityDescriptor,
504 dwSecurityInformation,
505 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
506 dwSecuityDescriptorSize,
507 &dwBytesNeeded);
508
509 /* FIXME: Unlock the service list */
510
511 if (NT_SUCCESS(Status))
512 {
513 *pcbBytesNeeded = dwBytesNeeded;
514 dwError = STATUS_SUCCESS;
515 }
516 else if (Status == STATUS_BUFFER_TOO_SMALL)
517 {
518 *pcbBytesNeeded = dwBytesNeeded;
519 dwError = ERROR_INSUFFICIENT_BUFFER;
520 }
521 else if (Status == STATUS_BAD_DESCRIPTOR_FORMAT)
522 {
523 dwError = ERROR_GEN_FAILURE;
524 }
525 else
526 {
527 dwError = RtlNtStatusToDosError(Status);
528 }
529
530 return dwError;
531 }
532
533
534 /* Function 5 */
535 unsigned long
536 ScmrSetServiceObjectSecurity(handle_t BindingHandle,
537 unsigned int hService,
538 unsigned long dwSecurityInformation,
539 unsigned char *lpSecurityDescriptor,
540 unsigned long dwSecuityDescriptorSize)
541 {
542 DPRINT1("ScmrSetServiceSecurity() is unimplemented\n");
543 return ERROR_CALL_NOT_IMPLEMENTED;
544 }
545
546
547 /* Function 6 */
548 unsigned long
549 ScmrQueryServiceStatus(handle_t BindingHandle,
550 unsigned int hService,
551 LPSERVICE_STATUS lpServiceStatus)
552 {
553 PSERVICE_HANDLE hSvc;
554 PSERVICE lpService;
555
556 DPRINT("ScmrQueryServiceStatus() called\n");
557
558 if (ScmShutdown)
559 return ERROR_SHUTDOWN_IN_PROGRESS;
560
561 hSvc = (PSERVICE_HANDLE)hService;
562 if (hSvc->Handle.Tag != SERVICE_TAG)
563 {
564 DPRINT1("Invalid handle tag!\n");
565 return ERROR_INVALID_HANDLE;
566 }
567
568 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
569 SERVICE_QUERY_STATUS))
570 {
571 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
572 return ERROR_ACCESS_DENIED;
573 }
574
575 lpService = hSvc->ServiceEntry;
576 if (lpService == NULL)
577 {
578 DPRINT1("lpService == NULL!\n");
579 return ERROR_INVALID_HANDLE;
580 }
581
582 /* Return service status information */
583 RtlCopyMemory(lpServiceStatus,
584 &lpService->Status,
585 sizeof(SERVICE_STATUS));
586
587 return ERROR_SUCCESS;
588 }
589
590
591 /* Function 7 */
592 unsigned long
593 ScmrSetServiceStatus(handle_t BindingHandle,
594 unsigned long hServiceStatus) /* FIXME */
595 {
596 DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
597 /* FIXME */
598 return ERROR_CALL_NOT_IMPLEMENTED;
599 }
600
601
602 /* Function 8 */
603 unsigned long
604 ScmrUnlockServiceDatabase(handle_t BindingHandle,
605 unsigned int hLock)
606 {
607 DPRINT1("ScmrUnlockServiceDatabase() called\n");
608 /* FIXME */
609 return ERROR_SUCCESS;
610 }
611
612
613 /* Function 9 */
614 unsigned long
615 ScmrNotifyBootConfigStatus(handle_t BindingHandle,
616 unsigned long BootAcceptable)
617 {
618 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
619 /* FIXME */
620 return ERROR_SUCCESS;
621 }
622
623
624 /* Function 10 */
625 unsigned long
626 ScmrI_ScSetServiceBitsW(handle_t BindingHandle,
627 unsigned long hServiceStatus,
628 unsigned long dwServiceBits,
629 unsigned long bSetBitsOn,
630 unsigned long bUpdateImmediately,
631 wchar_t *lpString)
632 {
633 DPRINT1("ScmrI_ScSetServiceBitsW() called\n");
634 /* FIXME */
635 return ERROR_SUCCESS;
636 }
637
638
639 /* Function 11 */
640 unsigned long
641 ScmrChangeServiceConfigW(handle_t BiningHandle,
642 unsigned int hService,
643 unsigned long dwServiceType,
644 unsigned long dwStartType,
645 unsigned long dwErrorControl,
646 wchar_t *lpBinaryPathName,
647 wchar_t *lpLoadOrderGroup,
648 unsigned long *lpdwTagId, /* in, out, unique */
649 wchar_t *lpDependencies,
650 unsigned long dwDependenciesLength,
651 wchar_t *lpServiceStartName,
652 wchar_t *lpPassword,
653 unsigned long dwPasswordLength,
654 wchar_t *lpDisplayName)
655 {
656 DWORD dwError = ERROR_SUCCESS;
657 PSERVICE_HANDLE hSvc;
658 PSERVICE lpService = NULL;
659 HKEY hServiceKey = NULL;
660
661 DPRINT("ScmrChangeServiceConfigW() called\n");
662 DPRINT("dwServiceType = %lu\n", dwServiceType);
663 DPRINT("dwStartType = %lu\n", dwStartType);
664 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
665 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
666 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
667 DPRINT("lpDisplayName = %S\n", lpDisplayName);
668
669 if (ScmShutdown)
670 return ERROR_SHUTDOWN_IN_PROGRESS;
671
672 hSvc = (PSERVICE_HANDLE)hService;
673 if (hSvc->Handle.Tag != SERVICE_TAG)
674 {
675 DPRINT1("Invalid handle tag!\n");
676 return ERROR_INVALID_HANDLE;
677 }
678
679 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
680 SERVICE_CHANGE_CONFIG))
681 {
682 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
683 return ERROR_ACCESS_DENIED;
684 }
685
686 lpService = hSvc->ServiceEntry;
687 if (lpService == NULL)
688 {
689 DPRINT1("lpService == NULL!\n");
690 return ERROR_INVALID_HANDLE;
691 }
692
693 /* FIXME: Lock database exclusively */
694
695 if (lpService->bDeleted)
696 {
697 /* FIXME: Unlock database */
698 DPRINT1("The service has already been marked for delete!\n");
699 return ERROR_SERVICE_MARKED_FOR_DELETE;
700 }
701
702 /* Open the service key */
703 dwError = ScmOpenServiceKey(lpService->szServiceName,
704 KEY_SET_VALUE,
705 &hServiceKey);
706 if (dwError != ERROR_SUCCESS)
707 goto done;
708
709 /* Write service data to the registry */
710 /* Set the display name */
711 if (lpDisplayName != NULL && *lpDisplayName != 0)
712 {
713 RegSetValueExW(hServiceKey,
714 L"DisplayName",
715 0,
716 REG_SZ,
717 (LPBYTE)lpDisplayName,
718 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
719 /* FIXME: update lpService->lpDisplayName */
720 }
721
722 if (dwServiceType != SERVICE_NO_CHANGE)
723 {
724 /* Set the service type */
725 dwError = RegSetValueExW(hServiceKey,
726 L"Type",
727 0,
728 REG_DWORD,
729 (LPBYTE)&dwServiceType,
730 sizeof(DWORD));
731 if (dwError != ERROR_SUCCESS)
732 goto done;
733
734 lpService->Status.dwServiceType = dwServiceType;
735 }
736
737 if (dwStartType != SERVICE_NO_CHANGE)
738 {
739 /* Set the start value */
740 dwError = RegSetValueExW(hServiceKey,
741 L"Start",
742 0,
743 REG_DWORD,
744 (LPBYTE)&dwStartType,
745 sizeof(DWORD));
746 if (dwError != ERROR_SUCCESS)
747 goto done;
748
749 lpService->dwStartType = dwStartType;
750 }
751
752 if (dwErrorControl != SERVICE_NO_CHANGE)
753 {
754 /* Set the error control value */
755 dwError = RegSetValueExW(hServiceKey,
756 L"ErrorControl",
757 0,
758 REG_DWORD,
759 (LPBYTE)&dwErrorControl,
760 sizeof(DWORD));
761 if (dwError != ERROR_SUCCESS)
762 goto done;
763
764 lpService->dwErrorControl = dwErrorControl;
765 }
766
767 #if 0
768 /* FIXME: set the new ImagePath value */
769
770 /* Set the image path */
771 if (dwServiceType & SERVICE_WIN32)
772 {
773 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
774 {
775 dwError = RegSetValueExW(hServiceKey,
776 L"ImagePath",
777 0,
778 REG_EXPAND_SZ,
779 (LPBYTE)lpBinaryPathName,
780 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
781 if (dwError != ERROR_SUCCESS)
782 goto done;
783 }
784 }
785 else if (dwServiceType & SERVICE_DRIVER)
786 {
787 if (lpImagePath != NULL && *lpImagePath != 0)
788 {
789 dwError = RegSetValueExW(hServiceKey,
790 L"ImagePath",
791 0,
792 REG_EXPAND_SZ,
793 (LPBYTE)lpImagePath,
794 (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
795 if (dwError != ERROR_SUCCESS)
796 goto done;
797 }
798 }
799 #endif
800
801 /* Set the group name */
802 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
803 {
804 dwError = RegSetValueExW(hServiceKey,
805 L"Group",
806 0,
807 REG_SZ,
808 (LPBYTE)lpLoadOrderGroup,
809 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
810 if (dwError != ERROR_SUCCESS)
811 goto done;
812 /* FIXME: update lpService->lpServiceGroup */
813 }
814
815 if (lpdwTagId != NULL)
816 {
817 dwError = ScmAssignNewTag(lpService->lpServiceGroup,
818 &lpService->dwTag);
819 if (dwError != ERROR_SUCCESS)
820 goto done;
821 dwError = RegSetValueExW(hServiceKey,
822 L"Tag",
823 0,
824 REG_DWORD,
825 (LPBYTE)&lpService->dwTag,
826 sizeof(DWORD));
827 if (dwError != ERROR_SUCCESS)
828 goto done;
829 *lpdwTagId = lpService->dwTag;
830 }
831
832 /* Write dependencies */
833 if (lpDependencies != NULL && *lpDependencies != 0)
834 {
835 dwError = ScmWriteDependencies(hServiceKey,
836 lpDependencies,
837 dwDependenciesLength);
838 if (dwError != ERROR_SUCCESS)
839 goto done;
840 }
841
842 if (lpPassword != NULL)
843 {
844 /* FIXME: Write password */
845 }
846
847 /* FIXME: Unlock database */
848
849 done:
850 if (hServiceKey != NULL)
851 RegCloseKey(hServiceKey);
852
853 DPRINT("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError);
854
855 return dwError;
856 }
857
858
859 /* Function 12 */
860 unsigned long
861 ScmrCreateServiceW(handle_t BindingHandle,
862 unsigned int hSCManager,
863 wchar_t *lpServiceName,
864 wchar_t *lpDisplayName,
865 unsigned long dwDesiredAccess,
866 unsigned long dwServiceType,
867 unsigned long dwStartType,
868 unsigned long dwErrorControl,
869 wchar_t *lpBinaryPathName,
870 wchar_t *lpLoadOrderGroup,
871 unsigned long *lpdwTagId, /* in, out */
872 wchar_t *lpDependencies,
873 unsigned long dwDependenciesLength,
874 wchar_t *lpServiceStartName,
875 wchar_t *lpPassword,
876 unsigned long dwPasswordLength,
877 unsigned int *hService) /* out */
878 {
879 PMANAGER_HANDLE hManager;
880 DWORD dwError = ERROR_SUCCESS;
881 PSERVICE lpService = NULL;
882 SC_HANDLE hServiceHandle = NULL;
883 LPWSTR lpImagePath = NULL;
884 HKEY hServiceKey = NULL;
885
886 DPRINT("ScmrCreateServiceW() called\n");
887 DPRINT("lpServiceName = %S\n", lpServiceName);
888 DPRINT("lpDisplayName = %S\n", lpDisplayName);
889 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
890 DPRINT("dwServiceType = %lu\n", dwServiceType);
891 DPRINT("dwStartType = %lu\n", dwStartType);
892 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
893 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
894 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
895
896 if (ScmShutdown)
897 return ERROR_SHUTDOWN_IN_PROGRESS;
898
899 hManager = (PMANAGER_HANDLE)hSCManager;
900 if (hManager->Handle.Tag != MANAGER_TAG)
901 {
902 DPRINT1("Invalid manager handle!\n");
903 return ERROR_INVALID_HANDLE;
904 }
905
906 /* Check access rights */
907 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
908 SC_MANAGER_CREATE_SERVICE))
909 {
910 DPRINT1("Insufficient access rights! 0x%lx\n",
911 hManager->Handle.DesiredAccess);
912 return ERROR_ACCESS_DENIED;
913 }
914
915 /* Fail if the service already exists! */
916 if (ScmGetServiceEntryByName(lpServiceName) != NULL)
917 return ERROR_SERVICE_EXISTS;
918
919 if (dwServiceType & SERVICE_DRIVER)
920 {
921 /* FIXME: Adjust the image path
922 * Following line is VERY BAD, because it assumes that the
923 * first part of full file name is the OS directory */
924 if (lpBinaryPathName[1] == ':') lpBinaryPathName += GetWindowsDirectoryW(NULL, 0);
925
926 lpImagePath = HeapAlloc(GetProcessHeap(),
927 HEAP_ZERO_MEMORY,
928 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
929 if (lpImagePath == NULL)
930 {
931 dwError = ERROR_NOT_ENOUGH_MEMORY;
932 goto done;
933 }
934 wcscpy(lpImagePath, lpBinaryPathName);
935 }
936
937 /* Allocate a new service entry */
938 dwError = ScmCreateNewServiceRecord(lpServiceName,
939 &lpService);
940 if (dwError != ERROR_SUCCESS)
941 goto done;
942
943 /* Fill the new service entry */
944 lpService->Status.dwServiceType = dwServiceType;
945 lpService->dwStartType = dwStartType;
946 lpService->dwErrorControl = dwErrorControl;
947
948 /* Fill the display name */
949 if (lpDisplayName != NULL &&
950 *lpDisplayName != 0 &&
951 wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
952 {
953 lpService->lpDisplayName = HeapAlloc(GetProcessHeap(), 0,
954 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
955 if (lpService->lpDisplayName == NULL)
956 {
957 dwError = ERROR_NOT_ENOUGH_MEMORY;
958 goto done;
959 }
960 wcscpy(lpService->lpDisplayName, lpDisplayName);
961 }
962
963 /* Write service data to the registry */
964 /* Create the service key */
965 dwError = ScmCreateServiceKey(lpServiceName,
966 KEY_WRITE,
967 &hServiceKey);
968 if (dwError != ERROR_SUCCESS)
969 goto done;
970
971 /* Set the display name */
972 if (lpDisplayName != NULL && *lpDisplayName != 0)
973 {
974 RegSetValueExW(hServiceKey,
975 L"DisplayName",
976 0,
977 REG_SZ,
978 (LPBYTE)lpDisplayName,
979 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
980 }
981
982 /* Set the service type */
983 dwError = RegSetValueExW(hServiceKey,
984 L"Type",
985 0,
986 REG_DWORD,
987 (LPBYTE)&dwServiceType,
988 sizeof(DWORD));
989 if (dwError != ERROR_SUCCESS)
990 goto done;
991
992 /* Set the start value */
993 dwError = RegSetValueExW(hServiceKey,
994 L"Start",
995 0,
996 REG_DWORD,
997 (LPBYTE)&dwStartType,
998 sizeof(DWORD));
999 if (dwError != ERROR_SUCCESS)
1000 goto done;
1001
1002 /* Set the error control value */
1003 dwError = RegSetValueExW(hServiceKey,
1004 L"ErrorControl",
1005 0,
1006 REG_DWORD,
1007 (LPBYTE)&dwErrorControl,
1008 sizeof(DWORD));
1009 if (dwError != ERROR_SUCCESS)
1010 goto done;
1011
1012 /* Set the image path */
1013 if (dwServiceType & SERVICE_WIN32)
1014 {
1015 dwError = RegSetValueExW(hServiceKey,
1016 L"ImagePath",
1017 0,
1018 REG_EXPAND_SZ,
1019 (LPBYTE)lpBinaryPathName,
1020 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
1021 if (dwError != ERROR_SUCCESS)
1022 goto done;
1023 }
1024 else if (dwServiceType & SERVICE_DRIVER)
1025 {
1026 dwError = RegSetValueExW(hServiceKey,
1027 L"ImagePath",
1028 0,
1029 REG_EXPAND_SZ,
1030 (LPBYTE)lpImagePath,
1031 (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
1032 if (dwError != ERROR_SUCCESS)
1033 goto done;
1034 }
1035
1036 /* Set the group name */
1037 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
1038 {
1039 dwError = RegSetValueExW(hServiceKey,
1040 L"Group",
1041 0,
1042 REG_SZ,
1043 (LPBYTE)lpLoadOrderGroup,
1044 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
1045 if (dwError != ERROR_SUCCESS)
1046 goto done;
1047 }
1048
1049 if (lpdwTagId != NULL)
1050 {
1051 dwError = ScmAssignNewTag(lpService->lpServiceGroup,
1052 &lpService->dwTag);
1053 if (dwError != ERROR_SUCCESS)
1054 goto done;
1055 dwError = RegSetValueExW(hServiceKey,
1056 L"Tag",
1057 0,
1058 REG_DWORD,
1059 (LPBYTE)&lpService->dwTag,
1060 sizeof(DWORD));
1061 if (dwError != ERROR_SUCCESS)
1062 goto done;
1063 }
1064
1065 /* Write dependencies */
1066 if (lpDependencies != NULL && *lpDependencies != 0)
1067 {
1068 dwError = ScmWriteDependencies(hServiceKey,
1069 lpDependencies,
1070 dwDependenciesLength);
1071 if (dwError != ERROR_SUCCESS)
1072 goto done;
1073 }
1074
1075 if (lpPassword != NULL)
1076 {
1077 /* FIXME: Write password */
1078 }
1079
1080 dwError = ScmCreateServiceHandle(lpService,
1081 &hServiceHandle);
1082 if (dwError != ERROR_SUCCESS)
1083 goto done;
1084
1085 dwError = ScmCheckAccess(hServiceHandle,
1086 dwDesiredAccess);
1087 if (dwError != ERROR_SUCCESS)
1088 goto done;
1089
1090 done:;
1091 if (hServiceKey != NULL)
1092 RegCloseKey(hServiceKey);
1093
1094 if (dwError == ERROR_SUCCESS)
1095 {
1096 DPRINT("hService %lx\n", hServiceHandle);
1097 *hService = (unsigned int)hServiceHandle;
1098
1099 if (lpdwTagId != NULL)
1100 *lpdwTagId = lpService->dwTag;
1101 }
1102 else
1103 {
1104 /* Release the display name buffer */
1105 if (lpService->lpServiceName != lpService->lpDisplayName)
1106 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
1107
1108 if (hServiceHandle != NULL)
1109 {
1110 /* Remove the service handle */
1111 HeapFree(GetProcessHeap(), 0, hServiceHandle);
1112 }
1113
1114 if (lpService != NULL)
1115 {
1116 /* FIXME: remove the service entry */
1117 }
1118 }
1119
1120 if (lpImagePath != NULL)
1121 HeapFree(GetProcessHeap(), 0, lpImagePath);
1122
1123 DPRINT("ScmrCreateServiceW() done (Error %lu)\n", dwError);
1124
1125 return dwError;
1126 }
1127
1128
1129 /* Function 13 */
1130 unsigned long
1131 ScmrEnumDependentServicesW(handle_t BindingHandle,
1132 unsigned int hService,
1133 unsigned long dwServiceState,
1134 unsigned char *lpServices,
1135 unsigned long cbBufSize,
1136 unsigned long *pcbBytesNeeded,
1137 unsigned long *lpServicesReturned)
1138 {
1139 DWORD dwError = ERROR_SUCCESS;
1140
1141 DPRINT1("ScmrEnumDependentServicesW() called\n");
1142
1143 DPRINT1("ScmrEnumDependentServicesW() done (Error %lu)\n", dwError);
1144
1145 return dwError;
1146 }
1147
1148
1149 /* Function 14 */
1150 unsigned long
1151 ScmrEnumServicesStatusW(handle_t BindingHandle,
1152 unsigned int hSCManager,
1153 unsigned long dwServiceType,
1154 unsigned long dwServiceState,
1155 unsigned char *lpServices,
1156 unsigned long dwBufSize,
1157 unsigned long *pcbBytesNeeded,
1158 unsigned long *lpServicesReturned,
1159 unsigned long *lpResumeHandle)
1160 {
1161 PMANAGER_HANDLE hManager;
1162 PSERVICE lpService;
1163 DWORD dwError = ERROR_SUCCESS;
1164
1165 DPRINT1("ScmrEnumServicesStatusW() called\n");
1166
1167 if (ScmShutdown)
1168 return ERROR_SHUTDOWN_IN_PROGRESS;
1169
1170 hManager = (PMANAGER_HANDLE)hSCManager;
1171 if (hManager->Handle.Tag != MANAGER_TAG)
1172 {
1173 DPRINT1("Invalid manager handle!\n");
1174 return ERROR_INVALID_HANDLE;
1175 }
1176
1177 /* Check access rights */
1178 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
1179 SC_MANAGER_ENUMERATE_SERVICE))
1180 {
1181 DPRINT1("Insufficient access rights! 0x%lx\n",
1182 hManager->Handle.DesiredAccess);
1183 return ERROR_ACCESS_DENIED;
1184 }
1185
1186 *pcbBytesNeeded = 0;
1187 *lpServicesReturned = 0;
1188
1189 /* Lock the service list shared */
1190
1191 lpService = ScmGetServiceEntryByResumeCount(*lpResumeHandle);
1192 if (lpService == NULL)
1193 {
1194 dwError = ERROR_MORE_DATA; /* Hack! */
1195 goto done;
1196 }
1197
1198 DPRINT1("Service name: %S\n", lpService->lpServiceName);
1199
1200 // DPRINT1("Display name: %S\n", lpService->lpDisplayName);
1201
1202
1203 *lpResumeHandle = lpService->dwResumeCount;
1204
1205 done:;
1206 /* Unlock the service list */
1207
1208
1209 DPRINT1("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError);
1210
1211 return dwError;
1212 }
1213
1214
1215 /* Function 15 */
1216 unsigned long
1217 ScmrOpenSCManagerW(handle_t BindingHandle,
1218 wchar_t *lpMachineName,
1219 wchar_t *lpDatabaseName,
1220 unsigned long dwDesiredAccess,
1221 unsigned int *hScm)
1222 {
1223 DWORD dwError;
1224 SC_HANDLE hHandle;
1225
1226 DPRINT("ScmrOpenSCManagerW() called\n");
1227 DPRINT("lpMachineName = %p\n", lpMachineName);
1228 DPRINT("lpMachineName: %S\n", lpMachineName);
1229 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
1230 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
1231 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1232
1233 if (ScmShutdown)
1234 return ERROR_SHUTDOWN_IN_PROGRESS;
1235
1236 dwError = ScmCreateManagerHandle(lpDatabaseName,
1237 &hHandle);
1238 if (dwError != ERROR_SUCCESS)
1239 {
1240 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
1241 return dwError;
1242 }
1243
1244 /* Check the desired access */
1245 dwError = ScmCheckAccess(hHandle,
1246 dwDesiredAccess | SC_MANAGER_CONNECT);
1247 if (dwError != ERROR_SUCCESS)
1248 {
1249 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1250 HeapFree(GetProcessHeap(), 0, hHandle);
1251 return dwError;
1252 }
1253
1254 *hScm = (unsigned int)hHandle;
1255 DPRINT("*hScm = %x\n", *hScm);
1256
1257 DPRINT("ScmrOpenSCManagerW() done\n");
1258
1259 return ERROR_SUCCESS;
1260 }
1261
1262
1263 /* Function 16 */
1264 unsigned int
1265 ScmrOpenServiceW(handle_t BindingHandle,
1266 unsigned int hSCManager,
1267 wchar_t *lpServiceName,
1268 unsigned long dwDesiredAccess,
1269 unsigned int *hService)
1270 {
1271 PSERVICE lpService;
1272 PMANAGER_HANDLE hManager;
1273 SC_HANDLE hHandle;
1274 DWORD dwError;
1275
1276 DPRINT("ScmrOpenServiceW() called\n");
1277 DPRINT("hSCManager = %x\n", hSCManager);
1278 DPRINT("lpServiceName = %p\n", lpServiceName);
1279 DPRINT("lpServiceName: %S\n", lpServiceName);
1280 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1281
1282 if (ScmShutdown)
1283 return ERROR_SHUTDOWN_IN_PROGRESS;
1284
1285 hManager = (PMANAGER_HANDLE)hSCManager;
1286 if (hManager->Handle.Tag != MANAGER_TAG)
1287 {
1288 DPRINT1("Invalid manager handle!\n");
1289 return ERROR_INVALID_HANDLE;
1290 }
1291
1292 /* FIXME: Lock the service list */
1293
1294 /* Get service database entry */
1295 lpService = ScmGetServiceEntryByName(lpServiceName);
1296 if (lpService == NULL)
1297 {
1298 DPRINT("Could not find a service!\n");
1299 return ERROR_SERVICE_DOES_NOT_EXIST;
1300 }
1301
1302 /* Create a service handle */
1303 dwError = ScmCreateServiceHandle(lpService,
1304 &hHandle);
1305 if (dwError != ERROR_SUCCESS)
1306 {
1307 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
1308 return dwError;
1309 }
1310
1311 /* Check the desired access */
1312 dwError = ScmCheckAccess(hHandle,
1313 dwDesiredAccess);
1314 if (dwError != ERROR_SUCCESS)
1315 {
1316 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1317 HeapFree(GetProcessHeap(), 0, hHandle);
1318 return dwError;
1319 }
1320
1321 *hService = (unsigned int)hHandle;
1322 DPRINT("*hService = %x\n", *hService);
1323
1324 DPRINT("ScmrOpenServiceW() done\n");
1325
1326 return ERROR_SUCCESS;
1327 }
1328
1329
1330 /* Function 17 */
1331 unsigned long
1332 ScmrQueryServiceConfigW(handle_t BindingHandle,
1333 unsigned int hService,
1334 unsigned char *lpServiceConfig, /* [out, unique, size_is(cbBufSize)] */
1335 unsigned long cbBufSize, /* [in] */
1336 unsigned long *pcbBytesNeeded) /* [out] */
1337 {
1338 DWORD dwError = ERROR_SUCCESS;
1339 PSERVICE_HANDLE hSvc;
1340 PSERVICE lpService = NULL;
1341 HKEY hServiceKey = NULL;
1342 LPWSTR lpImagePath = NULL;
1343 DWORD dwRequiredSize;
1344 LPQUERY_SERVICE_CONFIGW lpConfig;
1345 LPWSTR lpStr;
1346
1347 DPRINT1("ScmrQueryServiceConfigW() called\n");
1348
1349 if (ScmShutdown)
1350 return ERROR_SHUTDOWN_IN_PROGRESS;
1351
1352 hSvc = (PSERVICE_HANDLE)hService;
1353 if (hSvc->Handle.Tag != SERVICE_TAG)
1354 {
1355 DPRINT1("Invalid handle tag!\n");
1356 return ERROR_INVALID_HANDLE;
1357 }
1358
1359 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1360 SERVICE_QUERY_CONFIG))
1361 {
1362 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1363 return ERROR_ACCESS_DENIED;
1364 }
1365
1366 lpService = hSvc->ServiceEntry;
1367 if (lpService == NULL)
1368 {
1369 DPRINT1("lpService == NULL!\n");
1370 return ERROR_INVALID_HANDLE;
1371 }
1372
1373 /* FIXME: Lock the service database shared */
1374
1375 dwError = ScmOpenServiceKey(lpService->lpServiceName,
1376 KEY_READ,
1377 &hServiceKey);
1378 if (dwError != ERROR_SUCCESS)
1379 goto Done;
1380
1381 dwError = ScmReadString(hServiceKey,
1382 L"ImagePath",
1383 &lpImagePath);
1384 if (dwError != ERROR_SUCCESS)
1385 goto Done;
1386
1387 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
1388
1389 if (lpImagePath != NULL)
1390 dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
1391
1392 if (lpService->lpServiceGroup != NULL)
1393 dwRequiredSize += ((wcslen(lpService->lpServiceGroup) + 1) * sizeof(WCHAR));
1394
1395 /* FIXME: Add Dependencies length*/
1396
1397 /* FIXME: Add ServiceStartName length*/
1398
1399 if (lpService->lpDisplayName != NULL)
1400 dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
1401
1402 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
1403 {
1404 dwError = ERROR_INSUFFICIENT_BUFFER;
1405 }
1406 else
1407 {
1408 lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
1409 lpConfig->dwServiceType = lpService->Status.dwServiceType;
1410 lpConfig->dwStartType = lpService->dwStartType;
1411 lpConfig->dwErrorControl = lpService->dwErrorControl;
1412 lpConfig->dwTagId = lpService->dwTag;
1413
1414 lpStr = (LPWSTR)(lpConfig + 1);
1415
1416 if (lpImagePath != NULL)
1417 {
1418 wcscpy(lpStr, lpImagePath);
1419 lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1420 lpStr += (wcslen(lpImagePath) + 1);
1421 }
1422 else
1423 {
1424 lpConfig->lpBinaryPathName = NULL;
1425 }
1426
1427 if (lpService->lpServiceGroup != NULL)
1428 {
1429 wcscpy(lpStr, lpService->lpServiceGroup);
1430 lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1431 lpStr += (wcslen(lpService->lpServiceGroup) + 1);
1432 }
1433 else
1434 {
1435 lpConfig->lpLoadOrderGroup = NULL;
1436 }
1437
1438 /* FIXME: Append Dependencies */
1439 lpConfig->lpDependencies = NULL;
1440
1441 /* FIXME: Append ServiceStartName */
1442 lpConfig->lpServiceStartName = NULL;
1443
1444 if (lpService->lpDisplayName != NULL)
1445 {
1446 wcscpy(lpStr, lpService->lpDisplayName);
1447 lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1448 }
1449 else
1450 {
1451 lpConfig->lpDisplayName = NULL;
1452 }
1453 }
1454
1455 if (pcbBytesNeeded != NULL)
1456 *pcbBytesNeeded = dwRequiredSize;
1457
1458 Done:;
1459 if (lpImagePath != NULL)
1460 HeapFree(GetProcessHeap(), 0, lpImagePath);
1461
1462 if (hServiceKey != NULL)
1463 RegCloseKey(hServiceKey);
1464
1465 /* FIXME: Unlock the service database */
1466
1467 DPRINT1("ScmrQueryServiceConfigW() done\n");
1468
1469 return dwError;
1470 }
1471
1472
1473 /* Function 20 */
1474 unsigned long
1475 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
1476 unsigned int hSCManager,
1477 wchar_t *lpServiceName,
1478 wchar_t *lpDisplayName, /* [out, unique] */
1479 unsigned long *lpcchBuffer)
1480 {
1481 // PMANAGER_HANDLE hManager;
1482 PSERVICE lpService;
1483 DWORD dwLength;
1484 DWORD dwError;
1485
1486 DPRINT("ScmrGetServiceDisplayNameW() called\n");
1487 DPRINT("hSCManager = %x\n", hSCManager);
1488 DPRINT("lpServiceName: %S\n", lpServiceName);
1489 DPRINT("lpDisplayName: %p\n", lpDisplayName);
1490 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1491
1492 // hManager = (PMANAGER_HANDLE)hSCManager;
1493 // if (hManager->Handle.Tag != MANAGER_TAG)
1494 // {
1495 // DPRINT1("Invalid manager handle!\n");
1496 // return ERROR_INVALID_HANDLE;
1497 // }
1498
1499 /* Get service database entry */
1500 lpService = ScmGetServiceEntryByName(lpServiceName);
1501 if (lpService == NULL)
1502 {
1503 DPRINT1("Could not find a service!\n");
1504 return ERROR_SERVICE_DOES_NOT_EXIST;
1505 }
1506
1507 dwLength = wcslen(lpService->lpDisplayName) + 1;
1508
1509 if (lpDisplayName != NULL &&
1510 *lpcchBuffer >= dwLength)
1511 {
1512 wcscpy(lpDisplayName, lpService->lpDisplayName);
1513 }
1514
1515 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1516
1517 *lpcchBuffer = dwLength;
1518
1519 return dwError;
1520 }
1521
1522
1523 /* Function 21 */
1524 unsigned long
1525 ScmrGetServiceKeyNameW(handle_t BindingHandle,
1526 unsigned int hSCManager,
1527 wchar_t *lpDisplayName,
1528 wchar_t *lpServiceName, /* [out, unique] */
1529 unsigned long *lpcchBuffer)
1530 {
1531 // PMANAGER_HANDLE hManager;
1532 PSERVICE lpService;
1533 DWORD dwLength;
1534 DWORD dwError;
1535
1536 DPRINT("ScmrGetServiceKeyNameW() called\n");
1537 DPRINT("hSCManager = %x\n", hSCManager);
1538 DPRINT("lpDisplayName: %S\n", lpDisplayName);
1539 DPRINT("lpServiceName: %p\n", lpServiceName);
1540 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1541
1542 // hManager = (PMANAGER_HANDLE)hSCManager;
1543 // if (hManager->Handle.Tag != MANAGER_TAG)
1544 // {
1545 // DPRINT1("Invalid manager handle!\n");
1546 // return ERROR_INVALID_HANDLE;
1547 // }
1548
1549 /* Get service database entry */
1550 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
1551 if (lpService == NULL)
1552 {
1553 DPRINT1("Could not find a service!\n");
1554 return ERROR_SERVICE_DOES_NOT_EXIST;
1555 }
1556
1557 dwLength = wcslen(lpService->lpServiceName) + 1;
1558
1559 if (lpServiceName != NULL &&
1560 *lpcchBuffer >= dwLength)
1561 {
1562 wcscpy(lpServiceName, lpService->lpServiceName);
1563 }
1564
1565 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1566
1567 *lpcchBuffer = dwLength;
1568
1569 return dwError;
1570 }
1571
1572
1573 /* Function 27 */
1574 unsigned long
1575 ScmrOpenSCManagerA(handle_t BindingHandle,
1576 char *lpMachineName,
1577 char *lpDatabaseName,
1578 unsigned long dwDesiredAccess,
1579 unsigned int *hScm)
1580 {
1581 UNICODE_STRING MachineName;
1582 UNICODE_STRING DatabaseName;
1583 DWORD dwError;
1584
1585 DPRINT("ScmrOpenSCManagerA() called\n");
1586
1587 if (lpMachineName)
1588 RtlCreateUnicodeStringFromAsciiz(&MachineName,
1589 lpMachineName);
1590
1591 if (lpDatabaseName)
1592 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
1593 lpDatabaseName);
1594
1595 dwError = ScmrOpenSCManagerW(BindingHandle,
1596 lpMachineName ? MachineName.Buffer : NULL,
1597 lpDatabaseName ? DatabaseName.Buffer : NULL,
1598 dwDesiredAccess,
1599 hScm);
1600
1601 if (lpMachineName)
1602 RtlFreeUnicodeString(&MachineName);
1603
1604 if (lpDatabaseName)
1605 RtlFreeUnicodeString(&DatabaseName);
1606
1607 return dwError;
1608 }
1609
1610
1611 /* Function 28 */
1612 unsigned int
1613 ScmrOpenServiceA(handle_t BindingHandle,
1614 unsigned int hSCManager,
1615 char *lpServiceName,
1616 unsigned long dwDesiredAccess,
1617 unsigned int *hService)
1618 {
1619 UNICODE_STRING ServiceName;
1620 DWORD dwError;
1621
1622 DPRINT("ScmrOpenServiceA() called\n");
1623
1624 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
1625 lpServiceName);
1626
1627 dwError = ScmrOpenServiceW(BindingHandle,
1628 hSCManager,
1629 ServiceName.Buffer,
1630 dwDesiredAccess,
1631 hService);
1632
1633 RtlFreeUnicodeString(&ServiceName);
1634
1635 return dwError;
1636 }
1637
1638
1639 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
1640 {
1641 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
1642 }
1643
1644
1645 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
1646 {
1647 HeapFree(GetProcessHeap(), 0, ptr);
1648 }
1649
1650 /* EOF */