2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/rpcserver.c
5 * PURPOSE: RPC server interface for the advapi32 calls
6 * COPYRIGHT: Copyright 2005-2006 Eric Kohl
7 * Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
8 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
12 /* INCLUDES ****************************************************************/
20 /* GLOBALS *****************************************************************/
22 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
23 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
25 typedef struct _SCMGR_HANDLE
33 typedef struct _MANAGER_HANDLE
37 /* FIXME: Insert more data here */
39 WCHAR DatabaseName
[1];
40 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
43 typedef struct _SERVICE_HANDLE
48 PSERVICE ServiceEntry
;
50 /* FIXME: Insert more data here */
52 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
55 #define SC_MANAGER_READ \
56 (STANDARD_RIGHTS_READ | \
57 SC_MANAGER_QUERY_LOCK_STATUS | \
58 SC_MANAGER_ENUMERATE_SERVICE)
60 #define SC_MANAGER_WRITE \
61 (STANDARD_RIGHTS_WRITE | \
62 SC_MANAGER_MODIFY_BOOT_CONFIG | \
63 SC_MANAGER_CREATE_SERVICE)
65 #define SC_MANAGER_EXECUTE \
66 (STANDARD_RIGHTS_EXECUTE | \
68 SC_MANAGER_ENUMERATE_SERVICE | \
69 SC_MANAGER_CONNECT | \
70 SC_MANAGER_CREATE_SERVICE)
73 #define SERVICE_READ \
74 (STANDARD_RIGHTS_READ | \
75 SERVICE_INTERROGATE | \
76 SERVICE_ENUMERATE_DEPENDENTS | \
77 SERVICE_QUERY_STATUS | \
80 #define SERVICE_WRITE \
81 (STANDARD_RIGHTS_WRITE | \
82 SERVICE_CHANGE_CONFIG)
84 #define SERVICE_EXECUTE \
85 (STANDARD_RIGHTS_EXECUTE | \
86 SERVICE_USER_DEFINED_CONTROL | \
87 SERVICE_PAUSE_CONTINUE | \
92 /* VARIABLES ***************************************************************/
94 static GENERIC_MAPPING
95 ScmManagerMapping
= {SC_MANAGER_READ
,
98 SC_MANAGER_ALL_ACCESS
};
100 static GENERIC_MAPPING
101 ScmServiceMapping
= {SERVICE_READ
,
104 SC_MANAGER_ALL_ACCESS
};
107 /* FUNCTIONS ***************************************************************/
110 ScmStartRpcServer(VOID
)
114 DPRINT("ScmStartRpcServer() called\n");
116 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
120 if (Status
!= RPC_S_OK
)
122 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
126 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
129 if (Status
!= RPC_S_OK
)
131 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
135 Status
= RpcServerListen(1, 20, TRUE
);
136 if (Status
!= RPC_S_OK
)
138 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
142 DPRINT("ScmStartRpcServer() done\n");
147 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
152 if (lpDatabaseName
== NULL
)
153 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
155 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
157 sizeof(MANAGER_HANDLE
) + wcslen(lpDatabaseName
) * sizeof(WCHAR
));
159 return ERROR_NOT_ENOUGH_MEMORY
;
161 Ptr
->Handle
.Tag
= MANAGER_TAG
;
162 Ptr
->Handle
.RefCount
= 1;
164 /* FIXME: initialize more data here */
166 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
168 *Handle
= (SC_HANDLE
)Ptr
;
170 return ERROR_SUCCESS
;
175 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
180 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
182 sizeof(SERVICE_HANDLE
));
184 return ERROR_NOT_ENOUGH_MEMORY
;
186 Ptr
->Handle
.Tag
= SERVICE_TAG
;
187 Ptr
->Handle
.RefCount
= 1;
189 /* FIXME: initialize more data here */
190 Ptr
->ServiceEntry
= lpServiceEntry
;
192 *Handle
= (SC_HANDLE
)Ptr
;
194 return ERROR_SUCCESS
;
199 ScmCheckAccess(SC_HANDLE Handle
,
200 DWORD dwDesiredAccess
)
202 PMANAGER_HANDLE hMgr
;
204 hMgr
= (PMANAGER_HANDLE
)Handle
;
205 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
207 RtlMapGenericMask(&dwDesiredAccess
,
210 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
212 return ERROR_SUCCESS
;
214 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
216 RtlMapGenericMask(&dwDesiredAccess
,
219 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
221 return ERROR_SUCCESS
;
224 return ERROR_INVALID_HANDLE
;
229 ScmAssignNewTag(PSERVICE lpService
)
232 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
233 lpService
->dwTag
= 0;
234 return ERROR_SUCCESS
;
239 DWORD
RCloseServiceHandle(
240 handle_t BindingHandle
,
241 LPSC_RPC_HANDLE hSCObject
)
243 PMANAGER_HANDLE hManager
;
245 DPRINT("RCloseServiceHandle() called\n");
247 DPRINT("hSCObject = %p\n", *hSCObject
);
250 return ERROR_INVALID_HANDLE
;
252 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
253 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
255 DPRINT("Found manager handle\n");
257 hManager
->Handle
.RefCount
--;
258 if (hManager
->Handle
.RefCount
== 0)
260 /* FIXME: add cleanup code */
262 HeapFree(GetProcessHeap(), 0, hManager
);
265 DPRINT("RCloseServiceHandle() done\n");
266 return ERROR_SUCCESS
;
268 else if (hManager
->Handle
.Tag
== SERVICE_TAG
)
270 DPRINT("Found service handle\n");
272 hManager
->Handle
.RefCount
--;
273 if (hManager
->Handle
.RefCount
== 0)
275 /* FIXME: add cleanup code */
277 HeapFree(GetProcessHeap(), 0, hManager
);
280 DPRINT("RCloseServiceHandle() done\n");
281 return ERROR_SUCCESS
;
284 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
286 return ERROR_INVALID_HANDLE
;
291 DWORD
RControlService(
292 handle_t BindingHandle
,
293 SC_RPC_HANDLE hService
,
295 LPSERVICE_STATUS lpServiceStatus
)
297 PSERVICE_HANDLE hSvc
;
299 ACCESS_MASK DesiredAccess
;
300 DWORD dwError
= ERROR_SUCCESS
;
302 DPRINT("RControlService() called\n");
305 return ERROR_SHUTDOWN_IN_PROGRESS
;
307 /* Check the service handle */
308 hSvc
= (PSERVICE_HANDLE
)hService
;
309 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
311 DPRINT1("Invalid handle tag!\n");
312 return ERROR_INVALID_HANDLE
;
315 /* Check access rights */
318 case SERVICE_CONTROL_STOP
:
319 DesiredAccess
= SERVICE_STOP
;
322 case SERVICE_CONTROL_PAUSE
:
323 case SERVICE_CONTROL_CONTINUE
:
324 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
327 case SERVICE_INTERROGATE
:
328 DesiredAccess
= SERVICE_INTERROGATE
;
332 if (dwControl
>= 128 && dwControl
<= 255)
333 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
335 DesiredAccess
= SERVICE_QUERY_CONFIG
|
336 SERVICE_CHANGE_CONFIG
|
337 SERVICE_QUERY_STATUS
|
339 SERVICE_PAUSE_CONTINUE
;
343 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
345 return ERROR_ACCESS_DENIED
;
347 /* Check the service entry point */
348 lpService
= hSvc
->ServiceEntry
;
349 if (lpService
== NULL
)
351 DPRINT1("lpService == NULL!\n");
352 return ERROR_INVALID_HANDLE
;
355 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
357 /* Send control code to the driver */
358 dwError
= ScmControlDriver(lpService
,
364 /* Send control code to the service */
365 dwError
= ScmControlService(lpService
,
370 /* Return service status information */
371 RtlCopyMemory(lpServiceStatus
,
373 sizeof(SERVICE_STATUS
));
380 DWORD
RDeleteService(
381 handle_t BindingHandle
,
382 SC_RPC_HANDLE hService
)
384 PSERVICE_HANDLE hSvc
;
388 DPRINT("RDeleteService() called\n");
391 return ERROR_SHUTDOWN_IN_PROGRESS
;
393 hSvc
= (PSERVICE_HANDLE
)hService
;
394 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
395 return ERROR_INVALID_HANDLE
;
397 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
398 STANDARD_RIGHTS_REQUIRED
))
399 return ERROR_ACCESS_DENIED
;
401 lpService
= hSvc
->ServiceEntry
;
402 if (lpService
== NULL
)
404 DPRINT1("lpService == NULL!\n");
405 return ERROR_INVALID_HANDLE
;
408 /* FIXME: Acquire service database lock exclusively */
410 if (lpService
->bDeleted
)
412 DPRINT1("The service has already been marked for delete!\n");
413 return ERROR_SERVICE_MARKED_FOR_DELETE
;
416 /* Mark service for delete */
417 lpService
->bDeleted
= TRUE
;
419 dwError
= ScmMarkServiceForDelete(lpService
);
421 /* FIXME: Release service database lock */
423 DPRINT("RDeleteService() done\n");
430 DWORD
RLockServiceDatabase(
431 handle_t BindingHandle
,
432 SC_RPC_HANDLE hSCManager
,
433 LPSC_RPC_LOCK lpLock
)
435 PMANAGER_HANDLE hMgr
;
437 DPRINT("RLockServiceDatabase() called\n");
441 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
442 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
443 return ERROR_INVALID_HANDLE
;
445 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
447 return ERROR_ACCESS_DENIED
;
449 // return ScmLockDatabase(0, hMgr->0xC, hLock);
451 /* FIXME: Lock the database */
452 *lpLock
= (void *)0x12345678; /* Dummy! */
454 return ERROR_SUCCESS
;
459 DWORD
RQueryServiceObjectSecurity(
460 handle_t BindingHandle
,
461 SC_RPC_HANDLE hService
,
462 SECURITY_INFORMATION dwSecurityInformation
,
463 LPBYTE lpSecurityDescriptor
,
465 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
468 PSERVICE_HANDLE hSvc
;
470 ULONG DesiredAccess
= 0;
475 DPRINT("RQueryServiceObjectSecurity() called\n");
477 hSvc
= (PSERVICE_HANDLE
)hService
;
478 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
480 DPRINT1("Invalid handle tag!\n");
481 return ERROR_INVALID_HANDLE
;
484 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
485 GROUP_SECURITY_INFORMATION
||
486 OWNER_SECURITY_INFORMATION
))
487 DesiredAccess
|= READ_CONTROL
;
489 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
490 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
492 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
495 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
496 return ERROR_ACCESS_DENIED
;
499 lpService
= hSvc
->ServiceEntry
;
500 if (lpService
== NULL
)
502 DPRINT1("lpService == NULL!\n");
503 return ERROR_INVALID_HANDLE
;
506 /* FIXME: Lock the service list */
508 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
509 dwSecurityInformation
,
510 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
511 dwSecuityDescriptorSize
,
514 /* FIXME: Unlock the service list */
516 if (NT_SUCCESS(Status
))
518 *pcbBytesNeeded
= dwBytesNeeded
;
519 dwError
= STATUS_SUCCESS
;
521 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
523 *pcbBytesNeeded
= dwBytesNeeded
;
524 dwError
= ERROR_INSUFFICIENT_BUFFER
;
526 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
528 dwError
= ERROR_GEN_FAILURE
;
532 dwError
= RtlNtStatusToDosError(Status
);
538 return ERROR_CALL_NOT_IMPLEMENTED
;
543 DWORD
RSetServiceObjectSecurity(
544 handle_t BindingHandle
,
545 SC_RPC_HANDLE hService
,
546 DWORD dwSecurityInformation
,
547 LPBYTE lpSecurityDescriptor
,
548 DWORD dwSecuityDescriptorSize
)
550 PSERVICE_HANDLE hSvc
;
552 ULONG DesiredAccess
= 0;
553 HANDLE hToken
= NULL
;
558 DPRINT1("RSetServiceObjectSecurity() called\n");
560 hSvc
= (PSERVICE_HANDLE
)hService
;
561 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
563 DPRINT1("Invalid handle tag!\n");
564 return ERROR_INVALID_HANDLE
;
567 if (dwSecurityInformation
== 0 ||
568 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
569 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
570 return ERROR_INVALID_PARAMETER
;
572 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
573 return ERROR_INVALID_PARAMETER
;
575 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
576 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
578 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
579 DesiredAccess
|= WRITE_DAC
;
581 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
582 DesiredAccess
|= WRITE_OWNER
;
584 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
585 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
586 return ERROR_INVALID_PARAMETER
;
588 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
589 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
590 return ERROR_INVALID_PARAMETER
;
592 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
595 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
596 return ERROR_ACCESS_DENIED
;
599 lpService
= hSvc
->ServiceEntry
;
600 if (lpService
== NULL
)
602 DPRINT1("lpService == NULL!\n");
603 return ERROR_INVALID_HANDLE
;
606 if (lpService
->bDeleted
)
607 return ERROR_SERVICE_MARKED_FOR_DELETE
;
609 RpcImpersonateClient(NULL
);
611 Status
= NtOpenThreadToken(NtCurrentThread(),
615 if (!NT_SUCCESS(Status
))
616 return RtlNtStatusToDosError(Status
);
620 /* FIXME: Lock service database */
623 Status
= RtlSetSecurityObject(dwSecurityInformation
,
624 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
625 &lpService
->lpSecurityDescriptor
,
628 if (!NT_SUCCESS(Status
))
630 dwError
= RtlNtStatusToDosError(Status
);
635 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
636 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
638 if (dwError
!= ERROR_SUCCESS
)
642 dwError
= ERROR_SUCCESS
;
643 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
644 // lpService->lpSecurityDescriptor);
646 RegFlushKey(hServiceKey
);
647 RegCloseKey(hServiceKey
);
654 /* FIXME: Unlock service database */
656 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
663 DWORD
RQueryServiceStatus(
664 handle_t BindingHandle
,
665 SC_RPC_HANDLE hService
,
666 LPSERVICE_STATUS lpServiceStatus
)
668 PSERVICE_HANDLE hSvc
;
671 DPRINT("RQueryServiceStatus() called\n");
674 return ERROR_SHUTDOWN_IN_PROGRESS
;
676 hSvc
= (PSERVICE_HANDLE
)hService
;
677 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
679 DPRINT1("Invalid handle tag!\n");
680 return ERROR_INVALID_HANDLE
;
683 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
684 SERVICE_QUERY_STATUS
))
686 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
687 return ERROR_ACCESS_DENIED
;
690 lpService
= hSvc
->ServiceEntry
;
691 if (lpService
== NULL
)
693 DPRINT1("lpService == NULL!\n");
694 return ERROR_INVALID_HANDLE
;
697 /* Return service status information */
698 RtlCopyMemory(lpServiceStatus
,
700 sizeof(SERVICE_STATUS
));
702 return ERROR_SUCCESS
;
707 DWORD
RSetServiceStatus(
708 handle_t BindingHandle
,
709 SC_RPC_HANDLE hServiceStatus
,
710 LPSERVICE_STATUS lpServiceStatus
)
714 DPRINT("RSetServiceStatus() called\n");
717 return ERROR_SHUTDOWN_IN_PROGRESS
;
719 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
720 if (lpService
== NULL
)
722 DPRINT1("lpService == NULL!\n");
723 return ERROR_INVALID_HANDLE
;
726 RtlCopyMemory(&lpService
->Status
,
728 sizeof(SERVICE_STATUS
));
730 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
731 DPRINT("RSetServiceStatus() done\n");
733 return ERROR_SUCCESS
;
738 DWORD
RUnlockServiceDatabase(
739 handle_t BindingHandle
,
743 return ERROR_SUCCESS
;
748 DWORD
RNotifyBootConfigStatus(
749 handle_t BindingHandle
,
750 SVCCTL_HANDLEW lpMachineName
,
751 DWORD BootAcceptable
)
754 return ERROR_CALL_NOT_IMPLEMENTED
;
759 DWORD
RSetServiceBitsW(
760 handle_t BindingHandle
,
761 SC_RPC_HANDLE hServiceStatus
,
764 int bUpdateImmediately
,
768 return ERROR_CALL_NOT_IMPLEMENTED
;
773 DWORD
RChangeServiceConfigW(
774 handle_t BindingHandle
,
775 SC_RPC_HANDLE hService
,
778 DWORD dwErrorControl
,
779 LPWSTR lpBinaryPathName
,
780 LPWSTR lpLoadOrderGroup
,
782 LPBYTE lpDependencies
,
784 LPWSTR lpServiceStartName
,
787 LPWSTR lpDisplayName
)
789 DWORD dwError
= ERROR_SUCCESS
;
790 PSERVICE_HANDLE hSvc
;
791 PSERVICE lpService
= NULL
;
792 HKEY hServiceKey
= NULL
;
794 DPRINT("RChangeServiceConfigW() called\n");
795 DPRINT("dwServiceType = %lu\n", dwServiceType
);
796 DPRINT("dwStartType = %lu\n", dwStartType
);
797 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
798 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
799 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
800 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
803 return ERROR_SHUTDOWN_IN_PROGRESS
;
805 hSvc
= (PSERVICE_HANDLE
)hService
;
806 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
808 DPRINT1("Invalid handle tag!\n");
809 return ERROR_INVALID_HANDLE
;
812 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
813 SERVICE_CHANGE_CONFIG
))
815 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
816 return ERROR_ACCESS_DENIED
;
819 lpService
= hSvc
->ServiceEntry
;
820 if (lpService
== NULL
)
822 DPRINT1("lpService == NULL!\n");
823 return ERROR_INVALID_HANDLE
;
826 /* FIXME: Lock database exclusively */
828 if (lpService
->bDeleted
)
830 /* FIXME: Unlock database */
831 DPRINT1("The service has already been marked for delete!\n");
832 return ERROR_SERVICE_MARKED_FOR_DELETE
;
835 /* Open the service key */
836 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
839 if (dwError
!= ERROR_SUCCESS
)
842 /* Write service data to the registry */
843 /* Set the display name */
844 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
846 RegSetValueExW(hServiceKey
,
850 (LPBYTE
)lpDisplayName
,
851 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
852 /* FIXME: update lpService->lpDisplayName */
855 if (dwServiceType
!= SERVICE_NO_CHANGE
)
857 /* Set the service type */
858 dwError
= RegSetValueExW(hServiceKey
,
862 (LPBYTE
)&dwServiceType
,
864 if (dwError
!= ERROR_SUCCESS
)
867 lpService
->Status
.dwServiceType
= dwServiceType
;
870 if (dwStartType
!= SERVICE_NO_CHANGE
)
872 /* Set the start value */
873 dwError
= RegSetValueExW(hServiceKey
,
877 (LPBYTE
)&dwStartType
,
879 if (dwError
!= ERROR_SUCCESS
)
882 lpService
->dwStartType
= dwStartType
;
885 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
887 /* Set the error control value */
888 dwError
= RegSetValueExW(hServiceKey
,
892 (LPBYTE
)&dwErrorControl
,
894 if (dwError
!= ERROR_SUCCESS
)
897 lpService
->dwErrorControl
= dwErrorControl
;
901 /* FIXME: set the new ImagePath value */
903 /* Set the image path */
904 if (dwServiceType
& SERVICE_WIN32
)
906 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
908 dwError
= RegSetValueExW(hServiceKey
,
912 (LPBYTE
)lpBinaryPathName
,
913 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
914 if (dwError
!= ERROR_SUCCESS
)
918 else if (dwServiceType
& SERVICE_DRIVER
)
920 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
922 dwError
= RegSetValueExW(hServiceKey
,
927 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
928 if (dwError
!= ERROR_SUCCESS
)
934 /* Set the group name */
935 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
937 dwError
= RegSetValueExW(hServiceKey
,
941 (LPBYTE
)lpLoadOrderGroup
,
942 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
943 if (dwError
!= ERROR_SUCCESS
)
945 /* FIXME: update lpService->lpServiceGroup */
948 if (lpdwTagId
!= NULL
)
950 dwError
= ScmAssignNewTag(lpService
);
951 if (dwError
!= ERROR_SUCCESS
)
954 dwError
= RegSetValueExW(hServiceKey
,
958 (LPBYTE
)&lpService
->dwTag
,
960 if (dwError
!= ERROR_SUCCESS
)
963 *lpdwTagId
= lpService
->dwTag
;
966 /* Write dependencies */
967 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
969 dwError
= ScmWriteDependencies(hServiceKey
,
970 (LPWSTR
)lpDependencies
,
972 if (dwError
!= ERROR_SUCCESS
)
976 if (lpPassword
!= NULL
)
978 /* FIXME: Write password */
981 /* FIXME: Unlock database */
984 if (hServiceKey
!= NULL
)
985 RegCloseKey(hServiceKey
);
987 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
992 /* Create a path suitable for the bootloader out of the full path */
994 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
996 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
999 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1000 OBJECT_ATTRIBUTES ObjectAttributes
;
1002 HANDLE SymbolicLinkHandle
;
1004 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1006 ServiceNameLen
= wcslen(CanonName
);
1007 /* First check, if it's already good */
1008 if (ServiceNameLen
> 12 &&
1009 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1011 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1013 if (*RelativeName
== NULL
)
1015 DPRINT1("Error allocating memory for boot driver name!\n");
1016 return ERROR_NOT_ENOUGH_MEMORY
;
1020 wcscpy(*RelativeName
, CanonName
);
1022 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1023 return ERROR_SUCCESS
;
1026 /* If it has %SystemRoot% prefix, substitute it to \System*/
1027 if (ServiceNameLen
> 13 &&
1028 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1030 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1031 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1033 if (*RelativeName
== NULL
)
1035 DPRINT1("Error allocating memory for boot driver name!\n");
1036 return ERROR_NOT_ENOUGH_MEMORY
;
1040 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1041 wcscat(*RelativeName
, CanonName
+ 13);
1043 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1044 return ERROR_SUCCESS
;
1047 /* Get buffer size needed for expanding env strings */
1048 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1050 if (BufferSize
<= 1)
1052 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1053 return ERROR_INVALID_ENVIRONMENT
;
1056 /* Allocate memory, since the size is known now */
1057 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1060 DPRINT1("Error allocating memory for boot driver name!\n");
1061 return ERROR_NOT_ENOUGH_MEMORY
;
1065 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1068 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1069 LocalFree(Expanded
);
1070 return ERROR_NOT_ENOUGH_MEMORY
;
1073 /* Convert to NY-style path */
1074 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1076 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1077 return ERROR_INVALID_ENVIRONMENT
;
1080 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1082 /* No need to keep the dos-path anymore */
1083 LocalFree(Expanded
);
1085 /* Copy it to the allocated place */
1086 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1089 DPRINT1("Error allocating memory for boot driver name!\n");
1090 return ERROR_NOT_ENOUGH_MEMORY
;
1093 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1094 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1095 Expanded
[ExpandedLen
] = 0;
1097 if (ServiceNameLen
> ExpandedLen
&&
1098 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1100 /* Only \SystemRoot\ is missing */
1101 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1102 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1104 if (*RelativeName
== NULL
)
1106 DPRINT1("Error allocating memory for boot driver name!\n");
1107 LocalFree(Expanded
);
1108 return ERROR_NOT_ENOUGH_MEMORY
;
1111 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1112 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1114 RtlFreeUnicodeString(&NtPathName
);
1115 return ERROR_SUCCESS
;
1118 /* The most complex case starts here */
1119 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1120 InitializeObjectAttributes(&ObjectAttributes
,
1122 OBJ_CASE_INSENSITIVE
,
1126 /* Open this symlink */
1127 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1129 if (NT_SUCCESS(Status
))
1131 LinkTarget
.Length
= 0;
1132 LinkTarget
.MaximumLength
= 0;
1134 DPRINT("Opened symbolic link object\n");
1136 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1137 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1139 /* Check if required buffer size is sane */
1140 if (BufferSize
> 0xFFFD)
1142 DPRINT1("Too large buffer required\n");
1145 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1146 LocalFree(Expanded
);
1147 return ERROR_NOT_ENOUGH_MEMORY
;
1150 /* Alloc the string */
1151 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1152 if (!LinkTarget
.Buffer
)
1154 DPRINT1("Unable to alloc buffer\n");
1155 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1156 LocalFree(Expanded
);
1157 return ERROR_NOT_ENOUGH_MEMORY
;
1160 /* Do a real query now */
1161 LinkTarget
.Length
= BufferSize
;
1162 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1164 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1165 if (NT_SUCCESS(Status
))
1167 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1169 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1170 if ((ServiceNameLen
> ExpandedLen
) &&
1171 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1173 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1174 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1176 if (*RelativeName
== NULL
)
1178 DPRINT1("Unable to alloc buffer\n");
1179 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1180 LocalFree(Expanded
);
1181 RtlFreeUnicodeString(&NtPathName
);
1182 return ERROR_NOT_ENOUGH_MEMORY
;
1185 /* Copy it over, substituting the first part
1187 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1188 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1191 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1192 LocalFree(Expanded
);
1193 RtlFreeUnicodeString(&NtPathName
);
1195 /* Return success */
1196 return ERROR_SUCCESS
;
1200 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1201 LocalFree(Expanded
);
1202 RtlFreeUnicodeString(&NtPathName
);
1203 return ERROR_INVALID_PARAMETER
;
1208 DPRINT1("Error, Status = %08X\n", Status
);
1209 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1210 LocalFree(Expanded
);
1211 RtlFreeUnicodeString(&NtPathName
);
1212 return ERROR_INVALID_PARAMETER
;
1217 DPRINT1("Error, Status = %08X\n", Status
);
1218 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1219 LocalFree(Expanded
);
1220 RtlFreeUnicodeString(&NtPathName
);
1221 return ERROR_INVALID_PARAMETER
;
1226 DPRINT1("Error, Status = %08X\n", Status
);
1227 LocalFree(Expanded
);
1228 return ERROR_INVALID_PARAMETER
;
1232 *RelativeName
= NULL
;
1233 return ERROR_INVALID_PARAMETER
;
1237 ScmCanonDriverImagePath(DWORD dwStartType
,
1238 wchar_t *lpServiceName
,
1239 wchar_t **lpCanonName
)
1241 DWORD ServiceNameLen
, Result
;
1242 UNICODE_STRING NtServiceName
;
1243 WCHAR
*RelativeName
;
1244 WCHAR
*SourceName
= lpServiceName
;
1246 /* Calculate the length of the service's name */
1247 ServiceNameLen
= wcslen(lpServiceName
);
1249 /* 12 is wcslen(L"\\SystemRoot\\") */
1250 if (ServiceNameLen
> 12 &&
1251 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1253 /* SystemRoot prefix is already included */
1255 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1257 if (*lpCanonName
== NULL
)
1259 DPRINT1("Error allocating memory for canonized service name!\n");
1260 return ERROR_NOT_ENOUGH_MEMORY
;
1263 /* If it's a boot-time driver, it must be systemroot relative */
1264 if (dwStartType
== SERVICE_BOOT_START
)
1268 wcscpy(*lpCanonName
, SourceName
);
1270 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1274 /* Check if it has %SystemRoot% (len=13) */
1275 if (ServiceNameLen
> 13 &&
1276 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1278 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1279 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1281 if (*lpCanonName
== NULL
)
1283 DPRINT1("Error allocating memory for canonized service name!\n");
1284 return ERROR_NOT_ENOUGH_MEMORY
;
1287 /* If it's a boot-time driver, it must be systemroot relative */
1288 if (dwStartType
== SERVICE_BOOT_START
)
1289 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1291 wcscat(*lpCanonName
, lpServiceName
+ 13);
1293 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1297 /* Check if it's a relative path name */
1298 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1300 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1302 if (*lpCanonName
== NULL
)
1304 DPRINT1("Error allocating memory for canonized service name!\n");
1305 return ERROR_NOT_ENOUGH_MEMORY
;
1308 /* Just copy it over without changing */
1309 wcscpy(*lpCanonName
, lpServiceName
);
1314 /* It seems to be a DOS path, convert it */
1315 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1317 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1318 return ERROR_INVALID_PARAMETER
;
1321 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1323 if (*lpCanonName
== NULL
)
1325 DPRINT1("Error allocating memory for canonized service name!\n");
1326 RtlFreeUnicodeString(&NtServiceName
);
1327 return ERROR_NOT_ENOUGH_MEMORY
;
1330 /* Copy the string */
1331 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1333 /* The unicode string is not needed anymore */
1334 RtlFreeUnicodeString(&NtServiceName
);
1336 if (dwStartType
!= SERVICE_BOOT_START
)
1338 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1342 /* The service is boot-started, so must be relative */
1343 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1346 /* There is a problem, free name and return */
1347 LocalFree(*lpCanonName
);
1348 DPRINT1("Error converting named!\n");
1352 ASSERT(RelativeName
);
1354 /* Copy that string */
1355 wcscpy(*lpCanonName
, RelativeName
+ 12);
1357 /* Free the allocated buffer */
1358 LocalFree(RelativeName
);
1360 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1368 DWORD
RCreateServiceW(
1369 handle_t BindingHandle
,
1370 SC_RPC_HANDLE hSCManager
,
1371 LPWSTR lpServiceName
,
1372 LPWSTR lpDisplayName
,
1373 DWORD dwDesiredAccess
,
1374 DWORD dwServiceType
,
1376 DWORD dwErrorControl
,
1377 LPWSTR lpBinaryPathName
,
1378 LPWSTR lpLoadOrderGroup
,
1380 LPBYTE lpDependencies
,
1382 LPWSTR lpServiceStartName
,
1385 LPSC_RPC_HANDLE lpServiceHandle
)
1387 PMANAGER_HANDLE hManager
;
1388 DWORD dwError
= ERROR_SUCCESS
;
1389 PSERVICE lpService
= NULL
;
1390 SC_HANDLE hServiceHandle
= NULL
;
1391 LPWSTR lpImagePath
= NULL
;
1392 HKEY hServiceKey
= NULL
;
1394 DPRINT("RCreateServiceW() called\n");
1395 DPRINT("lpServiceName = %S\n", lpServiceName
);
1396 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1397 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1398 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1399 DPRINT("dwStartType = %lu\n", dwStartType
);
1400 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1401 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1402 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1405 return ERROR_SHUTDOWN_IN_PROGRESS
;
1407 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1408 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1410 DPRINT1("Invalid manager handle!\n");
1411 return ERROR_INVALID_HANDLE
;
1414 /* Check access rights */
1415 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1416 SC_MANAGER_CREATE_SERVICE
))
1418 DPRINT1("Insufficient access rights! 0x%lx\n",
1419 hManager
->Handle
.DesiredAccess
);
1420 return ERROR_ACCESS_DENIED
;
1423 /* Fail if the service already exists! */
1424 if (ScmGetServiceEntryByName(lpServiceName
) != NULL
)
1425 return ERROR_SERVICE_EXISTS
;
1427 if (dwServiceType
& SERVICE_DRIVER
)
1429 dwError
= ScmCanonDriverImagePath(dwStartType
,
1433 if (dwError
!= ERROR_SUCCESS
)
1437 /* Allocate a new service entry */
1438 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1440 if (dwError
!= ERROR_SUCCESS
)
1443 /* Fill the new service entry */
1444 lpService
->Status
.dwServiceType
= dwServiceType
;
1445 lpService
->dwStartType
= dwStartType
;
1446 lpService
->dwErrorControl
= dwErrorControl
;
1448 /* Fill the display name */
1449 if (lpDisplayName
!= NULL
&&
1450 *lpDisplayName
!= 0 &&
1451 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1453 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1454 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1455 if (lpService
->lpDisplayName
== NULL
)
1457 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1460 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1463 /* Assign the service to a group */
1464 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1466 dwError
= ScmSetServiceGroup(lpService
,
1468 if (dwError
!= ERROR_SUCCESS
)
1472 /* Assign a new tag */
1473 if (lpdwTagId
!= NULL
)
1475 dwError
= ScmAssignNewTag(lpService
);
1476 if (dwError
!= ERROR_SUCCESS
)
1480 /* Write service data to the registry */
1481 /* Create the service key */
1482 dwError
= ScmCreateServiceKey(lpServiceName
,
1485 if (dwError
!= ERROR_SUCCESS
)
1488 /* Set the display name */
1489 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1491 RegSetValueExW(hServiceKey
,
1495 (LPBYTE
)lpDisplayName
,
1496 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1499 /* Set the service type */
1500 dwError
= RegSetValueExW(hServiceKey
,
1504 (LPBYTE
)&dwServiceType
,
1506 if (dwError
!= ERROR_SUCCESS
)
1509 /* Set the start value */
1510 dwError
= RegSetValueExW(hServiceKey
,
1514 (LPBYTE
)&dwStartType
,
1516 if (dwError
!= ERROR_SUCCESS
)
1519 /* Set the error control value */
1520 dwError
= RegSetValueExW(hServiceKey
,
1524 (LPBYTE
)&dwErrorControl
,
1526 if (dwError
!= ERROR_SUCCESS
)
1529 /* Set the image path */
1530 if (dwServiceType
& SERVICE_WIN32
)
1532 dwError
= RegSetValueExW(hServiceKey
,
1536 (LPBYTE
)lpBinaryPathName
,
1537 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1538 if (dwError
!= ERROR_SUCCESS
)
1541 else if (dwServiceType
& SERVICE_DRIVER
)
1543 dwError
= RegSetValueExW(hServiceKey
,
1547 (LPBYTE
)lpImagePath
,
1548 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1549 if (dwError
!= ERROR_SUCCESS
)
1553 /* Set the group name */
1554 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1556 dwError
= RegSetValueExW(hServiceKey
,
1560 (LPBYTE
)lpLoadOrderGroup
,
1561 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1562 if (dwError
!= ERROR_SUCCESS
)
1566 if (lpdwTagId
!= NULL
)
1568 dwError
= RegSetValueExW(hServiceKey
,
1572 (LPBYTE
)&lpService
->dwTag
,
1574 if (dwError
!= ERROR_SUCCESS
)
1578 /* Write dependencies */
1579 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1581 dwError
= ScmWriteDependencies(hServiceKey
,
1582 (LPWSTR
)lpDependencies
,
1584 if (dwError
!= ERROR_SUCCESS
)
1588 if (lpPassword
!= NULL
)
1590 /* FIXME: Write password */
1593 dwError
= ScmCreateServiceHandle(lpService
,
1595 if (dwError
!= ERROR_SUCCESS
)
1598 dwError
= ScmCheckAccess(hServiceHandle
,
1600 if (dwError
!= ERROR_SUCCESS
)
1604 if (hServiceKey
!= NULL
)
1605 RegCloseKey(hServiceKey
);
1607 if (dwError
== ERROR_SUCCESS
)
1609 DPRINT("hService %p\n", hServiceHandle
);
1610 *lpServiceHandle
= (unsigned long)hServiceHandle
; /* FIXME: 64 bit portability */
1612 if (lpdwTagId
!= NULL
)
1613 *lpdwTagId
= lpService
->dwTag
;
1617 /* Release the display name buffer */
1618 if (lpService
->lpServiceName
!= NULL
)
1619 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1623 /* Remove the service handle */
1624 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1627 if (lpService
!= NULL
)
1629 /* FIXME: remove the service entry */
1633 if (lpImagePath
!= NULL
)
1634 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1636 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
1643 DWORD
REnumDependentServicesW(
1644 handle_t BindingHandle
,
1645 SC_RPC_HANDLE hService
,
1646 DWORD dwServiceState
,
1649 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
1650 LPBOUNDED_DWORD_256K lpServicesReturned
)
1652 DWORD dwError
= ERROR_SUCCESS
;
1655 *pcbBytesNeeded
= 0;
1656 *lpServicesReturned
= 0;
1658 DPRINT1("REnumDependentServicesW() done (Error %lu)\n", dwError
);
1665 DWORD
REnumServicesStatusW(
1666 handle_t BindingHandle
,
1667 SC_RPC_HANDLE hSCManager
,
1668 DWORD dwServiceType
,
1669 DWORD dwServiceState
,
1672 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
1673 LPBOUNDED_DWORD_256K lpServicesReturned
,
1674 LPBOUNDED_DWORD_256K lpResumeHandle
)
1676 PMANAGER_HANDLE hManager
;
1678 DWORD dwError
= ERROR_SUCCESS
;
1679 PLIST_ENTRY ServiceEntry
;
1680 PSERVICE CurrentService
;
1682 DWORD dwRequiredSize
;
1683 DWORD dwServiceCount
;
1685 DWORD dwLastResumeCount
;
1686 LPENUM_SERVICE_STATUSW lpStatusPtr
;
1689 DPRINT("REnumServicesStatusW() called\n");
1692 return ERROR_SHUTDOWN_IN_PROGRESS
;
1694 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1695 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1697 DPRINT1("Invalid manager handle!\n");
1698 return ERROR_INVALID_HANDLE
;
1701 /* Check access rights */
1702 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1703 SC_MANAGER_ENUMERATE_SERVICE
))
1705 DPRINT1("Insufficient access rights! 0x%lx\n",
1706 hManager
->Handle
.DesiredAccess
);
1707 return ERROR_ACCESS_DENIED
;
1710 *pcbBytesNeeded
= 0;
1711 *lpServicesReturned
= 0;
1713 dwLastResumeCount
= *lpResumeHandle
;
1715 /* FIXME: Lock the service list shared */
1717 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
1718 if (lpService
== NULL
)
1720 dwError
= ERROR_SUCCESS
;
1727 for (ServiceEntry
= &lpService
->ServiceListEntry
;
1728 ServiceEntry
!= &ServiceListHead
;
1729 ServiceEntry
= ServiceEntry
->Flink
)
1731 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1735 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1738 dwState
= SERVICE_ACTIVE
;
1739 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1740 dwState
= SERVICE_INACTIVE
;
1742 if ((dwState
& dwServiceState
) == 0)
1745 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
1746 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1747 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1749 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
1751 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
1752 dwRequiredSize
+= dwSize
;
1754 dwLastResumeCount
= CurrentService
->dwResumeCount
;
1758 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
1764 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
1765 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
1768 ServiceEntry
!= &ServiceListHead
;
1769 ServiceEntry
= ServiceEntry
->Flink
)
1771 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1775 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1778 dwState
= SERVICE_ACTIVE
;
1779 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1780 dwState
= SERVICE_INACTIVE
;
1782 if ((dwState
& dwServiceState
) == 0)
1785 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
1786 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1787 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
1789 dwError
= ERROR_MORE_DATA
;
1792 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
1794 *lpResumeHandle
= dwLastResumeCount
;
1795 *lpServicesReturned
= dwServiceCount
;
1796 *pcbBytesNeeded
= dwRequiredSize
;
1798 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
1799 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
1800 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
1803 for (ServiceEntry
= &lpService
->ServiceListEntry
;
1804 ServiceEntry
!= &ServiceListHead
;
1805 ServiceEntry
= ServiceEntry
->Flink
)
1807 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1811 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1814 dwState
= SERVICE_ACTIVE
;
1815 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1816 dwState
= SERVICE_INACTIVE
;
1818 if ((dwState
& dwServiceState
) == 0)
1821 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
1822 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1823 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1825 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
1827 /* Copy the service name */
1829 CurrentService
->lpServiceName
);
1830 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
1831 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
1833 /* Copy the display name */
1835 CurrentService
->lpDisplayName
);
1836 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
1837 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
1839 /* Copy the status information */
1840 memcpy(&lpStatusPtr
->ServiceStatus
,
1841 &CurrentService
->Status
,
1842 sizeof(SERVICE_STATUS
));
1845 dwRequiredSize
+= dwSize
;
1855 /* FIXME: Unlock the service list */
1857 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
1864 DWORD
ROpenSCManagerW(
1865 handle_t BindingHandle
,
1866 LPWSTR lpMachineName
,
1867 LPWSTR lpDatabaseName
,
1868 DWORD dwDesiredAccess
,
1869 LPSC_RPC_HANDLE lpScHandle
)
1874 DPRINT("ROpenSCManagerW() called\n");
1875 DPRINT("lpMachineName = %p\n", lpMachineName
);
1876 DPRINT("lpMachineName: %S\n", lpMachineName
);
1877 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
1878 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
1879 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
1882 return ERROR_SHUTDOWN_IN_PROGRESS
;
1885 return ERROR_INVALID_PARAMETER
;
1887 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
1889 if (dwError
!= ERROR_SUCCESS
)
1891 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
1895 /* Check the desired access */
1896 dwError
= ScmCheckAccess(hHandle
,
1897 dwDesiredAccess
| SC_MANAGER_CONNECT
);
1898 if (dwError
!= ERROR_SUCCESS
)
1900 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1901 HeapFree(GetProcessHeap(), 0, hHandle
);
1905 *lpScHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
1906 DPRINT("*hScm = %p\n", *lpScHandle
);
1908 DPRINT("ROpenSCManagerW() done\n");
1910 return ERROR_SUCCESS
;
1915 DWORD
ROpenServiceW(
1916 handle_t BindingHandle
,
1917 SC_RPC_HANDLE hSCManager
,
1918 LPWSTR lpServiceName
,
1919 DWORD dwDesiredAccess
,
1920 LPSC_RPC_HANDLE lpServiceHandle
)
1923 PMANAGER_HANDLE hManager
;
1927 DPRINT("ROpenServiceW() called\n");
1928 DPRINT("hSCManager = %p\n", hSCManager
);
1929 DPRINT("lpServiceName = %p\n", lpServiceName
);
1930 DPRINT("lpServiceName: %S\n", lpServiceName
);
1931 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
1934 return ERROR_SHUTDOWN_IN_PROGRESS
;
1936 if (!lpServiceHandle
)
1937 return ERROR_INVALID_PARAMETER
;
1939 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1940 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1942 DPRINT1("Invalid manager handle!\n");
1943 return ERROR_INVALID_HANDLE
;
1946 /* FIXME: Lock the service list */
1948 /* Get service database entry */
1949 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1950 if (lpService
== NULL
)
1952 DPRINT("Could not find a service!\n");
1953 return ERROR_SERVICE_DOES_NOT_EXIST
;
1956 /* Create a service handle */
1957 dwError
= ScmCreateServiceHandle(lpService
,
1959 if (dwError
!= ERROR_SUCCESS
)
1961 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
1965 /* Check the desired access */
1966 dwError
= ScmCheckAccess(hHandle
,
1968 if (dwError
!= ERROR_SUCCESS
)
1970 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1971 HeapFree(GetProcessHeap(), 0, hHandle
);
1975 *lpServiceHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
1976 DPRINT("*hService = %p\n", *lpServiceHandle
);
1978 DPRINT("ROpenServiceW() done\n");
1980 return ERROR_SUCCESS
;
1985 DWORD
RQueryServiceConfigW(
1986 handle_t BindingHandle
,
1987 SC_RPC_HANDLE hService
,
1988 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1990 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
1992 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
1993 DWORD dwError
= ERROR_SUCCESS
;
1994 PSERVICE_HANDLE hSvc
;
1995 PSERVICE lpService
= NULL
;
1996 HKEY hServiceKey
= NULL
;
1997 LPWSTR lpImagePath
= NULL
;
1998 LPWSTR lpServiceStartName
= NULL
;
1999 DWORD dwRequiredSize
;
2000 LPQUERY_SERVICE_CONFIGW lpConfig
;
2003 DPRINT("RQueryServiceConfigW() called\n");
2006 return ERROR_SHUTDOWN_IN_PROGRESS
;
2008 hSvc
= (PSERVICE_HANDLE
)hService
;
2009 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2011 DPRINT1("Invalid handle tag!\n");
2012 return ERROR_INVALID_HANDLE
;
2015 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2016 SERVICE_QUERY_CONFIG
))
2018 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2019 return ERROR_ACCESS_DENIED
;
2022 lpService
= hSvc
->ServiceEntry
;
2023 if (lpService
== NULL
)
2025 DPRINT1("lpService == NULL!\n");
2026 return ERROR_INVALID_HANDLE
;
2029 /* FIXME: Lock the service database shared */
2031 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2034 if (dwError
!= ERROR_SUCCESS
)
2037 dwError
= ScmReadString(hServiceKey
,
2040 if (dwError
!= ERROR_SUCCESS
)
2043 ScmReadString(hServiceKey
,
2045 &lpServiceStartName
);
2047 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2049 if (lpImagePath
!= NULL
)
2050 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2052 if (lpService
->lpGroup
!= NULL
)
2053 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2055 /* FIXME: Add Dependencies length*/
2057 if (lpServiceStartName
!= NULL
)
2058 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2060 if (lpService
->lpDisplayName
!= NULL
)
2061 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2063 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2065 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2069 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2070 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2071 lpConfig
->dwStartType
= lpService
->dwStartType
;
2072 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2073 lpConfig
->dwTagId
= lpService
->dwTag
;
2075 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2077 if (lpImagePath
!= NULL
)
2079 wcscpy(lpStr
, lpImagePath
);
2080 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2081 lpStr
+= (wcslen(lpImagePath
) + 1);
2085 lpConfig
->lpBinaryPathName
= NULL
;
2088 if (lpService
->lpGroup
!= NULL
)
2090 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2091 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2092 lpStr
+= (wcslen(lpService
->lpGroup
->lpGroupName
) + 1);
2096 lpConfig
->lpLoadOrderGroup
= NULL
;
2099 /* FIXME: Append Dependencies */
2100 lpConfig
->lpDependencies
= NULL
;
2102 if (lpServiceStartName
!= NULL
)
2104 wcscpy(lpStr
, lpServiceStartName
);
2105 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2106 lpStr
+= (wcslen(lpServiceStartName
) + 1);
2110 lpConfig
->lpServiceStartName
= NULL
;
2113 if (lpService
->lpDisplayName
!= NULL
)
2115 wcscpy(lpStr
, lpService
->lpDisplayName
);
2116 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2120 lpConfig
->lpDisplayName
= NULL
;
2124 if (pcbBytesNeeded
!= NULL
)
2125 *pcbBytesNeeded
= dwRequiredSize
;
2128 if (lpImagePath
!= NULL
)
2129 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2131 if (lpServiceStartName
!= NULL
)
2132 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2134 if (hServiceKey
!= NULL
)
2135 RegCloseKey(hServiceKey
);
2137 /* FIXME: Unlock the service database */
2139 DPRINT("RQueryServiceConfigW() done\n");
2146 DWORD
RQueryServiceLockStatusW(
2147 handle_t BindingHandle
,
2148 SC_RPC_HANDLE hSCManager
,
2149 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2151 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2154 return ERROR_CALL_NOT_IMPLEMENTED
;
2159 DWORD
RStartServiceW(
2160 handle_t BindingHandle
,
2161 SC_RPC_HANDLE hService
,
2163 LPSTRING_PTRSW argv
)
2165 DWORD dwError
= ERROR_SUCCESS
;
2166 PSERVICE_HANDLE hSvc
;
2167 PSERVICE lpService
= NULL
;
2169 DPRINT("RStartServiceW() called\n");
2172 return ERROR_SHUTDOWN_IN_PROGRESS
;
2174 hSvc
= (PSERVICE_HANDLE
)hService
;
2175 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2177 DPRINT1("Invalid handle tag!\n");
2178 return ERROR_INVALID_HANDLE
;
2181 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2184 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2185 return ERROR_ACCESS_DENIED
;
2188 lpService
= hSvc
->ServiceEntry
;
2189 if (lpService
== NULL
)
2191 DPRINT1("lpService == NULL!\n");
2192 return ERROR_INVALID_HANDLE
;
2195 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2196 return ERROR_SERVICE_DISABLED
;
2198 if (lpService
->bDeleted
)
2199 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2206 /* Start the service */
2207 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2214 DWORD
RGetServiceDisplayNameW(
2215 handle_t BindingHandle
,
2216 SC_RPC_HANDLE hSCManager
,
2217 LPWSTR lpServiceName
,
2218 LPWSTR lpDisplayName
,
2221 // PMANAGER_HANDLE hManager;
2226 DPRINT("RGetServiceDisplayNameW() called\n");
2227 DPRINT("hSCManager = %p\n", hSCManager
);
2228 DPRINT("lpServiceName: %S\n", lpServiceName
);
2229 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2230 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2232 // hManager = (PMANAGER_HANDLE)hSCManager;
2233 // if (hManager->Handle.Tag != MANAGER_TAG)
2235 // DPRINT1("Invalid manager handle!\n");
2236 // return ERROR_INVALID_HANDLE;
2239 /* Get service database entry */
2240 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2241 if (lpService
== NULL
)
2243 DPRINT1("Could not find a service!\n");
2244 return ERROR_SERVICE_DOES_NOT_EXIST
;
2247 dwLength
= wcslen(lpService
->lpDisplayName
) + 1;
2249 if (lpDisplayName
!= NULL
&&
2250 *lpcchBuffer
>= dwLength
)
2252 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2255 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2257 *lpcchBuffer
= dwLength
;
2264 DWORD
RGetServiceKeyNameW(
2265 handle_t BindingHandle
,
2266 SC_RPC_HANDLE hSCManager
,
2267 LPWSTR lpDisplayName
,
2268 LPWSTR lpServiceName
,
2271 // PMANAGER_HANDLE hManager;
2276 DPRINT("RGetServiceKeyNameW() called\n");
2277 DPRINT("hSCManager = %p\n", hSCManager
);
2278 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2279 DPRINT("lpServiceName: %p\n", lpServiceName
);
2280 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2282 // hManager = (PMANAGER_HANDLE)hSCManager;
2283 // if (hManager->Handle.Tag != MANAGER_TAG)
2285 // DPRINT1("Invalid manager handle!\n");
2286 // return ERROR_INVALID_HANDLE;
2289 /* Get service database entry */
2290 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2291 if (lpService
== NULL
)
2293 DPRINT1("Could not find a service!\n");
2294 return ERROR_SERVICE_DOES_NOT_EXIST
;
2297 dwLength
= wcslen(lpService
->lpServiceName
) + 1;
2299 if (lpServiceName
!= NULL
&&
2300 *lpcchBuffer
>= dwLength
)
2302 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2305 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2307 *lpcchBuffer
= dwLength
;
2314 DWORD
RSetServiceBitsA(
2315 handle_t BindingHandle
,
2316 SC_RPC_HANDLE hServiceStatus
,
2317 DWORD dwServiceBits
,
2319 int bUpdateImmediately
,
2323 return ERROR_CALL_NOT_IMPLEMENTED
;
2328 DWORD
RChangeServiceConfigA(
2329 handle_t BindingHandle
,
2330 SC_RPC_HANDLE hService
,
2331 DWORD dwServiceType
,
2333 DWORD dwErrorControl
,
2334 LPSTR lpBinaryPathName
,
2335 LPSTR lpLoadOrderGroup
,
2337 LPSTR lpDependencies
,
2339 LPSTR lpServiceStartName
,
2342 LPSTR lpDisplayName
)
2345 return ERROR_CALL_NOT_IMPLEMENTED
;
2350 DWORD
RCreateServiceA(
2351 handle_t BindingHandle
,
2352 SC_RPC_HANDLE hSCManager
,
2353 LPSTR lpServiceName
,
2354 LPSTR lpDisplayName
,
2355 DWORD dwDesiredAccess
,
2356 DWORD dwServiceType
,
2358 DWORD dwErrorControl
,
2359 LPSTR lpBinaryPathName
,
2360 LPSTR lpLoadOrderGroup
,
2362 LPBYTE lpDependencies
,
2364 LPSTR lpServiceStartName
,
2367 LPSC_RPC_HANDLE lpServiceHandle
)
2370 return ERROR_CALL_NOT_IMPLEMENTED
;
2375 DWORD
REnumDependentServicesA(
2376 handle_t BindingHandle
,
2377 SC_RPC_HANDLE hService
,
2378 DWORD dwServiceState
,
2381 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2382 LPBOUNDED_DWORD_256K lpServicesReturned
)
2385 *pcbBytesNeeded
= 0;
2386 *lpServicesReturned
= 0;
2387 return ERROR_CALL_NOT_IMPLEMENTED
;
2392 DWORD
REnumServicesStatusA(
2393 handle_t BindingHandle
,
2394 SC_RPC_HANDLE hSCManager
,
2395 DWORD dwServiceType
,
2396 DWORD dwServiceState
,
2399 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2400 LPBOUNDED_DWORD_256K lpServicesReturned
,
2401 LPBOUNDED_DWORD_256K lpResumeHandle
)
2404 return ERROR_CALL_NOT_IMPLEMENTED
;
2409 DWORD
ROpenSCManagerA(
2410 handle_t BindingHandle
,
2411 LPSTR lpMachineName
,
2412 LPSTR lpDatabaseName
,
2413 DWORD dwDesiredAccess
,
2414 LPSC_RPC_HANDLE lpScHandle
)
2416 UNICODE_STRING MachineName
;
2417 UNICODE_STRING DatabaseName
;
2420 DPRINT("ROpenSCManagerA() called\n");
2423 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
2427 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
2430 dwError
= ROpenSCManagerW(BindingHandle
,
2431 lpMachineName
? MachineName
.Buffer
: NULL
,
2432 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
2437 RtlFreeUnicodeString(&MachineName
);
2440 RtlFreeUnicodeString(&DatabaseName
);
2447 DWORD
ROpenServiceA(
2448 handle_t BindingHandle
,
2449 SC_RPC_HANDLE hSCManager
,
2450 LPSTR lpServiceName
,
2451 DWORD dwDesiredAccess
,
2452 LPSC_RPC_HANDLE lpServiceHandle
)
2454 UNICODE_STRING ServiceName
;
2457 DPRINT("ROpenServiceA() called\n");
2459 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
2462 dwError
= ROpenServiceW(BindingHandle
,
2468 RtlFreeUnicodeString(&ServiceName
);
2475 DWORD
RQueryServiceConfigA(
2476 handle_t BindingHandle
,
2477 SC_RPC_HANDLE hService
,
2478 LPQUERY_SERVICE_CONFIGA lpServiceConfig
,
2480 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2483 return ERROR_CALL_NOT_IMPLEMENTED
;
2488 DWORD
RQueryServiceLockStatusA(
2489 handle_t BindingHandle
,
2490 SC_RPC_HANDLE hSCManager
,
2491 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
2493 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2496 return ERROR_CALL_NOT_IMPLEMENTED
;
2501 DWORD
RStartServiceA(
2502 handle_t BindingHandle
,
2503 SC_RPC_HANDLE hService
,
2505 LPSTRING_PTRSA argv
)
2507 DWORD dwError
= ERROR_SUCCESS
;
2508 PSERVICE_HANDLE hSvc
;
2509 PSERVICE lpService
= NULL
;
2511 DPRINT1("RStartServiceA() called\n");
2514 return ERROR_SHUTDOWN_IN_PROGRESS
;
2516 hSvc
= (PSERVICE_HANDLE
)hService
;
2517 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2519 DPRINT1("Invalid handle tag!\n");
2520 return ERROR_INVALID_HANDLE
;
2523 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2526 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2527 return ERROR_ACCESS_DENIED
;
2530 lpService
= hSvc
->ServiceEntry
;
2531 if (lpService
== NULL
)
2533 DPRINT1("lpService == NULL!\n");
2534 return ERROR_INVALID_HANDLE
;
2537 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2538 return ERROR_SERVICE_DISABLED
;
2540 if (lpService
->bDeleted
)
2541 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2543 /* FIXME: Convert argument vector to Unicode */
2545 /* Start the service */
2546 dwError
= ScmStartService(lpService
, 0, NULL
);
2548 /* FIXME: Free argument vector */
2555 DWORD
RGetServiceDisplayNameA(
2556 handle_t BindingHandle
,
2557 SC_RPC_HANDLE hSCManager
,
2558 LPSTR lpServiceName
,
2559 LPSTR lpDisplayName
,
2560 LPBOUNDED_DWORD_4K lpcchBuffer
)
2563 return ERROR_CALL_NOT_IMPLEMENTED
;
2568 DWORD
RGetServiceKeyNameA(
2569 handle_t BindingHandle
,
2570 SC_RPC_HANDLE hSCManager
,
2571 LPSTR lpDisplayName
,
2573 LPBOUNDED_DWORD_4K lpcchBuffer
)
2576 return ERROR_CALL_NOT_IMPLEMENTED
;
2581 DWORD
RGetCurrentGroupStateW(
2582 handle_t BindingHandle
)
2585 return ERROR_CALL_NOT_IMPLEMENTED
;
2590 DWORD
REnumServiceGroupW(
2591 handle_t BindingHandle
,
2592 SC_RPC_HANDLE hSCManager
,
2593 DWORD dwServiceType
,
2594 DWORD dwServiceState
,
2597 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2598 LPBOUNDED_DWORD_256K lpServicesReturned
,
2599 LPBOUNDED_DWORD_256K lpResumeIndex
,
2600 LPWSTR pszGroupName
)
2603 return ERROR_CALL_NOT_IMPLEMENTED
;
2608 DWORD
RChangeServiceConfig2A(
2609 handle_t BindingHandle
,
2610 SC_RPC_HANDLE hService
,
2611 SC_RPC_CONFIG_INFOA Info
)
2614 return ERROR_CALL_NOT_IMPLEMENTED
;
2619 DWORD
RChangeServiceConfig2W(
2620 handle_t BindingHandle
,
2621 SC_RPC_HANDLE hService
,
2622 SC_RPC_CONFIG_INFOW Info
)
2624 DWORD dwError
= ERROR_SUCCESS
;
2625 PSERVICE_HANDLE hSvc
;
2626 PSERVICE lpService
= NULL
;
2627 HKEY hServiceKey
= NULL
;
2629 DPRINT("RChangeServiceConfig2W() called\n");
2630 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
2633 return ERROR_SHUTDOWN_IN_PROGRESS
;
2635 hSvc
= (PSERVICE_HANDLE
)hService
;
2636 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2638 DPRINT1("Invalid handle tag!\n");
2639 return ERROR_INVALID_HANDLE
;
2642 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2643 SERVICE_CHANGE_CONFIG
))
2645 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2646 return ERROR_ACCESS_DENIED
;
2649 lpService
= hSvc
->ServiceEntry
;
2650 if (lpService
== NULL
)
2652 DPRINT1("lpService == NULL!\n");
2653 return ERROR_INVALID_HANDLE
;
2656 /* FIXME: Lock database exclusively */
2658 if (lpService
->bDeleted
)
2660 /* FIXME: Unlock database */
2661 DPRINT1("The service has already been marked for delete!\n");
2662 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2665 /* Open the service key */
2666 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2669 if (dwError
!= ERROR_SUCCESS
)
2672 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
2674 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
2676 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
2677 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
2679 if (lpServiceDescription
!= NULL
&&
2680 lpServiceDescription
->lpDescription
!= NULL
)
2682 RegSetValueExW(hServiceKey
,
2686 (LPBYTE
)lpServiceDescription
->lpDescription
,
2687 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
2689 if (dwError
!= ERROR_SUCCESS
)
2693 else if (Info
.dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
2696 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
2701 /* FIXME: Unlock database */
2702 if (hServiceKey
!= NULL
)
2703 RegCloseKey(hServiceKey
);
2705 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
2712 DWORD
RQueryServiceConfig2A(
2713 handle_t BindingHandle
,
2714 SC_RPC_HANDLE hService
,
2718 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2721 return ERROR_CALL_NOT_IMPLEMENTED
;
2726 DWORD
RQueryServiceConfig2W(
2727 handle_t BindingHandle
,
2728 SC_RPC_HANDLE hService
,
2732 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2734 DWORD dwError
= ERROR_SUCCESS
;
2735 PSERVICE_HANDLE hSvc
;
2736 PSERVICE lpService
= NULL
;
2737 HKEY hServiceKey
= NULL
;
2738 DWORD dwRequiredSize
;
2739 LPWSTR lpDescription
= NULL
;
2741 DPRINT("RQueryServiceConfig2W() called\n");
2744 return ERROR_SHUTDOWN_IN_PROGRESS
;
2746 hSvc
= (PSERVICE_HANDLE
)hService
;
2747 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2749 DPRINT1("Invalid handle tag!\n");
2750 return ERROR_INVALID_HANDLE
;
2753 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2754 SERVICE_QUERY_CONFIG
))
2756 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2757 return ERROR_ACCESS_DENIED
;
2760 lpService
= hSvc
->ServiceEntry
;
2761 if (lpService
== NULL
)
2763 DPRINT1("lpService == NULL!\n");
2764 return ERROR_INVALID_HANDLE
;
2767 /* FIXME: Lock the service database shared */
2769 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2772 if (dwError
!= ERROR_SUCCESS
)
2775 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
2777 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
2780 dwError
= ScmReadString(hServiceKey
,
2783 if (dwError
!= ERROR_SUCCESS
)
2786 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
2788 if (cbBufSize
< dwRequiredSize
)
2790 *pcbBytesNeeded
= dwRequiredSize
;
2791 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2796 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
2797 wcscpy(lpStr
, lpDescription
);
2798 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
2801 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
2804 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
2809 if (lpDescription
!= NULL
)
2810 HeapFree(GetProcessHeap(), 0, lpDescription
);
2812 if (hServiceKey
!= NULL
)
2813 RegCloseKey(hServiceKey
);
2815 /* FIXME: Unlock database */
2817 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
2824 DWORD
RQueryServiceStatusEx(
2825 handle_t BindingHandle
,
2826 SC_RPC_HANDLE hService
,
2827 SC_STATUS_TYPE InfoLevel
,
2830 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2832 LPSERVICE_STATUS_PROCESS lpStatus
;
2833 PSERVICE_HANDLE hSvc
;
2836 DPRINT("RQueryServiceStatusEx() called\n");
2839 return ERROR_SHUTDOWN_IN_PROGRESS
;
2841 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
2842 return ERROR_INVALID_LEVEL
;
2844 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
2846 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
2847 return ERROR_INSUFFICIENT_BUFFER
;
2849 hSvc
= (PSERVICE_HANDLE
)hService
;
2850 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2852 DPRINT1("Invalid handle tag!\n");
2853 return ERROR_INVALID_HANDLE
;
2856 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2857 SERVICE_QUERY_STATUS
))
2859 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2860 return ERROR_ACCESS_DENIED
;
2863 lpService
= hSvc
->ServiceEntry
;
2864 if (lpService
== NULL
)
2866 DPRINT1("lpService == NULL!\n");
2867 return ERROR_INVALID_HANDLE
;
2870 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
2872 /* Return service status information */
2873 RtlCopyMemory(lpStatus
,
2875 sizeof(SERVICE_STATUS
));
2877 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
2878 lpStatus
->dwServiceFlags
= 0; /* FIXME */
2880 return ERROR_SUCCESS
;
2885 DWORD
REnumServicesStatusExA(
2886 handle_t BindingHandle
,
2887 SC_RPC_HANDLE hSCManager
,
2888 SC_ENUM_TYPE InfoLevel
,
2889 DWORD dwServiceType
,
2890 DWORD dwServiceState
,
2893 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2894 LPBOUNDED_DWORD_256K lpServicesReturned
,
2895 LPBOUNDED_DWORD_256K lpResumeIndex
,
2899 *pcbBytesNeeded
= 0;
2900 *lpServicesReturned
= 0;
2901 return ERROR_CALL_NOT_IMPLEMENTED
;
2906 DWORD
REnumServicesStatusExW(
2907 handle_t BindingHandle
,
2908 SC_RPC_HANDLE hSCManager
,
2909 SC_ENUM_TYPE InfoLevel
,
2910 DWORD dwServiceType
,
2911 DWORD dwServiceState
,
2914 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2915 LPBOUNDED_DWORD_256K lpServicesReturned
,
2916 LPBOUNDED_DWORD_256K lpResumeIndex
,
2917 LPWSTR pszGroupName
)
2919 PMANAGER_HANDLE hManager
;
2921 DWORD dwError
= ERROR_SUCCESS
;
2922 PLIST_ENTRY ServiceEntry
;
2923 PSERVICE CurrentService
;
2925 DWORD dwRequiredSize
;
2926 DWORD dwServiceCount
;
2928 DWORD dwLastResumeCount
;
2929 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
2932 DPRINT("REnumServicesStatusExW() called\n");
2935 return ERROR_SHUTDOWN_IN_PROGRESS
;
2937 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
2938 return ERROR_INVALID_LEVEL
;
2940 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2941 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2943 DPRINT1("Invalid manager handle!\n");
2944 return ERROR_INVALID_HANDLE
;
2947 /* Check access rights */
2948 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2949 SC_MANAGER_ENUMERATE_SERVICE
))
2951 DPRINT1("Insufficient access rights! 0x%lx\n",
2952 hManager
->Handle
.DesiredAccess
);
2953 return ERROR_ACCESS_DENIED
;
2956 *pcbBytesNeeded
= 0;
2957 *lpServicesReturned
= 0;
2959 dwLastResumeCount
= *lpResumeIndex
;
2961 /* Lock the service list shared */
2963 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2964 if (lpService
== NULL
)
2966 dwError
= ERROR_SUCCESS
;
2973 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2974 ServiceEntry
!= &ServiceListHead
;
2975 ServiceEntry
= ServiceEntry
->Flink
)
2977 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2981 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2984 dwState
= SERVICE_ACTIVE
;
2985 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2986 dwState
= SERVICE_INACTIVE
;
2988 if ((dwState
& dwServiceState
) == 0)
2993 if (*pszGroupName
== 0)
2995 if (CurrentService
->lpGroup
!= NULL
)
3000 if ((CurrentService
->lpGroup
== NULL
) ||
3001 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
3006 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
3007 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
3008 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
3010 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
3012 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
3013 dwRequiredSize
+= dwSize
;
3015 dwLastResumeCount
= CurrentService
->dwResumeCount
;
3019 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
3025 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
3026 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
3029 ServiceEntry
!= &ServiceListHead
;
3030 ServiceEntry
= ServiceEntry
->Flink
)
3032 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
3036 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
3039 dwState
= SERVICE_ACTIVE
;
3040 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
3041 dwState
= SERVICE_INACTIVE
;
3043 if ((dwState
& dwServiceState
) == 0)
3048 if (*pszGroupName
== 0)
3050 if (CurrentService
->lpGroup
!= NULL
)
3055 if ((CurrentService
->lpGroup
== NULL
) ||
3056 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
3061 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
3062 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
3063 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
3065 dwError
= ERROR_MORE_DATA
;
3068 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
3070 *lpResumeIndex
= dwLastResumeCount
;
3071 *lpServicesReturned
= dwServiceCount
;
3072 *pcbBytesNeeded
= dwRequiredSize
;
3074 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
3075 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
3076 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
3079 for (ServiceEntry
= &lpService
->ServiceListEntry
;
3080 ServiceEntry
!= &ServiceListHead
;
3081 ServiceEntry
= ServiceEntry
->Flink
)
3083 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
3087 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
3090 dwState
= SERVICE_ACTIVE
;
3091 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
3092 dwState
= SERVICE_INACTIVE
;
3094 if ((dwState
& dwServiceState
) == 0)
3099 if (*pszGroupName
== 0)
3101 if (CurrentService
->lpGroup
!= NULL
)
3106 if ((CurrentService
->lpGroup
== NULL
) ||
3107 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
3112 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
3113 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
3114 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
3116 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
3118 /* Copy the service name */
3120 CurrentService
->lpServiceName
);
3121 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
3122 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
3124 /* Copy the display name */
3126 CurrentService
->lpDisplayName
);
3127 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
3128 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
3130 /* Copy the status information */
3131 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
3132 &CurrentService
->Status
,
3133 sizeof(SERVICE_STATUS
));
3134 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
3135 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
3138 dwRequiredSize
+= dwSize
;
3148 /* Unlock the service list */
3150 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
3157 DWORD
RSendTSMessage(
3158 handle_t BindingHandle
)
3161 return ERROR_CALL_NOT_IMPLEMENTED
;
3166 DWORD
RCreateServiceWOW64A(
3167 handle_t BindingHandle
,
3168 LPSTR lpServiceName
,
3169 LPSTR lpDisplayName
,
3170 DWORD dwDesiredAccess
,
3171 DWORD dwServiceType
,
3173 DWORD dwErrorControl
,
3174 LPSTR lpBinaryPathName
,
3175 LPSTR lpLoadOrderGroup
,
3177 LPBYTE lpDependencies
,
3179 LPSTR lpServiceStartName
,
3182 LPSC_RPC_HANDLE lpServiceHandle
)
3185 return ERROR_CALL_NOT_IMPLEMENTED
;
3190 DWORD
RCreateServiceWOW64W(
3191 handle_t BindingHandle
,
3192 LPWSTR lpServiceName
,
3193 LPWSTR lpDisplayName
,
3194 DWORD dwDesiredAccess
,
3195 DWORD dwServiceType
,
3197 DWORD dwErrorControl
,
3198 LPWSTR lpBinaryPathName
,
3199 LPWSTR lpLoadOrderGroup
,
3201 LPBYTE lpDependencies
,
3203 LPWSTR lpServiceStartName
,
3206 LPSC_RPC_HANDLE lpServiceHandle
)
3209 return ERROR_CALL_NOT_IMPLEMENTED
;
3214 DWORD
RQueryServiceTagInfo(
3215 handle_t BindingHandle
)
3218 return ERROR_CALL_NOT_IMPLEMENTED
;
3223 DWORD
RNotifyServiceStatusChange(
3224 handle_t BindingHandle
,
3225 SC_RPC_HANDLE hService
,
3226 SC_RPC_NOTIFY_PARAMS NotifyParams
,
3227 GUID
*pClientProcessGuid
,
3228 GUID
*pSCMProcessGuid
,
3229 PBOOL pfCreateRemoteQueue
,
3230 LPSC_NOTIFY_RPC_HANDLE phNotify
)
3233 return ERROR_CALL_NOT_IMPLEMENTED
;
3238 DWORD
RGetNotifyResults(
3239 handle_t BindingHandle
,
3240 SC_NOTIFY_RPC_HANDLE hNotify
,
3241 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
3244 return ERROR_CALL_NOT_IMPLEMENTED
;
3249 DWORD
RCloseNotifyHandle(
3250 handle_t BindingHandle
,
3251 LPSC_NOTIFY_RPC_HANDLE phNotify
,
3255 return ERROR_CALL_NOT_IMPLEMENTED
;
3260 DWORD
RControlServiceExA(
3261 handle_t BindingHandle
,
3262 SC_RPC_HANDLE hService
,
3267 return ERROR_CALL_NOT_IMPLEMENTED
;
3272 DWORD
RControlServiceExW(
3273 handle_t BindingHandle
,
3274 SC_RPC_HANDLE hService
,
3279 return ERROR_CALL_NOT_IMPLEMENTED
;
3284 DWORD
RSendPnPMessage(
3285 handle_t BindingHandle
)
3288 return ERROR_CALL_NOT_IMPLEMENTED
;
3293 DWORD
RValidatePnPService(
3294 handle_t BindingHandle
)
3297 return ERROR_CALL_NOT_IMPLEMENTED
;
3302 DWORD
ROpenServiceStatusHandle(
3303 handle_t BindingHandle
)
3306 return ERROR_CALL_NOT_IMPLEMENTED
;
3312 handle_t BindingHandle
)
3315 return ERROR_CALL_NOT_IMPLEMENTED
;
3319 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
3321 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
3325 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
3327 HeapFree(GetProcessHeap(), 0, ptr
);
3331 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
3336 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
3341 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)