5 /* INCLUDES ****************************************************************/
14 /* GLOBALS *****************************************************************/
16 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
17 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
19 typedef struct _SCMGR_HANDLE
27 typedef struct _MANAGER_HANDLE
31 /* FIXME: Insert more data here */
33 WCHAR DatabaseName
[1];
34 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
37 typedef struct _SERVICE_HANDLE
42 PSERVICE ServiceEntry
;
44 /* FIXME: Insert more data here */
46 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
49 #define SC_MANAGER_READ \
50 (STANDARD_RIGHTS_READ | \
51 SC_MANAGER_QUERY_LOCK_STATUS | \
52 SC_MANAGER_ENUMERATE_SERVICE)
54 #define SC_MANAGER_WRITE \
55 (STANDARD_RIGHTS_WRITE | \
56 SC_MANAGER_MODIFY_BOOT_CONFIG | \
57 SC_MANAGER_CREATE_SERVICE)
59 #define SC_MANAGER_EXECUTE \
60 (STANDARD_RIGHTS_EXECUTE | \
62 SC_MANAGER_ENUMERATE_SERVICE | \
63 SC_MANAGER_CONNECT | \
64 SC_MANAGER_CREATE_SERVICE)
67 #define SERVICE_READ \
68 (STANDARD_RIGHTS_READ | \
69 SERVICE_INTERROGATE | \
70 SERVICE_ENUMERATE_DEPENDENTS | \
71 SERVICE_QUERY_STATUS | \
74 #define SERVICE_WRITE \
75 (STANDARD_RIGHTS_WRITE | \
76 SERVICE_CHANGE_CONFIG)
78 #define SERVICE_EXECUTE \
79 (STANDARD_RIGHTS_EXECUTE | \
80 SERVICE_USER_DEFINED_CONTROL | \
81 SERVICE_PAUSE_CONTINUE | \
86 /* VARIABLES ***************************************************************/
88 static GENERIC_MAPPING
89 ScmManagerMapping
= {SC_MANAGER_READ
,
92 SC_MANAGER_ALL_ACCESS
};
94 static GENERIC_MAPPING
95 ScmServiceMapping
= {SERVICE_READ
,
98 SC_MANAGER_ALL_ACCESS
};
101 /* FUNCTIONS ***************************************************************/
104 ScmStartRpcServer(VOID
)
108 DPRINT("ScmStartRpcServer() called");
110 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
114 if (Status
!= RPC_S_OK
)
116 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
120 Status
= RpcServerRegisterIf(svcctl_ServerIfHandle
,
123 if (Status
!= RPC_S_OK
)
125 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
129 Status
= RpcServerListen(1, 20, TRUE
);
130 if (Status
!= RPC_S_OK
)
132 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
136 DPRINT("ScmStartRpcServer() done");
141 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
146 if (lpDatabaseName
== NULL
)
147 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
149 Ptr
= HeapAlloc(GetProcessHeap(),
151 sizeof(MANAGER_HANDLE
) + wcslen(lpDatabaseName
) * sizeof(WCHAR
));
153 return ERROR_NOT_ENOUGH_MEMORY
;
155 Ptr
->Handle
.Tag
= MANAGER_TAG
;
156 Ptr
->Handle
.RefCount
= 1;
158 /* FIXME: initialize more data here */
160 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
162 *Handle
= (SC_HANDLE
)Ptr
;
164 return ERROR_SUCCESS
;
169 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
174 Ptr
= HeapAlloc(GetProcessHeap(),
176 sizeof(SERVICE_HANDLE
));
178 return ERROR_NOT_ENOUGH_MEMORY
;
180 Ptr
->Handle
.Tag
= SERVICE_TAG
;
181 Ptr
->Handle
.RefCount
= 1;
183 /* FIXME: initialize more data here */
184 Ptr
->ServiceEntry
= lpServiceEntry
;
186 *Handle
= (SC_HANDLE
)Ptr
;
188 return ERROR_SUCCESS
;
193 ScmCheckAccess(SC_HANDLE Handle
,
194 DWORD dwDesiredAccess
)
196 PMANAGER_HANDLE hMgr
;
198 hMgr
= (PMANAGER_HANDLE
)Handle
;
199 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
201 RtlMapGenericMask(&dwDesiredAccess
,
204 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
206 return ERROR_SUCCESS
;
208 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
210 RtlMapGenericMask(&dwDesiredAccess
,
213 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
215 return ERROR_SUCCESS
;
218 return ERROR_INVALID_HANDLE
;
223 ScmAssignNewTag(LPWSTR lpServiceGroup
,
227 DPRINT("Assigning new tag in group %S\n", lpServiceGroup
);
229 return ERROR_SUCCESS
;
235 ScmrCloseServiceHandle(handle_t BindingHandle
,
236 unsigned int hScObject
)
238 PMANAGER_HANDLE hManager
;
240 DPRINT("ScmrCloseServiceHandle() called\n");
242 DPRINT("hScObject = %X\n", hScObject
);
245 return ERROR_INVALID_HANDLE
;
247 hManager
= (PMANAGER_HANDLE
)hScObject
;
248 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
250 DPRINT("Found manager handle\n");
252 hManager
->Handle
.RefCount
--;
253 if (hManager
->Handle
.RefCount
== 0)
255 /* FIXME: add cleanup code */
257 HeapFree(GetProcessHeap(), 0, hManager
);
260 DPRINT("ScmrCloseServiceHandle() done\n");
261 return ERROR_SUCCESS
;
263 else if (hManager
->Handle
.Tag
== SERVICE_TAG
)
265 DPRINT("Found service handle\n");
267 hManager
->Handle
.RefCount
--;
268 if (hManager
->Handle
.RefCount
== 0)
270 /* FIXME: add cleanup code */
272 HeapFree(GetProcessHeap(), 0, hManager
);
275 DPRINT("ScmrCloseServiceHandle() done\n");
276 return ERROR_SUCCESS
;
279 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
281 return ERROR_INVALID_HANDLE
;
287 ScmrControlService(handle_t BindingHandle
,
288 unsigned int hService
,
289 unsigned long dwControl
,
290 LPSERVICE_STATUS lpServiceStatus
)
292 PSERVICE_HANDLE hSvc
;
294 ACCESS_MASK DesiredAccess
;
295 DWORD dwError
= ERROR_SUCCESS
;
297 DPRINT("ScmrControlService() called\n");
300 return ERROR_SHUTDOWN_IN_PROGRESS
;
302 /* Check the service handle */
303 hSvc
= (PSERVICE_HANDLE
)hService
;
304 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
306 DPRINT1("Invalid handle tag!\n");
307 return ERROR_INVALID_HANDLE
;
310 /* Check access rights */
313 case SERVICE_CONTROL_STOP
:
314 DesiredAccess
= SERVICE_STOP
;
317 case SERVICE_CONTROL_PAUSE
:
318 case SERVICE_CONTROL_CONTINUE
:
319 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
322 case SERVICE_INTERROGATE
:
323 DesiredAccess
= SERVICE_INTERROGATE
;
327 if (dwControl
>= 128 && dwControl
<= 255)
328 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
330 DesiredAccess
= SERVICE_QUERY_CONFIG
|
331 SERVICE_CHANGE_CONFIG
|
332 SERVICE_QUERY_STATUS
|
334 SERVICE_PAUSE_CONTINUE
;
338 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
340 return ERROR_ACCESS_DENIED
;
342 /* Check the service entry point */
343 lpService
= hSvc
->ServiceEntry
;
344 if (lpService
== NULL
)
346 DPRINT1("lpService == NULL!\n");
347 return ERROR_INVALID_HANDLE
;
350 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
352 /* Send control code to the driver */
353 dwError
= ScmControlDriver(lpService
,
359 /* FIXME: Send control code to the service */
361 dwError
= ScmControlService(lpService
,
365 dwError
= ERROR_INVALID_SERVICE_CONTROL
;
368 /* Return service status information */
369 RtlCopyMemory(lpServiceStatus
,
371 sizeof(SERVICE_STATUS
));
379 ScmrDeleteService(handle_t BindingHandle
,
380 unsigned int hService
)
382 PSERVICE_HANDLE hSvc
;
386 DPRINT("ScmrDeleteService() called\n");
389 return ERROR_SHUTDOWN_IN_PROGRESS
;
391 hSvc
= (PSERVICE_HANDLE
)hService
;
392 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
393 return ERROR_INVALID_HANDLE
;
395 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
396 STANDARD_RIGHTS_REQUIRED
))
397 return ERROR_ACCESS_DENIED
;
399 lpService
= hSvc
->ServiceEntry
;
400 if (lpService
== NULL
)
402 DPRINT1("lpService == NULL!\n");
403 return ERROR_INVALID_HANDLE
;
406 /* FIXME: Acquire service database lock exclusively */
408 if (lpService
->bDeleted
)
410 DPRINT1("The service has already been marked for delete!\n");
411 return ERROR_SERVICE_MARKED_FOR_DELETE
;
414 /* Mark service for delete */
415 lpService
->bDeleted
= TRUE
;
417 dwError
= ScmMarkServiceForDelete(lpService
);
419 /* FIXME: Release service database lock */
421 DPRINT("ScmrDeleteService() done\n");
429 ScmrLockServiceDatabase(handle_t BindingHandle
,
430 unsigned int hSCManager
,
433 PMANAGER_HANDLE hMgr
;
435 DPRINT("ScmrLockServiceDatabase() called\n");
439 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
440 if (hMgr
->Handle
.Tag
!= MANAGER_TAG
)
441 return ERROR_INVALID_HANDLE
;
443 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
445 return ERROR_ACCESS_DENIED
;
447 /* FIXME: Lock the database */
448 *hLock
= 0x12345678; /* Dummy! */
450 return ERROR_SUCCESS
;
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
)
463 PSERVICE_HANDLE hSvc
;
465 ULONG DesiredAccess
= 0;
470 DPRINT("ScmrQueryServiceSecurity() called\n");
472 hSvc
= (PSERVICE_HANDLE
)hService
;
473 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
475 DPRINT1("Invalid handle tag!\n");
476 return ERROR_INVALID_HANDLE
;
479 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
480 GROUP_SECURITY_INFORMATION
||
481 OWNER_SECURITY_INFORMATION
))
482 DesiredAccess
|= READ_CONTROL
;
484 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
485 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
487 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
490 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
491 return ERROR_ACCESS_DENIED
;
494 lpService
= hSvc
->ServiceEntry
;
495 if (lpService
== NULL
)
497 DPRINT1("lpService == NULL!\n");
498 return ERROR_INVALID_HANDLE
;
501 /* FIXME: Lock the service list */
503 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
504 dwSecurityInformation
,
505 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
506 dwSecuityDescriptorSize
,
509 /* FIXME: Unlock the service list */
511 if (NT_SUCCESS(Status
))
513 *pcbBytesNeeded
= dwBytesNeeded
;
514 dwError
= STATUS_SUCCESS
;
516 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
518 *pcbBytesNeeded
= dwBytesNeeded
;
519 dwError
= ERROR_INSUFFICIENT_BUFFER
;
521 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
523 dwError
= ERROR_GEN_FAILURE
;
527 dwError
= RtlNtStatusToDosError(Status
);
536 ScmrSetServiceObjectSecurity(handle_t BindingHandle
,
537 unsigned int hService
,
538 unsigned long dwSecurityInformation
,
539 unsigned char *lpSecurityDescriptor
,
540 unsigned long dwSecuityDescriptorSize
)
542 DPRINT1("ScmrSetServiceSecurity() is unimplemented\n");
543 return ERROR_CALL_NOT_IMPLEMENTED
;
549 ScmrQueryServiceStatus(handle_t BindingHandle
,
550 unsigned int hService
,
551 LPSERVICE_STATUS lpServiceStatus
)
553 PSERVICE_HANDLE hSvc
;
556 DPRINT("ScmrQueryServiceStatus() called\n");
559 return ERROR_SHUTDOWN_IN_PROGRESS
;
561 hSvc
= (PSERVICE_HANDLE
)hService
;
562 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
564 DPRINT1("Invalid handle tag!\n");
565 return ERROR_INVALID_HANDLE
;
568 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
569 SERVICE_QUERY_STATUS
))
571 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
572 return ERROR_ACCESS_DENIED
;
575 lpService
= hSvc
->ServiceEntry
;
576 if (lpService
== NULL
)
578 DPRINT1("lpService == NULL!\n");
579 return ERROR_INVALID_HANDLE
;
582 /* Return service status information */
583 RtlCopyMemory(lpServiceStatus
,
585 sizeof(SERVICE_STATUS
));
587 return ERROR_SUCCESS
;
593 ScmrSetServiceStatus(handle_t BindingHandle
,
594 unsigned long hServiceStatus
) /* FIXME */
596 DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
598 return ERROR_CALL_NOT_IMPLEMENTED
;
604 ScmrUnlockServiceDatabase(handle_t BindingHandle
,
607 DPRINT1("ScmrUnlockServiceDatabase() called\n");
609 return ERROR_SUCCESS
;
615 ScmrNotifyBootConfigStatus(handle_t BindingHandle
,
616 unsigned long BootAcceptable
)
618 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
620 return ERROR_SUCCESS
;
626 ScmrI_ScSetServiceBitsW(handle_t BindingHandle
,
627 unsigned long hServiceStatus
,
628 unsigned long dwServiceBits
,
629 unsigned long bSetBitsOn
,
630 unsigned long bUpdateImmediately
,
633 DPRINT1("ScmrI_ScSetServiceBitsW() called\n");
635 return ERROR_SUCCESS
;
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
,
653 unsigned long dwPasswordLength
,
654 wchar_t *lpDisplayName
)
656 DWORD dwError
= ERROR_SUCCESS
;
657 PSERVICE_HANDLE hSvc
;
658 PSERVICE lpService
= NULL
;
659 HKEY hServiceKey
= NULL
;
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
);
670 return ERROR_SHUTDOWN_IN_PROGRESS
;
672 hSvc
= (PSERVICE_HANDLE
)hService
;
673 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
675 DPRINT1("Invalid handle tag!\n");
676 return ERROR_INVALID_HANDLE
;
679 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
680 SERVICE_CHANGE_CONFIG
))
682 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
683 return ERROR_ACCESS_DENIED
;
686 lpService
= hSvc
->ServiceEntry
;
687 if (lpService
== NULL
)
689 DPRINT1("lpService == NULL!\n");
690 return ERROR_INVALID_HANDLE
;
693 /* FIXME: Lock database exclusively */
695 if (lpService
->bDeleted
)
697 /* FIXME: Unlock database */
698 DPRINT1("The service has already been marked for delete!\n");
699 return ERROR_SERVICE_MARKED_FOR_DELETE
;
702 /* Open the service key */
703 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
706 if (dwError
!= ERROR_SUCCESS
)
709 /* Write service data to the registry */
710 /* Set the display name */
711 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
713 RegSetValueExW(hServiceKey
,
717 (LPBYTE
)lpDisplayName
,
718 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
719 /* FIXME: update lpService->lpDisplayName */
722 if (dwServiceType
!= SERVICE_NO_CHANGE
)
724 /* Set the service type */
725 dwError
= RegSetValueExW(hServiceKey
,
729 (LPBYTE
)&dwServiceType
,
731 if (dwError
!= ERROR_SUCCESS
)
734 lpService
->Status
.dwServiceType
= dwServiceType
;
737 if (dwStartType
!= SERVICE_NO_CHANGE
)
739 /* Set the start value */
740 dwError
= RegSetValueExW(hServiceKey
,
744 (LPBYTE
)&dwStartType
,
746 if (dwError
!= ERROR_SUCCESS
)
749 lpService
->dwStartType
= dwStartType
;
752 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
754 /* Set the error control value */
755 dwError
= RegSetValueExW(hServiceKey
,
759 (LPBYTE
)&dwErrorControl
,
761 if (dwError
!= ERROR_SUCCESS
)
764 lpService
->dwErrorControl
= dwErrorControl
;
768 /* FIXME: set the new ImagePath value */
770 /* Set the image path */
771 if (dwServiceType
& SERVICE_WIN32
)
773 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
775 dwError
= RegSetValueExW(hServiceKey
,
779 (LPBYTE
)lpBinaryPathName
,
780 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
781 if (dwError
!= ERROR_SUCCESS
)
785 else if (dwServiceType
& SERVICE_DRIVER
)
787 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
789 dwError
= RegSetValueExW(hServiceKey
,
794 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
795 if (dwError
!= ERROR_SUCCESS
)
801 /* Set the group name */
802 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
804 dwError
= RegSetValueExW(hServiceKey
,
808 (LPBYTE
)lpLoadOrderGroup
,
809 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
810 if (dwError
!= ERROR_SUCCESS
)
812 /* FIXME: update lpService->lpServiceGroup */
815 if (lpdwTagId
!= NULL
)
817 dwError
= ScmAssignNewTag(lpService
->lpServiceGroup
,
819 if (dwError
!= ERROR_SUCCESS
)
821 dwError
= RegSetValueExW(hServiceKey
,
825 (LPBYTE
)&lpService
->dwTag
,
827 if (dwError
!= ERROR_SUCCESS
)
829 *lpdwTagId
= lpService
->dwTag
;
832 /* Write dependencies */
833 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
835 dwError
= ScmWriteDependencies(hServiceKey
,
837 dwDependenciesLength
);
838 if (dwError
!= ERROR_SUCCESS
)
842 if (lpPassword
!= NULL
)
844 /* FIXME: Write password */
847 /* FIXME: Unlock database */
850 if (hServiceKey
!= NULL
)
851 RegCloseKey(hServiceKey
);
853 DPRINT("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError
);
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
,
876 unsigned long dwPasswordLength
,
877 unsigned int *hService
) /* out */
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
;
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
);
897 return ERROR_SHUTDOWN_IN_PROGRESS
;
899 hManager
= (PMANAGER_HANDLE
)hSCManager
;
900 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
902 DPRINT1("Invalid manager handle!\n");
903 return ERROR_INVALID_HANDLE
;
906 /* Check access rights */
907 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
908 SC_MANAGER_CREATE_SERVICE
))
910 DPRINT1("Insufficient access rights! 0x%lx\n",
911 hManager
->Handle
.DesiredAccess
);
912 return ERROR_ACCESS_DENIED
;
915 /* Fail if the service already exists! */
916 if (ScmGetServiceEntryByName(lpServiceName
) != NULL
)
917 return ERROR_SERVICE_EXISTS
;
919 if (dwServiceType
& SERVICE_DRIVER
)
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);
926 lpImagePath
= HeapAlloc(GetProcessHeap(),
928 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
929 if (lpImagePath
== NULL
)
931 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
934 wcscpy(lpImagePath
, lpBinaryPathName
);
937 /* Allocate a new service entry */
938 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
940 if (dwError
!= ERROR_SUCCESS
)
943 /* Fill the new service entry */
944 lpService
->Status
.dwServiceType
= dwServiceType
;
945 lpService
->dwStartType
= dwStartType
;
946 lpService
->dwErrorControl
= dwErrorControl
;
948 /* Fill the display name */
949 if (lpDisplayName
!= NULL
&&
950 *lpDisplayName
!= 0 &&
951 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
953 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(), 0,
954 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
955 if (lpService
->lpDisplayName
== NULL
)
957 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
960 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
963 /* Write service data to the registry */
964 /* Create the service key */
965 dwError
= ScmCreateServiceKey(lpServiceName
,
968 if (dwError
!= ERROR_SUCCESS
)
971 /* Set the display name */
972 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
974 RegSetValueExW(hServiceKey
,
978 (LPBYTE
)lpDisplayName
,
979 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
982 /* Set the service type */
983 dwError
= RegSetValueExW(hServiceKey
,
987 (LPBYTE
)&dwServiceType
,
989 if (dwError
!= ERROR_SUCCESS
)
992 /* Set the start value */
993 dwError
= RegSetValueExW(hServiceKey
,
997 (LPBYTE
)&dwStartType
,
999 if (dwError
!= ERROR_SUCCESS
)
1002 /* Set the error control value */
1003 dwError
= RegSetValueExW(hServiceKey
,
1007 (LPBYTE
)&dwErrorControl
,
1009 if (dwError
!= ERROR_SUCCESS
)
1012 /* Set the image path */
1013 if (dwServiceType
& SERVICE_WIN32
)
1015 dwError
= RegSetValueExW(hServiceKey
,
1019 (LPBYTE
)lpBinaryPathName
,
1020 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1021 if (dwError
!= ERROR_SUCCESS
)
1024 else if (dwServiceType
& SERVICE_DRIVER
)
1026 dwError
= RegSetValueExW(hServiceKey
,
1030 (LPBYTE
)lpImagePath
,
1031 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1032 if (dwError
!= ERROR_SUCCESS
)
1036 /* Set the group name */
1037 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1039 dwError
= RegSetValueExW(hServiceKey
,
1043 (LPBYTE
)lpLoadOrderGroup
,
1044 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1045 if (dwError
!= ERROR_SUCCESS
)
1049 if (lpdwTagId
!= NULL
)
1051 dwError
= ScmAssignNewTag(lpService
->lpServiceGroup
,
1053 if (dwError
!= ERROR_SUCCESS
)
1055 dwError
= RegSetValueExW(hServiceKey
,
1059 (LPBYTE
)&lpService
->dwTag
,
1061 if (dwError
!= ERROR_SUCCESS
)
1065 /* Write dependencies */
1066 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1068 dwError
= ScmWriteDependencies(hServiceKey
,
1070 dwDependenciesLength
);
1071 if (dwError
!= ERROR_SUCCESS
)
1075 if (lpPassword
!= NULL
)
1077 /* FIXME: Write password */
1080 dwError
= ScmCreateServiceHandle(lpService
,
1082 if (dwError
!= ERROR_SUCCESS
)
1085 dwError
= ScmCheckAccess(hServiceHandle
,
1087 if (dwError
!= ERROR_SUCCESS
)
1091 if (hServiceKey
!= NULL
)
1092 RegCloseKey(hServiceKey
);
1094 if (dwError
== ERROR_SUCCESS
)
1096 DPRINT("hService %lx\n", hServiceHandle
);
1097 *hService
= (unsigned int)hServiceHandle
;
1099 if (lpdwTagId
!= NULL
)
1100 *lpdwTagId
= lpService
->dwTag
;
1104 /* Release the display name buffer */
1105 if (lpService
->lpServiceName
!= lpService
->lpDisplayName
)
1106 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1108 if (hServiceHandle
!= NULL
)
1110 /* Remove the service handle */
1111 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1114 if (lpService
!= NULL
)
1116 /* FIXME: remove the service entry */
1120 if (lpImagePath
!= NULL
)
1121 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1123 DPRINT("ScmrCreateServiceW() done (Error %lu)\n", dwError
);
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
)
1139 DWORD dwError
= ERROR_SUCCESS
;
1141 DPRINT1("ScmrEnumDependentServicesW() called\n");
1143 DPRINT1("ScmrEnumDependentServicesW() done (Error %lu)\n", dwError
);
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
)
1161 PMANAGER_HANDLE hManager
;
1163 DWORD dwError
= ERROR_SUCCESS
;
1165 DPRINT1("ScmrEnumServicesStatusW() called\n");
1168 return ERROR_SHUTDOWN_IN_PROGRESS
;
1170 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1171 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
1173 DPRINT1("Invalid manager handle!\n");
1174 return ERROR_INVALID_HANDLE
;
1177 /* Check access rights */
1178 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1179 SC_MANAGER_ENUMERATE_SERVICE
))
1181 DPRINT1("Insufficient access rights! 0x%lx\n",
1182 hManager
->Handle
.DesiredAccess
);
1183 return ERROR_ACCESS_DENIED
;
1186 *pcbBytesNeeded
= 0;
1187 *lpServicesReturned
= 0;
1189 /* Lock the service list shared */
1191 lpService
= ScmGetServiceEntryByResumeCount(*lpResumeHandle
);
1192 if (lpService
== NULL
)
1194 dwError
= ERROR_MORE_DATA
; /* Hack! */
1198 DPRINT1("Service name: %S\n", lpService
->lpServiceName
);
1200 // DPRINT1("Display name: %S\n", lpService->lpDisplayName);
1203 *lpResumeHandle
= lpService
->dwResumeCount
;
1206 /* Unlock the service list */
1209 DPRINT1("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError
);
1217 ScmrOpenSCManagerW(handle_t BindingHandle
,
1218 wchar_t *lpMachineName
,
1219 wchar_t *lpDatabaseName
,
1220 unsigned long dwDesiredAccess
,
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
);
1234 return ERROR_SHUTDOWN_IN_PROGRESS
;
1236 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
1238 if (dwError
!= ERROR_SUCCESS
)
1240 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
1244 /* Check the desired access */
1245 dwError
= ScmCheckAccess(hHandle
,
1246 dwDesiredAccess
| SC_MANAGER_CONNECT
);
1247 if (dwError
!= ERROR_SUCCESS
)
1249 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1250 HeapFree(GetProcessHeap(), 0, hHandle
);
1254 *hScm
= (unsigned int)hHandle
;
1255 DPRINT("*hScm = %x\n", *hScm
);
1257 DPRINT("ScmrOpenSCManagerW() done\n");
1259 return ERROR_SUCCESS
;
1265 ScmrOpenServiceW(handle_t BindingHandle
,
1266 unsigned int hSCManager
,
1267 wchar_t *lpServiceName
,
1268 unsigned long dwDesiredAccess
,
1269 unsigned int *hService
)
1272 PMANAGER_HANDLE hManager
;
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
);
1283 return ERROR_SHUTDOWN_IN_PROGRESS
;
1285 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1286 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
1288 DPRINT1("Invalid manager handle!\n");
1289 return ERROR_INVALID_HANDLE
;
1292 /* FIXME: Lock the service list */
1294 /* Get service database entry */
1295 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1296 if (lpService
== NULL
)
1298 DPRINT("Could not find a service!\n");
1299 return ERROR_SERVICE_DOES_NOT_EXIST
;
1302 /* Create a service handle */
1303 dwError
= ScmCreateServiceHandle(lpService
,
1305 if (dwError
!= ERROR_SUCCESS
)
1307 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
1311 /* Check the desired access */
1312 dwError
= ScmCheckAccess(hHandle
,
1314 if (dwError
!= ERROR_SUCCESS
)
1316 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1317 HeapFree(GetProcessHeap(), 0, hHandle
);
1321 *hService
= (unsigned int)hHandle
;
1322 DPRINT("*hService = %x\n", *hService
);
1324 DPRINT("ScmrOpenServiceW() done\n");
1326 return ERROR_SUCCESS
;
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] */
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
;
1347 DPRINT1("ScmrQueryServiceConfigW() called\n");
1350 return ERROR_SHUTDOWN_IN_PROGRESS
;
1352 hSvc
= (PSERVICE_HANDLE
)hService
;
1353 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1355 DPRINT1("Invalid handle tag!\n");
1356 return ERROR_INVALID_HANDLE
;
1359 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1360 SERVICE_QUERY_CONFIG
))
1362 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1363 return ERROR_ACCESS_DENIED
;
1366 lpService
= hSvc
->ServiceEntry
;
1367 if (lpService
== NULL
)
1369 DPRINT1("lpService == NULL!\n");
1370 return ERROR_INVALID_HANDLE
;
1373 /* FIXME: Lock the service database shared */
1375 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1378 if (dwError
!= ERROR_SUCCESS
)
1381 dwError
= ScmReadString(hServiceKey
,
1384 if (dwError
!= ERROR_SUCCESS
)
1387 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
1389 if (lpImagePath
!= NULL
)
1390 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1392 if (lpService
->lpServiceGroup
!= NULL
)
1393 dwRequiredSize
+= ((wcslen(lpService
->lpServiceGroup
) + 1) * sizeof(WCHAR
));
1395 /* FIXME: Add Dependencies length*/
1397 /* FIXME: Add ServiceStartName length*/
1399 if (lpService
->lpDisplayName
!= NULL
)
1400 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1402 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
1404 dwError
= ERROR_INSUFFICIENT_BUFFER
;
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
;
1414 lpStr
= (LPWSTR
)(lpConfig
+ 1);
1416 if (lpImagePath
!= NULL
)
1418 wcscpy(lpStr
, lpImagePath
);
1419 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1420 lpStr
+= (wcslen(lpImagePath
) + 1);
1424 lpConfig
->lpBinaryPathName
= NULL
;
1427 if (lpService
->lpServiceGroup
!= NULL
)
1429 wcscpy(lpStr
, lpService
->lpServiceGroup
);
1430 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1431 lpStr
+= (wcslen(lpService
->lpServiceGroup
) + 1);
1435 lpConfig
->lpLoadOrderGroup
= NULL
;
1438 /* FIXME: Append Dependencies */
1439 lpConfig
->lpDependencies
= NULL
;
1441 /* FIXME: Append ServiceStartName */
1442 lpConfig
->lpServiceStartName
= NULL
;
1444 if (lpService
->lpDisplayName
!= NULL
)
1446 wcscpy(lpStr
, lpService
->lpDisplayName
);
1447 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1451 lpConfig
->lpDisplayName
= NULL
;
1455 if (pcbBytesNeeded
!= NULL
)
1456 *pcbBytesNeeded
= dwRequiredSize
;
1459 if (lpImagePath
!= NULL
)
1460 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1462 if (hServiceKey
!= NULL
)
1463 RegCloseKey(hServiceKey
);
1465 /* FIXME: Unlock the service database */
1467 DPRINT1("ScmrQueryServiceConfigW() done\n");
1475 ScmrGetServiceDisplayNameW(handle_t BindingHandle
,
1476 unsigned int hSCManager
,
1477 wchar_t *lpServiceName
,
1478 wchar_t *lpDisplayName
, /* [out, unique] */
1479 unsigned long *lpcchBuffer
)
1481 // PMANAGER_HANDLE hManager;
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
);
1492 // hManager = (PMANAGER_HANDLE)hSCManager;
1493 // if (hManager->Handle.Tag != MANAGER_TAG)
1495 // DPRINT1("Invalid manager handle!\n");
1496 // return ERROR_INVALID_HANDLE;
1499 /* Get service database entry */
1500 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1501 if (lpService
== NULL
)
1503 DPRINT1("Could not find a service!\n");
1504 return ERROR_SERVICE_DOES_NOT_EXIST
;
1507 dwLength
= wcslen(lpService
->lpDisplayName
) + 1;
1509 if (lpDisplayName
!= NULL
&&
1510 *lpcchBuffer
>= dwLength
)
1512 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
1515 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
1517 *lpcchBuffer
= dwLength
;
1525 ScmrGetServiceKeyNameW(handle_t BindingHandle
,
1526 unsigned int hSCManager
,
1527 wchar_t *lpDisplayName
,
1528 wchar_t *lpServiceName
, /* [out, unique] */
1529 unsigned long *lpcchBuffer
)
1531 // PMANAGER_HANDLE hManager;
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
);
1542 // hManager = (PMANAGER_HANDLE)hSCManager;
1543 // if (hManager->Handle.Tag != MANAGER_TAG)
1545 // DPRINT1("Invalid manager handle!\n");
1546 // return ERROR_INVALID_HANDLE;
1549 /* Get service database entry */
1550 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
1551 if (lpService
== NULL
)
1553 DPRINT1("Could not find a service!\n");
1554 return ERROR_SERVICE_DOES_NOT_EXIST
;
1557 dwLength
= wcslen(lpService
->lpServiceName
) + 1;
1559 if (lpServiceName
!= NULL
&&
1560 *lpcchBuffer
>= dwLength
)
1562 wcscpy(lpServiceName
, lpService
->lpServiceName
);
1565 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
1567 *lpcchBuffer
= dwLength
;
1575 ScmrOpenSCManagerA(handle_t BindingHandle
,
1576 char *lpMachineName
,
1577 char *lpDatabaseName
,
1578 unsigned long dwDesiredAccess
,
1581 UNICODE_STRING MachineName
;
1582 UNICODE_STRING DatabaseName
;
1585 DPRINT("ScmrOpenSCManagerA() called\n");
1588 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
1592 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
1595 dwError
= ScmrOpenSCManagerW(BindingHandle
,
1596 lpMachineName
? MachineName
.Buffer
: NULL
,
1597 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
1602 RtlFreeUnicodeString(&MachineName
);
1605 RtlFreeUnicodeString(&DatabaseName
);
1613 ScmrOpenServiceA(handle_t BindingHandle
,
1614 unsigned int hSCManager
,
1615 char *lpServiceName
,
1616 unsigned long dwDesiredAccess
,
1617 unsigned int *hService
)
1619 UNICODE_STRING ServiceName
;
1622 DPRINT("ScmrOpenServiceA() called\n");
1624 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
1627 dwError
= ScmrOpenServiceW(BindingHandle
,
1633 RtlFreeUnicodeString(&ServiceName
);
1639 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
1641 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
1645 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
1647 HeapFree(GetProcessHeap(), 0, ptr
);