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
,
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");
2245 /* If the service could not be found and lpcchBuffer is 0, windows
2246 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2247 if (*lpcchBuffer
== 0)
2250 *lpDisplayName
= '\0';
2253 return ERROR_SERVICE_DOES_NOT_EXIST
;
2256 if (!lpService
->lpDisplayName
)
2258 dwLength
= wcslen(lpService
->lpServiceName
);
2260 if (lpServiceName
!= NULL
&&
2261 *lpcchBuffer
> dwLength
)
2263 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2268 dwLength
= wcslen(lpService
->lpDisplayName
);
2270 if (lpDisplayName
!= NULL
&&
2271 *lpcchBuffer
> dwLength
)
2273 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2277 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2279 *lpcchBuffer
= dwLength
;
2286 DWORD
RGetServiceKeyNameW(
2287 handle_t BindingHandle
,
2288 SC_RPC_HANDLE hSCManager
,
2289 LPWSTR lpDisplayName
,
2290 LPWSTR lpServiceName
,
2293 // PMANAGER_HANDLE hManager;
2298 DPRINT("RGetServiceKeyNameW() called\n");
2299 DPRINT("hSCManager = %p\n", hSCManager
);
2300 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2301 DPRINT("lpServiceName: %p\n", lpServiceName
);
2302 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2304 // hManager = (PMANAGER_HANDLE)hSCManager;
2305 // if (hManager->Handle.Tag != MANAGER_TAG)
2307 // DPRINT1("Invalid manager handle!\n");
2308 // return ERROR_INVALID_HANDLE;
2311 /* Get service database entry */
2312 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2313 if (lpService
== NULL
)
2315 DPRINT1("Could not find a service!\n");
2317 /* If the service could not be found and lpcchBuffer is 0, windows
2318 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2319 if (*lpcchBuffer
== 0)
2322 *lpServiceName
= '\0';
2325 return ERROR_SERVICE_DOES_NOT_EXIST
;
2328 dwLength
= wcslen(lpService
->lpServiceName
);
2330 if (lpServiceName
!= NULL
&&
2331 *lpcchBuffer
> dwLength
)
2333 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2334 *lpcchBuffer
= dwLength
;
2335 return ERROR_SUCCESS
;
2338 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2340 *lpcchBuffer
= dwLength
* 2;
2347 DWORD
RSetServiceBitsA(
2348 handle_t BindingHandle
,
2349 SC_RPC_HANDLE hServiceStatus
,
2350 DWORD dwServiceBits
,
2352 int bUpdateImmediately
,
2356 return ERROR_CALL_NOT_IMPLEMENTED
;
2361 DWORD
RChangeServiceConfigA(
2362 handle_t BindingHandle
,
2363 SC_RPC_HANDLE hService
,
2364 DWORD dwServiceType
,
2366 DWORD dwErrorControl
,
2367 LPSTR lpBinaryPathName
,
2368 LPSTR lpLoadOrderGroup
,
2370 LPSTR lpDependencies
,
2372 LPSTR lpServiceStartName
,
2375 LPSTR lpDisplayName
)
2378 return ERROR_CALL_NOT_IMPLEMENTED
;
2383 DWORD
RCreateServiceA(
2384 handle_t BindingHandle
,
2385 SC_RPC_HANDLE hSCManager
,
2386 LPSTR lpServiceName
,
2387 LPSTR lpDisplayName
,
2388 DWORD dwDesiredAccess
,
2389 DWORD dwServiceType
,
2391 DWORD dwErrorControl
,
2392 LPSTR lpBinaryPathName
,
2393 LPSTR lpLoadOrderGroup
,
2395 LPBYTE lpDependencies
,
2397 LPSTR lpServiceStartName
,
2400 LPSC_RPC_HANDLE lpServiceHandle
)
2403 return ERROR_CALL_NOT_IMPLEMENTED
;
2408 DWORD
REnumDependentServicesA(
2409 handle_t BindingHandle
,
2410 SC_RPC_HANDLE hService
,
2411 DWORD dwServiceState
,
2414 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2415 LPBOUNDED_DWORD_256K lpServicesReturned
)
2418 *pcbBytesNeeded
= 0;
2419 *lpServicesReturned
= 0;
2420 return ERROR_CALL_NOT_IMPLEMENTED
;
2425 DWORD
REnumServicesStatusA(
2426 handle_t BindingHandle
,
2427 SC_RPC_HANDLE hSCManager
,
2428 DWORD dwServiceType
,
2429 DWORD dwServiceState
,
2432 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2433 LPBOUNDED_DWORD_256K lpServicesReturned
,
2434 LPBOUNDED_DWORD_256K lpResumeHandle
)
2437 return ERROR_CALL_NOT_IMPLEMENTED
;
2442 DWORD
ROpenSCManagerA(
2443 handle_t BindingHandle
,
2444 LPSTR lpMachineName
,
2445 LPSTR lpDatabaseName
,
2446 DWORD dwDesiredAccess
,
2447 LPSC_RPC_HANDLE lpScHandle
)
2449 UNICODE_STRING MachineName
;
2450 UNICODE_STRING DatabaseName
;
2453 DPRINT("ROpenSCManagerA() called\n");
2456 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
2460 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
2463 dwError
= ROpenSCManagerW(BindingHandle
,
2464 lpMachineName
? MachineName
.Buffer
: NULL
,
2465 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
2470 RtlFreeUnicodeString(&MachineName
);
2473 RtlFreeUnicodeString(&DatabaseName
);
2480 DWORD
ROpenServiceA(
2481 handle_t BindingHandle
,
2482 SC_RPC_HANDLE hSCManager
,
2483 LPSTR lpServiceName
,
2484 DWORD dwDesiredAccess
,
2485 LPSC_RPC_HANDLE lpServiceHandle
)
2487 UNICODE_STRING ServiceName
;
2490 DPRINT("ROpenServiceA() called\n");
2492 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
2495 dwError
= ROpenServiceW(BindingHandle
,
2501 RtlFreeUnicodeString(&ServiceName
);
2508 DWORD
RQueryServiceConfigA(
2509 handle_t BindingHandle
,
2510 SC_RPC_HANDLE hService
,
2511 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
2513 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2516 return ERROR_CALL_NOT_IMPLEMENTED
;
2521 DWORD
RQueryServiceLockStatusA(
2522 handle_t BindingHandle
,
2523 SC_RPC_HANDLE hSCManager
,
2524 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
2526 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2529 return ERROR_CALL_NOT_IMPLEMENTED
;
2534 DWORD
RStartServiceA(
2535 handle_t BindingHandle
,
2536 SC_RPC_HANDLE hService
,
2538 LPSTRING_PTRSA argv
)
2540 DWORD dwError
= ERROR_SUCCESS
;
2541 PSERVICE_HANDLE hSvc
;
2542 PSERVICE lpService
= NULL
;
2544 DPRINT1("RStartServiceA() called\n");
2547 return ERROR_SHUTDOWN_IN_PROGRESS
;
2549 hSvc
= (PSERVICE_HANDLE
)hService
;
2550 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2552 DPRINT1("Invalid handle tag!\n");
2553 return ERROR_INVALID_HANDLE
;
2556 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2559 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2560 return ERROR_ACCESS_DENIED
;
2563 lpService
= hSvc
->ServiceEntry
;
2564 if (lpService
== NULL
)
2566 DPRINT1("lpService == NULL!\n");
2567 return ERROR_INVALID_HANDLE
;
2570 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2571 return ERROR_SERVICE_DISABLED
;
2573 if (lpService
->bDeleted
)
2574 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2576 /* FIXME: Convert argument vector to Unicode */
2578 /* Start the service */
2579 dwError
= ScmStartService(lpService
, 0, NULL
);
2581 /* FIXME: Free argument vector */
2588 DWORD
RGetServiceDisplayNameA(
2589 handle_t BindingHandle
,
2590 SC_RPC_HANDLE hSCManager
,
2591 LPSTR lpServiceName
,
2592 LPSTR lpDisplayName
,
2593 LPBOUNDED_DWORD_4K lpcchBuffer
)
2595 // PMANAGER_HANDLE hManager;
2599 LPWSTR lpServiceNameW
;
2601 DPRINT("RGetServiceDisplayNameA() called\n");
2602 DPRINT("hSCManager = %p\n", hSCManager
);
2603 DPRINT("lpServiceName: %s\n", lpServiceName
);
2604 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2605 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2607 // hManager = (PMANAGER_HANDLE)hSCManager;
2608 // if (hManager->Handle.Tag != MANAGER_TAG)
2610 // DPRINT1("Invalid manager handle!\n");
2611 // return ERROR_INVALID_HANDLE;
2614 dwLength
= strlen(lpServiceName
) + 1;
2615 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
2617 dwLength
* sizeof(WCHAR
));
2618 if (!lpServiceNameW
)
2619 return ERROR_NOT_ENOUGH_MEMORY
;
2621 MultiByteToWideChar(CP_ACP
,
2624 strlen(lpServiceName
),
2628 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
2630 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
2632 if (lpService
== NULL
)
2634 DPRINT1("Could not find a service!\n");
2636 /* If the service could not be found and lpcchBuffer is 0, windows
2637 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2638 if (*lpcchBuffer
== 0)
2641 *lpDisplayName
= '\0';
2643 return ERROR_SERVICE_DOES_NOT_EXIST
;
2646 if (!lpService
->lpDisplayName
)
2648 dwLength
= wcslen(lpService
->lpServiceName
);
2649 if (lpServiceName
!= NULL
&&
2650 *lpcchBuffer
> dwLength
)
2652 WideCharToMultiByte(CP_ACP
,
2654 lpService
->lpServiceName
,
2655 wcslen(lpService
->lpServiceName
),
2660 return ERROR_SUCCESS
;
2665 dwLength
= wcslen(lpService
->lpDisplayName
);
2666 if (lpDisplayName
!= NULL
&&
2667 *lpcchBuffer
> dwLength
)
2669 WideCharToMultiByte(CP_ACP
,
2671 lpService
->lpDisplayName
,
2672 wcslen(lpService
->lpDisplayName
),
2677 return ERROR_SUCCESS
;
2681 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2683 *lpcchBuffer
= dwLength
* 2;
2690 DWORD
RGetServiceKeyNameA(
2691 handle_t BindingHandle
,
2692 SC_RPC_HANDLE hSCManager
,
2693 LPSTR lpDisplayName
,
2694 LPSTR lpServiceName
,
2695 LPBOUNDED_DWORD_4K lpcchBuffer
)
2700 LPWSTR lpDisplayNameW
;
2702 DPRINT("RGetServiceKeyNameA() called\n");
2703 DPRINT("hSCManager = %p\n", hSCManager
);
2704 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
2705 DPRINT("lpServiceName: %p\n", lpServiceName
);
2706 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2708 dwLength
= strlen(lpDisplayName
) + 1;
2709 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2711 dwLength
* sizeof(WCHAR
));
2712 if (!lpDisplayNameW
)
2713 return ERROR_NOT_ENOUGH_MEMORY
;
2715 MultiByteToWideChar(CP_ACP
,
2718 strlen(lpDisplayName
),
2722 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
2724 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
2726 if (lpService
== NULL
)
2728 DPRINT1("Could not find the service!\n");
2730 /* If the service could not be found and lpcchBuffer is 0,
2731 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
2732 if (*lpcchBuffer
== 0)
2735 *lpServiceName
= '\0';
2738 return ERROR_SERVICE_DOES_NOT_EXIST
;
2741 dwLength
= wcslen(lpService
->lpServiceName
);
2742 if (lpService
!= NULL
&&
2743 *lpcchBuffer
> dwLength
)
2745 WideCharToMultiByte(CP_ACP
,
2747 lpService
->lpServiceName
,
2748 wcslen(lpService
->lpServiceName
),
2753 return ERROR_SUCCESS
;
2756 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2758 *lpcchBuffer
= dwLength
* 2;
2765 DWORD
RGetCurrentGroupStateW(
2766 handle_t BindingHandle
)
2769 return ERROR_CALL_NOT_IMPLEMENTED
;
2774 DWORD
REnumServiceGroupW(
2775 handle_t BindingHandle
,
2776 SC_RPC_HANDLE hSCManager
,
2777 DWORD dwServiceType
,
2778 DWORD dwServiceState
,
2781 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2782 LPBOUNDED_DWORD_256K lpServicesReturned
,
2783 LPBOUNDED_DWORD_256K lpResumeIndex
,
2784 LPCWSTR pszGroupName
)
2787 return ERROR_CALL_NOT_IMPLEMENTED
;
2792 DWORD
RChangeServiceConfig2A(
2793 handle_t BindingHandle
,
2794 SC_RPC_HANDLE hService
,
2795 SC_RPC_CONFIG_INFOA Info
)
2798 return ERROR_CALL_NOT_IMPLEMENTED
;
2803 DWORD
RChangeServiceConfig2W(
2804 handle_t BindingHandle
,
2805 SC_RPC_HANDLE hService
,
2806 SC_RPC_CONFIG_INFOW Info
)
2808 DWORD dwError
= ERROR_SUCCESS
;
2809 PSERVICE_HANDLE hSvc
;
2810 PSERVICE lpService
= NULL
;
2811 HKEY hServiceKey
= NULL
;
2813 DPRINT("RChangeServiceConfig2W() called\n");
2814 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
2817 return ERROR_SHUTDOWN_IN_PROGRESS
;
2819 hSvc
= (PSERVICE_HANDLE
)hService
;
2820 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2822 DPRINT1("Invalid handle tag!\n");
2823 return ERROR_INVALID_HANDLE
;
2826 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2827 SERVICE_CHANGE_CONFIG
))
2829 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2830 return ERROR_ACCESS_DENIED
;
2833 lpService
= hSvc
->ServiceEntry
;
2834 if (lpService
== NULL
)
2836 DPRINT1("lpService == NULL!\n");
2837 return ERROR_INVALID_HANDLE
;
2840 /* FIXME: Lock database exclusively */
2842 if (lpService
->bDeleted
)
2844 /* FIXME: Unlock database */
2845 DPRINT1("The service has already been marked for delete!\n");
2846 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2849 /* Open the service key */
2850 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2853 if (dwError
!= ERROR_SUCCESS
)
2856 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
2858 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
2860 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
2861 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
2863 if (lpServiceDescription
!= NULL
&&
2864 lpServiceDescription
->lpDescription
!= NULL
)
2866 RegSetValueExW(hServiceKey
,
2870 (LPBYTE
)lpServiceDescription
->lpDescription
,
2871 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
2873 if (dwError
!= ERROR_SUCCESS
)
2877 else if (Info
.dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
2880 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
2885 /* FIXME: Unlock database */
2886 if (hServiceKey
!= NULL
)
2887 RegCloseKey(hServiceKey
);
2889 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
2896 DWORD
RQueryServiceConfig2A(
2897 handle_t BindingHandle
,
2898 SC_RPC_HANDLE hService
,
2902 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2905 return ERROR_CALL_NOT_IMPLEMENTED
;
2910 DWORD
RQueryServiceConfig2W(
2911 handle_t BindingHandle
,
2912 SC_RPC_HANDLE hService
,
2916 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2918 DWORD dwError
= ERROR_SUCCESS
;
2919 PSERVICE_HANDLE hSvc
;
2920 PSERVICE lpService
= NULL
;
2921 HKEY hServiceKey
= NULL
;
2922 DWORD dwRequiredSize
;
2923 LPWSTR lpDescription
= NULL
;
2925 DPRINT("RQueryServiceConfig2W() called\n");
2928 return ERROR_SHUTDOWN_IN_PROGRESS
;
2930 hSvc
= (PSERVICE_HANDLE
)hService
;
2931 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2933 DPRINT1("Invalid handle tag!\n");
2934 return ERROR_INVALID_HANDLE
;
2937 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2938 SERVICE_QUERY_CONFIG
))
2940 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2941 return ERROR_ACCESS_DENIED
;
2944 lpService
= hSvc
->ServiceEntry
;
2945 if (lpService
== NULL
)
2947 DPRINT1("lpService == NULL!\n");
2948 return ERROR_INVALID_HANDLE
;
2951 /* FIXME: Lock the service database shared */
2953 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2956 if (dwError
!= ERROR_SUCCESS
)
2959 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
2961 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
2964 dwError
= ScmReadString(hServiceKey
,
2967 if (dwError
!= ERROR_SUCCESS
)
2970 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
2972 if (cbBufSize
< dwRequiredSize
)
2974 *pcbBytesNeeded
= dwRequiredSize
;
2975 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2980 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
2981 wcscpy(lpStr
, lpDescription
);
2982 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
2985 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
2988 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
2993 if (lpDescription
!= NULL
)
2994 HeapFree(GetProcessHeap(), 0, lpDescription
);
2996 if (hServiceKey
!= NULL
)
2997 RegCloseKey(hServiceKey
);
2999 /* FIXME: Unlock database */
3001 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
3008 DWORD
RQueryServiceStatusEx(
3009 handle_t BindingHandle
,
3010 SC_RPC_HANDLE hService
,
3011 SC_STATUS_TYPE InfoLevel
,
3014 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3016 LPSERVICE_STATUS_PROCESS lpStatus
;
3017 PSERVICE_HANDLE hSvc
;
3020 DPRINT("RQueryServiceStatusEx() called\n");
3023 return ERROR_SHUTDOWN_IN_PROGRESS
;
3025 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
3026 return ERROR_INVALID_LEVEL
;
3028 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
3030 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
3031 return ERROR_INSUFFICIENT_BUFFER
;
3033 hSvc
= (PSERVICE_HANDLE
)hService
;
3034 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3036 DPRINT1("Invalid handle tag!\n");
3037 return ERROR_INVALID_HANDLE
;
3040 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3041 SERVICE_QUERY_STATUS
))
3043 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3044 return ERROR_ACCESS_DENIED
;
3047 lpService
= hSvc
->ServiceEntry
;
3048 if (lpService
== NULL
)
3050 DPRINT1("lpService == NULL!\n");
3051 return ERROR_INVALID_HANDLE
;
3054 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
3056 /* Return service status information */
3057 RtlCopyMemory(lpStatus
,
3059 sizeof(SERVICE_STATUS
));
3061 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
3062 lpStatus
->dwServiceFlags
= 0; /* FIXME */
3064 return ERROR_SUCCESS
;
3069 DWORD
REnumServicesStatusExA(
3070 handle_t BindingHandle
,
3071 SC_RPC_HANDLE hSCManager
,
3072 SC_ENUM_TYPE InfoLevel
,
3073 DWORD dwServiceType
,
3074 DWORD dwServiceState
,
3077 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3078 LPBOUNDED_DWORD_256K lpServicesReturned
,
3079 LPBOUNDED_DWORD_256K lpResumeIndex
,
3080 LPCSTR pszGroupName
)
3083 *pcbBytesNeeded
= 0;
3084 *lpServicesReturned
= 0;
3085 return ERROR_CALL_NOT_IMPLEMENTED
;
3090 DWORD
REnumServicesStatusExW(
3091 handle_t BindingHandle
,
3092 SC_RPC_HANDLE hSCManager
,
3093 SC_ENUM_TYPE InfoLevel
,
3094 DWORD dwServiceType
,
3095 DWORD dwServiceState
,
3098 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3099 LPBOUNDED_DWORD_256K lpServicesReturned
,
3100 LPBOUNDED_DWORD_256K lpResumeIndex
,
3101 LPCWSTR pszGroupName
)
3103 PMANAGER_HANDLE hManager
;
3105 DWORD dwError
= ERROR_SUCCESS
;
3106 PLIST_ENTRY ServiceEntry
;
3107 PSERVICE CurrentService
;
3109 DWORD dwRequiredSize
;
3110 DWORD dwServiceCount
;
3112 DWORD dwLastResumeCount
;
3113 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
3116 DPRINT("REnumServicesStatusExW() called\n");
3119 return ERROR_SHUTDOWN_IN_PROGRESS
;
3121 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
3122 return ERROR_INVALID_LEVEL
;
3124 hManager
= (PMANAGER_HANDLE
)hSCManager
;
3125 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
3127 DPRINT1("Invalid manager handle!\n");
3128 return ERROR_INVALID_HANDLE
;
3131 /* Check access rights */
3132 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
3133 SC_MANAGER_ENUMERATE_SERVICE
))
3135 DPRINT1("Insufficient access rights! 0x%lx\n",
3136 hManager
->Handle
.DesiredAccess
);
3137 return ERROR_ACCESS_DENIED
;
3140 *pcbBytesNeeded
= 0;
3141 *lpServicesReturned
= 0;
3143 dwLastResumeCount
= *lpResumeIndex
;
3145 /* Lock the service list shared */
3147 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
3148 if (lpService
== NULL
)
3150 dwError
= ERROR_SUCCESS
;
3157 for (ServiceEntry
= &lpService
->ServiceListEntry
;
3158 ServiceEntry
!= &ServiceListHead
;
3159 ServiceEntry
= ServiceEntry
->Flink
)
3161 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
3165 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
3168 dwState
= SERVICE_ACTIVE
;
3169 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
3170 dwState
= SERVICE_INACTIVE
;
3172 if ((dwState
& dwServiceState
) == 0)
3177 if (*pszGroupName
== 0)
3179 if (CurrentService
->lpGroup
!= NULL
)
3184 if ((CurrentService
->lpGroup
== NULL
) ||
3185 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
3190 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
3191 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
3192 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
3194 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
3196 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
3197 dwRequiredSize
+= dwSize
;
3199 dwLastResumeCount
= CurrentService
->dwResumeCount
;
3203 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
3209 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
3210 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
3213 ServiceEntry
!= &ServiceListHead
;
3214 ServiceEntry
= ServiceEntry
->Flink
)
3216 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
3220 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
3223 dwState
= SERVICE_ACTIVE
;
3224 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
3225 dwState
= SERVICE_INACTIVE
;
3227 if ((dwState
& dwServiceState
) == 0)
3232 if (*pszGroupName
== 0)
3234 if (CurrentService
->lpGroup
!= NULL
)
3239 if ((CurrentService
->lpGroup
== NULL
) ||
3240 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
3245 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
3246 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
3247 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
3249 dwError
= ERROR_MORE_DATA
;
3252 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
3254 *lpResumeIndex
= dwLastResumeCount
;
3255 *lpServicesReturned
= dwServiceCount
;
3256 *pcbBytesNeeded
= dwRequiredSize
;
3258 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
3259 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
3260 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
3263 for (ServiceEntry
= &lpService
->ServiceListEntry
;
3264 ServiceEntry
!= &ServiceListHead
;
3265 ServiceEntry
= ServiceEntry
->Flink
)
3267 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
3271 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
3274 dwState
= SERVICE_ACTIVE
;
3275 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
3276 dwState
= SERVICE_INACTIVE
;
3278 if ((dwState
& dwServiceState
) == 0)
3283 if (*pszGroupName
== 0)
3285 if (CurrentService
->lpGroup
!= NULL
)
3290 if ((CurrentService
->lpGroup
== NULL
) ||
3291 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
3296 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
3297 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
3298 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
3300 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
3302 /* Copy the service name */
3304 CurrentService
->lpServiceName
);
3305 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
3306 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
3308 /* Copy the display name */
3310 CurrentService
->lpDisplayName
);
3311 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
3312 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
3314 /* Copy the status information */
3315 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
3316 &CurrentService
->Status
,
3317 sizeof(SERVICE_STATUS
));
3318 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
3319 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
3322 dwRequiredSize
+= dwSize
;
3332 /* Unlock the service list */
3334 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
3341 DWORD
RSendTSMessage(
3342 handle_t BindingHandle
)
3345 return ERROR_CALL_NOT_IMPLEMENTED
;
3350 DWORD
RCreateServiceWOW64A(
3351 handle_t BindingHandle
,
3352 LPSTR lpServiceName
,
3353 LPSTR lpDisplayName
,
3354 DWORD dwDesiredAccess
,
3355 DWORD dwServiceType
,
3357 DWORD dwErrorControl
,
3358 LPSTR lpBinaryPathName
,
3359 LPSTR lpLoadOrderGroup
,
3361 LPBYTE lpDependencies
,
3363 LPSTR lpServiceStartName
,
3366 LPSC_RPC_HANDLE lpServiceHandle
)
3369 return ERROR_CALL_NOT_IMPLEMENTED
;
3374 DWORD
RCreateServiceWOW64W(
3375 handle_t BindingHandle
,
3376 LPWSTR lpServiceName
,
3377 LPWSTR lpDisplayName
,
3378 DWORD dwDesiredAccess
,
3379 DWORD dwServiceType
,
3381 DWORD dwErrorControl
,
3382 LPWSTR lpBinaryPathName
,
3383 LPWSTR lpLoadOrderGroup
,
3385 LPBYTE lpDependencies
,
3387 LPWSTR lpServiceStartName
,
3390 LPSC_RPC_HANDLE lpServiceHandle
)
3393 return ERROR_CALL_NOT_IMPLEMENTED
;
3398 DWORD
RQueryServiceTagInfo(
3399 handle_t BindingHandle
)
3402 return ERROR_CALL_NOT_IMPLEMENTED
;
3407 DWORD
RNotifyServiceStatusChange(
3408 handle_t BindingHandle
,
3409 SC_RPC_HANDLE hService
,
3410 SC_RPC_NOTIFY_PARAMS NotifyParams
,
3411 GUID
*pClientProcessGuid
,
3412 GUID
*pSCMProcessGuid
,
3413 PBOOL pfCreateRemoteQueue
,
3414 LPSC_NOTIFY_RPC_HANDLE phNotify
)
3417 return ERROR_CALL_NOT_IMPLEMENTED
;
3422 DWORD
RGetNotifyResults(
3423 handle_t BindingHandle
,
3424 SC_NOTIFY_RPC_HANDLE hNotify
,
3425 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
3428 return ERROR_CALL_NOT_IMPLEMENTED
;
3433 DWORD
RCloseNotifyHandle(
3434 handle_t BindingHandle
,
3435 LPSC_NOTIFY_RPC_HANDLE phNotify
,
3439 return ERROR_CALL_NOT_IMPLEMENTED
;
3444 DWORD
RControlServiceExA(
3445 handle_t BindingHandle
,
3446 SC_RPC_HANDLE hService
,
3451 return ERROR_CALL_NOT_IMPLEMENTED
;
3456 DWORD
RControlServiceExW(
3457 handle_t BindingHandle
,
3458 SC_RPC_HANDLE hService
,
3463 return ERROR_CALL_NOT_IMPLEMENTED
;
3468 DWORD
RSendPnPMessage(
3469 handle_t BindingHandle
)
3472 return ERROR_CALL_NOT_IMPLEMENTED
;
3477 DWORD
RValidatePnPService(
3478 handle_t BindingHandle
)
3481 return ERROR_CALL_NOT_IMPLEMENTED
;
3486 DWORD
ROpenServiceStatusHandle(
3487 handle_t BindingHandle
)
3490 return ERROR_CALL_NOT_IMPLEMENTED
;
3496 handle_t BindingHandle
)
3499 return ERROR_CALL_NOT_IMPLEMENTED
;
3503 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
3505 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
3509 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
3511 HeapFree(GetProcessHeap(), 0, ptr
);
3515 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
3520 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
3525 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)