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>
11 /* INCLUDES ****************************************************************/
20 /* GLOBALS *****************************************************************/
22 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
23 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
24 #define INVALID_TAG 0xAABBCCDD
26 typedef struct _SCMGR_HANDLE
33 typedef struct _MANAGER_HANDLE
36 WCHAR DatabaseName
[1];
37 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
40 typedef struct _SERVICE_HANDLE
43 PSERVICE ServiceEntry
;
44 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
47 #define SC_MANAGER_READ \
48 (STANDARD_RIGHTS_READ | \
49 SC_MANAGER_QUERY_LOCK_STATUS | \
50 SC_MANAGER_ENUMERATE_SERVICE)
52 #define SC_MANAGER_WRITE \
53 (STANDARD_RIGHTS_WRITE | \
54 SC_MANAGER_MODIFY_BOOT_CONFIG | \
55 SC_MANAGER_CREATE_SERVICE)
57 #define SC_MANAGER_EXECUTE \
58 (STANDARD_RIGHTS_EXECUTE | \
60 SC_MANAGER_ENUMERATE_SERVICE | \
61 SC_MANAGER_CONNECT | \
62 SC_MANAGER_CREATE_SERVICE)
65 #define SERVICE_READ \
66 (STANDARD_RIGHTS_READ | \
67 SERVICE_INTERROGATE | \
68 SERVICE_ENUMERATE_DEPENDENTS | \
69 SERVICE_QUERY_STATUS | \
72 #define SERVICE_WRITE \
73 (STANDARD_RIGHTS_WRITE | \
74 SERVICE_CHANGE_CONFIG)
76 #define SERVICE_EXECUTE \
77 (STANDARD_RIGHTS_EXECUTE | \
78 SERVICE_USER_DEFINED_CONTROL | \
79 SERVICE_PAUSE_CONTINUE | \
83 #define TAG_ARRAY_SIZE 32
85 /* VARIABLES ***************************************************************/
87 static GENERIC_MAPPING
88 ScmManagerMapping
= {SC_MANAGER_READ
,
91 SC_MANAGER_ALL_ACCESS
};
93 static GENERIC_MAPPING
94 ScmServiceMapping
= {SERVICE_READ
,
100 /* FUNCTIONS ***************************************************************/
103 ScmStartRpcServer(VOID
)
107 DPRINT("ScmStartRpcServer() called\n");
109 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
113 if (Status
!= RPC_S_OK
)
115 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
119 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
122 if (Status
!= RPC_S_OK
)
124 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
128 Status
= RpcServerListen(1, 20, TRUE
);
129 if (Status
!= RPC_S_OK
)
131 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
135 DPRINT("ScmStartRpcServer() done\n");
140 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
145 if (lpDatabaseName
== NULL
)
146 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
148 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
150 DPRINT("Database %S, does not exist\n", lpDatabaseName
);
151 return ERROR_DATABASE_DOES_NOT_EXIST
;
153 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
155 DPRINT("Invalid Database name %S.\n", lpDatabaseName
);
156 return ERROR_INVALID_NAME
;
159 Ptr
= HeapAlloc(GetProcessHeap(),
161 FIELD_OFFSET(MANAGER_HANDLE
, DatabaseName
[wcslen(lpDatabaseName
) + 1]));
163 return ERROR_NOT_ENOUGH_MEMORY
;
165 Ptr
->Handle
.Tag
= MANAGER_TAG
;
167 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
169 *Handle
= (SC_HANDLE
)Ptr
;
171 return ERROR_SUCCESS
;
176 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
181 Ptr
= HeapAlloc(GetProcessHeap(),
183 sizeof(SERVICE_HANDLE
));
185 return ERROR_NOT_ENOUGH_MEMORY
;
187 Ptr
->Handle
.Tag
= SERVICE_TAG
;
189 Ptr
->ServiceEntry
= lpServiceEntry
;
191 *Handle
= (SC_HANDLE
)Ptr
;
193 return ERROR_SUCCESS
;
197 static PMANAGER_HANDLE
198 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
200 PMANAGER_HANDLE pManager
= NULL
;
204 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
205 pManager
= (PMANAGER_HANDLE
)Handle
;
207 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
209 DPRINT1("Exception: Invalid Service Manager handle!\n");
217 static PSERVICE_HANDLE
218 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
220 PSERVICE_HANDLE pService
= NULL
;
224 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
225 pService
= (PSERVICE_HANDLE
)Handle
;
227 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
229 DPRINT1("Exception: Invalid Service handle!\n");
238 ScmCheckAccess(SC_HANDLE Handle
,
239 DWORD dwDesiredAccess
)
241 PMANAGER_HANDLE hMgr
;
243 hMgr
= (PMANAGER_HANDLE
)Handle
;
244 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
246 RtlMapGenericMask(&dwDesiredAccess
,
249 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
251 return ERROR_SUCCESS
;
253 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
255 RtlMapGenericMask(&dwDesiredAccess
,
258 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
260 return ERROR_SUCCESS
;
263 return ERROR_INVALID_HANDLE
;
268 ScmAssignNewTag(PSERVICE lpService
)
272 DWORD dwGroupTagCount
= 0;
273 PDWORD pdwGroupTags
= NULL
;
275 DWORD dwTagUsedBase
= 1;
276 BOOLEAN TagUsed
[TAG_ARRAY_SIZE
];
280 PLIST_ENTRY ServiceEntry
;
281 PSERVICE CurrentService
;
283 ASSERT(lpService
!= NULL
);
284 ASSERT(lpService
->lpGroup
!= NULL
);
286 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
287 L
"System\\CurrentControlSet\\Control\\GroupOrderList",
292 if (dwError
!= ERROR_SUCCESS
)
295 /* query value length */
297 dwError
= RegQueryValueExW(hKey
,
298 lpService
->lpGroup
->szGroupName
,
304 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_MORE_DATA
)
307 pdwGroupTags
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbDataSize
);
310 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
314 dwError
= RegQueryValueExW(hKey
,
315 lpService
->lpGroup
->szGroupName
,
318 (LPBYTE
)pdwGroupTags
,
321 if (dwError
!= ERROR_SUCCESS
)
324 if (cbDataSize
< sizeof(pdwGroupTags
[0]))
327 dwGroupTagCount
= min(pdwGroupTags
[0], cbDataSize
/ sizeof(pdwGroupTags
[0]) - 1);
332 /* mark all tags as unused */
333 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
336 /* mark tags in GroupOrderList as used */
337 for (i
= 1; i
<= dwGroupTagCount
; i
++)
339 nTagOffset
= pdwGroupTags
[i
] - dwTagUsedBase
;
340 if (nTagOffset
>= 0 && nTagOffset
< TAG_ARRAY_SIZE
)
341 TagUsed
[nTagOffset
] = TRUE
;
344 /* mark tags in service list as used */
345 ServiceEntry
= lpService
->ServiceListEntry
.Flink
;
346 while (ServiceEntry
!= &lpService
->ServiceListEntry
)
348 ASSERT(ServiceEntry
!= NULL
);
349 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
350 if (CurrentService
->lpGroup
== lpService
->lpGroup
)
352 nTagOffset
= CurrentService
->dwTag
- dwTagUsedBase
;
353 if (nTagOffset
>= 0 && nTagOffset
< TAG_ARRAY_SIZE
)
354 TagUsed
[nTagOffset
] = TRUE
;
357 ServiceEntry
= ServiceEntry
->Flink
;
360 /* find unused tag, if any */
361 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
365 dwFreeTag
= dwTagUsedBase
+ i
;
370 dwTagUsedBase
+= TAG_ARRAY_SIZE
;
371 } while (!dwFreeTag
);
375 HeapFree(GetProcessHeap(), 0, pdwGroupTags
);
382 lpService
->dwTag
= dwFreeTag
;
383 DPRINT("Assigning new tag %lu to service %S in group %S\n",
384 lpService
->dwTag
, lpService
->lpServiceName
, lpService
->lpGroup
->szGroupName
);
385 dwError
= ERROR_SUCCESS
;
389 DPRINT1("Failed to assign new tag to service %S, error=%lu\n",
390 lpService
->lpServiceName
, dwError
);
397 /* Create a path suitable for the bootloader out of the full path */
399 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
401 SIZE_T ServiceNameLen
, ExpandedLen
;
405 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
406 OBJECT_ATTRIBUTES ObjectAttributes
;
408 HANDLE SymbolicLinkHandle
;
410 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
413 return ERROR_INVALID_PARAMETER
;
415 *RelativeName
= NULL
;
417 ServiceNameLen
= wcslen(CanonName
);
419 /* First check, if it's already good */
420 if (ServiceNameLen
> 12 &&
421 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
423 *RelativeName
= HeapAlloc(GetProcessHeap(),
425 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
426 if (*RelativeName
== NULL
)
428 DPRINT("Error allocating memory for boot driver name!\n");
429 return ERROR_NOT_ENOUGH_MEMORY
;
433 wcscpy(*RelativeName
, CanonName
);
435 DPRINT("Bootdriver name %S\n", *RelativeName
);
436 return ERROR_SUCCESS
;
439 /* If it has %SystemRoot% prefix, substitute it to \System*/
440 if (ServiceNameLen
> 13 &&
441 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
443 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
444 *RelativeName
= HeapAlloc(GetProcessHeap(),
446 ServiceNameLen
* sizeof(WCHAR
));
448 if (*RelativeName
== NULL
)
450 DPRINT("Error allocating memory for boot driver name!\n");
451 return ERROR_NOT_ENOUGH_MEMORY
;
455 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
456 wcscat(*RelativeName
, CanonName
+ 13);
458 DPRINT("Bootdriver name %S\n", *RelativeName
);
459 return ERROR_SUCCESS
;
462 /* Get buffer size needed for expanding env strings */
463 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
467 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
468 return ERROR_INVALID_ENVIRONMENT
;
471 /* Allocate memory, since the size is known now */
472 Expanded
= HeapAlloc(GetProcessHeap(),
474 (BufferSize
+ 1) * sizeof(WCHAR
));
477 DPRINT("Error allocating memory for boot driver name!\n");
478 return ERROR_NOT_ENOUGH_MEMORY
;
482 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
485 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
486 HeapFree(GetProcessHeap(), 0, Expanded
);
487 return ERROR_NOT_ENOUGH_MEMORY
;
490 /* Convert to NT-style path */
491 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
493 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
494 return ERROR_INVALID_ENVIRONMENT
;
497 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
499 /* No need to keep the dos-path anymore */
500 HeapFree(GetProcessHeap(), 0, Expanded
);
502 /* Copy it to the allocated place */
503 Expanded
= HeapAlloc(GetProcessHeap(),
505 NtPathName
.Length
+ sizeof(UNICODE_NULL
));
508 DPRINT("Error allocating memory for boot driver name!\n");
509 RtlFreeUnicodeString(&NtPathName
);
510 return ERROR_NOT_ENOUGH_MEMORY
;
513 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
514 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
515 Expanded
[ExpandedLen
] = UNICODE_NULL
;
516 RtlFreeUnicodeString(&NtPathName
);
518 if (ServiceNameLen
> ExpandedLen
&&
519 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
521 HeapFree(GetProcessHeap(), 0, Expanded
);
523 /* Only \SystemRoot\ is missing */
524 *RelativeName
= HeapAlloc(GetProcessHeap(),
526 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
527 if (*RelativeName
== NULL
)
529 DPRINT("Error allocating memory for boot driver name!\n");
530 return ERROR_NOT_ENOUGH_MEMORY
;
533 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
534 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
536 return ERROR_SUCCESS
;
539 /* No longer need this */
540 HeapFree(GetProcessHeap(), 0, Expanded
);
542 /* The most complex case starts here */
543 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
544 InitializeObjectAttributes(&ObjectAttributes
,
546 OBJ_CASE_INSENSITIVE
,
550 /* Open this symlink */
551 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
552 if (NT_SUCCESS(Status
))
554 DPRINT("Opened symbolic link object\n");
556 RtlInitEmptyUnicodeString(&LinkTarget
, NULL
, 0);
557 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
558 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
560 /* Check if required buffer size is sane */
561 if (BufferSize
> UNICODE_STRING_MAX_BYTES
- sizeof(UNICODE_NULL
))
563 DPRINT("Too large buffer required\n");
565 NtClose(SymbolicLinkHandle
);
566 return ERROR_NOT_ENOUGH_MEMORY
;
569 /* Alloc the string */
570 LinkTarget
.Length
= (USHORT
)BufferSize
;
571 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(UNICODE_NULL
);
572 LinkTarget
.Buffer
= HeapAlloc(GetProcessHeap(),
574 LinkTarget
.MaximumLength
);
575 if (!LinkTarget
.Buffer
)
577 DPRINT("Unable to alloc buffer\n");
578 NtClose(SymbolicLinkHandle
);
579 return ERROR_NOT_ENOUGH_MEMORY
;
582 /* Do a real query now */
583 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
584 NtClose(SymbolicLinkHandle
);
585 if (NT_SUCCESS(Status
))
587 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
589 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
590 if ((ServiceNameLen
> ExpandedLen
) &&
591 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
593 *RelativeName
= HeapAlloc(GetProcessHeap(),
595 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
597 if (*RelativeName
== NULL
)
599 DPRINT("Unable to alloc buffer\n");
600 return ERROR_NOT_ENOUGH_MEMORY
;
603 /* Copy it over, substituting the first part
605 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
606 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
609 return ERROR_SUCCESS
;
613 return ERROR_INVALID_PARAMETER
;
618 DPRINT("Error, Status = %08X\n", Status
);
619 return ERROR_INVALID_PARAMETER
;
624 DPRINT("Error, Status = %08X\n", Status
);
625 NtClose(SymbolicLinkHandle
);
626 return ERROR_INVALID_PARAMETER
;
632 DPRINT("Error, Status = %08X\n", Status
);
633 return ERROR_INVALID_PARAMETER
;
639 ScmCanonDriverImagePath(DWORD dwStartType
,
640 const wchar_t *lpServiceName
,
641 wchar_t **lpCanonName
)
644 SIZE_T ServiceNameLen
;
645 UNICODE_STRING NtServiceName
;
647 const WCHAR
*SourceName
= lpServiceName
;
649 /* Calculate the length of the service's name */
650 ServiceNameLen
= wcslen(lpServiceName
);
652 /* 12 is wcslen(L"\\SystemRoot\\") */
653 if (ServiceNameLen
> 12 &&
654 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
656 /* SystemRoot prefix is already included */
657 *lpCanonName
= HeapAlloc(GetProcessHeap(),
659 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
661 if (*lpCanonName
== NULL
)
663 DPRINT("Error allocating memory for canonized service name!\n");
664 return ERROR_NOT_ENOUGH_MEMORY
;
667 /* If it's a boot-time driver, it must be systemroot relative */
668 if (dwStartType
== SERVICE_BOOT_START
)
672 wcscpy(*lpCanonName
, SourceName
);
674 DPRINT("Canonicalized name %S\n", *lpCanonName
);
678 /* Check if it has %SystemRoot% (len=13) */
679 if (ServiceNameLen
> 13 &&
680 !_wcsnicmp(L
"%SystemRoot%\\", lpServiceName
, 13))
682 /* Substitute %SystemRoot% with \\SystemRoot\\ */
683 *lpCanonName
= HeapAlloc(GetProcessHeap(),
685 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
687 if (*lpCanonName
== NULL
)
689 DPRINT("Error allocating memory for canonized service name!\n");
690 return ERROR_NOT_ENOUGH_MEMORY
;
693 /* If it's a boot-time driver, it must be systemroot relative */
694 if (dwStartType
== SERVICE_BOOT_START
)
695 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
697 wcscat(*lpCanonName
, lpServiceName
+ 13);
699 DPRINT("Canonicalized name %S\n", *lpCanonName
);
703 /* Check if it's a relative path name */
704 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
706 *lpCanonName
= HeapAlloc(GetProcessHeap(),
708 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
710 if (*lpCanonName
== NULL
)
712 DPRINT("Error allocating memory for canonized service name!\n");
713 return ERROR_NOT_ENOUGH_MEMORY
;
716 /* Just copy it over without changing */
717 wcscpy(*lpCanonName
, lpServiceName
);
722 /* It seems to be a DOS path, convert it */
723 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
725 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
726 return ERROR_INVALID_PARAMETER
;
729 *lpCanonName
= HeapAlloc(GetProcessHeap(),
731 NtServiceName
.Length
+ sizeof(WCHAR
));
733 if (*lpCanonName
== NULL
)
735 DPRINT("Error allocating memory for canonized service name!\n");
736 RtlFreeUnicodeString(&NtServiceName
);
737 return ERROR_NOT_ENOUGH_MEMORY
;
740 /* Copy the string */
741 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
743 /* The unicode string is not needed anymore */
744 RtlFreeUnicodeString(&NtServiceName
);
746 if (dwStartType
!= SERVICE_BOOT_START
)
748 DPRINT("Canonicalized name %S\n", *lpCanonName
);
752 /* The service is boot-started, so must be relative */
753 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
756 /* There is a problem, free name and return */
757 HeapFree(GetProcessHeap(), 0, *lpCanonName
);
758 DPRINT("Error converting named!\n");
762 ASSERT(RelativeName
);
764 /* Copy that string */
765 wcscpy(*lpCanonName
, RelativeName
+ 12);
767 /* Free the allocated buffer */
768 HeapFree(GetProcessHeap(), 0, RelativeName
);
770 DPRINT("Canonicalized name %S\n", *lpCanonName
);
777 /* Internal recursive function */
778 /* Need to search for every dependency on every service */
780 Int_EnumDependentServicesW(HKEY hServicesKey
,
782 DWORD dwServiceState
,
783 PSERVICE
*lpServices
,
784 LPDWORD pcbBytesNeeded
,
785 LPDWORD lpServicesReturned
)
787 DWORD dwError
= ERROR_SUCCESS
;
788 WCHAR szNameBuf
[MAX_PATH
];
789 WCHAR szValueBuf
[MAX_PATH
];
790 WCHAR
*lpszNameBuf
= szNameBuf
;
791 WCHAR
*lpszValueBuf
= szValueBuf
;
795 PSERVICE lpCurrentService
;
796 HKEY hServiceEnumKey
;
797 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
798 DWORD dwDependServiceStrPtr
= 0;
799 DWORD dwRequiredSize
= 0;
801 /* Get the number of service keys */
802 dwError
= RegQueryInfoKeyW(hServicesKey
,
814 if (dwError
!= ERROR_SUCCESS
)
816 DPRINT("ERROR! Unable to get number of services keys.\n");
820 /* Iterate the service keys to see if another service depends on the this service */
821 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
824 dwError
= RegEnumKeyExW(hServicesKey
,
832 if (dwError
!= ERROR_SUCCESS
)
835 /* Open the Service key */
836 dwError
= RegOpenKeyExW(hServicesKey
,
841 if (dwError
!= ERROR_SUCCESS
)
844 dwSize
= MAX_PATH
* sizeof(WCHAR
);
846 /* Check for the DependOnService Value */
847 dwError
= RegQueryValueExW(hServiceEnumKey
,
851 (LPBYTE
)lpszValueBuf
,
854 /* FIXME: Handle load order. */
856 /* If the service found has a DependOnService value */
857 if (dwError
== ERROR_SUCCESS
)
859 dwDependServiceStrPtr
= 0;
861 /* Can be more than one Dependencies in the DependOnService string */
862 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
864 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
866 /* Get the current enumed service pointer */
867 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
869 /* Check for valid Service */
870 if (!lpCurrentService
)
872 /* This should never happen! */
873 DPRINT("This should not happen at this point, report to Developer\n");
874 return ERROR_NOT_FOUND
;
877 /* Determine state the service is in */
878 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
879 dwCurrentServiceState
= SERVICE_INACTIVE
;
881 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
882 if ((dwCurrentServiceState
== dwServiceState
) ||
883 (dwServiceState
== SERVICE_STATE_ALL
))
885 /* Calculate the required size */
886 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
887 dwRequiredSize
+= (DWORD
)((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
888 dwRequiredSize
+= (DWORD
)((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
890 /* Add the size for service name and display name pointers */
891 dwRequiredSize
+= (2 * sizeof(PVOID
));
893 /* increase the BytesNeeded size */
894 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
896 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
899 /* Recursive call to check for its dependencies */
900 Int_EnumDependentServicesW(hServicesKey
,
907 /* If the lpServices is valid set the service pointer */
909 lpServices
[*lpServicesReturned
] = lpCurrentService
;
911 *lpServicesReturned
= *lpServicesReturned
+ 1;
915 dwDependServiceStrPtr
+= (DWORD
)(wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
918 else if (*pcbBytesNeeded
)
920 dwError
= ERROR_SUCCESS
;
923 RegCloseKey(hServiceEnumKey
);
934 LPSC_RPC_HANDLE hSCObject
)
936 PMANAGER_HANDLE hManager
;
937 PSERVICE_HANDLE hService
;
941 DWORD pcbBytesNeeded
= 0;
942 DWORD dwServicesReturned
= 0;
944 DPRINT("RCloseServiceHandle() called\n");
946 DPRINT("hSCObject = %p\n", *hSCObject
);
949 return ERROR_INVALID_HANDLE
;
951 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
952 hService
= ScmGetServiceFromHandle(*hSCObject
);
954 if (hManager
!= NULL
)
956 DPRINT("Found manager handle\n");
958 /* Make sure we don't access stale memory if someone tries to use this handle again. */
959 hManager
->Handle
.Tag
= INVALID_TAG
;
961 HeapFree(GetProcessHeap(), 0, hManager
);
966 DPRINT("RCloseServiceHandle() done\n");
967 return ERROR_SUCCESS
;
969 else if (hService
!= NULL
)
971 DPRINT("Found service handle\n");
973 /* Lock the service database exclusively */
974 ScmLockDatabaseExclusive();
976 /* Get the pointer to the service record */
977 lpService
= hService
->ServiceEntry
;
979 /* Make sure we don't access stale memory if someone tries to use this handle again. */
980 hService
->Handle
.Tag
= INVALID_TAG
;
982 /* Free the handle */
983 HeapFree(GetProcessHeap(), 0, hService
);
986 ASSERT(lpService
->dwRefCount
> 0);
988 lpService
->dwRefCount
--;
989 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
990 lpService
->dwRefCount
);
992 if (lpService
->dwRefCount
== 0)
994 /* If this service has been marked for deletion */
995 if (lpService
->bDeleted
&&
996 lpService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
998 /* Open the Services Reg key */
999 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1000 L
"System\\CurrentControlSet\\Services",
1002 KEY_SET_VALUE
| KEY_READ
,
1004 if (dwError
!= ERROR_SUCCESS
)
1006 DPRINT("Failed to open services key\n");
1007 ScmUnlockDatabase();
1011 /* Call the internal function with NULL, just to get bytes we need */
1012 Int_EnumDependentServicesW(hServicesKey
,
1017 &dwServicesReturned
);
1019 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */
1022 DPRINT("Deletion failed due to running dependencies.\n");
1023 RegCloseKey(hServicesKey
);
1024 ScmUnlockDatabase();
1025 return ERROR_SUCCESS
;
1028 /* There are no references and no running dependencies,
1029 it is now safe to delete the service */
1031 /* Delete the Service Key */
1032 dwError
= ScmDeleteRegKey(hServicesKey
,
1033 lpService
->lpServiceName
);
1035 RegCloseKey(hServicesKey
);
1037 if (dwError
!= ERROR_SUCCESS
)
1039 DPRINT("Failed to Delete the Service Registry key\n");
1040 ScmUnlockDatabase();
1044 /* Delete the Service */
1045 ScmDeleteServiceRecord(lpService
);
1049 ScmUnlockDatabase();
1053 DPRINT("RCloseServiceHandle() done\n");
1054 return ERROR_SUCCESS
;
1057 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
1059 return ERROR_INVALID_HANDLE
;
1067 SC_RPC_HANDLE hService
,
1069 LPSERVICE_STATUS lpServiceStatus
)
1071 PSERVICE_HANDLE hSvc
;
1073 ACCESS_MASK DesiredAccess
;
1074 DWORD dwError
= ERROR_SUCCESS
;
1075 DWORD pcbBytesNeeded
= 0;
1076 DWORD dwServicesReturned
= 0;
1077 DWORD dwControlsAccepted
;
1078 DWORD dwCurrentState
;
1079 HKEY hServicesKey
= NULL
;
1080 LPCWSTR lpLogStrings
[2];
1081 WCHAR szLogBuffer
[80];
1084 DPRINT("RControlService() called\n");
1087 return ERROR_SHUTDOWN_IN_PROGRESS
;
1089 /* Check the service handle */
1090 hSvc
= ScmGetServiceFromHandle(hService
);
1093 DPRINT1("Invalid service handle!\n");
1094 return ERROR_INVALID_HANDLE
;
1097 /* Check the service entry point */
1098 lpService
= hSvc
->ServiceEntry
;
1099 if (lpService
== NULL
)
1101 DPRINT1("lpService == NULL!\n");
1102 return ERROR_INVALID_HANDLE
;
1105 /* Check access rights */
1108 case SERVICE_CONTROL_STOP
:
1109 DesiredAccess
= SERVICE_STOP
;
1112 case SERVICE_CONTROL_PAUSE
:
1113 case SERVICE_CONTROL_CONTINUE
:
1114 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
1117 case SERVICE_CONTROL_INTERROGATE
:
1118 DesiredAccess
= SERVICE_INTERROGATE
;
1122 if (dwControl
>= 128 && dwControl
<= 255)
1123 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
1125 return ERROR_INVALID_PARAMETER
;
1129 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1131 return ERROR_ACCESS_DENIED
;
1133 /* Return the current service status information */
1134 RtlCopyMemory(lpServiceStatus
,
1136 sizeof(SERVICE_STATUS
));
1138 if (dwControl
== SERVICE_CONTROL_STOP
)
1140 /* Check if the service has dependencies running as windows
1141 doesn't stop a service that does */
1143 /* Open the Services Reg key */
1144 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1145 L
"System\\CurrentControlSet\\Services",
1149 if (dwError
!= ERROR_SUCCESS
)
1151 DPRINT("Failed to open services key\n");
1155 /* Call the internal function with NULL, just to get bytes we need */
1156 Int_EnumDependentServicesW(hServicesKey
,
1161 &dwServicesReturned
);
1163 RegCloseKey(hServicesKey
);
1165 /* If pcbBytesNeeded is not zero then there are services running that
1166 are dependent on this service */
1167 if (pcbBytesNeeded
!= 0)
1169 DPRINT("Service has running dependencies. Failed to stop service.\n");
1170 return ERROR_DEPENDENT_SERVICES_RUNNING
;
1174 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1176 /* Send control code to the driver */
1177 dwError
= ScmControlDriver(lpService
,
1183 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
1184 dwCurrentState
= lpService
->Status
.dwCurrentState
;
1186 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1187 if (lpService
->lpImage
== NULL
|| dwCurrentState
== SERVICE_STOPPED
)
1188 return ERROR_SERVICE_NOT_ACTIVE
;
1190 /* Check the current state before sending a control request */
1191 switch (dwCurrentState
)
1193 case SERVICE_STOP_PENDING
:
1194 case SERVICE_STOPPED
:
1195 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1197 case SERVICE_START_PENDING
:
1200 case SERVICE_CONTROL_STOP
:
1203 case SERVICE_CONTROL_INTERROGATE
:
1204 RtlCopyMemory(lpServiceStatus
,
1206 sizeof(SERVICE_STATUS
));
1207 return ERROR_SUCCESS
;
1210 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1215 /* Check if the control code is acceptable to the service */
1218 case SERVICE_CONTROL_STOP
:
1219 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
1220 return ERROR_INVALID_SERVICE_CONTROL
;
1223 case SERVICE_CONTROL_PAUSE
:
1224 case SERVICE_CONTROL_CONTINUE
:
1225 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
1226 return ERROR_INVALID_SERVICE_CONTROL
;
1230 /* Send control code to the service */
1231 dwError
= ScmControlService(lpService
,
1234 /* Return service status information */
1235 RtlCopyMemory(lpServiceStatus
,
1237 sizeof(SERVICE_STATUS
));
1240 if (dwError
== ERROR_SUCCESS
)
1242 if (dwControl
== SERVICE_CONTROL_STOP
||
1243 dwControl
== SERVICE_CONTROL_PAUSE
||
1244 dwControl
== SERVICE_CONTROL_CONTINUE
)
1246 /* Log a successful send control */
1250 case SERVICE_CONTROL_STOP
:
1251 uID
= IDS_SERVICE_STOP
;
1254 case SERVICE_CONTROL_PAUSE
:
1255 uID
= IDS_SERVICE_PAUSE
;
1258 case SERVICE_CONTROL_CONTINUE
:
1259 uID
= IDS_SERVICE_RESUME
;
1262 LoadStringW(GetModuleHandle(NULL
), uID
, szLogBuffer
, 80);
1264 lpLogStrings
[0] = lpService
->lpDisplayName
;
1265 lpLogStrings
[1] = szLogBuffer
;
1267 ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS
,
1268 EVENTLOG_INFORMATION_TYPE
,
1282 SC_RPC_HANDLE hService
)
1284 PSERVICE_HANDLE hSvc
;
1288 DPRINT("RDeleteService() called\n");
1291 return ERROR_SHUTDOWN_IN_PROGRESS
;
1293 hSvc
= ScmGetServiceFromHandle(hService
);
1296 DPRINT1("Invalid service handle!\n");
1297 return ERROR_INVALID_HANDLE
;
1300 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1302 return ERROR_ACCESS_DENIED
;
1304 lpService
= hSvc
->ServiceEntry
;
1305 if (lpService
== NULL
)
1307 DPRINT("lpService == NULL!\n");
1308 return ERROR_INVALID_HANDLE
;
1311 /* Lock the service database exclusively */
1312 ScmLockDatabaseExclusive();
1314 if (lpService
->bDeleted
)
1316 DPRINT("The service has already been marked for delete!\n");
1317 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1321 /* Mark service for delete */
1322 lpService
->bDeleted
= TRUE
;
1324 dwError
= ScmMarkServiceForDelete(lpService
);
1327 /* Unlock the service database */
1328 ScmUnlockDatabase();
1330 DPRINT("RDeleteService() done\n");
1339 RLockServiceDatabase(
1340 SC_RPC_HANDLE hSCManager
,
1341 LPSC_RPC_LOCK lpLock
)
1343 PMANAGER_HANDLE hMgr
;
1345 DPRINT("RLockServiceDatabase() called\n");
1349 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
1352 DPRINT1("Invalid service manager handle!\n");
1353 return ERROR_INVALID_HANDLE
;
1356 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
1358 return ERROR_ACCESS_DENIED
;
1360 return ScmAcquireServiceStartLock(FALSE
, lpLock
);
1367 RQueryServiceObjectSecurity(
1368 SC_RPC_HANDLE hService
,
1369 SECURITY_INFORMATION dwSecurityInformation
,
1370 LPBYTE lpSecurityDescriptor
,
1372 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1374 PSERVICE_HANDLE hSvc
;
1376 ULONG DesiredAccess
= 0;
1378 DWORD dwBytesNeeded
;
1381 DPRINT("RQueryServiceObjectSecurity() called\n");
1383 hSvc
= ScmGetServiceFromHandle(hService
);
1386 DPRINT1("Invalid service handle!\n");
1387 return ERROR_INVALID_HANDLE
;
1390 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1391 GROUP_SECURITY_INFORMATION
|
1392 OWNER_SECURITY_INFORMATION
))
1393 DesiredAccess
|= READ_CONTROL
;
1395 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1396 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1398 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1401 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1402 return ERROR_ACCESS_DENIED
;
1405 lpService
= hSvc
->ServiceEntry
;
1406 if (lpService
== NULL
)
1408 DPRINT("lpService == NULL!\n");
1409 return ERROR_INVALID_HANDLE
;
1412 /* Lock the service database */
1413 ScmLockDatabaseShared();
1415 /* Retrieve the security descriptor */
1416 Status
= RtlQuerySecurityObject(lpService
->pSecurityDescriptor
,
1417 dwSecurityInformation
,
1418 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1422 /* Unlock the service database */
1423 ScmUnlockDatabase();
1425 if (NT_SUCCESS(Status
))
1427 *pcbBytesNeeded
= dwBytesNeeded
;
1428 dwError
= STATUS_SUCCESS
;
1430 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1432 *pcbBytesNeeded
= dwBytesNeeded
;
1433 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1435 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1437 dwError
= ERROR_GEN_FAILURE
;
1441 dwError
= RtlNtStatusToDosError(Status
);
1451 RSetServiceObjectSecurity(
1452 SC_RPC_HANDLE hService
,
1453 DWORD dwSecurityInformation
,
1454 LPBYTE lpSecurityDescriptor
,
1455 DWORD dwSecurityDescriptorSize
)
1457 PSERVICE_HANDLE hSvc
;
1459 ACCESS_MASK DesiredAccess
= 0;
1460 HANDLE hToken
= NULL
;
1461 HKEY hServiceKey
= NULL
;
1462 BOOL bDatabaseLocked
= FALSE
;
1466 DPRINT("RSetServiceObjectSecurity() called\n");
1468 hSvc
= ScmGetServiceFromHandle(hService
);
1471 DPRINT1("Invalid service handle!\n");
1472 return ERROR_INVALID_HANDLE
;
1475 if (dwSecurityInformation
== 0 ||
1476 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1477 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1478 return ERROR_INVALID_PARAMETER
;
1480 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1481 return ERROR_INVALID_PARAMETER
;
1483 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1484 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1486 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1487 DesiredAccess
|= WRITE_DAC
;
1489 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1490 DesiredAccess
|= WRITE_OWNER
;
1492 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1493 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1494 return ERROR_INVALID_PARAMETER
;
1496 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1497 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1498 return ERROR_INVALID_PARAMETER
;
1500 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1503 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1504 return ERROR_ACCESS_DENIED
;
1507 lpService
= hSvc
->ServiceEntry
;
1508 if (lpService
== NULL
)
1510 DPRINT1("lpService == NULL!\n");
1511 return ERROR_INVALID_HANDLE
;
1514 if (lpService
->bDeleted
)
1515 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1518 RpcImpersonateClient(NULL
);
1520 Status
= NtOpenThreadToken(NtCurrentThread(),
1524 if (!NT_SUCCESS(Status
))
1525 return RtlNtStatusToDosError(Status
);
1530 /* Build the new security descriptor */
1531 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1532 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1533 &lpService
->pSecurityDescriptor
,
1536 if (!NT_SUCCESS(Status
))
1538 dwError
= RtlNtStatusToDosError(Status
);
1542 /* Lock the service database exclusive */
1543 ScmLockDatabaseExclusive();
1544 bDatabaseLocked
= TRUE
;
1546 /* Open the service key */
1547 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1548 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1550 if (dwError
!= ERROR_SUCCESS
)
1553 /* Store the new security descriptor */
1554 dwError
= ScmWriteSecurityDescriptor(hServiceKey
,
1555 lpService
->pSecurityDescriptor
);
1557 RegFlushKey(hServiceKey
);
1560 if (hServiceKey
!= NULL
)
1561 RegCloseKey(hServiceKey
);
1563 /* Unlock service database */
1564 if (bDatabaseLocked
== TRUE
)
1565 ScmUnlockDatabase();
1570 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1579 RQueryServiceStatus(
1580 SC_RPC_HANDLE hService
,
1581 LPSERVICE_STATUS lpServiceStatus
)
1583 PSERVICE_HANDLE hSvc
;
1586 DPRINT("RQueryServiceStatus() called\n");
1589 return ERROR_SHUTDOWN_IN_PROGRESS
;
1591 hSvc
= ScmGetServiceFromHandle(hService
);
1594 DPRINT1("Invalid service handle!\n");
1595 return ERROR_INVALID_HANDLE
;
1598 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1599 SERVICE_QUERY_STATUS
))
1601 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1602 return ERROR_ACCESS_DENIED
;
1605 lpService
= hSvc
->ServiceEntry
;
1606 if (lpService
== NULL
)
1608 DPRINT("lpService == NULL!\n");
1609 return ERROR_INVALID_HANDLE
;
1612 /* Lock the service database shared */
1613 ScmLockDatabaseShared();
1615 /* Return service status information */
1616 RtlCopyMemory(lpServiceStatus
,
1618 sizeof(SERVICE_STATUS
));
1620 /* Unlock the service database */
1621 ScmUnlockDatabase();
1623 return ERROR_SUCCESS
;
1628 ScmIsValidServiceState(DWORD dwCurrentState
)
1630 switch (dwCurrentState
)
1632 case SERVICE_STOPPED
:
1633 case SERVICE_START_PENDING
:
1634 case SERVICE_STOP_PENDING
:
1635 case SERVICE_RUNNING
:
1636 case SERVICE_CONTINUE_PENDING
:
1637 case SERVICE_PAUSE_PENDING
:
1638 case SERVICE_PAUSED
:
1651 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1652 LPSERVICE_STATUS lpServiceStatus
)
1655 DWORD dwPreviousState
;
1656 DWORD dwPreviousType
;
1657 LPCWSTR lpLogStrings
[2];
1658 WCHAR szLogBuffer
[80];
1661 DPRINT("RSetServiceStatus() called\n");
1662 DPRINT("hServiceStatus = %lu\n", hServiceStatus
);
1663 DPRINT("dwServiceType = 0x%lx\n", lpServiceStatus
->dwServiceType
);
1664 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1665 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1666 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1667 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1668 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1669 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1671 if (hServiceStatus
== 0)
1673 DPRINT("hServiceStatus == NULL!\n");
1674 return ERROR_INVALID_HANDLE
;
1677 lpService
= (PSERVICE
)hServiceStatus
;
1679 /* Check current state */
1680 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1682 DPRINT("Invalid service state!\n");
1683 return ERROR_INVALID_DATA
;
1686 /* Check service type */
1687 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1688 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1690 DPRINT("Invalid service type!\n");
1691 return ERROR_INVALID_DATA
;
1694 /* Check accepted controls */
1695 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1697 DPRINT("Invalid controls accepted!\n");
1698 return ERROR_INVALID_DATA
;
1701 /* Set the wait hint and check point only if the service is in a pending state,
1702 otherwise they should be 0 */
1703 if (lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
||
1704 lpServiceStatus
->dwCurrentState
== SERVICE_PAUSED
||
1705 lpServiceStatus
->dwCurrentState
== SERVICE_RUNNING
)
1707 lpServiceStatus
->dwWaitHint
= 0;
1708 lpServiceStatus
->dwCheckPoint
= 0;
1711 /* Lock the service database exclusively */
1712 ScmLockDatabaseExclusive();
1714 /* Save the current service state */
1715 dwPreviousState
= lpService
->Status
.dwCurrentState
;
1717 /* Save the current service type */
1718 dwPreviousType
= lpService
->Status
.dwServiceType
;
1720 /* Update the service status */
1721 RtlCopyMemory(&lpService
->Status
,
1723 sizeof(SERVICE_STATUS
));
1725 /* Restore the previous service type */
1726 lpService
->Status
.dwServiceType
= dwPreviousType
;
1728 /* Unlock the service database */
1729 ScmUnlockDatabase();
1731 if ((lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
) &&
1732 (dwPreviousState
!= SERVICE_STOPPED
) &&
1733 (lpServiceStatus
->dwWin32ExitCode
!= ERROR_SUCCESS
))
1735 /* Log a failed service stop */
1736 swprintf(szLogBuffer
, L
"%lu", lpServiceStatus
->dwWin32ExitCode
);
1737 lpLogStrings
[0] = lpService
->lpDisplayName
;
1738 lpLogStrings
[1] = szLogBuffer
;
1740 ScmLogEvent(EVENT_SERVICE_EXIT_FAILED
,
1741 EVENTLOG_ERROR_TYPE
,
1745 else if (lpServiceStatus
->dwCurrentState
!= dwPreviousState
&&
1746 (lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
||
1747 lpServiceStatus
->dwCurrentState
== SERVICE_RUNNING
||
1748 lpServiceStatus
->dwCurrentState
== SERVICE_PAUSED
))
1750 /* Log a successful service status change */
1751 switch(lpServiceStatus
->dwCurrentState
)
1753 case SERVICE_STOPPED
:
1754 uID
= IDS_SERVICE_STOPPED
;
1757 case SERVICE_RUNNING
:
1758 uID
= IDS_SERVICE_RUNNING
;
1761 case SERVICE_PAUSED
:
1762 uID
= IDS_SERVICE_PAUSED
;
1766 LoadStringW(GetModuleHandle(NULL
), uID
, szLogBuffer
, 80);
1767 lpLogStrings
[0] = lpService
->lpDisplayName
;
1768 lpLogStrings
[1] = szLogBuffer
;
1770 ScmLogEvent(EVENT_SERVICE_STATUS_SUCCESS
,
1771 EVENTLOG_INFORMATION_TYPE
,
1776 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1777 DPRINT("RSetServiceStatus() done\n");
1779 return ERROR_SUCCESS
;
1786 RUnlockServiceDatabase(
1789 DPRINT("RUnlockServiceDatabase(%p)\n", Lock
);
1790 return ScmReleaseServiceStartLock(Lock
);
1797 RNotifyBootConfigStatus(
1798 SVCCTL_HANDLEW lpMachineName
,
1799 DWORD BootAcceptable
)
1801 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1802 return ERROR_SUCCESS
;
1805 // return ERROR_CALL_NOT_IMPLEMENTED;
1812 RI_ScSetServiceBitsW(
1813 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1814 DWORD dwServiceBits
,
1816 int bUpdateImmediately
,
1820 return ERROR_CALL_NOT_IMPLEMENTED
;
1827 RChangeServiceConfigW(
1828 SC_RPC_HANDLE hService
,
1829 DWORD dwServiceType
,
1831 DWORD dwErrorControl
,
1832 LPWSTR lpBinaryPathName
,
1833 LPWSTR lpLoadOrderGroup
,
1835 LPBYTE lpDependencies
,
1837 LPWSTR lpServiceStartName
,
1840 LPWSTR lpDisplayName
)
1842 DWORD dwError
= ERROR_SUCCESS
;
1843 PSERVICE_HANDLE hSvc
;
1844 PSERVICE lpService
= NULL
;
1845 HKEY hServiceKey
= NULL
;
1846 LPWSTR lpDisplayNameW
= NULL
;
1847 LPWSTR lpImagePathW
= NULL
;
1849 DPRINT("RChangeServiceConfigW() called\n");
1850 DPRINT("dwServiceType = 0x%lx\n", dwServiceType
);
1851 DPRINT("dwStartType = %lu\n", dwStartType
);
1852 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1853 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1854 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1855 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1858 return ERROR_SHUTDOWN_IN_PROGRESS
;
1860 hSvc
= ScmGetServiceFromHandle(hService
);
1863 DPRINT1("Invalid service handle!\n");
1864 return ERROR_INVALID_HANDLE
;
1867 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1868 SERVICE_CHANGE_CONFIG
))
1870 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1871 return ERROR_ACCESS_DENIED
;
1874 /* Check for invalid service type value */
1875 if ((dwServiceType
!= SERVICE_NO_CHANGE
) &&
1876 (dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
1877 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
1878 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
1879 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
1880 return ERROR_INVALID_PARAMETER
;
1882 /* Check for invalid start type value */
1883 if ((dwStartType
!= SERVICE_NO_CHANGE
) &&
1884 (dwStartType
!= SERVICE_BOOT_START
) &&
1885 (dwStartType
!= SERVICE_SYSTEM_START
) &&
1886 (dwStartType
!= SERVICE_AUTO_START
) &&
1887 (dwStartType
!= SERVICE_DEMAND_START
) &&
1888 (dwStartType
!= SERVICE_DISABLED
))
1889 return ERROR_INVALID_PARAMETER
;
1891 /* Only drivers can be boot start or system start services */
1892 if ((dwStartType
== SERVICE_BOOT_START
) ||
1893 (dwStartType
== SERVICE_SYSTEM_START
))
1895 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
1896 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
1897 return ERROR_INVALID_PARAMETER
;
1900 /* Check for invalid error control value */
1901 if ((dwErrorControl
!= SERVICE_NO_CHANGE
) &&
1902 (dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
1903 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
1904 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
1905 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
1906 return ERROR_INVALID_PARAMETER
;
1908 lpService
= hSvc
->ServiceEntry
;
1909 if (lpService
== NULL
)
1911 DPRINT("lpService == NULL!\n");
1912 return ERROR_INVALID_HANDLE
;
1915 /* Lock the service database exclusively */
1916 ScmLockDatabaseExclusive();
1918 if (lpService
->bDeleted
)
1920 DPRINT("The service has already been marked for delete!\n");
1921 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1925 /* Open the service key */
1926 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1929 if (dwError
!= ERROR_SUCCESS
)
1932 /* Write service data to the registry */
1933 /* Set the display name */
1934 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1936 RegSetValueExW(hServiceKey
,
1940 (LPBYTE
)lpDisplayName
,
1941 (DWORD
)((wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
)));
1943 /* Update the display name */
1944 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
1946 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1947 if (lpDisplayNameW
== NULL
)
1949 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1953 wcscpy(lpDisplayNameW
, lpDisplayName
);
1954 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1955 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1957 lpService
->lpDisplayName
= lpDisplayNameW
;
1960 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1962 /* Set the service type */
1963 dwError
= RegSetValueExW(hServiceKey
,
1967 (LPBYTE
)&dwServiceType
,
1969 if (dwError
!= ERROR_SUCCESS
)
1972 lpService
->Status
.dwServiceType
= dwServiceType
;
1975 if (dwStartType
!= SERVICE_NO_CHANGE
)
1977 /* Set the start value */
1978 dwError
= RegSetValueExW(hServiceKey
,
1982 (LPBYTE
)&dwStartType
,
1984 if (dwError
!= ERROR_SUCCESS
)
1987 lpService
->dwStartType
= dwStartType
;
1990 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1992 /* Set the error control value */
1993 dwError
= RegSetValueExW(hServiceKey
,
1997 (LPBYTE
)&dwErrorControl
,
1999 if (dwError
!= ERROR_SUCCESS
)
2002 lpService
->dwErrorControl
= dwErrorControl
;
2005 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2007 /* Set the image path */
2008 lpImagePathW
= lpBinaryPathName
;
2010 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
2012 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
2016 if (dwError
!= ERROR_SUCCESS
)
2020 dwError
= RegSetValueExW(hServiceKey
,
2024 (LPBYTE
)lpImagePathW
,
2025 (DWORD
)((wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
)));
2027 if (lpImagePathW
!= lpBinaryPathName
)
2028 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
2030 if (dwError
!= ERROR_SUCCESS
)
2034 /* Set the group name */
2035 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2037 dwError
= RegSetValueExW(hServiceKey
,
2041 (LPBYTE
)lpLoadOrderGroup
,
2042 (DWORD
)((wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
)));
2043 if (dwError
!= ERROR_SUCCESS
)
2046 dwError
= ScmSetServiceGroup(lpService
,
2048 if (dwError
!= ERROR_SUCCESS
)
2053 if (lpdwTagId
!= NULL
)
2055 dwError
= ScmAssignNewTag(lpService
);
2056 if (dwError
!= ERROR_SUCCESS
)
2059 dwError
= RegSetValueExW(hServiceKey
,
2063 (LPBYTE
)&lpService
->dwTag
,
2065 if (dwError
!= ERROR_SUCCESS
)
2068 *lpdwTagId
= lpService
->dwTag
;
2071 /* Write dependencies */
2072 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2074 dwError
= ScmWriteDependencies(hServiceKey
,
2075 (LPWSTR
)lpDependencies
,
2077 if (dwError
!= ERROR_SUCCESS
)
2081 if (lpPassword
!= NULL
)
2083 if (wcslen((LPWSTR
)lpPassword
) != 0)
2085 /* FIXME: Decrypt the password */
2087 /* Write the password */
2088 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
2089 (LPCWSTR
)lpPassword
);
2090 if (dwError
!= ERROR_SUCCESS
)
2095 /* Delete the password */
2096 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
2098 if (dwError
== ERROR_FILE_NOT_FOUND
)
2099 dwError
= ERROR_SUCCESS
;
2101 if (dwError
!= ERROR_SUCCESS
)
2107 if (hServiceKey
!= NULL
)
2108 RegCloseKey(hServiceKey
);
2110 /* Unlock the service database */
2111 ScmUnlockDatabase();
2113 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
2123 SC_RPC_HANDLE hSCManager
,
2124 LPCWSTR lpServiceName
,
2125 LPCWSTR lpDisplayName
,
2126 DWORD dwDesiredAccess
,
2127 DWORD dwServiceType
,
2129 DWORD dwErrorControl
,
2130 LPCWSTR lpBinaryPathName
,
2131 LPCWSTR lpLoadOrderGroup
,
2133 LPBYTE lpDependencies
,
2135 LPCWSTR lpServiceStartName
,
2138 LPSC_RPC_HANDLE lpServiceHandle
)
2140 PMANAGER_HANDLE hManager
;
2141 DWORD dwError
= ERROR_SUCCESS
;
2142 PSERVICE lpService
= NULL
;
2143 SC_HANDLE hServiceHandle
= NULL
;
2144 LPWSTR lpImagePath
= NULL
;
2145 HKEY hServiceKey
= NULL
;
2146 LPWSTR lpObjectName
;
2148 DPRINT("RCreateServiceW() called\n");
2149 DPRINT("lpServiceName = %S\n", lpServiceName
);
2150 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
2151 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
2152 DPRINT("dwServiceType = 0x%lx\n", dwServiceType
);
2153 DPRINT("dwStartType = %lu\n", dwStartType
);
2154 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2155 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
2156 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
2157 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
2160 return ERROR_SHUTDOWN_IN_PROGRESS
;
2162 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2163 if (hManager
== NULL
)
2165 DPRINT1("Invalid service manager handle!\n");
2166 return ERROR_INVALID_HANDLE
;
2169 /* Check access rights */
2170 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2171 SC_MANAGER_CREATE_SERVICE
))
2173 DPRINT("Insufficient access rights! 0x%lx\n",
2174 hManager
->Handle
.DesiredAccess
);
2175 return ERROR_ACCESS_DENIED
;
2178 if (wcslen(lpServiceName
) == 0)
2180 return ERROR_INVALID_NAME
;
2183 if (wcslen(lpBinaryPathName
) == 0)
2185 return ERROR_INVALID_PARAMETER
;
2188 /* Check for invalid service type value */
2189 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2190 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2191 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2192 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2193 return ERROR_INVALID_PARAMETER
;
2195 /* Check for invalid start type value */
2196 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2197 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2198 (dwStartType
!= SERVICE_AUTO_START
) &&
2199 (dwStartType
!= SERVICE_DEMAND_START
) &&
2200 (dwStartType
!= SERVICE_DISABLED
))
2201 return ERROR_INVALID_PARAMETER
;
2203 /* Only drivers can be boot start or system start services */
2204 if ((dwStartType
== SERVICE_BOOT_START
) ||
2205 (dwStartType
== SERVICE_SYSTEM_START
))
2207 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2208 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2209 return ERROR_INVALID_PARAMETER
;
2212 /* Check for invalid error control value */
2213 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2214 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2215 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2216 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2217 return ERROR_INVALID_PARAMETER
;
2219 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2220 (lpServiceStartName
))
2222 /* We allow LocalSystem to run interactive. */
2223 if (wcsicmp(lpServiceStartName
, L
"LocalSystem"))
2225 return ERROR_INVALID_PARAMETER
;
2229 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2231 return ERROR_INVALID_PARAMETER
;
2234 /* Lock the service database exclusively */
2235 ScmLockDatabaseExclusive();
2237 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2240 /* Unlock the service database */
2241 ScmUnlockDatabase();
2243 /* Check if it is marked for deletion */
2244 if (lpService
->bDeleted
)
2245 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2247 /* Return Error exist */
2248 return ERROR_SERVICE_EXISTS
;
2251 if (lpDisplayName
!= NULL
&&
2252 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2254 /* Unlock the service database */
2255 ScmUnlockDatabase();
2257 return ERROR_DUPLICATE_SERVICE_NAME
;
2260 if (dwServiceType
& SERVICE_DRIVER
)
2262 dwError
= ScmCanonDriverImagePath(dwStartType
,
2265 if (dwError
!= ERROR_SUCCESS
)
2270 if (dwStartType
== SERVICE_BOOT_START
||
2271 dwStartType
== SERVICE_SYSTEM_START
)
2273 /* Unlock the service database */
2274 ScmUnlockDatabase();
2276 return ERROR_INVALID_PARAMETER
;
2280 /* Allocate a new service entry */
2281 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2285 if (dwError
!= ERROR_SUCCESS
)
2288 /* Fill the new service entry */
2289 lpService
->dwErrorControl
= dwErrorControl
;
2291 /* Fill the display name */
2292 if (lpDisplayName
!= NULL
&&
2293 *lpDisplayName
!= 0 &&
2294 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2296 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(),
2298 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2299 if (lpService
->lpDisplayName
== NULL
)
2301 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2304 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2307 /* Assign the service to a group */
2308 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2310 dwError
= ScmSetServiceGroup(lpService
,
2312 if (dwError
!= ERROR_SUCCESS
)
2316 /* Assign a new tag */
2317 if (lpdwTagId
!= NULL
)
2319 dwError
= ScmAssignNewTag(lpService
);
2320 if (dwError
!= ERROR_SUCCESS
)
2324 /* Assign the default security descriptor */
2325 if (dwServiceType
& SERVICE_WIN32
)
2327 dwError
= ScmCreateDefaultServiceSD(&lpService
->pSecurityDescriptor
);
2328 if (dwError
!= ERROR_SUCCESS
)
2332 /* Write service data to the registry */
2333 /* Create the service key */
2334 dwError
= ScmCreateServiceKey(lpServiceName
,
2337 if (dwError
!= ERROR_SUCCESS
)
2340 /* Set the display name */
2341 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2343 RegSetValueExW(hServiceKey
,
2347 (LPBYTE
)lpDisplayName
,
2348 (DWORD
)((wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
)));
2351 /* Set the service type */
2352 dwError
= RegSetValueExW(hServiceKey
,
2356 (LPBYTE
)&dwServiceType
,
2358 if (dwError
!= ERROR_SUCCESS
)
2361 /* Set the start value */
2362 dwError
= RegSetValueExW(hServiceKey
,
2366 (LPBYTE
)&dwStartType
,
2368 if (dwError
!= ERROR_SUCCESS
)
2371 /* Set the error control value */
2372 dwError
= RegSetValueExW(hServiceKey
,
2376 (LPBYTE
)&dwErrorControl
,
2378 if (dwError
!= ERROR_SUCCESS
)
2381 /* Set the image path */
2382 if (dwServiceType
& SERVICE_WIN32
)
2384 dwError
= RegSetValueExW(hServiceKey
,
2388 (LPBYTE
)lpBinaryPathName
,
2389 (DWORD
)((wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
)));
2390 if (dwError
!= ERROR_SUCCESS
)
2393 else if (dwServiceType
& SERVICE_DRIVER
)
2395 dwError
= RegSetValueExW(hServiceKey
,
2399 (LPBYTE
)lpImagePath
,
2400 (DWORD
)((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
)));
2401 if (dwError
!= ERROR_SUCCESS
)
2405 /* Set the group name */
2406 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2408 dwError
= RegSetValueExW(hServiceKey
,
2412 (LPBYTE
)lpLoadOrderGroup
,
2413 (DWORD
)((wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
)));
2414 if (dwError
!= ERROR_SUCCESS
)
2418 /* Set the service tag */
2419 if (lpdwTagId
!= NULL
)
2421 dwError
= RegSetValueExW(hServiceKey
,
2425 (LPBYTE
)&lpService
->dwTag
,
2427 if (dwError
!= ERROR_SUCCESS
)
2431 /* Write dependencies */
2432 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2434 dwError
= ScmWriteDependencies(hServiceKey
,
2435 (LPCWSTR
)lpDependencies
,
2437 if (dwError
!= ERROR_SUCCESS
)
2441 /* Start name and password are only used by Win32 services */
2442 if (dwServiceType
& SERVICE_WIN32
)
2444 /* Write service start name */
2445 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2446 dwError
= RegSetValueExW(hServiceKey
,
2450 (LPBYTE
)lpObjectName
,
2451 (DWORD
)((wcslen(lpObjectName
) + 1) * sizeof(WCHAR
)));
2452 if (dwError
!= ERROR_SUCCESS
)
2455 if (lpPassword
!= NULL
&& wcslen((LPWSTR
)lpPassword
) != 0)
2457 /* FIXME: Decrypt the password */
2459 /* Write the password */
2460 dwError
= ScmSetServicePassword(lpServiceName
,
2461 (LPCWSTR
)lpPassword
);
2462 if (dwError
!= ERROR_SUCCESS
)
2467 /* Write the security descriptor */
2468 dwError
= ScmWriteSecurityDescriptor(hServiceKey
,
2469 lpService
->pSecurityDescriptor
);
2470 if (dwError
!= ERROR_SUCCESS
)
2474 dwError
= ScmCreateServiceHandle(lpService
,
2476 if (dwError
!= ERROR_SUCCESS
)
2479 dwError
= ScmCheckAccess(hServiceHandle
,
2481 if (dwError
!= ERROR_SUCCESS
)
2484 lpService
->dwRefCount
= 1;
2485 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2488 /* Unlock the service database */
2489 ScmUnlockDatabase();
2491 if (hServiceKey
!= NULL
)
2492 RegCloseKey(hServiceKey
);
2494 if (dwError
== ERROR_SUCCESS
)
2496 DPRINT("hService %p\n", hServiceHandle
);
2497 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2499 if (lpdwTagId
!= NULL
)
2500 *lpdwTagId
= lpService
->dwTag
;
2504 if (lpService
!= NULL
&&
2505 lpService
->lpServiceName
!= NULL
)
2507 /* Release the display name buffer */
2508 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2513 /* Remove the service handle */
2514 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2517 if (lpService
!= NULL
)
2519 /* FIXME: remove the service entry */
2523 if (lpImagePath
!= NULL
)
2524 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2526 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2535 REnumDependentServicesW(
2536 SC_RPC_HANDLE hService
,
2537 DWORD dwServiceState
,
2540 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2541 LPBOUNDED_DWORD_256K lpServicesReturned
)
2543 DWORD dwError
= ERROR_SUCCESS
;
2544 DWORD dwServicesReturned
= 0;
2545 DWORD dwServiceCount
;
2546 HKEY hServicesKey
= NULL
;
2547 PSERVICE_HANDLE hSvc
;
2548 PSERVICE lpService
= NULL
;
2549 PSERVICE
*lpServicesArray
= NULL
;
2550 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2553 *pcbBytesNeeded
= 0;
2554 *lpServicesReturned
= 0;
2556 DPRINT("REnumDependentServicesW() called\n");
2558 hSvc
= ScmGetServiceFromHandle(hService
);
2561 DPRINT1("Invalid service handle!\n");
2562 return ERROR_INVALID_HANDLE
;
2565 lpService
= hSvc
->ServiceEntry
;
2567 /* Check access rights */
2568 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2569 SC_MANAGER_ENUMERATE_SERVICE
))
2571 DPRINT("Insufficient access rights! 0x%lx\n",
2572 hSvc
->Handle
.DesiredAccess
);
2573 return ERROR_ACCESS_DENIED
;
2576 /* Open the Services Reg key */
2577 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2578 L
"System\\CurrentControlSet\\Services",
2582 if (dwError
!= ERROR_SUCCESS
)
2585 /* First determine the bytes needed and get the number of dependent services */
2586 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2591 &dwServicesReturned
);
2592 if (dwError
!= ERROR_SUCCESS
)
2595 /* If buffer size is less than the bytes needed or pointer is null */
2596 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2598 dwError
= ERROR_MORE_DATA
;
2602 /* Allocate memory for array of service pointers */
2603 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2605 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2606 if (!lpServicesArray
)
2608 DPRINT1("Could not allocate a buffer!!\n");
2609 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2613 dwServicesReturned
= 0;
2614 *pcbBytesNeeded
= 0;
2616 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2621 &dwServicesReturned
);
2622 if (dwError
!= ERROR_SUCCESS
)
2627 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
)lpServices
;
2628 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2630 /* Copy EnumDepenedentService to Buffer */
2631 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2633 lpService
= lpServicesArray
[dwServiceCount
];
2635 /* Copy status info */
2636 memcpy(&lpServicesPtr
->ServiceStatus
,
2638 sizeof(SERVICE_STATUS
));
2640 /* Copy display name */
2641 wcscpy(lpStr
, lpService
->lpDisplayName
);
2642 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2643 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2645 /* Copy service name */
2646 wcscpy(lpStr
, lpService
->lpServiceName
);
2647 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2648 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2653 *lpServicesReturned
= dwServicesReturned
;
2656 if (lpServicesArray
!= NULL
)
2657 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2659 RegCloseKey(hServicesKey
);
2661 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2670 REnumServicesStatusW(
2671 SC_RPC_HANDLE hSCManager
,
2672 DWORD dwServiceType
,
2673 DWORD dwServiceState
,
2676 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2677 LPBOUNDED_DWORD_256K lpServicesReturned
,
2678 LPBOUNDED_DWORD_256K lpResumeHandle
)
2680 /* Enumerate all the services, not regarding of their group */
2681 return REnumServiceGroupW(hSCManager
,
2697 LPWSTR lpMachineName
,
2698 LPWSTR lpDatabaseName
,
2699 DWORD dwDesiredAccess
,
2700 LPSC_RPC_HANDLE lpScHandle
)
2705 DPRINT("ROpenSCManagerW() called\n");
2706 DPRINT("lpMachineName = %p\n", lpMachineName
);
2707 DPRINT("lpMachineName: %S\n", lpMachineName
);
2708 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2709 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2710 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2713 return ERROR_SHUTDOWN_IN_PROGRESS
;
2716 return ERROR_INVALID_PARAMETER
;
2718 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2720 if (dwError
!= ERROR_SUCCESS
)
2722 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2726 /* Check the desired access */
2727 dwError
= ScmCheckAccess(hHandle
,
2728 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2729 if (dwError
!= ERROR_SUCCESS
)
2731 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2732 HeapFree(GetProcessHeap(), 0, hHandle
);
2736 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2737 DPRINT("*hScm = %p\n", *lpScHandle
);
2739 DPRINT("ROpenSCManagerW() done\n");
2741 return ERROR_SUCCESS
;
2749 SC_RPC_HANDLE hSCManager
,
2750 LPWSTR lpServiceName
,
2751 DWORD dwDesiredAccess
,
2752 LPSC_RPC_HANDLE lpServiceHandle
)
2755 PMANAGER_HANDLE hManager
;
2757 DWORD dwError
= ERROR_SUCCESS
;
2759 DPRINT("ROpenServiceW() called\n");
2760 DPRINT("hSCManager = %p\n", hSCManager
);
2761 DPRINT("lpServiceName = %p\n", lpServiceName
);
2762 DPRINT("lpServiceName: %S\n", lpServiceName
);
2763 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2766 return ERROR_SHUTDOWN_IN_PROGRESS
;
2768 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2769 if (hManager
== NULL
)
2771 DPRINT1("Invalid service manager handle!\n");
2772 return ERROR_INVALID_HANDLE
;
2775 if (!lpServiceHandle
)
2776 return ERROR_INVALID_PARAMETER
;
2779 return ERROR_INVALID_ADDRESS
;
2781 /* Lock the service database exclusive */
2782 ScmLockDatabaseExclusive();
2784 /* Get service database entry */
2785 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2786 if (lpService
== NULL
)
2788 DPRINT("Could not find a service!\n");
2789 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2793 /* Create a service handle */
2794 dwError
= ScmCreateServiceHandle(lpService
,
2796 if (dwError
!= ERROR_SUCCESS
)
2798 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2802 /* Check the desired access */
2803 dwError
= ScmCheckAccess(hHandle
,
2805 if (dwError
!= ERROR_SUCCESS
)
2807 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2808 HeapFree(GetProcessHeap(), 0, hHandle
);
2812 lpService
->dwRefCount
++;
2813 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2815 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2816 DPRINT("*hService = %p\n", *lpServiceHandle
);
2819 /* Unlock the service database */
2820 ScmUnlockDatabase();
2822 DPRINT("ROpenServiceW() done\n");
2831 RQueryServiceConfigW(
2832 SC_RPC_HANDLE hService
,
2833 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2835 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2837 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2838 DWORD dwError
= ERROR_SUCCESS
;
2839 PSERVICE_HANDLE hSvc
;
2840 PSERVICE lpService
= NULL
;
2841 HKEY hServiceKey
= NULL
;
2842 LPWSTR lpImagePath
= NULL
;
2843 LPWSTR lpServiceStartName
= NULL
;
2844 LPWSTR lpDependencies
= NULL
;
2845 DWORD dwDependenciesLength
= 0;
2846 DWORD dwRequiredSize
;
2847 WCHAR lpEmptyString
[] = {0,0};
2850 DPRINT("RQueryServiceConfigW() called\n");
2853 return ERROR_SHUTDOWN_IN_PROGRESS
;
2855 hSvc
= ScmGetServiceFromHandle(hService
);
2858 DPRINT1("Invalid service handle!\n");
2859 return ERROR_INVALID_HANDLE
;
2862 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2863 SERVICE_QUERY_CONFIG
))
2865 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2866 return ERROR_ACCESS_DENIED
;
2869 lpService
= hSvc
->ServiceEntry
;
2870 if (lpService
== NULL
)
2872 DPRINT("lpService == NULL!\n");
2873 return ERROR_INVALID_HANDLE
;
2876 /* Lock the service database shared */
2877 ScmLockDatabaseShared();
2879 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2882 if (dwError
!= ERROR_SUCCESS
)
2885 /* Read the image path */
2886 dwError
= ScmReadString(hServiceKey
,
2889 if (dwError
!= ERROR_SUCCESS
)
2892 /* Read the service start name */
2893 ScmReadString(hServiceKey
,
2895 &lpServiceStartName
);
2897 /* Read the dependencies */
2898 ScmReadDependencies(hServiceKey
,
2900 &dwDependenciesLength
);
2902 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2904 if (lpImagePath
!= NULL
)
2905 dwRequiredSize
+= (DWORD
)((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2907 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2909 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
2910 dwRequiredSize
+= (DWORD
)((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2912 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2914 if (lpDependencies
!= NULL
)
2915 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2917 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2919 if (lpServiceStartName
!= NULL
)
2920 dwRequiredSize
+= (DWORD
)((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2922 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2924 if (lpService
->lpDisplayName
!= NULL
)
2925 dwRequiredSize
+= (DWORD
)((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2927 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2929 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2931 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2935 lpServiceConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2936 lpServiceConfig
->dwStartType
= lpService
->dwStartType
;
2937 lpServiceConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2938 lpServiceConfig
->dwTagId
= lpService
->dwTag
;
2940 lpStr
= (LPWSTR
)(lpServiceConfig
+ 1);
2942 /* Append the image path */
2943 if (lpImagePath
!= NULL
)
2945 wcscpy(lpStr
, lpImagePath
);
2949 wcscpy(lpStr
, lpEmptyString
);
2952 lpServiceConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2953 lpStr
+= (wcslen(lpStr
) + 1);
2955 /* Append the group name */
2956 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
2958 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2962 wcscpy(lpStr
, lpEmptyString
);
2965 lpServiceConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2966 lpStr
+= (wcslen(lpStr
) + 1);
2968 /* Append Dependencies */
2969 if (lpDependencies
!= NULL
)
2973 dwDependenciesLength
* sizeof(WCHAR
));
2977 wcscpy(lpStr
, lpEmptyString
);
2980 lpServiceConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2981 if (lpDependencies
!= NULL
)
2982 lpStr
+= dwDependenciesLength
;
2984 lpStr
+= (wcslen(lpStr
) + 1);
2986 /* Append the service start name */
2987 if (lpServiceStartName
!= NULL
)
2989 wcscpy(lpStr
, lpServiceStartName
);
2993 wcscpy(lpStr
, lpEmptyString
);
2996 lpServiceConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2997 lpStr
+= (wcslen(lpStr
) + 1);
2999 /* Append the display name */
3000 if (lpService
->lpDisplayName
!= NULL
)
3002 wcscpy(lpStr
, lpService
->lpDisplayName
);
3006 wcscpy(lpStr
, lpEmptyString
);
3009 lpServiceConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3012 if (pcbBytesNeeded
!= NULL
)
3013 *pcbBytesNeeded
= dwRequiredSize
;
3016 /* Unlock the service database */
3017 ScmUnlockDatabase();
3019 if (lpImagePath
!= NULL
)
3020 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3022 if (lpServiceStartName
!= NULL
)
3023 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3025 if (lpDependencies
!= NULL
)
3026 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3028 if (hServiceKey
!= NULL
)
3029 RegCloseKey(hServiceKey
);
3031 DPRINT("RQueryServiceConfigW() done\n");
3040 RQueryServiceLockStatusW(
3041 SC_RPC_HANDLE hSCManager
,
3042 LPBYTE lpBuf
, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
3044 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3046 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
= (LPQUERY_SERVICE_LOCK_STATUSW
)lpBuf
;
3047 PMANAGER_HANDLE hMgr
;
3048 DWORD dwRequiredSize
;
3050 if (!lpLockStatus
|| !pcbBytesNeeded
)
3051 return ERROR_INVALID_PARAMETER
;
3053 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
3056 DPRINT1("Invalid service manager handle!\n");
3057 return ERROR_INVALID_HANDLE
;
3060 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
3061 SC_MANAGER_QUERY_LOCK_STATUS
))
3063 DPRINT("Insufficient access rights! 0x%lx\n", hMgr
->Handle
.DesiredAccess
);
3064 return ERROR_ACCESS_DENIED
;
3067 /* FIXME: we need to compute instead the real length of the owner name */
3068 dwRequiredSize
= sizeof(QUERY_SERVICE_LOCK_STATUSW
) + sizeof(WCHAR
);
3069 *pcbBytesNeeded
= dwRequiredSize
;
3071 if (cbBufSize
< dwRequiredSize
)
3072 return ERROR_INSUFFICIENT_BUFFER
;
3074 ScmQueryServiceLockStatusW(lpLockStatus
);
3076 return ERROR_SUCCESS
;
3084 SC_RPC_HANDLE hService
,
3086 LPSTRING_PTRSW argv
)
3088 DWORD dwError
= ERROR_SUCCESS
;
3089 PSERVICE_HANDLE hSvc
;
3090 PSERVICE lpService
= NULL
;
3095 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3096 DPRINT(" argc: %lu\n", argc
);
3099 for (i
= 0; i
< argc
; i
++)
3101 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
].StringPtr
);
3107 return ERROR_SHUTDOWN_IN_PROGRESS
;
3109 hSvc
= ScmGetServiceFromHandle(hService
);
3112 DPRINT1("Invalid service handle!\n");
3113 return ERROR_INVALID_HANDLE
;
3116 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3119 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3120 return ERROR_ACCESS_DENIED
;
3123 lpService
= hSvc
->ServiceEntry
;
3124 if (lpService
== NULL
)
3126 DPRINT("lpService == NULL!\n");
3127 return ERROR_INVALID_HANDLE
;
3130 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3131 return ERROR_SERVICE_DISABLED
;
3133 if (lpService
->bDeleted
)
3134 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3136 /* Start the service */
3137 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3146 RGetServiceDisplayNameW(
3147 SC_RPC_HANDLE hSCManager
,
3148 LPCWSTR lpServiceName
,
3149 LPWSTR lpDisplayName
,
3152 // PMANAGER_HANDLE hManager;
3157 DPRINT("RGetServiceDisplayNameW() called\n");
3158 DPRINT("hSCManager = %p\n", hSCManager
);
3159 DPRINT("lpServiceName: %S\n", lpServiceName
);
3160 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3161 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3163 // hManager = (PMANAGER_HANDLE)hSCManager;
3164 // if (hManager->Handle.Tag != MANAGER_TAG)
3166 // DPRINT("Invalid manager handle!\n");
3167 // return ERROR_INVALID_HANDLE;
3170 /* Get service database entry */
3171 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3172 if (lpService
== NULL
)
3174 DPRINT("Could not find a service!\n");
3176 /* If the service could not be found and lpcchBuffer is less than 2, windows
3177 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3178 if (*lpcchBuffer
< 2)
3181 if (lpDisplayName
!= NULL
)
3187 return ERROR_SERVICE_DOES_NOT_EXIST
;
3190 if (!lpService
->lpDisplayName
)
3192 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
3194 if (lpDisplayName
!= NULL
&&
3195 *lpcchBuffer
> dwLength
)
3197 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3202 dwLength
= (DWORD
)wcslen(lpService
->lpDisplayName
);
3204 if (lpDisplayName
!= NULL
&&
3205 *lpcchBuffer
> dwLength
)
3207 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3211 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3213 *lpcchBuffer
= dwLength
;
3222 RGetServiceKeyNameW(
3223 SC_RPC_HANDLE hSCManager
,
3224 LPCWSTR lpDisplayName
,
3225 LPWSTR lpServiceName
,
3228 // PMANAGER_HANDLE hManager;
3233 DPRINT("RGetServiceKeyNameW() called\n");
3234 DPRINT("hSCManager = %p\n", hSCManager
);
3235 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3236 DPRINT("lpServiceName: %p\n", lpServiceName
);
3237 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3239 // hManager = (PMANAGER_HANDLE)hSCManager;
3240 // if (hManager->Handle.Tag != MANAGER_TAG)
3242 // DPRINT("Invalid manager handle!\n");
3243 // return ERROR_INVALID_HANDLE;
3246 /* Get service database entry */
3247 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3248 if (lpService
== NULL
)
3250 DPRINT("Could not find a service!\n");
3252 /* If the service could not be found and lpcchBuffer is less than 2, windows
3253 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3254 if (*lpcchBuffer
< 2)
3257 if (lpServiceName
!= NULL
)
3263 return ERROR_SERVICE_DOES_NOT_EXIST
;
3266 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
3268 if (lpServiceName
!= NULL
&&
3269 *lpcchBuffer
> dwLength
)
3271 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3272 *lpcchBuffer
= dwLength
;
3273 return ERROR_SUCCESS
;
3276 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3278 *lpcchBuffer
= dwLength
;
3287 RI_ScSetServiceBitsA(
3288 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3289 DWORD dwServiceBits
,
3291 int bUpdateImmediately
,
3295 return ERROR_CALL_NOT_IMPLEMENTED
;
3302 RChangeServiceConfigA(
3303 SC_RPC_HANDLE hService
,
3304 DWORD dwServiceType
,
3306 DWORD dwErrorControl
,
3307 LPSTR lpBinaryPathName
,
3308 LPSTR lpLoadOrderGroup
,
3310 LPBYTE lpDependencies
,
3312 LPSTR lpServiceStartName
,
3315 LPSTR lpDisplayName
)
3317 DWORD dwError
= ERROR_SUCCESS
;
3318 PSERVICE_HANDLE hSvc
;
3319 PSERVICE lpService
= NULL
;
3320 HKEY hServiceKey
= NULL
;
3321 LPWSTR lpDisplayNameW
= NULL
;
3322 LPWSTR lpBinaryPathNameW
= NULL
;
3323 LPWSTR lpCanonicalImagePathW
= NULL
;
3324 LPWSTR lpLoadOrderGroupW
= NULL
;
3325 LPWSTR lpDependenciesW
= NULL
;
3327 DPRINT("RChangeServiceConfigA() called\n");
3328 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3329 DPRINT("dwStartType = %lu\n", dwStartType
);
3330 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3331 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3332 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3333 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3336 return ERROR_SHUTDOWN_IN_PROGRESS
;
3338 hSvc
= ScmGetServiceFromHandle(hService
);
3341 DPRINT1("Invalid service handle!\n");
3342 return ERROR_INVALID_HANDLE
;
3345 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3346 SERVICE_CHANGE_CONFIG
))
3348 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3349 return ERROR_ACCESS_DENIED
;
3352 lpService
= hSvc
->ServiceEntry
;
3353 if (lpService
== NULL
)
3355 DPRINT("lpService == NULL!\n");
3356 return ERROR_INVALID_HANDLE
;
3359 /* Lock the service database exclusively */
3360 ScmLockDatabaseExclusive();
3362 if (lpService
->bDeleted
)
3364 DPRINT("The service has already been marked for delete!\n");
3365 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3369 /* Open the service key */
3370 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3373 if (dwError
!= ERROR_SUCCESS
)
3376 /* Write service data to the registry */
3378 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3380 /* Set the display name */
3381 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3383 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3384 if (lpDisplayNameW
== NULL
)
3386 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3390 MultiByteToWideChar(CP_ACP
,
3395 (int)(strlen(lpDisplayName
) + 1));
3397 RegSetValueExW(hServiceKey
,
3401 (LPBYTE
)lpDisplayNameW
,
3402 (DWORD
)((wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
)));
3404 /* Update lpService->lpDisplayName */
3405 if (lpService
->lpDisplayName
)
3406 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3408 lpService
->lpDisplayName
= lpDisplayNameW
;
3411 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3413 /* Set the service type */
3414 dwError
= RegSetValueExW(hServiceKey
,
3418 (LPBYTE
)&dwServiceType
,
3420 if (dwError
!= ERROR_SUCCESS
)
3423 lpService
->Status
.dwServiceType
= dwServiceType
;
3426 if (dwStartType
!= SERVICE_NO_CHANGE
)
3428 /* Set the start value */
3429 dwError
= RegSetValueExW(hServiceKey
,
3433 (LPBYTE
)&dwStartType
,
3435 if (dwError
!= ERROR_SUCCESS
)
3438 lpService
->dwStartType
= dwStartType
;
3441 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3443 /* Set the error control value */
3444 dwError
= RegSetValueExW(hServiceKey
,
3448 (LPBYTE
)&dwErrorControl
,
3450 if (dwError
!= ERROR_SUCCESS
)
3453 lpService
->dwErrorControl
= dwErrorControl
;
3456 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3458 /* Set the image path */
3459 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(),
3461 (strlen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
3462 if (lpBinaryPathNameW
== NULL
)
3464 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3468 MultiByteToWideChar(CP_ACP
,
3473 (int)(strlen(lpBinaryPathName
) + 1));
3475 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
3477 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
3479 &lpCanonicalImagePathW
);
3481 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3483 if (dwError
!= ERROR_SUCCESS
)
3486 lpBinaryPathNameW
= lpCanonicalImagePathW
;
3489 dwError
= RegSetValueExW(hServiceKey
,
3493 (LPBYTE
)lpBinaryPathNameW
,
3494 (DWORD
)((wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
)));
3496 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3498 if (dwError
!= ERROR_SUCCESS
)
3502 /* Set the group name */
3503 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3505 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3507 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3508 if (lpLoadOrderGroupW
== NULL
)
3510 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3514 MultiByteToWideChar(CP_ACP
,
3519 (int)(strlen(lpLoadOrderGroup
) + 1));
3521 dwError
= RegSetValueExW(hServiceKey
,
3525 (LPBYTE
)lpLoadOrderGroupW
,
3526 (DWORD
)((wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
)));
3527 if (dwError
!= ERROR_SUCCESS
)
3529 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3533 dwError
= ScmSetServiceGroup(lpService
,
3536 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3538 if (dwError
!= ERROR_SUCCESS
)
3542 if (lpdwTagId
!= NULL
)
3544 dwError
= ScmAssignNewTag(lpService
);
3545 if (dwError
!= ERROR_SUCCESS
)
3548 dwError
= RegSetValueExW(hServiceKey
,
3552 (LPBYTE
)&lpService
->dwTag
,
3554 if (dwError
!= ERROR_SUCCESS
)
3557 *lpdwTagId
= lpService
->dwTag
;
3560 /* Write dependencies */
3561 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3563 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3565 (strlen((LPSTR
)lpDependencies
) + 1) * sizeof(WCHAR
));
3566 if (lpDependenciesW
== NULL
)
3568 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3572 MultiByteToWideChar(CP_ACP
,
3574 (LPSTR
)lpDependencies
,
3577 (int)(strlen((LPSTR
)lpDependencies
) + 1));
3579 dwError
= ScmWriteDependencies(hServiceKey
,
3580 (LPWSTR
)lpDependenciesW
,
3583 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3585 if (dwError
!= ERROR_SUCCESS
)
3589 if (lpPassword
!= NULL
)
3591 if (wcslen((LPWSTR
)lpPassword
) != 0)
3593 /* FIXME: Decrypt the password */
3595 /* Write the password */
3596 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
3597 (LPCWSTR
)lpPassword
);
3598 if (dwError
!= ERROR_SUCCESS
)
3603 /* Delete the password */
3604 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
3606 if (dwError
== ERROR_FILE_NOT_FOUND
)
3607 dwError
= ERROR_SUCCESS
;
3609 if (dwError
!= ERROR_SUCCESS
)
3615 /* Unlock the service database */
3616 ScmUnlockDatabase();
3618 if (hServiceKey
!= NULL
)
3619 RegCloseKey(hServiceKey
);
3621 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3631 SC_RPC_HANDLE hSCManager
,
3632 LPSTR lpServiceName
,
3633 LPSTR lpDisplayName
,
3634 DWORD dwDesiredAccess
,
3635 DWORD dwServiceType
,
3637 DWORD dwErrorControl
,
3638 LPSTR lpBinaryPathName
,
3639 LPSTR lpLoadOrderGroup
,
3641 LPBYTE lpDependencies
,
3643 LPSTR lpServiceStartName
,
3646 LPSC_RPC_HANDLE lpServiceHandle
)
3648 DWORD dwError
= ERROR_SUCCESS
;
3649 LPWSTR lpServiceNameW
= NULL
;
3650 LPWSTR lpDisplayNameW
= NULL
;
3651 LPWSTR lpBinaryPathNameW
= NULL
;
3652 LPWSTR lpLoadOrderGroupW
= NULL
;
3653 LPWSTR lpDependenciesW
= NULL
;
3654 LPWSTR lpServiceStartNameW
= NULL
;
3655 DWORD dwDependenciesLength
= 0;
3662 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3663 lpServiceNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3664 if (!lpServiceNameW
)
3666 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3669 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3674 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3675 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3676 if (!lpDisplayNameW
)
3678 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3681 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3684 if (lpBinaryPathName
)
3686 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3687 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3688 if (!lpBinaryPathNameW
)
3690 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3693 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3696 if (lpLoadOrderGroup
)
3698 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3699 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3700 if (!lpLoadOrderGroupW
)
3702 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3705 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3710 lpStr
= (LPCSTR
)lpDependencies
;
3713 cchLength
= strlen(lpStr
) + 1;
3714 dwDependenciesLength
+= (DWORD
)cchLength
;
3715 lpStr
= lpStr
+ cchLength
;
3717 dwDependenciesLength
++;
3719 lpDependenciesW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDependenciesLength
* sizeof(WCHAR
));
3720 if (!lpDependenciesW
)
3722 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3725 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3728 if (lpServiceStartName
)
3730 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3731 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3732 if (!lpServiceStartNameW
)
3734 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3737 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3740 dwError
= RCreateServiceW(hSCManager
,
3750 (LPBYTE
)lpDependenciesW
,
3751 dwDependenciesLength
,
3752 lpServiceStartNameW
,
3758 if (lpServiceNameW
!=NULL
)
3759 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3761 if (lpDisplayNameW
!= NULL
)
3762 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3764 if (lpBinaryPathNameW
!= NULL
)
3765 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3767 if (lpLoadOrderGroupW
!= NULL
)
3768 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3770 if (lpDependenciesW
!= NULL
)
3771 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3773 if (lpServiceStartNameW
!= NULL
)
3774 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3783 REnumDependentServicesA(
3784 SC_RPC_HANDLE hService
,
3785 DWORD dwServiceState
,
3788 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3789 LPBOUNDED_DWORD_256K lpServicesReturned
)
3791 DWORD dwError
= ERROR_SUCCESS
;
3792 DWORD dwServicesReturned
= 0;
3793 DWORD dwServiceCount
;
3794 HKEY hServicesKey
= NULL
;
3795 PSERVICE_HANDLE hSvc
;
3796 PSERVICE lpService
= NULL
;
3797 PSERVICE
*lpServicesArray
= NULL
;
3798 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3801 *pcbBytesNeeded
= 0;
3802 *lpServicesReturned
= 0;
3804 DPRINT("REnumDependentServicesA() called\n");
3806 hSvc
= ScmGetServiceFromHandle(hService
);
3809 DPRINT1("Invalid service handle!\n");
3810 return ERROR_INVALID_HANDLE
;
3813 lpService
= hSvc
->ServiceEntry
;
3815 /* Check access rights */
3816 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3817 SC_MANAGER_ENUMERATE_SERVICE
))
3819 DPRINT("Insufficient access rights! 0x%lx\n",
3820 hSvc
->Handle
.DesiredAccess
);
3821 return ERROR_ACCESS_DENIED
;
3824 /* Open the Services Reg key */
3825 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3826 L
"System\\CurrentControlSet\\Services",
3831 if (dwError
!= ERROR_SUCCESS
)
3834 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3835 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3836 are the same for both. Verified in WINXP. */
3838 /* First determine the bytes needed and get the number of dependent services*/
3839 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3844 &dwServicesReturned
);
3845 if (dwError
!= ERROR_SUCCESS
)
3848 /* If buffer size is less than the bytes needed or pointer is null*/
3849 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3851 dwError
= ERROR_MORE_DATA
;
3855 /* Allocate memory for array of service pointers */
3856 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3858 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3859 if (!lpServicesArray
)
3861 DPRINT("Could not allocate a buffer!!\n");
3862 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3866 dwServicesReturned
= 0;
3867 *pcbBytesNeeded
= 0;
3869 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3874 &dwServicesReturned
);
3875 if (dwError
!= ERROR_SUCCESS
)
3880 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3881 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3883 /* Copy EnumDepenedentService to Buffer */
3884 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3886 lpService
= lpServicesArray
[dwServiceCount
];
3888 /* Copy the status info */
3889 memcpy(&lpServicesPtr
->ServiceStatus
,
3891 sizeof(SERVICE_STATUS
));
3893 /* Copy display name */
3894 WideCharToMultiByte(CP_ACP
,
3896 lpService
->lpDisplayName
,
3899 (int)wcslen(lpService
->lpDisplayName
),
3902 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3903 lpStr
+= strlen(lpStr
) + 1;
3905 /* Copy service name */
3906 WideCharToMultiByte(CP_ACP
,
3908 lpService
->lpServiceName
,
3911 (int)wcslen(lpService
->lpServiceName
),
3914 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3915 lpStr
+= strlen(lpStr
) + 1;
3920 *lpServicesReturned
= dwServicesReturned
;
3923 if (lpServicesArray
)
3924 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3926 RegCloseKey(hServicesKey
);
3928 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3937 REnumServicesStatusA(
3938 SC_RPC_HANDLE hSCManager
,
3939 DWORD dwServiceType
,
3940 DWORD dwServiceState
,
3943 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3944 LPBOUNDED_DWORD_256K lpServicesReturned
,
3945 LPBOUNDED_DWORD_256K lpResumeHandle
)
3947 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3948 LPENUM_SERVICE_STATUSW lpStatusPtrIncrW
;
3949 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3950 LPWSTR lpStringPtrW
;
3953 DWORD dwServiceCount
;
3955 DPRINT("REnumServicesStatusA() called\n");
3957 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
3959 return ERROR_INVALID_ADDRESS
;
3962 if ((dwBufSize
> 0) && (lpBuffer
))
3964 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3967 DPRINT("Failed to allocate buffer!\n");
3968 return ERROR_NOT_ENOUGH_MEMORY
;
3972 dwError
= REnumServicesStatusW(hSCManager
,
3975 (LPBYTE
)lpStatusPtrW
,
3981 /* if no services were returned then we are Done */
3982 if (*lpServicesReturned
== 0)
3985 lpStatusPtrIncrW
= lpStatusPtrW
;
3986 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3987 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3988 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3989 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3990 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3992 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3994 /* Copy the service name */
3995 WideCharToMultiByte(CP_ACP
,
4000 (int)wcslen(lpStringPtrW
),
4004 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4005 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4006 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4008 /* Copy the display name */
4009 WideCharToMultiByte(CP_ACP
,
4014 (int)wcslen(lpStringPtrW
),
4018 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4019 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4020 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4022 /* Copy the status information */
4023 memcpy(&lpStatusPtrA
->ServiceStatus
,
4024 &lpStatusPtrIncrW
->ServiceStatus
,
4025 sizeof(SERVICE_STATUS
));
4033 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4035 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
4045 LPSTR lpMachineName
,
4046 LPSTR lpDatabaseName
,
4047 DWORD dwDesiredAccess
,
4048 LPSC_RPC_HANDLE lpScHandle
)
4050 UNICODE_STRING MachineName
;
4051 UNICODE_STRING DatabaseName
;
4054 DPRINT("ROpenSCManagerA() called\n");
4057 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
4061 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
4064 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
4065 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
4070 RtlFreeUnicodeString(&MachineName
);
4073 RtlFreeUnicodeString(&DatabaseName
);
4083 SC_RPC_HANDLE hSCManager
,
4084 LPSTR lpServiceName
,
4085 DWORD dwDesiredAccess
,
4086 LPSC_RPC_HANDLE lpServiceHandle
)
4088 UNICODE_STRING ServiceName
;
4091 DPRINT("ROpenServiceA() called\n");
4094 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
4097 dwError
= ROpenServiceW(hSCManager
,
4098 lpServiceName
? ServiceName
.Buffer
: NULL
,
4103 RtlFreeUnicodeString(&ServiceName
);
4112 RQueryServiceConfigA(
4113 SC_RPC_HANDLE hService
,
4114 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4116 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4118 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
4119 DWORD dwError
= ERROR_SUCCESS
;
4120 PSERVICE_HANDLE hSvc
;
4121 PSERVICE lpService
= NULL
;
4122 HKEY hServiceKey
= NULL
;
4123 LPWSTR lpImagePath
= NULL
;
4124 LPWSTR lpServiceStartName
= NULL
;
4125 LPWSTR lpDependencies
= NULL
;
4126 DWORD dwDependenciesLength
= 0;
4127 DWORD dwRequiredSize
;
4128 CHAR lpEmptyString
[]={0,0};
4131 DPRINT("RQueryServiceConfigA() called\n");
4134 return ERROR_SHUTDOWN_IN_PROGRESS
;
4136 hSvc
= ScmGetServiceFromHandle(hService
);
4139 DPRINT1("Invalid service handle!\n");
4140 return ERROR_INVALID_HANDLE
;
4143 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4144 SERVICE_QUERY_CONFIG
))
4146 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4147 return ERROR_ACCESS_DENIED
;
4150 lpService
= hSvc
->ServiceEntry
;
4151 if (lpService
== NULL
)
4153 DPRINT("lpService == NULL!\n");
4154 return ERROR_INVALID_HANDLE
;
4157 /* Lock the service database shared */
4158 ScmLockDatabaseShared();
4160 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4163 if (dwError
!= ERROR_SUCCESS
)
4166 /* Read the image path */
4167 dwError
= ScmReadString(hServiceKey
,
4170 if (dwError
!= ERROR_SUCCESS
)
4173 /* Read the service start name */
4174 ScmReadString(hServiceKey
,
4176 &lpServiceStartName
);
4178 /* Read the dependencies */
4179 ScmReadDependencies(hServiceKey
,
4181 &dwDependenciesLength
);
4183 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGA
);
4185 if (lpImagePath
!= NULL
)
4186 dwRequiredSize
+= (DWORD
)(wcslen(lpImagePath
) + 1);
4188 dwRequiredSize
+= 2;
4190 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
4191 dwRequiredSize
+= (DWORD
)(wcslen(lpService
->lpGroup
->lpGroupName
) + 1);
4193 dwRequiredSize
+= 2;
4195 /* Add Dependencies length */
4196 if (lpDependencies
!= NULL
)
4197 dwRequiredSize
+= dwDependenciesLength
;
4199 dwRequiredSize
+= 2;
4201 if (lpServiceStartName
!= NULL
)
4202 dwRequiredSize
+= (DWORD
)(wcslen(lpServiceStartName
) + 1);
4204 dwRequiredSize
+= 2;
4206 if (lpService
->lpDisplayName
!= NULL
)
4207 dwRequiredSize
+= (DWORD
)(wcslen(lpService
->lpDisplayName
) + 1);
4209 dwRequiredSize
+= 2;
4211 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
4213 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4217 lpServiceConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
4218 lpServiceConfig
->dwStartType
= lpService
->dwStartType
;
4219 lpServiceConfig
->dwErrorControl
= lpService
->dwErrorControl
;
4220 lpServiceConfig
->dwTagId
= lpService
->dwTag
;
4222 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
4224 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4225 Verified in WINXP */
4229 WideCharToMultiByte(CP_ACP
,
4234 (int)(wcslen(lpImagePath
) + 1),
4240 strcpy(lpStr
, lpEmptyString
);
4243 lpServiceConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4244 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4246 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4248 WideCharToMultiByte(CP_ACP
,
4250 lpService
->lpGroup
->lpGroupName
,
4253 (int)(wcslen(lpService
->lpGroup
->lpGroupName
) + 1),
4259 strcpy(lpStr
, lpEmptyString
);
4262 lpServiceConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4263 lpStr
+= (strlen(lpStr
) + 1);
4265 /* Append Dependencies */
4268 WideCharToMultiByte(CP_ACP
,
4271 dwDependenciesLength
,
4273 dwDependenciesLength
,
4279 strcpy(lpStr
, lpEmptyString
);
4282 lpServiceConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4284 lpStr
+= dwDependenciesLength
;
4286 lpStr
+= (strlen(lpStr
) + 1);
4288 if (lpServiceStartName
)
4290 WideCharToMultiByte(CP_ACP
,
4295 (int)(wcslen(lpServiceStartName
) + 1),
4301 strcpy(lpStr
, lpEmptyString
);
4304 lpServiceConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4305 lpStr
+= (strlen(lpStr
) + 1);
4307 if (lpService
->lpDisplayName
)
4309 WideCharToMultiByte(CP_ACP
,
4311 lpService
->lpDisplayName
,
4314 (int)(wcslen(lpService
->lpDisplayName
) + 1),
4320 strcpy(lpStr
, lpEmptyString
);
4323 lpServiceConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4326 if (pcbBytesNeeded
!= NULL
)
4327 *pcbBytesNeeded
= dwRequiredSize
;
4330 /* Unlock the service database */
4331 ScmUnlockDatabase();
4333 if (lpImagePath
!= NULL
)
4334 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4336 if (lpServiceStartName
!= NULL
)
4337 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4339 if (lpDependencies
!= NULL
)
4340 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4342 if (hServiceKey
!= NULL
)
4343 RegCloseKey(hServiceKey
);
4345 DPRINT("RQueryServiceConfigA() done\n");
4354 RQueryServiceLockStatusA(
4355 SC_RPC_HANDLE hSCManager
,
4356 LPBYTE lpBuf
, // LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
4358 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4360 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
= (LPQUERY_SERVICE_LOCK_STATUSA
)lpBuf
;
4361 PMANAGER_HANDLE hMgr
;
4362 DWORD dwRequiredSize
;
4364 if (!lpLockStatus
|| !pcbBytesNeeded
)
4365 return ERROR_INVALID_PARAMETER
;
4367 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
4370 DPRINT1("Invalid service manager handle!\n");
4371 return ERROR_INVALID_HANDLE
;
4374 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
4375 SC_MANAGER_QUERY_LOCK_STATUS
))
4377 DPRINT("Insufficient access rights! 0x%lx\n", hMgr
->Handle
.DesiredAccess
);
4378 return ERROR_ACCESS_DENIED
;
4381 /* FIXME: we need to compute instead the real length of the owner name */
4382 dwRequiredSize
= sizeof(QUERY_SERVICE_LOCK_STATUSA
) + sizeof(CHAR
);
4383 *pcbBytesNeeded
= dwRequiredSize
;
4385 if (cbBufSize
< dwRequiredSize
)
4386 return ERROR_INSUFFICIENT_BUFFER
;
4388 ScmQueryServiceLockStatusA(lpLockStatus
);
4390 return ERROR_SUCCESS
;
4398 SC_RPC_HANDLE hService
,
4400 LPSTRING_PTRSA argv
)
4402 DWORD dwError
= ERROR_SUCCESS
;
4403 PSERVICE_HANDLE hSvc
;
4404 PSERVICE lpService
= NULL
;
4405 LPWSTR
*lpVector
= NULL
;
4409 DPRINT("RStartServiceA() called\n");
4412 return ERROR_SHUTDOWN_IN_PROGRESS
;
4414 hSvc
= ScmGetServiceFromHandle(hService
);
4417 DPRINT1("Invalid service handle!\n");
4418 return ERROR_INVALID_HANDLE
;
4421 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4424 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4425 return ERROR_ACCESS_DENIED
;
4428 lpService
= hSvc
->ServiceEntry
;
4429 if (lpService
== NULL
)
4431 DPRINT("lpService == NULL!\n");
4432 return ERROR_INVALID_HANDLE
;
4435 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4436 return ERROR_SERVICE_DISABLED
;
4438 if (lpService
->bDeleted
)
4439 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4441 /* Build a Unicode argument vector */
4444 lpVector
= HeapAlloc(GetProcessHeap(),
4446 argc
* sizeof(LPWSTR
));
4447 if (lpVector
== NULL
)
4448 return ERROR_NOT_ENOUGH_MEMORY
;
4450 for (i
= 0; i
< argc
; i
++)
4452 dwLength
= MultiByteToWideChar(CP_ACP
,
4459 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4461 dwLength
* sizeof(WCHAR
));
4462 if (lpVector
[i
] == NULL
)
4464 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4468 MultiByteToWideChar(CP_ACP
,
4477 /* Start the service */
4478 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4481 /* Free the Unicode argument vector */
4482 if (lpVector
!= NULL
)
4484 for (i
= 0; i
< argc
; i
++)
4486 if (lpVector
[i
] != NULL
)
4487 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4489 HeapFree(GetProcessHeap(), 0, lpVector
);
4499 RGetServiceDisplayNameA(
4500 SC_RPC_HANDLE hSCManager
,
4501 LPCSTR lpServiceName
,
4502 LPSTR lpDisplayName
,
4503 LPBOUNDED_DWORD_4K lpcchBuffer
)
4505 // PMANAGER_HANDLE hManager;
4506 PSERVICE lpService
= NULL
;
4509 LPWSTR lpServiceNameW
;
4511 DPRINT("RGetServiceDisplayNameA() called\n");
4512 DPRINT("hSCManager = %p\n", hSCManager
);
4513 DPRINT("lpServiceName: %s\n", lpServiceName
);
4514 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4515 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4517 // hManager = (PMANAGER_HANDLE)hSCManager;
4518 // if (hManager->Handle.Tag != MANAGER_TAG)
4520 // DPRINT("Invalid manager handle!\n");
4521 // return ERROR_INVALID_HANDLE;
4524 if (lpServiceName
!= NULL
)
4526 dwLength
= (DWORD
)(strlen(lpServiceName
) + 1);
4527 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4529 dwLength
* sizeof(WCHAR
));
4530 if (!lpServiceNameW
)
4531 return ERROR_NOT_ENOUGH_MEMORY
;
4533 MultiByteToWideChar(CP_ACP
,
4540 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4542 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4545 if (lpService
== NULL
)
4547 DPRINT("Could not find a service!\n");
4549 /* If the service could not be found and lpcchBuffer is 0, windows
4550 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4551 if (*lpcchBuffer
== 0)
4554 if (lpDisplayName
!= NULL
)
4559 return ERROR_SERVICE_DOES_NOT_EXIST
;
4562 if (!lpService
->lpDisplayName
)
4564 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
4565 if (lpDisplayName
!= NULL
&&
4566 *lpcchBuffer
> dwLength
)
4568 WideCharToMultiByte(CP_ACP
,
4570 lpService
->lpServiceName
,
4571 (int)wcslen(lpService
->lpServiceName
),
4576 return ERROR_SUCCESS
;
4581 dwLength
= (DWORD
)wcslen(lpService
->lpDisplayName
);
4582 if (lpDisplayName
!= NULL
&&
4583 *lpcchBuffer
> dwLength
)
4585 WideCharToMultiByte(CP_ACP
,
4587 lpService
->lpDisplayName
,
4588 (int)wcslen(lpService
->lpDisplayName
),
4593 return ERROR_SUCCESS
;
4597 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4599 *lpcchBuffer
= dwLength
* 2;
4608 RGetServiceKeyNameA(
4609 SC_RPC_HANDLE hSCManager
,
4610 LPCSTR lpDisplayName
,
4611 LPSTR lpServiceName
,
4612 LPBOUNDED_DWORD_4K lpcchBuffer
)
4617 LPWSTR lpDisplayNameW
;
4619 DPRINT("RGetServiceKeyNameA() called\n");
4620 DPRINT("hSCManager = %p\n", hSCManager
);
4621 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4622 DPRINT("lpServiceName: %p\n", lpServiceName
);
4623 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4625 dwLength
= (DWORD
)(strlen(lpDisplayName
) + 1);
4626 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4628 dwLength
* sizeof(WCHAR
));
4629 if (!lpDisplayNameW
)
4630 return ERROR_NOT_ENOUGH_MEMORY
;
4632 MultiByteToWideChar(CP_ACP
,
4639 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4641 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4643 if (lpService
== NULL
)
4645 DPRINT("Could not find the service!\n");
4647 /* If the service could not be found and lpcchBuffer is 0,
4648 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4649 if (*lpcchBuffer
== 0)
4652 if (lpServiceName
!= NULL
)
4658 return ERROR_SERVICE_DOES_NOT_EXIST
;
4661 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
4662 if (lpServiceName
!= NULL
&&
4663 *lpcchBuffer
> dwLength
)
4665 WideCharToMultiByte(CP_ACP
,
4667 lpService
->lpServiceName
,
4668 (int)wcslen(lpService
->lpServiceName
),
4673 return ERROR_SUCCESS
;
4676 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4678 *lpcchBuffer
= dwLength
* 2;
4687 RI_ScGetCurrentGroupStateW(
4688 SC_RPC_HANDLE hSCManager
,
4689 LPWSTR lpLoadOrderGroup
,
4692 PMANAGER_HANDLE hManager
;
4693 PSERVICE_GROUP pServiceGroup
;
4694 DWORD dwError
= ERROR_SUCCESS
;
4696 DPRINT("RI_ScGetCurrentGroupStateW() called\n");
4699 return ERROR_SHUTDOWN_IN_PROGRESS
;
4701 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
4702 if (hManager
== NULL
)
4704 DPRINT1("Invalid service manager handle!\n");
4705 return ERROR_INVALID_HANDLE
;
4708 /* Check for SC_MANAGER_ENUMERATE_SERVICE access right */
4709 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4710 SC_MANAGER_ENUMERATE_SERVICE
))
4712 DPRINT("Insufficient access rights! 0x%lx\n",
4713 hManager
->Handle
.DesiredAccess
);
4714 return ERROR_ACCESS_DENIED
;
4717 /* Lock the service database shared */
4718 ScmLockDatabaseShared();
4720 /* Get the group list entry */
4721 pServiceGroup
= ScmGetServiceGroupByName(lpLoadOrderGroup
);
4722 if (pServiceGroup
== NULL
)
4724 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
4728 /* FIXME: Return the group state */
4732 /* Unlock the service database */
4733 ScmUnlockDatabase();
4735 DPRINT("RI_ScGetCurrentGroupStateW() done (Error %lu)\n", dwError
);
4745 SC_RPC_HANDLE hSCManager
,
4746 DWORD dwServiceType
,
4747 DWORD dwServiceState
,
4750 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4751 LPBOUNDED_DWORD_256K lpServicesReturned
,
4752 LPBOUNDED_DWORD_256K lpResumeIndex
,
4753 LPCWSTR pszGroupName
)
4755 PMANAGER_HANDLE hManager
;
4757 DWORD dwError
= ERROR_SUCCESS
;
4758 PLIST_ENTRY ServiceEntry
;
4759 PSERVICE CurrentService
;
4761 DWORD dwRequiredSize
;
4762 DWORD dwServiceCount
;
4764 DWORD dwLastResumeCount
= 0;
4765 LPENUM_SERVICE_STATUSW lpStatusPtr
;
4768 DPRINT("REnumServiceGroupW() called\n");
4771 return ERROR_SHUTDOWN_IN_PROGRESS
;
4773 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
4774 if (hManager
== NULL
)
4776 DPRINT1("Invalid service manager handle!\n");
4777 return ERROR_INVALID_HANDLE
;
4780 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
4782 return ERROR_INVALID_ADDRESS
;
4785 *pcbBytesNeeded
= 0;
4786 *lpServicesReturned
= 0;
4788 if ((dwServiceType
== 0) ||
4789 ((dwServiceType
& ~SERVICE_TYPE_ALL
) != 0))
4791 DPRINT("Not a valid Service Type!\n");
4792 return ERROR_INVALID_PARAMETER
;
4795 if ((dwServiceState
== 0) ||
4796 ((dwServiceState
& ~SERVICE_STATE_ALL
) != 0))
4798 DPRINT("Not a valid Service State!\n");
4799 return ERROR_INVALID_PARAMETER
;
4802 /* Check access rights */
4803 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4804 SC_MANAGER_ENUMERATE_SERVICE
))
4806 DPRINT("Insufficient access rights! 0x%lx\n",
4807 hManager
->Handle
.DesiredAccess
);
4808 return ERROR_ACCESS_DENIED
;
4812 dwLastResumeCount
= *lpResumeIndex
;
4814 /* Lock the service database shared */
4815 ScmLockDatabaseShared();
4817 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4818 if (lpService
== NULL
)
4820 dwError
= ERROR_SUCCESS
;
4827 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4828 ServiceEntry
!= &ServiceListHead
;
4829 ServiceEntry
= ServiceEntry
->Flink
)
4831 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4835 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4838 dwState
= SERVICE_ACTIVE
;
4839 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4840 dwState
= SERVICE_INACTIVE
;
4842 if ((dwState
& dwServiceState
) == 0)
4847 if (*pszGroupName
== 0)
4849 if (CurrentService
->lpGroup
!= NULL
)
4854 if ((CurrentService
->lpGroup
== NULL
) ||
4855 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4860 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
4861 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4862 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4864 if (dwRequiredSize
+ dwSize
> cbBufSize
)
4866 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4870 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4871 dwRequiredSize
+= dwSize
;
4873 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4876 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4877 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4880 ServiceEntry
!= &ServiceListHead
;
4881 ServiceEntry
= ServiceEntry
->Flink
)
4883 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4887 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4890 dwState
= SERVICE_ACTIVE
;
4891 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4892 dwState
= SERVICE_INACTIVE
;
4894 if ((dwState
& dwServiceState
) == 0)
4899 if (*pszGroupName
== 0)
4901 if (CurrentService
->lpGroup
!= NULL
)
4906 if ((CurrentService
->lpGroup
== NULL
) ||
4907 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4912 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
4913 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4914 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4916 dwError
= ERROR_MORE_DATA
;
4919 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4922 *lpResumeIndex
= dwLastResumeCount
;
4924 *lpServicesReturned
= dwServiceCount
;
4925 *pcbBytesNeeded
= dwRequiredSize
;
4927 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
4928 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4929 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
4932 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4933 ServiceEntry
!= &ServiceListHead
;
4934 ServiceEntry
= ServiceEntry
->Flink
)
4936 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4940 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4943 dwState
= SERVICE_ACTIVE
;
4944 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4945 dwState
= SERVICE_INACTIVE
;
4947 if ((dwState
& dwServiceState
) == 0)
4952 if (*pszGroupName
== 0)
4954 if (CurrentService
->lpGroup
!= NULL
)
4959 if ((CurrentService
->lpGroup
== NULL
) ||
4960 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4965 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
4966 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4967 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4969 if (dwRequiredSize
+ dwSize
> cbBufSize
)
4972 /* Copy the service name */
4973 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
4974 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4975 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4977 /* Copy the display name */
4978 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
4979 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4980 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4982 /* Copy the status information */
4983 memcpy(&lpStatusPtr
->ServiceStatus
,
4984 &CurrentService
->Status
,
4985 sizeof(SERVICE_STATUS
));
4988 dwRequiredSize
+= dwSize
;
4991 if (dwError
== ERROR_SUCCESS
)
4993 *pcbBytesNeeded
= 0;
4994 if (lpResumeIndex
) *lpResumeIndex
= 0;
4998 /* Unlock the service database */
4999 ScmUnlockDatabase();
5001 DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError
);
5010 RChangeServiceConfig2A(
5011 SC_RPC_HANDLE hService
,
5012 SC_RPC_CONFIG_INFOA Info
)
5014 SC_RPC_CONFIG_INFOW InfoW
;
5015 DWORD dwRet
, dwLength
;
5018 DPRINT("RChangeServiceConfig2A() called\n");
5019 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
5021 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
5023 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5025 LPSERVICE_DESCRIPTIONW lpServiceDescriptionW
;
5026 LPSERVICE_DESCRIPTIONA lpServiceDescriptionA
;
5028 lpServiceDescriptionA
= Info
.psd
;
5030 if (lpServiceDescriptionA
&&
5031 lpServiceDescriptionA
->lpDescription
)
5033 dwLength
= (DWORD
)((strlen(lpServiceDescriptionA
->lpDescription
) + 1) * sizeof(WCHAR
));
5035 lpServiceDescriptionW
= HeapAlloc(GetProcessHeap(),
5037 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
5038 if (!lpServiceDescriptionW
)
5040 return ERROR_NOT_ENOUGH_MEMORY
;
5043 lpServiceDescriptionW
->lpDescription
= (LPWSTR
)(lpServiceDescriptionW
+ 1);
5045 MultiByteToWideChar(CP_ACP
,
5047 lpServiceDescriptionA
->lpDescription
,
5049 lpServiceDescriptionW
->lpDescription
,
5052 ptr
= lpServiceDescriptionW
;
5053 InfoW
.psd
= lpServiceDescriptionW
;
5056 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5058 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
5059 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
5060 DWORD dwRebootLen
= 0;
5061 DWORD dwCommandLen
= 0;
5062 DWORD dwActionArrayLen
= 0;
5063 LPWSTR lpStr
= NULL
;
5065 lpServiceFailureActionsA
= Info
.psfa
;
5067 if (lpServiceFailureActionsA
)
5070 * The following code is inspired by the
5071 * SERVICE_CONFIG_FAILURE_ACTIONS case of
5072 * the RQueryServiceConfig2W function.
5075 /* Retrieve the needed length for the two data strings */
5076 if (lpServiceFailureActionsA
->lpRebootMsg
)
5078 dwRebootLen
= (DWORD
)((strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
));
5080 if (lpServiceFailureActionsA
->lpCommand
)
5082 dwCommandLen
= (DWORD
)((strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
));
5086 * Retrieve the size of the lpsaActions array if needed.
5087 * We will copy the lpsaActions array only if there is at
5088 * least one action AND that the original array is valid.
5090 if (lpServiceFailureActionsA
->cActions
> 0 && lpServiceFailureActionsA
->lpsaActions
)
5092 dwActionArrayLen
= lpServiceFailureActionsA
->cActions
* sizeof(SC_ACTION
);
5095 /* Compute the total length for the UNICODE structure, including data */
5096 dwLength
= sizeof(SERVICE_FAILURE_ACTIONSW
) +
5097 dwActionArrayLen
+ dwRebootLen
+ dwCommandLen
;
5099 /* Allocate the structure */
5100 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
5103 if (!lpServiceFailureActionsW
)
5105 return ERROR_NOT_ENOUGH_MEMORY
;
5108 /* Copy the members */
5109 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
5110 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
5112 /* Copy the lpsaActions array if needed */
5113 if (dwActionArrayLen
> 0)
5115 /* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */
5116 lpServiceFailureActionsW
->lpsaActions
= (LPSC_ACTION
)((ULONG_PTR
)(lpServiceFailureActionsW
+ 1));
5118 /* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */
5119 RtlCopyMemory(lpServiceFailureActionsW
->lpsaActions
,
5120 lpServiceFailureActionsA
->lpsaActions
,
5125 /* No lpsaActions array */
5126 lpServiceFailureActionsW
->lpsaActions
= NULL
;
5128 /* The data strings are stored just after the lpsaActions array */
5129 lpStr
= (LPWSTR
)((ULONG_PTR
)(lpServiceFailureActionsW
+ 1) + dwActionArrayLen
);
5132 * Convert the data strings to UNICODE
5135 lpServiceFailureActionsW
->lpRebootMsg
= NULL
;
5136 lpServiceFailureActionsW
->lpCommand
= NULL
;
5140 /* lpRebootMsg points just after the lpsaActions array */
5141 lpServiceFailureActionsW
->lpRebootMsg
= lpStr
;
5143 MultiByteToWideChar(CP_ACP
,
5145 lpServiceFailureActionsA
->lpRebootMsg
,
5147 lpServiceFailureActionsW
->lpRebootMsg
,
5150 lpStr
+= dwRebootLen
/ sizeof(WCHAR
);
5155 /* lpRebootMsg points just after the lpRebootMsg data string */
5156 lpServiceFailureActionsW
->lpCommand
= lpStr
;
5158 MultiByteToWideChar(CP_ACP
,
5160 lpServiceFailureActionsA
->lpCommand
,
5162 lpServiceFailureActionsW
->lpCommand
,
5166 /* Set the pointers */
5167 ptr
= lpServiceFailureActionsW
;
5168 InfoW
.psfa
= lpServiceFailureActionsW
;
5172 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
5174 HeapFree(GetProcessHeap(), 0, ptr
);
5181 ScmSetFailureActions(HKEY hServiceKey
,
5182 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
)
5184 LPSERVICE_FAILURE_ACTIONSW lpReadBuffer
= NULL
;
5185 LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer
= NULL
;
5186 DWORD dwRequiredSize
= 0;
5190 /* There is nothing to be done if we have no failure actions */
5191 if (lpFailureActions
== NULL
)
5192 return ERROR_SUCCESS
;
5195 * 1- Retrieve the original value of FailureActions.
5198 /* Query value length */
5199 dwError
= RegQueryValueExW(hServiceKey
,
5205 if (dwError
!= ERROR_SUCCESS
&&
5206 dwError
!= ERROR_MORE_DATA
&&
5207 dwError
!= ERROR_FILE_NOT_FOUND
)
5210 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSW
), dwRequiredSize
)
5211 : sizeof(SERVICE_FAILURE_ACTIONSW
);
5213 /* Initialize the read buffer */
5214 lpReadBuffer
= HeapAlloc(GetProcessHeap(),
5217 if (lpReadBuffer
== NULL
)
5218 return ERROR_NOT_ENOUGH_MEMORY
;
5220 /* Now we can fill the read buffer */
5221 if (dwError
!= ERROR_FILE_NOT_FOUND
&&
5222 dwType
== REG_BINARY
)
5224 dwError
= RegQueryValueExW(hServiceKey
,
5228 (LPBYTE
)lpReadBuffer
,
5230 if (dwError
!= ERROR_SUCCESS
&&
5231 dwError
!= ERROR_FILE_NOT_FOUND
)
5234 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSW
))
5235 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5240 * The value of the error doesn't really matter, the only
5241 * important thing is that it must be != ERROR_SUCCESS.
5243 dwError
= ERROR_INVALID_DATA
;
5246 if (dwError
== ERROR_SUCCESS
)
5248 lpReadBuffer
->cActions
= min(lpReadBuffer
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSW
)) / sizeof(SC_ACTION
));
5249 lpReadBuffer
->lpsaActions
= (lpReadBuffer
->cActions
> 0 ? (LPSC_ACTION
)(lpReadBuffer
+ 1) : NULL
);
5253 lpReadBuffer
->dwResetPeriod
= 0;
5254 lpReadBuffer
->cActions
= 0;
5255 lpReadBuffer
->lpsaActions
= NULL
;
5258 lpReadBuffer
->lpRebootMsg
= NULL
;
5259 lpReadBuffer
->lpCommand
= NULL
;
5262 * 2- Initialize the new value to set.
5265 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5267 if (lpFailureActions
->lpsaActions
== NULL
)
5270 * lpFailureActions->cActions is ignored.
5271 * Therefore we use the original values
5272 * of cActions and lpsaActions.
5274 dwRequiredSize
+= lpReadBuffer
->cActions
* sizeof(SC_ACTION
);
5279 * The reset period and array of failure actions
5280 * are deleted if lpFailureActions->cActions == 0 .
5282 dwRequiredSize
+= lpFailureActions
->cActions
* sizeof(SC_ACTION
);
5285 lpWriteBuffer
= HeapAlloc(GetProcessHeap(),
5288 if (lpWriteBuffer
== NULL
)
5290 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
5294 /* Clean the pointers as they have no meaning when the structure is stored in the registry */
5295 lpWriteBuffer
->lpRebootMsg
= NULL
;
5296 lpWriteBuffer
->lpCommand
= NULL
;
5297 lpWriteBuffer
->lpsaActions
= NULL
;
5299 /* Set the members */
5300 if (lpFailureActions
->lpsaActions
== NULL
)
5303 * lpFailureActions->dwResetPeriod and lpFailureActions->cActions are ignored.
5304 * Therefore we use the original values of dwResetPeriod, cActions and lpsaActions.
5306 lpWriteBuffer
->dwResetPeriod
= lpReadBuffer
->dwResetPeriod
;
5307 lpWriteBuffer
->cActions
= lpReadBuffer
->cActions
;
5309 if (lpReadBuffer
->lpsaActions
!= NULL
)
5311 memmove(lpWriteBuffer
+ 1,
5312 lpReadBuffer
->lpsaActions
,
5313 lpReadBuffer
->cActions
* sizeof(SC_ACTION
));
5318 if (lpFailureActions
->cActions
> 0)
5320 lpWriteBuffer
->dwResetPeriod
= lpFailureActions
->dwResetPeriod
;
5321 lpWriteBuffer
->cActions
= lpFailureActions
->cActions
;
5323 memmove(lpWriteBuffer
+ 1,
5324 lpFailureActions
->lpsaActions
,
5325 lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5329 /* The reset period and array of failure actions are deleted */
5330 lpWriteBuffer
->dwResetPeriod
= 0;
5331 lpWriteBuffer
->cActions
= 0;
5335 /* Save the new failure actions into the registry */
5336 dwError
= RegSetValueExW(hServiceKey
,
5340 (LPBYTE
)lpWriteBuffer
,
5343 /* We modify the strings only in case of success.*/
5344 if (dwError
== ERROR_SUCCESS
)
5346 /* Modify the Reboot Message value, if specified */
5347 if (lpFailureActions
->lpRebootMsg
!= NULL
)
5349 /* If the Reboot Message is "" then we delete it */
5350 if (*lpFailureActions
->lpRebootMsg
== 0)
5352 DPRINT("Delete Reboot Message value\n");
5353 RegDeleteValueW(hServiceKey
, L
"RebootMessage");
5357 DPRINT("Setting Reboot Message value %S\n", lpFailureActions
->lpRebootMsg
);
5358 RegSetValueExW(hServiceKey
,
5362 (LPBYTE
)lpFailureActions
->lpRebootMsg
,
5363 (DWORD
)((wcslen(lpFailureActions
->lpRebootMsg
) + 1) * sizeof(WCHAR
)));
5367 /* Modify the Failure Command value, if specified */
5368 if (lpFailureActions
->lpCommand
!= NULL
)
5370 /* If the FailureCommand string is an empty string, delete the value */
5371 if (*lpFailureActions
->lpCommand
== 0)
5373 DPRINT("Delete Failure Command value\n");
5374 RegDeleteValueW(hServiceKey
, L
"FailureCommand");
5378 DPRINT("Setting Failure Command value %S\n", lpFailureActions
->lpCommand
);
5379 RegSetValueExW(hServiceKey
,
5383 (LPBYTE
)lpFailureActions
->lpCommand
,
5384 (DWORD
)((wcslen(lpFailureActions
->lpCommand
) + 1) * sizeof(WCHAR
)));
5390 if (lpWriteBuffer
!= NULL
)
5391 HeapFree(GetProcessHeap(), 0, lpWriteBuffer
);
5393 if (lpReadBuffer
!= NULL
)
5394 HeapFree(GetProcessHeap(), 0, lpReadBuffer
);
5403 RChangeServiceConfig2W(
5404 SC_RPC_HANDLE hService
,
5405 SC_RPC_CONFIG_INFOW Info
)
5407 DWORD dwError
= ERROR_SUCCESS
;
5408 PSERVICE_HANDLE hSvc
;
5409 PSERVICE lpService
= NULL
;
5410 HKEY hServiceKey
= NULL
;
5411 ACCESS_MASK RequiredAccess
= SERVICE_CHANGE_CONFIG
;
5413 DPRINT("RChangeServiceConfig2W() called\n");
5414 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
5417 return ERROR_SHUTDOWN_IN_PROGRESS
;
5419 hSvc
= ScmGetServiceFromHandle(hService
);
5422 DPRINT("Invalid service handle!\n");
5423 return ERROR_INVALID_HANDLE
;
5426 if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5427 RequiredAccess
|= SERVICE_START
;
5429 /* Check the access rights */
5430 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5433 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5434 return ERROR_ACCESS_DENIED
;
5437 if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5439 /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */
5443 lpService
= hSvc
->ServiceEntry
;
5444 if (lpService
== NULL
)
5446 DPRINT("lpService == NULL!\n");
5447 return ERROR_INVALID_HANDLE
;
5450 /* Failure actions can only be set for Win32 services, not for drivers */
5451 if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5453 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
5454 return ERROR_CANNOT_DETECT_DRIVER_FAILURE
;
5457 /* Lock the service database exclusively */
5458 ScmLockDatabaseExclusive();
5460 if (lpService
->bDeleted
)
5462 DPRINT("The service has already been marked for delete!\n");
5463 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
5467 /* Open the service key */
5468 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
5469 KEY_READ
| KEY_SET_VALUE
,
5471 if (dwError
!= ERROR_SUCCESS
)
5474 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5476 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
5478 /* Modify the service description, if specified */
5479 if (lpServiceDescription
!= NULL
&&
5480 lpServiceDescription
->lpDescription
!= NULL
)
5482 /* If the description is "" then we delete it */
5483 if (*lpServiceDescription
->lpDescription
== 0)
5485 DPRINT("Delete service description\n");
5486 dwError
= RegDeleteValueW(hServiceKey
, L
"Description");
5488 if (dwError
== ERROR_FILE_NOT_FOUND
)
5489 dwError
= ERROR_SUCCESS
;
5493 DPRINT("Setting service description value %S\n", lpServiceDescription
->lpDescription
);
5494 dwError
= RegSetValueExW(hServiceKey
,
5498 (LPBYTE
)lpServiceDescription
->lpDescription
,
5499 (DWORD
)((wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
)));
5504 dwError
= ERROR_SUCCESS
;
5507 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5509 dwError
= ScmSetFailureActions(hServiceKey
,
5510 (LPSERVICE_FAILURE_ACTIONSW
)Info
.psfa
);
5514 if (hServiceKey
!= NULL
)
5515 RegCloseKey(hServiceKey
);
5517 /* Unlock the service database */
5518 ScmUnlockDatabase();
5520 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
5529 RQueryServiceConfig2A(
5530 SC_RPC_HANDLE hService
,
5534 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5536 DWORD dwError
= ERROR_SUCCESS
;
5537 PSERVICE_HANDLE hSvc
;
5538 PSERVICE lpService
= NULL
;
5539 HKEY hServiceKey
= NULL
;
5540 DWORD dwRequiredSize
= 0;
5542 LPWSTR lpDescriptionW
= NULL
;
5543 LPWSTR lpRebootMessageW
= NULL
;
5544 LPWSTR lpFailureCommandW
= NULL
;
5546 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
5547 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
5550 return ERROR_INVALID_ADDRESS
;
5553 return ERROR_SHUTDOWN_IN_PROGRESS
;
5555 hSvc
= ScmGetServiceFromHandle(hService
);
5558 DPRINT1("Invalid service handle!\n");
5559 return ERROR_INVALID_HANDLE
;
5562 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5563 SERVICE_QUERY_CONFIG
))
5565 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5566 return ERROR_ACCESS_DENIED
;
5569 lpService
= hSvc
->ServiceEntry
;
5570 if (lpService
== NULL
)
5572 DPRINT("lpService == NULL!\n");
5573 return ERROR_INVALID_HANDLE
;
5576 /* Lock the service database shared */
5577 ScmLockDatabaseShared();
5579 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
5582 if (dwError
!= ERROR_SUCCESS
)
5585 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5587 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
5590 dwError
= ScmReadString(hServiceKey
,
5593 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5596 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
5597 if (dwError
== ERROR_SUCCESS
)
5598 *pcbBytesNeeded
+= (DWORD
)((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
5600 if (cbBufSize
< *pcbBytesNeeded
)
5602 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5606 if (dwError
== ERROR_SUCCESS
)
5608 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
5610 WideCharToMultiByte(CP_ACP
,
5615 (int)wcslen(lpDescriptionW
),
5618 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
5622 lpServiceDescription
->lpDescription
= NULL
;
5623 dwError
= ERROR_SUCCESS
;
5626 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5628 LPSERVICE_FAILURE_ACTIONSA lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSA
)lpBuffer
;
5631 /* Query value length */
5632 dwError
= RegQueryValueExW(hServiceKey
,
5638 if (dwError
!= ERROR_SUCCESS
&&
5639 dwError
!= ERROR_MORE_DATA
&&
5640 dwError
!= ERROR_FILE_NOT_FOUND
)
5643 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSA
), dwRequiredSize
)
5644 : sizeof(SERVICE_FAILURE_ACTIONSA
);
5646 /* Get the strings */
5647 ScmReadString(hServiceKey
,
5649 &lpFailureCommandW
);
5651 ScmReadString(hServiceKey
,
5655 if (lpRebootMessageW
)
5656 dwRequiredSize
+= (DWORD
)((wcslen(lpRebootMessageW
) + 1) * sizeof(WCHAR
));
5658 if (lpFailureCommandW
)
5659 dwRequiredSize
+= (DWORD
)((wcslen(lpFailureCommandW
) + 1) * sizeof(WCHAR
));
5661 if (cbBufSize
< dwRequiredSize
)
5663 *pcbBytesNeeded
= dwRequiredSize
;
5664 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5668 /* Now we can fill the buffer */
5669 if (dwError
!= ERROR_FILE_NOT_FOUND
&& dwType
== REG_BINARY
)
5671 dwError
= RegQueryValueExW(hServiceKey
,
5675 (LPBYTE
)lpFailureActions
,
5677 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5680 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSA
))
5681 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSA
);
5686 * The value of the error doesn't really matter, the only
5687 * important thing is that it must be != ERROR_SUCCESS .
5689 dwError
= ERROR_INVALID_DATA
;
5692 if (dwError
== ERROR_SUCCESS
)
5694 lpFailureActions
->cActions
= min(lpFailureActions
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSA
)) / sizeof(SC_ACTION
));
5696 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5697 lpFailureActions
->lpsaActions
= (lpFailureActions
->cActions
> 0 ? (LPSC_ACTION
)(ULONG_PTR
)sizeof(SERVICE_FAILURE_ACTIONSA
) : NULL
);
5699 lpStr
= (LPSTR
)((ULONG_PTR
)(lpFailureActions
+ 1) + lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5703 lpFailureActions
->dwResetPeriod
= 0;
5704 lpFailureActions
->cActions
= 0;
5705 lpFailureActions
->lpsaActions
= NULL
;
5706 lpStr
= (LPSTR
)(lpFailureActions
+ 1);
5709 lpFailureActions
->lpRebootMsg
= NULL
;
5710 lpFailureActions
->lpCommand
= NULL
;
5712 if (lpRebootMessageW
)
5714 WideCharToMultiByte(CP_ACP
,
5719 (int)wcslen(lpRebootMessageW
),
5722 lpFailureActions
->lpRebootMsg
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5723 lpStr
+= strlen(lpStr
) + 1;
5726 if (lpFailureCommandW
)
5728 WideCharToMultiByte(CP_ACP
,
5733 (int)wcslen(lpFailureCommandW
),
5736 lpFailureActions
->lpCommand
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5737 /* lpStr += strlen(lpStr) + 1; */
5740 dwError
= ERROR_SUCCESS
;
5744 /* Unlock the service database */
5745 ScmUnlockDatabase();
5747 if (lpDescriptionW
!= NULL
)
5748 HeapFree(GetProcessHeap(), 0, lpDescriptionW
);
5750 if (lpRebootMessageW
!= NULL
)
5751 HeapFree(GetProcessHeap(), 0, lpRebootMessageW
);
5753 if (lpFailureCommandW
!= NULL
)
5754 HeapFree(GetProcessHeap(), 0, lpFailureCommandW
);
5756 if (hServiceKey
!= NULL
)
5757 RegCloseKey(hServiceKey
);
5759 DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError
);
5768 RQueryServiceConfig2W(
5769 SC_RPC_HANDLE hService
,
5773 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5775 DWORD dwError
= ERROR_SUCCESS
;
5776 PSERVICE_HANDLE hSvc
;
5777 PSERVICE lpService
= NULL
;
5778 HKEY hServiceKey
= NULL
;
5779 DWORD dwRequiredSize
= 0;
5781 LPWSTR lpDescription
= NULL
;
5782 LPWSTR lpRebootMessage
= NULL
;
5783 LPWSTR lpFailureCommand
= NULL
;
5785 DPRINT("RQueryServiceConfig2W() called\n");
5788 return ERROR_INVALID_ADDRESS
;
5791 return ERROR_SHUTDOWN_IN_PROGRESS
;
5793 hSvc
= ScmGetServiceFromHandle(hService
);
5796 DPRINT1("Invalid service handle!\n");
5797 return ERROR_INVALID_HANDLE
;
5800 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5801 SERVICE_QUERY_CONFIG
))
5803 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5804 return ERROR_ACCESS_DENIED
;
5807 lpService
= hSvc
->ServiceEntry
;
5808 if (lpService
== NULL
)
5810 DPRINT("lpService == NULL!\n");
5811 return ERROR_INVALID_HANDLE
;
5814 /* Lock the service database shared */
5815 ScmLockDatabaseShared();
5817 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
5820 if (dwError
!= ERROR_SUCCESS
)
5823 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5825 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
5828 dwError
= ScmReadString(hServiceKey
,
5831 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5834 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
5835 if (dwError
== ERROR_SUCCESS
)
5836 *pcbBytesNeeded
+= (DWORD
)((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
5838 if (cbBufSize
< *pcbBytesNeeded
)
5840 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5844 if (dwError
== ERROR_SUCCESS
)
5846 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
5847 wcscpy(lpStr
, lpDescription
);
5848 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
5852 lpServiceDescription
->lpDescription
= NULL
;
5853 dwError
= ERROR_SUCCESS
;
5856 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5858 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
5859 LPWSTR lpStr
= NULL
;
5861 /* Query value length */
5862 dwError
= RegQueryValueExW(hServiceKey
,
5868 if (dwError
!= ERROR_SUCCESS
&&
5869 dwError
!= ERROR_MORE_DATA
&&
5870 dwError
!= ERROR_FILE_NOT_FOUND
)
5873 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSW
), dwRequiredSize
)
5874 : sizeof(SERVICE_FAILURE_ACTIONSW
);
5876 /* Get the strings */
5877 ScmReadString(hServiceKey
,
5881 ScmReadString(hServiceKey
,
5885 if (lpRebootMessage
)
5886 dwRequiredSize
+= (DWORD
)((wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
));
5888 if (lpFailureCommand
)
5889 dwRequiredSize
+= (DWORD
)((wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
));
5891 if (cbBufSize
< dwRequiredSize
)
5893 *pcbBytesNeeded
= dwRequiredSize
;
5894 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5898 /* Now we can fill the buffer */
5899 if (dwError
!= ERROR_FILE_NOT_FOUND
&& dwType
== REG_BINARY
)
5901 dwError
= RegQueryValueExW(hServiceKey
,
5905 (LPBYTE
)lpFailureActions
,
5907 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5910 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSW
))
5911 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5916 * The value of the error doesn't really matter, the only
5917 * important thing is that it must be != ERROR_SUCCESS .
5919 dwError
= ERROR_INVALID_DATA
;
5922 if (dwError
== ERROR_SUCCESS
)
5924 lpFailureActions
->cActions
= min(lpFailureActions
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSW
)) / sizeof(SC_ACTION
));
5926 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5927 lpFailureActions
->lpsaActions
= (lpFailureActions
->cActions
> 0 ? (LPSC_ACTION
)(ULONG_PTR
)sizeof(SERVICE_FAILURE_ACTIONSW
) : NULL
);
5929 lpStr
= (LPWSTR
)((ULONG_PTR
)(lpFailureActions
+ 1) + lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5933 lpFailureActions
->dwResetPeriod
= 0;
5934 lpFailureActions
->cActions
= 0;
5935 lpFailureActions
->lpsaActions
= NULL
;
5936 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
5939 lpFailureActions
->lpRebootMsg
= NULL
;
5940 lpFailureActions
->lpCommand
= NULL
;
5942 if (lpRebootMessage
)
5944 wcscpy(lpStr
, lpRebootMessage
);
5945 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5946 lpStr
+= wcslen(lpStr
) + 1;
5949 if (lpFailureCommand
)
5951 wcscpy(lpStr
, lpFailureCommand
);
5952 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5953 /* lpStr += wcslen(lpStr) + 1; */
5956 dwError
= ERROR_SUCCESS
;
5960 /* Unlock the service database */
5961 ScmUnlockDatabase();
5963 if (lpDescription
!= NULL
)
5964 HeapFree(GetProcessHeap(), 0, lpDescription
);
5966 if (lpRebootMessage
!= NULL
)
5967 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5969 if (lpFailureCommand
!= NULL
)
5970 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5972 if (hServiceKey
!= NULL
)
5973 RegCloseKey(hServiceKey
);
5975 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5984 RQueryServiceStatusEx(
5985 SC_RPC_HANDLE hService
,
5986 SC_STATUS_TYPE InfoLevel
,
5989 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5991 LPSERVICE_STATUS_PROCESS lpStatus
;
5992 PSERVICE_HANDLE hSvc
;
5995 DPRINT("RQueryServiceStatusEx() called\n");
5998 return ERROR_SHUTDOWN_IN_PROGRESS
;
6000 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
6001 return ERROR_INVALID_LEVEL
;
6003 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
6005 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
6006 return ERROR_INSUFFICIENT_BUFFER
;
6008 hSvc
= ScmGetServiceFromHandle(hService
);
6011 DPRINT1("Invalid service handle!\n");
6012 return ERROR_INVALID_HANDLE
;
6015 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
6016 SERVICE_QUERY_STATUS
))
6018 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
6019 return ERROR_ACCESS_DENIED
;
6022 lpService
= hSvc
->ServiceEntry
;
6023 if (lpService
== NULL
)
6025 DPRINT("lpService == NULL!\n");
6026 return ERROR_INVALID_HANDLE
;
6029 /* Lock the service database shared */
6030 ScmLockDatabaseShared();
6032 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
6034 /* Return service status information */
6035 RtlCopyMemory(lpStatus
,
6037 sizeof(SERVICE_STATUS
));
6039 /* Copy the service process ID */
6040 if ((lpService
->Status
.dwCurrentState
== SERVICE_STOPPED
) || (lpService
->lpImage
== NULL
))
6041 lpStatus
->dwProcessId
= 0;
6043 lpStatus
->dwProcessId
= lpService
->lpImage
->dwProcessId
;
6045 lpStatus
->dwServiceFlags
= 0; /* FIXME */
6047 /* Unlock the service database */
6048 ScmUnlockDatabase();
6050 return ERROR_SUCCESS
;
6057 REnumServicesStatusExA(
6058 SC_RPC_HANDLE hSCManager
,
6059 SC_ENUM_TYPE InfoLevel
,
6060 DWORD dwServiceType
,
6061 DWORD dwServiceState
,
6064 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
6065 LPBOUNDED_DWORD_256K lpServicesReturned
,
6066 LPBOUNDED_DWORD_256K lpResumeIndex
,
6067 LPCSTR pszGroupName
)
6069 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
6070 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW
;
6071 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
6072 LPWSTR lpStringPtrW
;
6074 LPWSTR pszGroupNameW
= NULL
;
6076 DWORD dwServiceCount
;
6078 DPRINT("REnumServicesStatusExA() called\n");
6080 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
6082 return ERROR_INVALID_ADDRESS
;
6087 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
6090 DPRINT("Failed to allocate buffer!\n");
6091 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
6095 MultiByteToWideChar(CP_ACP
,
6100 (int)(strlen(pszGroupName
) + 1));
6103 if ((cbBufSize
> 0) && (lpBuffer
))
6105 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
6108 DPRINT("Failed to allocate buffer!\n");
6109 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
6114 dwError
= REnumServicesStatusExW(hSCManager
,
6118 (LPBYTE
)lpStatusPtrW
,
6125 /* if no services were returned then we are Done */
6126 if (*lpServicesReturned
== 0)
6129 lpStatusPtrIncrW
= lpStatusPtrW
;
6130 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
6131 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
6132 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
6133 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
6134 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
6136 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
6138 /* Copy the service name */
6139 WideCharToMultiByte(CP_ACP
,
6144 (int)wcslen(lpStringPtrW
),
6148 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
6149 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
6150 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
6152 /* Copy the display name */
6153 WideCharToMultiByte(CP_ACP
,
6158 (int)wcslen(lpStringPtrW
),
6162 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
6163 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
6164 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
6166 /* Copy the status information */
6167 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
6168 &lpStatusPtrIncrW
->ServiceStatusProcess
,
6169 sizeof(SERVICE_STATUS
));
6171 /* Copy the service process ID */
6172 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrIncrW
->ServiceStatusProcess
.dwProcessId
;
6174 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
6182 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
6185 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
6187 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
6196 REnumServicesStatusExW(
6197 SC_RPC_HANDLE hSCManager
,
6198 SC_ENUM_TYPE InfoLevel
,
6199 DWORD dwServiceType
,
6200 DWORD dwServiceState
,
6203 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
6204 LPBOUNDED_DWORD_256K lpServicesReturned
,
6205 LPBOUNDED_DWORD_256K lpResumeIndex
,
6206 LPCWSTR pszGroupName
)
6208 PMANAGER_HANDLE hManager
;
6210 DWORD dwError
= ERROR_SUCCESS
;
6211 PLIST_ENTRY ServiceEntry
;
6212 PSERVICE CurrentService
;
6214 DWORD dwRequiredSize
;
6215 DWORD dwServiceCount
;
6217 DWORD dwLastResumeCount
= 0;
6218 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
6221 DPRINT("REnumServicesStatusExW() called\n");
6224 return ERROR_SHUTDOWN_IN_PROGRESS
;
6226 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
6227 return ERROR_INVALID_LEVEL
;
6229 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
6230 if (hManager
== NULL
)
6232 DPRINT1("Invalid service manager handle!\n");
6233 return ERROR_INVALID_HANDLE
;
6236 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
6238 return ERROR_INVALID_ADDRESS
;
6241 *pcbBytesNeeded
= 0;
6242 *lpServicesReturned
= 0;
6244 if ((dwServiceType
== 0) ||
6245 ((dwServiceType
& ~SERVICE_TYPE_ALL
) != 0))
6247 DPRINT("Not a valid Service Type!\n");
6248 return ERROR_INVALID_PARAMETER
;
6251 if ((dwServiceState
== 0) ||
6252 ((dwServiceState
& ~SERVICE_STATE_ALL
) != 0))
6254 DPRINT("Not a valid Service State!\n");
6255 return ERROR_INVALID_PARAMETER
;
6258 /* Check access rights */
6259 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
6260 SC_MANAGER_ENUMERATE_SERVICE
))
6262 DPRINT("Insufficient access rights! 0x%lx\n",
6263 hManager
->Handle
.DesiredAccess
);
6264 return ERROR_ACCESS_DENIED
;
6268 dwLastResumeCount
= *lpResumeIndex
;
6270 /* Lock the service database shared */
6271 ScmLockDatabaseShared();
6273 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
6274 if (lpService
== NULL
)
6276 dwError
= ERROR_SUCCESS
;
6283 for (ServiceEntry
= &lpService
->ServiceListEntry
;
6284 ServiceEntry
!= &ServiceListHead
;
6285 ServiceEntry
= ServiceEntry
->Flink
)
6287 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
6291 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
6294 dwState
= SERVICE_ACTIVE
;
6295 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
6296 dwState
= SERVICE_INACTIVE
;
6298 if ((dwState
& dwServiceState
) == 0)
6303 if (*pszGroupName
== 0)
6305 if (CurrentService
->lpGroup
!= NULL
)
6310 if ((CurrentService
->lpGroup
== NULL
) ||
6311 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
6316 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
6317 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
6318 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
6320 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
6322 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
6323 dwRequiredSize
+= dwSize
;
6325 dwLastResumeCount
= CurrentService
->dwResumeCount
;
6329 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
6335 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
6336 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
6339 ServiceEntry
!= &ServiceListHead
;
6340 ServiceEntry
= ServiceEntry
->Flink
)
6342 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
6346 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
6349 dwState
= SERVICE_ACTIVE
;
6350 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
6351 dwState
= SERVICE_INACTIVE
;
6353 if ((dwState
& dwServiceState
) == 0)
6358 if (*pszGroupName
== 0)
6360 if (CurrentService
->lpGroup
!= NULL
)
6365 if ((CurrentService
->lpGroup
== NULL
) ||
6366 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
6371 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
6372 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
6373 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
6375 dwError
= ERROR_MORE_DATA
;
6378 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
6381 *lpResumeIndex
= dwLastResumeCount
;
6383 *lpServicesReturned
= dwServiceCount
;
6384 *pcbBytesNeeded
= dwRequiredSize
;
6386 /* If there was no services that matched */
6387 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
6389 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
6393 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
6394 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
6395 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
6398 for (ServiceEntry
= &lpService
->ServiceListEntry
;
6399 ServiceEntry
!= &ServiceListHead
;
6400 ServiceEntry
= ServiceEntry
->Flink
)
6402 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
6406 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
6409 dwState
= SERVICE_ACTIVE
;
6410 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
6411 dwState
= SERVICE_INACTIVE
;
6413 if ((dwState
& dwServiceState
) == 0)
6418 if (*pszGroupName
== 0)
6420 if (CurrentService
->lpGroup
!= NULL
)
6425 if ((CurrentService
->lpGroup
== NULL
) ||
6426 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
6431 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
6432 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
6433 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
6435 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
6437 /* Copy the service name */
6439 CurrentService
->lpServiceName
);
6440 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
6441 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
6443 /* Copy the display name */
6445 CurrentService
->lpDisplayName
);
6446 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
6447 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
6449 /* Copy the status information */
6450 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
6451 &CurrentService
->Status
,
6452 sizeof(SERVICE_STATUS
));
6454 /* Copy the service process ID */
6455 if ((CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
) || (CurrentService
->lpImage
== NULL
))
6456 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= 0;
6458 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->lpImage
->dwProcessId
;
6460 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
6463 dwRequiredSize
+= dwSize
;
6473 *pcbBytesNeeded
= 0;
6479 /* Unlock the service database */
6480 ScmUnlockDatabase();
6482 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
6492 handle_t BindingHandle
) /* FIXME */
6495 return ERROR_CALL_NOT_IMPLEMENTED
;
6502 RCreateServiceWOW64A(
6503 handle_t BindingHandle
,
6504 LPSTR lpServiceName
,
6505 LPSTR lpDisplayName
,
6506 DWORD dwDesiredAccess
,
6507 DWORD dwServiceType
,
6509 DWORD dwErrorControl
,
6510 LPSTR lpBinaryPathName
,
6511 LPSTR lpLoadOrderGroup
,
6513 LPBYTE lpDependencies
,
6515 LPSTR lpServiceStartName
,
6518 LPSC_RPC_HANDLE lpServiceHandle
)
6521 return ERROR_CALL_NOT_IMPLEMENTED
;
6528 RCreateServiceWOW64W(
6529 handle_t BindingHandle
,
6530 LPWSTR lpServiceName
,
6531 LPWSTR lpDisplayName
,
6532 DWORD dwDesiredAccess
,
6533 DWORD dwServiceType
,
6535 DWORD dwErrorControl
,
6536 LPWSTR lpBinaryPathName
,
6537 LPWSTR lpLoadOrderGroup
,
6539 LPBYTE lpDependencies
,
6541 LPWSTR lpServiceStartName
,
6544 LPSC_RPC_HANDLE lpServiceHandle
)
6547 return ERROR_CALL_NOT_IMPLEMENTED
;
6554 RQueryServiceTagInfo(
6555 handle_t BindingHandle
) /* FIXME */
6558 return ERROR_CALL_NOT_IMPLEMENTED
;
6565 RNotifyServiceStatusChange(
6566 SC_RPC_HANDLE hService
,
6567 SC_RPC_NOTIFY_PARAMS NotifyParams
,
6568 GUID
*pClientProcessGuid
,
6569 GUID
*pSCMProcessGuid
,
6570 PBOOL pfCreateRemoteQueue
,
6571 LPSC_NOTIFY_RPC_HANDLE phNotify
)
6574 return ERROR_CALL_NOT_IMPLEMENTED
;
6582 SC_NOTIFY_RPC_HANDLE hNotify
,
6583 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
6586 return ERROR_CALL_NOT_IMPLEMENTED
;
6594 LPSC_NOTIFY_RPC_HANDLE phNotify
,
6598 return ERROR_CALL_NOT_IMPLEMENTED
;
6606 SC_RPC_HANDLE hService
,
6611 return ERROR_CALL_NOT_IMPLEMENTED
;
6619 SC_RPC_HANDLE hService
,
6624 return ERROR_CALL_NOT_IMPLEMENTED
;
6632 handle_t BindingHandle
) /* FIXME */
6635 return ERROR_CALL_NOT_IMPLEMENTED
;
6642 RValidatePnPService(
6643 handle_t BindingHandle
) /* FIXME */
6646 return ERROR_CALL_NOT_IMPLEMENTED
;
6653 ROpenServiceStatusHandle(
6654 handle_t BindingHandle
) /* FIXME */
6657 return ERROR_CALL_NOT_IMPLEMENTED
;
6665 handle_t BindingHandle
) /* FIXME */
6668 return ERROR_CALL_NOT_IMPLEMENTED
;
6672 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
6674 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
6678 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
6680 HeapFree(GetProcessHeap(), 0, ptr
);
6684 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
6686 /* Close the handle */
6687 RCloseServiceHandle(&hSCObject
);
6691 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
6693 /* Unlock the database */
6694 RUnlockServiceDatabase(&Lock
);
6698 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)