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 ****************************************************************/
21 /* GLOBALS *****************************************************************/
23 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
24 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
25 #define INVALID_TAG 0xAABBCCDD
27 typedef struct _SCMGR_HANDLE
34 typedef struct _MANAGER_HANDLE
37 WCHAR DatabaseName
[1];
38 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
41 typedef struct _SERVICE_HANDLE
44 PSERVICE ServiceEntry
;
45 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
48 #define SC_MANAGER_READ \
49 (STANDARD_RIGHTS_READ | \
50 SC_MANAGER_QUERY_LOCK_STATUS | \
51 SC_MANAGER_ENUMERATE_SERVICE)
53 #define SC_MANAGER_WRITE \
54 (STANDARD_RIGHTS_WRITE | \
55 SC_MANAGER_MODIFY_BOOT_CONFIG | \
56 SC_MANAGER_CREATE_SERVICE)
58 #define SC_MANAGER_EXECUTE \
59 (STANDARD_RIGHTS_EXECUTE | \
61 SC_MANAGER_ENUMERATE_SERVICE | \
62 SC_MANAGER_CONNECT | \
63 SC_MANAGER_CREATE_SERVICE)
66 #define SERVICE_READ \
67 (STANDARD_RIGHTS_READ | \
68 SERVICE_INTERROGATE | \
69 SERVICE_ENUMERATE_DEPENDENTS | \
70 SERVICE_QUERY_STATUS | \
73 #define SERVICE_WRITE \
74 (STANDARD_RIGHTS_WRITE | \
75 SERVICE_CHANGE_CONFIG)
77 #define SERVICE_EXECUTE \
78 (STANDARD_RIGHTS_EXECUTE | \
79 SERVICE_USER_DEFINED_CONTROL | \
80 SERVICE_PAUSE_CONTINUE | \
84 #define TAG_ARRAY_SIZE 32
86 /* VARIABLES ***************************************************************/
88 static GENERIC_MAPPING
89 ScmManagerMapping
= {SC_MANAGER_READ
,
92 SC_MANAGER_ALL_ACCESS
};
94 static GENERIC_MAPPING
95 ScmServiceMapping
= {SERVICE_READ
,
100 DWORD g_dwServiceBits
= 0;
102 /* FUNCTIONS ***************************************************************/
105 ScmStartRpcServer(VOID
)
109 DPRINT("ScmStartRpcServer() called\n");
111 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
115 if (Status
!= RPC_S_OK
)
117 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
121 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
124 if (Status
!= RPC_S_OK
)
126 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
130 Status
= RpcServerListen(1, 20, TRUE
);
131 if (Status
!= RPC_S_OK
)
133 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
137 DPRINT("ScmStartRpcServer() done\n");
142 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
147 if (lpDatabaseName
== NULL
)
148 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
150 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
152 DPRINT("Database %S, does not exist\n", lpDatabaseName
);
153 return ERROR_DATABASE_DOES_NOT_EXIST
;
155 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
157 DPRINT("Invalid Database name %S.\n", lpDatabaseName
);
158 return ERROR_INVALID_NAME
;
161 Ptr
= HeapAlloc(GetProcessHeap(),
163 FIELD_OFFSET(MANAGER_HANDLE
, DatabaseName
[wcslen(lpDatabaseName
) + 1]));
165 return ERROR_NOT_ENOUGH_MEMORY
;
167 Ptr
->Handle
.Tag
= MANAGER_TAG
;
169 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
171 *Handle
= (SC_HANDLE
)Ptr
;
173 return ERROR_SUCCESS
;
178 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
183 Ptr
= HeapAlloc(GetProcessHeap(),
185 sizeof(SERVICE_HANDLE
));
187 return ERROR_NOT_ENOUGH_MEMORY
;
189 Ptr
->Handle
.Tag
= SERVICE_TAG
;
191 Ptr
->ServiceEntry
= lpServiceEntry
;
193 *Handle
= (SC_HANDLE
)Ptr
;
195 return ERROR_SUCCESS
;
199 static PMANAGER_HANDLE
200 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
202 PMANAGER_HANDLE pManager
= NULL
;
206 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
207 pManager
= (PMANAGER_HANDLE
)Handle
;
209 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
211 DPRINT1("Exception: Invalid Service Manager handle!\n");
219 static PSERVICE_HANDLE
220 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
222 PSERVICE_HANDLE pService
= NULL
;
226 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
227 pService
= (PSERVICE_HANDLE
)Handle
;
229 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
231 DPRINT1("Exception: Invalid Service handle!\n");
240 ScmCheckAccess(SC_HANDLE Handle
,
241 DWORD dwDesiredAccess
)
243 PMANAGER_HANDLE hMgr
;
245 hMgr
= (PMANAGER_HANDLE
)Handle
;
246 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
248 RtlMapGenericMask(&dwDesiredAccess
,
251 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
253 return ERROR_SUCCESS
;
255 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
257 RtlMapGenericMask(&dwDesiredAccess
,
260 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
262 return ERROR_SUCCESS
;
265 return ERROR_INVALID_HANDLE
;
270 ScmAssignNewTag(PSERVICE lpService
)
274 DWORD dwGroupTagCount
= 0;
275 PDWORD pdwGroupTags
= NULL
;
277 DWORD dwTagUsedBase
= 1;
278 BOOLEAN TagUsed
[TAG_ARRAY_SIZE
];
282 PLIST_ENTRY ServiceEntry
;
283 PSERVICE CurrentService
;
285 ASSERT(lpService
!= NULL
);
286 ASSERT(lpService
->lpGroup
!= NULL
);
288 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
289 L
"System\\CurrentControlSet\\Control\\GroupOrderList",
294 if (dwError
!= ERROR_SUCCESS
)
297 /* query value length */
299 dwError
= RegQueryValueExW(hKey
,
300 lpService
->lpGroup
->szGroupName
,
306 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_MORE_DATA
)
309 pdwGroupTags
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbDataSize
);
312 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
316 dwError
= RegQueryValueExW(hKey
,
317 lpService
->lpGroup
->szGroupName
,
320 (LPBYTE
)pdwGroupTags
,
323 if (dwError
!= ERROR_SUCCESS
)
326 if (cbDataSize
< sizeof(pdwGroupTags
[0]))
329 dwGroupTagCount
= min(pdwGroupTags
[0], cbDataSize
/ sizeof(pdwGroupTags
[0]) - 1);
334 /* mark all tags as unused */
335 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
338 /* mark tags in GroupOrderList as used */
339 for (i
= 1; i
<= dwGroupTagCount
; i
++)
341 nTagOffset
= pdwGroupTags
[i
] - dwTagUsedBase
;
342 if (nTagOffset
>= 0 && nTagOffset
< TAG_ARRAY_SIZE
)
343 TagUsed
[nTagOffset
] = TRUE
;
346 /* mark tags in service list as used */
347 ServiceEntry
= lpService
->ServiceListEntry
.Flink
;
348 while (ServiceEntry
!= &lpService
->ServiceListEntry
)
350 ASSERT(ServiceEntry
!= NULL
);
351 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
352 if (CurrentService
->lpGroup
== lpService
->lpGroup
)
354 nTagOffset
= CurrentService
->dwTag
- dwTagUsedBase
;
355 if (nTagOffset
>= 0 && nTagOffset
< TAG_ARRAY_SIZE
)
356 TagUsed
[nTagOffset
] = TRUE
;
359 ServiceEntry
= ServiceEntry
->Flink
;
362 /* find unused tag, if any */
363 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
367 dwFreeTag
= dwTagUsedBase
+ i
;
372 dwTagUsedBase
+= TAG_ARRAY_SIZE
;
373 } while (!dwFreeTag
);
377 HeapFree(GetProcessHeap(), 0, pdwGroupTags
);
384 lpService
->dwTag
= dwFreeTag
;
385 DPRINT("Assigning new tag %lu to service %S in group %S\n",
386 lpService
->dwTag
, lpService
->lpServiceName
, lpService
->lpGroup
->szGroupName
);
387 dwError
= ERROR_SUCCESS
;
391 DPRINT1("Failed to assign new tag to service %S, error=%lu\n",
392 lpService
->lpServiceName
, dwError
);
399 /* Create a path suitable for the bootloader out of the full path */
401 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
403 SIZE_T ServiceNameLen
, ExpandedLen
;
407 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
408 OBJECT_ATTRIBUTES ObjectAttributes
;
410 HANDLE SymbolicLinkHandle
;
412 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
415 return ERROR_INVALID_PARAMETER
;
417 *RelativeName
= NULL
;
419 ServiceNameLen
= wcslen(CanonName
);
421 /* First check, if it's already good */
422 if (ServiceNameLen
> 12 &&
423 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
425 *RelativeName
= HeapAlloc(GetProcessHeap(),
427 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
428 if (*RelativeName
== NULL
)
430 DPRINT("Error allocating memory for boot driver name!\n");
431 return ERROR_NOT_ENOUGH_MEMORY
;
435 wcscpy(*RelativeName
, CanonName
);
437 DPRINT("Bootdriver name %S\n", *RelativeName
);
438 return ERROR_SUCCESS
;
441 /* If it has %SystemRoot% prefix, substitute it to \System*/
442 if (ServiceNameLen
> 13 &&
443 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
445 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
446 *RelativeName
= HeapAlloc(GetProcessHeap(),
448 ServiceNameLen
* sizeof(WCHAR
));
450 if (*RelativeName
== NULL
)
452 DPRINT("Error allocating memory for boot driver name!\n");
453 return ERROR_NOT_ENOUGH_MEMORY
;
457 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
458 wcscat(*RelativeName
, CanonName
+ 13);
460 DPRINT("Bootdriver name %S\n", *RelativeName
);
461 return ERROR_SUCCESS
;
464 /* Get buffer size needed for expanding env strings */
465 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
469 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
470 return ERROR_INVALID_ENVIRONMENT
;
473 /* Allocate memory, since the size is known now */
474 Expanded
= HeapAlloc(GetProcessHeap(),
476 (BufferSize
+ 1) * sizeof(WCHAR
));
479 DPRINT("Error allocating memory for boot driver name!\n");
480 return ERROR_NOT_ENOUGH_MEMORY
;
484 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
487 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
488 HeapFree(GetProcessHeap(), 0, Expanded
);
489 return ERROR_NOT_ENOUGH_MEMORY
;
492 /* Convert to NT-style path */
493 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
495 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
496 return ERROR_INVALID_ENVIRONMENT
;
499 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
501 /* No need to keep the dos-path anymore */
502 HeapFree(GetProcessHeap(), 0, Expanded
);
504 /* Copy it to the allocated place */
505 Expanded
= HeapAlloc(GetProcessHeap(),
507 NtPathName
.Length
+ sizeof(UNICODE_NULL
));
510 DPRINT("Error allocating memory for boot driver name!\n");
511 RtlFreeUnicodeString(&NtPathName
);
512 return ERROR_NOT_ENOUGH_MEMORY
;
515 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
516 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
517 Expanded
[ExpandedLen
] = UNICODE_NULL
;
518 RtlFreeUnicodeString(&NtPathName
);
520 if (ServiceNameLen
> ExpandedLen
&&
521 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
523 HeapFree(GetProcessHeap(), 0, Expanded
);
525 /* Only \SystemRoot\ is missing */
526 *RelativeName
= HeapAlloc(GetProcessHeap(),
528 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
529 if (*RelativeName
== NULL
)
531 DPRINT("Error allocating memory for boot driver name!\n");
532 return ERROR_NOT_ENOUGH_MEMORY
;
535 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
536 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
538 return ERROR_SUCCESS
;
541 /* No longer need this */
542 HeapFree(GetProcessHeap(), 0, Expanded
);
544 /* The most complex case starts here */
545 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
546 InitializeObjectAttributes(&ObjectAttributes
,
548 OBJ_CASE_INSENSITIVE
,
552 /* Open this symlink */
553 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
554 if (NT_SUCCESS(Status
))
556 DPRINT("Opened symbolic link object\n");
558 RtlInitEmptyUnicodeString(&LinkTarget
, NULL
, 0);
559 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
560 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
562 /* Check if required buffer size is sane */
563 if (BufferSize
> UNICODE_STRING_MAX_BYTES
- sizeof(UNICODE_NULL
))
565 DPRINT("Too large buffer required\n");
567 NtClose(SymbolicLinkHandle
);
568 return ERROR_NOT_ENOUGH_MEMORY
;
571 /* Alloc the string */
572 LinkTarget
.Length
= (USHORT
)BufferSize
;
573 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(UNICODE_NULL
);
574 LinkTarget
.Buffer
= HeapAlloc(GetProcessHeap(),
576 LinkTarget
.MaximumLength
);
577 if (!LinkTarget
.Buffer
)
579 DPRINT("Unable to alloc buffer\n");
580 NtClose(SymbolicLinkHandle
);
581 return ERROR_NOT_ENOUGH_MEMORY
;
584 /* Do a real query now */
585 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
586 NtClose(SymbolicLinkHandle
);
587 if (NT_SUCCESS(Status
))
589 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
591 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
592 if ((ServiceNameLen
> ExpandedLen
) &&
593 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
595 *RelativeName
= HeapAlloc(GetProcessHeap(),
597 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
599 if (*RelativeName
== NULL
)
601 DPRINT("Unable to alloc buffer\n");
602 return ERROR_NOT_ENOUGH_MEMORY
;
605 /* Copy it over, substituting the first part
607 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
608 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
611 return ERROR_SUCCESS
;
615 return ERROR_INVALID_PARAMETER
;
620 DPRINT("Error, Status = %08X\n", Status
);
621 return ERROR_INVALID_PARAMETER
;
626 DPRINT("Error, Status = %08X\n", Status
);
627 NtClose(SymbolicLinkHandle
);
628 return ERROR_INVALID_PARAMETER
;
634 DPRINT("Error, Status = %08X\n", Status
);
635 return ERROR_INVALID_PARAMETER
;
641 ScmCanonDriverImagePath(DWORD dwStartType
,
642 const wchar_t *lpServiceName
,
643 wchar_t **lpCanonName
)
646 SIZE_T ServiceNameLen
;
647 UNICODE_STRING NtServiceName
;
649 const WCHAR
*SourceName
= lpServiceName
;
651 /* Calculate the length of the service's name */
652 ServiceNameLen
= wcslen(lpServiceName
);
654 /* 12 is wcslen(L"\\SystemRoot\\") */
655 if (ServiceNameLen
> 12 &&
656 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
658 /* SystemRoot prefix is already included */
659 *lpCanonName
= HeapAlloc(GetProcessHeap(),
661 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
663 if (*lpCanonName
== NULL
)
665 DPRINT("Error allocating memory for canonized service name!\n");
666 return ERROR_NOT_ENOUGH_MEMORY
;
669 /* If it's a boot-time driver, it must be systemroot relative */
670 if (dwStartType
== SERVICE_BOOT_START
)
674 wcscpy(*lpCanonName
, SourceName
);
676 DPRINT("Canonicalized name %S\n", *lpCanonName
);
680 /* Check if it has %SystemRoot% (len=13) */
681 if (ServiceNameLen
> 13 &&
682 !_wcsnicmp(L
"%SystemRoot%\\", lpServiceName
, 13))
684 /* Substitute %SystemRoot% with \\SystemRoot\\ */
685 *lpCanonName
= HeapAlloc(GetProcessHeap(),
687 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
689 if (*lpCanonName
== NULL
)
691 DPRINT("Error allocating memory for canonized service name!\n");
692 return ERROR_NOT_ENOUGH_MEMORY
;
695 /* If it's a boot-time driver, it must be systemroot relative */
696 if (dwStartType
== SERVICE_BOOT_START
)
697 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
699 wcscat(*lpCanonName
, lpServiceName
+ 13);
701 DPRINT("Canonicalized name %S\n", *lpCanonName
);
705 /* Check if it's a relative path name */
706 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
708 *lpCanonName
= HeapAlloc(GetProcessHeap(),
710 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
712 if (*lpCanonName
== NULL
)
714 DPRINT("Error allocating memory for canonized service name!\n");
715 return ERROR_NOT_ENOUGH_MEMORY
;
718 /* Just copy it over without changing */
719 wcscpy(*lpCanonName
, lpServiceName
);
724 /* It seems to be a DOS path, convert it */
725 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
727 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
728 return ERROR_INVALID_PARAMETER
;
731 *lpCanonName
= HeapAlloc(GetProcessHeap(),
733 NtServiceName
.Length
+ sizeof(WCHAR
));
735 if (*lpCanonName
== NULL
)
737 DPRINT("Error allocating memory for canonized service name!\n");
738 RtlFreeUnicodeString(&NtServiceName
);
739 return ERROR_NOT_ENOUGH_MEMORY
;
742 /* Copy the string */
743 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
745 /* The unicode string is not needed anymore */
746 RtlFreeUnicodeString(&NtServiceName
);
748 if (dwStartType
!= SERVICE_BOOT_START
)
750 DPRINT("Canonicalized name %S\n", *lpCanonName
);
754 /* The service is boot-started, so must be relative */
755 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
758 /* There is a problem, free name and return */
759 HeapFree(GetProcessHeap(), 0, *lpCanonName
);
760 DPRINT("Error converting named!\n");
764 ASSERT(RelativeName
);
766 /* Copy that string */
767 wcscpy(*lpCanonName
, RelativeName
+ 12);
769 /* Free the allocated buffer */
770 HeapFree(GetProcessHeap(), 0, RelativeName
);
772 DPRINT("Canonicalized name %S\n", *lpCanonName
);
779 /* Internal recursive function */
780 /* Need to search for every dependency on every service */
782 Int_EnumDependentServicesW(HKEY hServicesKey
,
784 DWORD dwServiceState
,
785 PSERVICE
*lpServices
,
786 LPDWORD pcbBytesNeeded
,
787 LPDWORD lpServicesReturned
)
789 DWORD dwError
= ERROR_SUCCESS
;
790 WCHAR szNameBuf
[MAX_PATH
];
791 WCHAR szValueBuf
[MAX_PATH
];
792 WCHAR
*lpszNameBuf
= szNameBuf
;
793 WCHAR
*lpszValueBuf
= szValueBuf
;
797 PSERVICE lpCurrentService
;
798 HKEY hServiceEnumKey
;
799 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
800 DWORD dwDependServiceStrPtr
= 0;
801 DWORD dwRequiredSize
= 0;
803 /* Get the number of service keys */
804 dwError
= RegQueryInfoKeyW(hServicesKey
,
816 if (dwError
!= ERROR_SUCCESS
)
818 DPRINT("ERROR! Unable to get number of services keys.\n");
822 /* Iterate the service keys to see if another service depends on the this service */
823 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
826 dwError
= RegEnumKeyExW(hServicesKey
,
834 if (dwError
!= ERROR_SUCCESS
)
837 /* Open the Service key */
838 dwError
= RegOpenKeyExW(hServicesKey
,
843 if (dwError
!= ERROR_SUCCESS
)
846 dwSize
= MAX_PATH
* sizeof(WCHAR
);
848 /* Check for the DependOnService Value */
849 dwError
= RegQueryValueExW(hServiceEnumKey
,
853 (LPBYTE
)lpszValueBuf
,
856 /* FIXME: Handle load order. */
858 /* If the service found has a DependOnService value */
859 if (dwError
== ERROR_SUCCESS
)
861 dwDependServiceStrPtr
= 0;
863 /* Can be more than one Dependencies in the DependOnService string */
864 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
866 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
868 /* Get the current enumed service pointer */
869 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
871 /* Check for valid Service */
872 if (!lpCurrentService
)
874 /* This should never happen! */
875 DPRINT("This should not happen at this point, report to Developer\n");
876 return ERROR_NOT_FOUND
;
879 /* Determine state the service is in */
880 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
881 dwCurrentServiceState
= SERVICE_INACTIVE
;
883 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
884 if ((dwCurrentServiceState
== dwServiceState
) ||
885 (dwServiceState
== SERVICE_STATE_ALL
))
887 /* Calculate the required size */
888 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
889 dwRequiredSize
+= (DWORD
)((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
890 dwRequiredSize
+= (DWORD
)((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
892 /* Add the size for service name and display name pointers */
893 dwRequiredSize
+= (2 * sizeof(PVOID
));
895 /* increase the BytesNeeded size */
896 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
898 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
901 /* Recursive call to check for its dependencies */
902 Int_EnumDependentServicesW(hServicesKey
,
909 /* If the lpServices is valid set the service pointer */
911 lpServices
[*lpServicesReturned
] = lpCurrentService
;
913 *lpServicesReturned
= *lpServicesReturned
+ 1;
917 dwDependServiceStrPtr
+= (DWORD
)(wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
920 else if (*pcbBytesNeeded
)
922 dwError
= ERROR_SUCCESS
;
925 RegCloseKey(hServiceEnumKey
);
936 LPSC_RPC_HANDLE hSCObject
)
938 PMANAGER_HANDLE hManager
;
939 PSERVICE_HANDLE hService
;
943 DWORD pcbBytesNeeded
= 0;
944 DWORD dwServicesReturned
= 0;
946 DPRINT("RCloseServiceHandle() called\n");
948 DPRINT("hSCObject = %p\n", *hSCObject
);
951 return ERROR_INVALID_HANDLE
;
953 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
954 hService
= ScmGetServiceFromHandle(*hSCObject
);
956 if (hManager
!= NULL
)
958 DPRINT("Found manager handle\n");
960 /* Make sure we don't access stale memory if someone tries to use this handle again. */
961 hManager
->Handle
.Tag
= INVALID_TAG
;
963 HeapFree(GetProcessHeap(), 0, hManager
);
968 DPRINT("RCloseServiceHandle() done\n");
969 return ERROR_SUCCESS
;
971 else if (hService
!= NULL
)
973 DPRINT("Found service handle\n");
975 /* Lock the service database exclusively */
976 ScmLockDatabaseExclusive();
978 /* Get the pointer to the service record */
979 lpService
= hService
->ServiceEntry
;
981 /* Make sure we don't access stale memory if someone tries to use this handle again. */
982 hService
->Handle
.Tag
= INVALID_TAG
;
984 /* Free the handle */
985 HeapFree(GetProcessHeap(), 0, hService
);
988 ASSERT(lpService
->dwRefCount
> 0);
990 lpService
->dwRefCount
--;
991 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
992 lpService
->dwRefCount
);
994 if (lpService
->dwRefCount
== 0)
996 /* If this service has been marked for deletion */
997 if (lpService
->bDeleted
&&
998 lpService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1000 /* Open the Services Reg key */
1001 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1002 L
"System\\CurrentControlSet\\Services",
1004 KEY_SET_VALUE
| KEY_READ
,
1006 if (dwError
!= ERROR_SUCCESS
)
1008 DPRINT("Failed to open services key\n");
1009 ScmUnlockDatabase();
1013 /* Call the internal function with NULL, just to get bytes we need */
1014 Int_EnumDependentServicesW(hServicesKey
,
1019 &dwServicesReturned
);
1021 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */
1024 DPRINT("Deletion failed due to running dependencies.\n");
1025 RegCloseKey(hServicesKey
);
1026 ScmUnlockDatabase();
1027 return ERROR_SUCCESS
;
1030 /* There are no references and no running dependencies,
1031 it is now safe to delete the service */
1033 /* Delete the Service Key */
1034 dwError
= ScmDeleteRegKey(hServicesKey
,
1035 lpService
->lpServiceName
);
1037 RegCloseKey(hServicesKey
);
1039 if (dwError
!= ERROR_SUCCESS
)
1041 DPRINT("Failed to Delete the Service Registry key\n");
1042 ScmUnlockDatabase();
1046 /* Delete the Service */
1047 ScmDeleteServiceRecord(lpService
);
1051 ScmUnlockDatabase();
1055 DPRINT("RCloseServiceHandle() done\n");
1056 return ERROR_SUCCESS
;
1059 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
1061 return ERROR_INVALID_HANDLE
;
1069 SC_RPC_HANDLE hService
,
1071 LPSERVICE_STATUS lpServiceStatus
)
1073 PSERVICE_HANDLE hSvc
;
1075 ACCESS_MASK DesiredAccess
;
1076 DWORD dwError
= ERROR_SUCCESS
;
1077 DWORD pcbBytesNeeded
= 0;
1078 DWORD dwServicesReturned
= 0;
1079 DWORD dwControlsAccepted
;
1080 DWORD dwCurrentState
;
1081 HKEY hServicesKey
= NULL
;
1082 LPCWSTR lpLogStrings
[2];
1083 WCHAR szLogBuffer
[80];
1086 DPRINT("RControlService() called\n");
1089 return ERROR_SHUTDOWN_IN_PROGRESS
;
1091 /* Check the service handle */
1092 hSvc
= ScmGetServiceFromHandle(hService
);
1095 DPRINT1("Invalid service handle!\n");
1096 return ERROR_INVALID_HANDLE
;
1099 /* Check the service entry point */
1100 lpService
= hSvc
->ServiceEntry
;
1101 if (lpService
== NULL
)
1103 DPRINT1("lpService == NULL!\n");
1104 return ERROR_INVALID_HANDLE
;
1107 /* Check access rights */
1110 case SERVICE_CONTROL_STOP
:
1111 DesiredAccess
= SERVICE_STOP
;
1114 case SERVICE_CONTROL_PAUSE
:
1115 case SERVICE_CONTROL_CONTINUE
:
1116 case SERVICE_CONTROL_PARAMCHANGE
:
1117 case SERVICE_CONTROL_NETBINDADD
:
1118 case SERVICE_CONTROL_NETBINDREMOVE
:
1119 case SERVICE_CONTROL_NETBINDENABLE
:
1120 case SERVICE_CONTROL_NETBINDDISABLE
:
1121 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
1124 case SERVICE_CONTROL_INTERROGATE
:
1125 DesiredAccess
= SERVICE_INTERROGATE
;
1129 if (dwControl
>= 128 && dwControl
<= 255)
1130 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
1132 return ERROR_INVALID_PARAMETER
;
1136 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1138 return ERROR_ACCESS_DENIED
;
1140 /* Return the current service status information */
1141 RtlCopyMemory(lpServiceStatus
,
1143 sizeof(SERVICE_STATUS
));
1145 if (dwControl
== SERVICE_CONTROL_STOP
)
1147 /* Check if the service has dependencies running as windows
1148 doesn't stop a service that does */
1150 /* Open the Services Reg key */
1151 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1152 L
"System\\CurrentControlSet\\Services",
1156 if (dwError
!= ERROR_SUCCESS
)
1158 DPRINT("Failed to open services key\n");
1162 /* Call the internal function with NULL, just to get bytes we need */
1163 Int_EnumDependentServicesW(hServicesKey
,
1168 &dwServicesReturned
);
1170 RegCloseKey(hServicesKey
);
1172 /* If pcbBytesNeeded is not zero then there are services running that
1173 are dependent on this service */
1174 if (pcbBytesNeeded
!= 0)
1176 DPRINT("Service has running dependencies. Failed to stop service.\n");
1177 return ERROR_DEPENDENT_SERVICES_RUNNING
;
1181 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1183 /* Send control code to the driver */
1184 dwError
= ScmControlDriver(lpService
,
1190 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
1191 dwCurrentState
= lpService
->Status
.dwCurrentState
;
1193 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1194 if (lpService
->lpImage
== NULL
|| dwCurrentState
== SERVICE_STOPPED
)
1195 return ERROR_SERVICE_NOT_ACTIVE
;
1197 /* Check the current state before sending a control request */
1198 switch (dwCurrentState
)
1200 case SERVICE_STOP_PENDING
:
1201 case SERVICE_STOPPED
:
1202 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1204 case SERVICE_START_PENDING
:
1207 case SERVICE_CONTROL_STOP
:
1210 case SERVICE_CONTROL_INTERROGATE
:
1211 RtlCopyMemory(lpServiceStatus
,
1213 sizeof(SERVICE_STATUS
));
1214 return ERROR_SUCCESS
;
1217 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1222 /* Check if the control code is acceptable to the service */
1225 case SERVICE_CONTROL_STOP
:
1226 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
1227 return ERROR_INVALID_SERVICE_CONTROL
;
1230 case SERVICE_CONTROL_PAUSE
:
1231 case SERVICE_CONTROL_CONTINUE
:
1232 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
1233 return ERROR_INVALID_SERVICE_CONTROL
;
1236 case SERVICE_CONTROL_PARAMCHANGE
:
1237 if ((dwControlsAccepted
& SERVICE_ACCEPT_PARAMCHANGE
) == 0)
1238 return ERROR_INVALID_SERVICE_CONTROL
;
1241 case SERVICE_CONTROL_NETBINDADD
:
1242 case SERVICE_CONTROL_NETBINDREMOVE
:
1243 case SERVICE_CONTROL_NETBINDENABLE
:
1244 case SERVICE_CONTROL_NETBINDDISABLE
:
1245 if ((dwControlsAccepted
& SERVICE_ACCEPT_NETBINDCHANGE
) == 0)
1246 return ERROR_INVALID_SERVICE_CONTROL
;
1250 /* Send control code to the service */
1251 dwError
= ScmControlService(lpService
->lpImage
->hControlPipe
,
1252 lpService
->lpServiceName
,
1253 (SERVICE_STATUS_HANDLE
)lpService
,
1256 /* Return service status information */
1257 RtlCopyMemory(lpServiceStatus
,
1259 sizeof(SERVICE_STATUS
));
1262 if (dwError
== ERROR_SUCCESS
)
1264 if (dwControl
== SERVICE_CONTROL_STOP
||
1265 dwControl
== SERVICE_CONTROL_PAUSE
||
1266 dwControl
== SERVICE_CONTROL_CONTINUE
)
1268 /* Log a successful send control */
1272 case SERVICE_CONTROL_STOP
:
1273 uID
= IDS_SERVICE_STOP
;
1276 case SERVICE_CONTROL_PAUSE
:
1277 uID
= IDS_SERVICE_PAUSE
;
1280 case SERVICE_CONTROL_CONTINUE
:
1281 uID
= IDS_SERVICE_RESUME
;
1284 LoadStringW(GetModuleHandle(NULL
), uID
, szLogBuffer
, ARRAYSIZE(szLogBuffer
));
1286 lpLogStrings
[0] = lpService
->lpDisplayName
;
1287 lpLogStrings
[1] = szLogBuffer
;
1289 ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS
,
1290 EVENTLOG_INFORMATION_TYPE
,
1304 SC_RPC_HANDLE hService
)
1306 PSERVICE_HANDLE hSvc
;
1310 DPRINT("RDeleteService() called\n");
1313 return ERROR_SHUTDOWN_IN_PROGRESS
;
1315 hSvc
= ScmGetServiceFromHandle(hService
);
1318 DPRINT1("Invalid service handle!\n");
1319 return ERROR_INVALID_HANDLE
;
1322 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1324 return ERROR_ACCESS_DENIED
;
1326 lpService
= hSvc
->ServiceEntry
;
1327 if (lpService
== NULL
)
1329 DPRINT("lpService == NULL!\n");
1330 return ERROR_INVALID_HANDLE
;
1333 /* Lock the service database exclusively */
1334 ScmLockDatabaseExclusive();
1336 if (lpService
->bDeleted
)
1338 DPRINT("The service has already been marked for delete!\n");
1339 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1343 /* Mark service for delete */
1344 lpService
->bDeleted
= TRUE
;
1346 dwError
= ScmMarkServiceForDelete(lpService
);
1349 /* Unlock the service database */
1350 ScmUnlockDatabase();
1352 DPRINT("RDeleteService() done\n");
1361 RLockServiceDatabase(
1362 SC_RPC_HANDLE hSCManager
,
1363 LPSC_RPC_LOCK lpLock
)
1365 PMANAGER_HANDLE hMgr
;
1367 DPRINT("RLockServiceDatabase() called\n");
1371 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
1374 DPRINT1("Invalid service manager handle!\n");
1375 return ERROR_INVALID_HANDLE
;
1378 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
1380 return ERROR_ACCESS_DENIED
;
1382 return ScmAcquireServiceStartLock(FALSE
, lpLock
);
1389 RQueryServiceObjectSecurity(
1390 SC_RPC_HANDLE hService
,
1391 SECURITY_INFORMATION dwSecurityInformation
,
1392 LPBYTE lpSecurityDescriptor
,
1394 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1396 PSERVICE_HANDLE hSvc
;
1398 ULONG DesiredAccess
= 0;
1400 DWORD dwBytesNeeded
;
1403 DPRINT("RQueryServiceObjectSecurity() called\n");
1405 hSvc
= ScmGetServiceFromHandle(hService
);
1408 DPRINT1("Invalid service handle!\n");
1409 return ERROR_INVALID_HANDLE
;
1412 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1413 GROUP_SECURITY_INFORMATION
|
1414 OWNER_SECURITY_INFORMATION
))
1415 DesiredAccess
|= READ_CONTROL
;
1417 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1418 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1420 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1423 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1424 return ERROR_ACCESS_DENIED
;
1427 lpService
= hSvc
->ServiceEntry
;
1428 if (lpService
== NULL
)
1430 DPRINT("lpService == NULL!\n");
1431 return ERROR_INVALID_HANDLE
;
1434 /* Lock the service database */
1435 ScmLockDatabaseShared();
1437 /* Retrieve the security descriptor */
1438 Status
= RtlQuerySecurityObject(lpService
->pSecurityDescriptor
,
1439 dwSecurityInformation
,
1440 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1444 /* Unlock the service database */
1445 ScmUnlockDatabase();
1447 if (NT_SUCCESS(Status
))
1449 *pcbBytesNeeded
= dwBytesNeeded
;
1450 dwError
= STATUS_SUCCESS
;
1452 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1454 *pcbBytesNeeded
= dwBytesNeeded
;
1455 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1457 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1459 dwError
= ERROR_GEN_FAILURE
;
1463 dwError
= RtlNtStatusToDosError(Status
);
1473 RSetServiceObjectSecurity(
1474 SC_RPC_HANDLE hService
,
1475 DWORD dwSecurityInformation
,
1476 LPBYTE lpSecurityDescriptor
,
1477 DWORD dwSecurityDescriptorSize
)
1479 PSERVICE_HANDLE hSvc
;
1481 ACCESS_MASK DesiredAccess
= 0;
1482 HANDLE hToken
= NULL
;
1483 HKEY hServiceKey
= NULL
;
1484 BOOL bDatabaseLocked
= FALSE
;
1488 DPRINT("RSetServiceObjectSecurity() called\n");
1490 hSvc
= ScmGetServiceFromHandle(hService
);
1493 DPRINT1("Invalid service handle!\n");
1494 return ERROR_INVALID_HANDLE
;
1497 if (dwSecurityInformation
== 0 ||
1498 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1499 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1500 return ERROR_INVALID_PARAMETER
;
1502 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1503 return ERROR_INVALID_PARAMETER
;
1505 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1506 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1508 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1509 DesiredAccess
|= WRITE_DAC
;
1511 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1512 DesiredAccess
|= WRITE_OWNER
;
1514 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1515 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1516 return ERROR_INVALID_PARAMETER
;
1518 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1519 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1520 return ERROR_INVALID_PARAMETER
;
1522 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1525 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1526 return ERROR_ACCESS_DENIED
;
1529 lpService
= hSvc
->ServiceEntry
;
1530 if (lpService
== NULL
)
1532 DPRINT1("lpService == NULL!\n");
1533 return ERROR_INVALID_HANDLE
;
1536 if (lpService
->bDeleted
)
1537 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1540 RpcImpersonateClient(NULL
);
1542 Status
= NtOpenThreadToken(NtCurrentThread(),
1546 if (!NT_SUCCESS(Status
))
1547 return RtlNtStatusToDosError(Status
);
1552 /* Build the new security descriptor */
1553 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1554 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1555 &lpService
->pSecurityDescriptor
,
1558 if (!NT_SUCCESS(Status
))
1560 dwError
= RtlNtStatusToDosError(Status
);
1564 /* Lock the service database exclusive */
1565 ScmLockDatabaseExclusive();
1566 bDatabaseLocked
= TRUE
;
1568 /* Open the service key */
1569 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1570 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1572 if (dwError
!= ERROR_SUCCESS
)
1575 /* Store the new security descriptor */
1576 dwError
= ScmWriteSecurityDescriptor(hServiceKey
,
1577 lpService
->pSecurityDescriptor
);
1579 RegFlushKey(hServiceKey
);
1582 if (hServiceKey
!= NULL
)
1583 RegCloseKey(hServiceKey
);
1585 /* Unlock service database */
1586 if (bDatabaseLocked
== TRUE
)
1587 ScmUnlockDatabase();
1592 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1601 RQueryServiceStatus(
1602 SC_RPC_HANDLE hService
,
1603 LPSERVICE_STATUS lpServiceStatus
)
1605 PSERVICE_HANDLE hSvc
;
1608 DPRINT("RQueryServiceStatus() called\n");
1611 return ERROR_SHUTDOWN_IN_PROGRESS
;
1613 hSvc
= ScmGetServiceFromHandle(hService
);
1616 DPRINT1("Invalid service handle!\n");
1617 return ERROR_INVALID_HANDLE
;
1620 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1621 SERVICE_QUERY_STATUS
))
1623 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1624 return ERROR_ACCESS_DENIED
;
1627 lpService
= hSvc
->ServiceEntry
;
1628 if (lpService
== NULL
)
1630 DPRINT("lpService == NULL!\n");
1631 return ERROR_INVALID_HANDLE
;
1634 /* Lock the service database shared */
1635 ScmLockDatabaseShared();
1637 /* Return service status information */
1638 RtlCopyMemory(lpServiceStatus
,
1640 sizeof(SERVICE_STATUS
));
1642 /* Unlock the service database */
1643 ScmUnlockDatabase();
1645 return ERROR_SUCCESS
;
1650 ScmIsValidServiceState(DWORD dwCurrentState
)
1652 switch (dwCurrentState
)
1654 case SERVICE_STOPPED
:
1655 case SERVICE_START_PENDING
:
1656 case SERVICE_STOP_PENDING
:
1657 case SERVICE_RUNNING
:
1658 case SERVICE_CONTINUE_PENDING
:
1659 case SERVICE_PAUSE_PENDING
:
1660 case SERVICE_PAUSED
:
1673 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1674 LPSERVICE_STATUS lpServiceStatus
)
1677 DWORD dwPreviousState
;
1678 DWORD dwPreviousType
;
1679 LPCWSTR lpLogStrings
[2];
1680 WCHAR szLogBuffer
[80];
1683 DPRINT("RSetServiceStatus() called\n");
1684 DPRINT("hServiceStatus = %lu\n", hServiceStatus
);
1685 DPRINT("dwServiceType = 0x%lx\n", lpServiceStatus
->dwServiceType
);
1686 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1687 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1688 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1689 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1690 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1691 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1693 if (hServiceStatus
== 0)
1695 DPRINT("hServiceStatus == NULL!\n");
1696 return ERROR_INVALID_HANDLE
;
1699 lpService
= (PSERVICE
)hServiceStatus
;
1701 /* Check current state */
1702 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1704 DPRINT("Invalid service state!\n");
1705 return ERROR_INVALID_DATA
;
1708 /* Check service type */
1709 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1710 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1712 DPRINT("Invalid service type!\n");
1713 return ERROR_INVALID_DATA
;
1716 /* Check accepted controls */
1717 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1719 DPRINT("Invalid controls accepted!\n");
1720 return ERROR_INVALID_DATA
;
1723 /* Set the wait hint and check point only if the service is in a pending state,
1724 otherwise they should be 0 */
1725 if (lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
||
1726 lpServiceStatus
->dwCurrentState
== SERVICE_PAUSED
||
1727 lpServiceStatus
->dwCurrentState
== SERVICE_RUNNING
)
1729 lpServiceStatus
->dwWaitHint
= 0;
1730 lpServiceStatus
->dwCheckPoint
= 0;
1733 /* Lock the service database exclusively */
1734 ScmLockDatabaseExclusive();
1736 /* Save the current service state */
1737 dwPreviousState
= lpService
->Status
.dwCurrentState
;
1739 /* Save the current service type */
1740 dwPreviousType
= lpService
->Status
.dwServiceType
;
1742 /* Update the service status */
1743 RtlCopyMemory(&lpService
->Status
,
1745 sizeof(SERVICE_STATUS
));
1747 /* Restore the previous service type */
1748 lpService
->Status
.dwServiceType
= dwPreviousType
;
1750 /* Dereference a stopped service */
1751 if ((lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1752 (lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
))
1754 /* Decrement the image run counter */
1755 lpService
->lpImage
->dwImageRunCount
--;
1757 /* If we just stopped the last running service... */
1758 if (lpService
->lpImage
->dwImageRunCount
== 0)
1760 /* Stop the dispatcher thread */
1761 ScmControlService(lpService
->lpImage
->hControlPipe
,
1763 (SERVICE_STATUS_HANDLE
)lpService
,
1764 SERVICE_CONTROL_STOP
);
1766 /* Remove the service image */
1767 ScmRemoveServiceImage(lpService
->lpImage
);
1768 lpService
->lpImage
= NULL
;
1772 /* Unlock the service database */
1773 ScmUnlockDatabase();
1775 if ((lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
) &&
1776 (dwPreviousState
!= SERVICE_STOPPED
) &&
1777 (lpServiceStatus
->dwWin32ExitCode
!= ERROR_SUCCESS
))
1779 /* Log a failed service stop */
1780 StringCchPrintfW(szLogBuffer
, ARRAYSIZE(szLogBuffer
),
1781 L
"%lu", lpServiceStatus
->dwWin32ExitCode
);
1782 lpLogStrings
[0] = lpService
->lpDisplayName
;
1783 lpLogStrings
[1] = szLogBuffer
;
1785 ScmLogEvent(EVENT_SERVICE_EXIT_FAILED
,
1786 EVENTLOG_ERROR_TYPE
,
1790 else if (lpServiceStatus
->dwCurrentState
!= dwPreviousState
&&
1791 (lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
||
1792 lpServiceStatus
->dwCurrentState
== SERVICE_RUNNING
||
1793 lpServiceStatus
->dwCurrentState
== SERVICE_PAUSED
))
1795 /* Log a successful service status change */
1796 switch(lpServiceStatus
->dwCurrentState
)
1798 case SERVICE_STOPPED
:
1799 uID
= IDS_SERVICE_STOPPED
;
1802 case SERVICE_RUNNING
:
1803 uID
= IDS_SERVICE_RUNNING
;
1806 case SERVICE_PAUSED
:
1807 uID
= IDS_SERVICE_PAUSED
;
1811 LoadStringW(GetModuleHandle(NULL
), uID
, szLogBuffer
, ARRAYSIZE(szLogBuffer
));
1812 lpLogStrings
[0] = lpService
->lpDisplayName
;
1813 lpLogStrings
[1] = szLogBuffer
;
1815 ScmLogEvent(EVENT_SERVICE_STATUS_SUCCESS
,
1816 EVENTLOG_INFORMATION_TYPE
,
1821 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1822 DPRINT("RSetServiceStatus() done\n");
1824 return ERROR_SUCCESS
;
1831 RUnlockServiceDatabase(
1834 DPRINT("RUnlockServiceDatabase(%p)\n", Lock
);
1835 return ScmReleaseServiceStartLock(Lock
);
1842 RNotifyBootConfigStatus(
1843 SVCCTL_HANDLEW lpMachineName
,
1844 DWORD BootAcceptable
)
1846 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1847 return ERROR_SUCCESS
;
1850 // return ERROR_CALL_NOT_IMPLEMENTED;
1857 RI_ScSetServiceBitsW(
1858 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1859 DWORD dwServiceBits
,
1861 int bUpdateImmediately
,
1866 DPRINT("RI_ScSetServiceBitsW(%p %lx %d %d %S)\n",
1867 hServiceStatus
, dwServiceBits
, bSetBitsOn
,
1868 bUpdateImmediately
, lpString
);
1871 return ERROR_SHUTDOWN_IN_PROGRESS
;
1873 if (lpString
!= NULL
)
1874 return ERROR_INVALID_PARAMETER
;
1876 if (hServiceStatus
== 0)
1878 DPRINT("hServiceStatus == NULL!\n");
1879 return ERROR_INVALID_HANDLE
;
1882 // FIXME: Validate the status handle
1883 pService
= (PSERVICE
)hServiceStatus
;
1887 DPRINT("Old service bits: %08lx\n", pService
->dwServiceBits
);
1888 DPRINT("Old global service bits: %08lx\n", g_dwServiceBits
);
1889 pService
->dwServiceBits
|= dwServiceBits
;
1890 g_dwServiceBits
|= dwServiceBits
;
1891 DPRINT("New service bits: %08lx\n", pService
->dwServiceBits
);
1892 DPRINT("New global service bits: %08lx\n", g_dwServiceBits
);
1896 DPRINT("Old service bits: %08lx\n", pService
->dwServiceBits
);
1897 DPRINT("Old global service bits: %08lx\n", g_dwServiceBits
);
1898 pService
->dwServiceBits
&= ~dwServiceBits
;
1899 g_dwServiceBits
&= ~dwServiceBits
;
1900 DPRINT("New service bits: %08lx\n", pService
->dwServiceBits
);
1901 DPRINT("New global service bits: %08lx\n", g_dwServiceBits
);
1904 return ERROR_SUCCESS
;
1911 RChangeServiceConfigW(
1912 SC_RPC_HANDLE hService
,
1913 DWORD dwServiceType
,
1915 DWORD dwErrorControl
,
1916 LPWSTR lpBinaryPathName
,
1917 LPWSTR lpLoadOrderGroup
,
1919 LPBYTE lpDependencies
,
1921 LPWSTR lpServiceStartName
,
1924 LPWSTR lpDisplayName
)
1926 DWORD dwError
= ERROR_SUCCESS
;
1927 PSERVICE_HANDLE hSvc
;
1928 PSERVICE lpService
= NULL
;
1929 HKEY hServiceKey
= NULL
;
1930 LPWSTR lpDisplayNameW
= NULL
;
1931 LPWSTR lpImagePathW
= NULL
;
1933 DPRINT("RChangeServiceConfigW() called\n");
1934 DPRINT("dwServiceType = 0x%lx\n", dwServiceType
);
1935 DPRINT("dwStartType = %lu\n", dwStartType
);
1936 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1937 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1938 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1939 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1942 return ERROR_SHUTDOWN_IN_PROGRESS
;
1944 hSvc
= ScmGetServiceFromHandle(hService
);
1947 DPRINT1("Invalid service handle!\n");
1948 return ERROR_INVALID_HANDLE
;
1951 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1952 SERVICE_CHANGE_CONFIG
))
1954 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1955 return ERROR_ACCESS_DENIED
;
1958 /* Check for invalid service type value */
1959 if ((dwServiceType
!= SERVICE_NO_CHANGE
) &&
1960 (dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
1961 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
1962 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
1963 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
1964 return ERROR_INVALID_PARAMETER
;
1966 /* Check for invalid start type value */
1967 if ((dwStartType
!= SERVICE_NO_CHANGE
) &&
1968 (dwStartType
!= SERVICE_BOOT_START
) &&
1969 (dwStartType
!= SERVICE_SYSTEM_START
) &&
1970 (dwStartType
!= SERVICE_AUTO_START
) &&
1971 (dwStartType
!= SERVICE_DEMAND_START
) &&
1972 (dwStartType
!= SERVICE_DISABLED
))
1973 return ERROR_INVALID_PARAMETER
;
1975 /* Only drivers can be boot start or system start services */
1976 if ((dwStartType
== SERVICE_BOOT_START
) ||
1977 (dwStartType
== SERVICE_SYSTEM_START
))
1979 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
1980 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
1981 return ERROR_INVALID_PARAMETER
;
1984 /* Check for invalid error control value */
1985 if ((dwErrorControl
!= SERVICE_NO_CHANGE
) &&
1986 (dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
1987 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
1988 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
1989 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
1990 return ERROR_INVALID_PARAMETER
;
1992 lpService
= hSvc
->ServiceEntry
;
1993 if (lpService
== NULL
)
1995 DPRINT("lpService == NULL!\n");
1996 return ERROR_INVALID_HANDLE
;
1999 /* Lock the service database exclusively */
2000 ScmLockDatabaseExclusive();
2002 if (lpService
->bDeleted
)
2004 DPRINT("The service has already been marked for delete!\n");
2005 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
2009 /* Open the service key */
2010 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2013 if (dwError
!= ERROR_SUCCESS
)
2016 /* Write service data to the registry */
2017 /* Set the display name */
2018 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2020 RegSetValueExW(hServiceKey
,
2024 (LPBYTE
)lpDisplayName
,
2025 (DWORD
)((wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
)));
2027 /* Update the display name */
2028 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2030 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2031 if (lpDisplayNameW
== NULL
)
2033 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2037 wcscpy(lpDisplayNameW
, lpDisplayName
);
2038 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
2039 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2041 lpService
->lpDisplayName
= lpDisplayNameW
;
2044 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2046 /* Set the service type */
2047 dwError
= RegSetValueExW(hServiceKey
,
2051 (LPBYTE
)&dwServiceType
,
2053 if (dwError
!= ERROR_SUCCESS
)
2056 lpService
->Status
.dwServiceType
= dwServiceType
;
2059 if (dwStartType
!= SERVICE_NO_CHANGE
)
2061 /* Set the start value */
2062 dwError
= RegSetValueExW(hServiceKey
,
2066 (LPBYTE
)&dwStartType
,
2068 if (dwError
!= ERROR_SUCCESS
)
2071 lpService
->dwStartType
= dwStartType
;
2074 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
2076 /* Set the error control value */
2077 dwError
= RegSetValueExW(hServiceKey
,
2081 (LPBYTE
)&dwErrorControl
,
2083 if (dwError
!= ERROR_SUCCESS
)
2086 lpService
->dwErrorControl
= dwErrorControl
;
2089 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2091 /* Set the image path */
2092 lpImagePathW
= lpBinaryPathName
;
2094 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
2096 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
2100 if (dwError
!= ERROR_SUCCESS
)
2104 dwError
= RegSetValueExW(hServiceKey
,
2108 (LPBYTE
)lpImagePathW
,
2109 (DWORD
)((wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
)));
2111 if (lpImagePathW
!= lpBinaryPathName
)
2112 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
2114 if (dwError
!= ERROR_SUCCESS
)
2118 /* Set the group name */
2119 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2121 dwError
= RegSetValueExW(hServiceKey
,
2125 (LPBYTE
)lpLoadOrderGroup
,
2126 (DWORD
)((wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
)));
2127 if (dwError
!= ERROR_SUCCESS
)
2130 dwError
= ScmSetServiceGroup(lpService
,
2132 if (dwError
!= ERROR_SUCCESS
)
2137 if (lpdwTagId
!= NULL
)
2139 dwError
= ScmAssignNewTag(lpService
);
2140 if (dwError
!= ERROR_SUCCESS
)
2143 dwError
= RegSetValueExW(hServiceKey
,
2147 (LPBYTE
)&lpService
->dwTag
,
2149 if (dwError
!= ERROR_SUCCESS
)
2152 *lpdwTagId
= lpService
->dwTag
;
2155 /* Write dependencies */
2156 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2158 dwError
= ScmWriteDependencies(hServiceKey
,
2159 (LPWSTR
)lpDependencies
,
2161 if (dwError
!= ERROR_SUCCESS
)
2165 if (lpPassword
!= NULL
)
2167 if (wcslen((LPWSTR
)lpPassword
) != 0)
2169 /* FIXME: Decrypt the password */
2171 /* Write the password */
2172 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
2173 (LPCWSTR
)lpPassword
);
2174 if (dwError
!= ERROR_SUCCESS
)
2179 /* Delete the password */
2180 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
2182 if (dwError
== ERROR_FILE_NOT_FOUND
)
2183 dwError
= ERROR_SUCCESS
;
2185 if (dwError
!= ERROR_SUCCESS
)
2191 if (hServiceKey
!= NULL
)
2192 RegCloseKey(hServiceKey
);
2194 /* Unlock the service database */
2195 ScmUnlockDatabase();
2197 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
2207 SC_RPC_HANDLE hSCManager
,
2208 LPCWSTR lpServiceName
,
2209 LPCWSTR lpDisplayName
,
2210 DWORD dwDesiredAccess
,
2211 DWORD dwServiceType
,
2213 DWORD dwErrorControl
,
2214 LPCWSTR lpBinaryPathName
,
2215 LPCWSTR lpLoadOrderGroup
,
2217 LPBYTE lpDependencies
,
2219 LPCWSTR lpServiceStartName
,
2222 LPSC_RPC_HANDLE lpServiceHandle
)
2224 PMANAGER_HANDLE hManager
;
2225 DWORD dwError
= ERROR_SUCCESS
;
2226 PSERVICE lpService
= NULL
;
2227 SC_HANDLE hServiceHandle
= NULL
;
2228 LPWSTR lpImagePath
= NULL
;
2229 HKEY hServiceKey
= NULL
;
2230 LPWSTR lpObjectName
;
2232 DPRINT("RCreateServiceW() called\n");
2233 DPRINT("lpServiceName = %S\n", lpServiceName
);
2234 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
2235 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
2236 DPRINT("dwServiceType = 0x%lx\n", dwServiceType
);
2237 DPRINT("dwStartType = %lu\n", dwStartType
);
2238 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2239 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
2240 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
2241 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
2244 return ERROR_SHUTDOWN_IN_PROGRESS
;
2246 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2247 if (hManager
== NULL
)
2249 DPRINT1("Invalid service manager handle!\n");
2250 return ERROR_INVALID_HANDLE
;
2253 /* Check access rights */
2254 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2255 SC_MANAGER_CREATE_SERVICE
))
2257 DPRINT("Insufficient access rights! 0x%lx\n",
2258 hManager
->Handle
.DesiredAccess
);
2259 return ERROR_ACCESS_DENIED
;
2262 if (wcslen(lpServiceName
) == 0)
2264 return ERROR_INVALID_NAME
;
2267 if (wcslen(lpBinaryPathName
) == 0)
2269 return ERROR_INVALID_PARAMETER
;
2272 /* Check for invalid service type value */
2273 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2274 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2275 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2276 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2277 return ERROR_INVALID_PARAMETER
;
2279 /* Check for invalid start type value */
2280 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2281 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2282 (dwStartType
!= SERVICE_AUTO_START
) &&
2283 (dwStartType
!= SERVICE_DEMAND_START
) &&
2284 (dwStartType
!= SERVICE_DISABLED
))
2285 return ERROR_INVALID_PARAMETER
;
2287 /* Only drivers can be boot start or system start services */
2288 if ((dwStartType
== SERVICE_BOOT_START
) ||
2289 (dwStartType
== SERVICE_SYSTEM_START
))
2291 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2292 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2293 return ERROR_INVALID_PARAMETER
;
2296 /* Check for invalid error control value */
2297 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2298 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2299 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2300 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2301 return ERROR_INVALID_PARAMETER
;
2303 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2304 (lpServiceStartName
))
2306 /* We allow LocalSystem to run interactive. */
2307 if (wcsicmp(lpServiceStartName
, L
"LocalSystem"))
2309 return ERROR_INVALID_PARAMETER
;
2313 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2315 return ERROR_INVALID_PARAMETER
;
2318 /* Lock the service database exclusively */
2319 ScmLockDatabaseExclusive();
2321 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2324 /* Unlock the service database */
2325 ScmUnlockDatabase();
2327 /* Check if it is marked for deletion */
2328 if (lpService
->bDeleted
)
2329 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2331 /* Return Error exist */
2332 return ERROR_SERVICE_EXISTS
;
2335 if (lpDisplayName
!= NULL
&&
2336 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2338 /* Unlock the service database */
2339 ScmUnlockDatabase();
2341 return ERROR_DUPLICATE_SERVICE_NAME
;
2344 if (dwServiceType
& SERVICE_DRIVER
)
2346 dwError
= ScmCanonDriverImagePath(dwStartType
,
2349 if (dwError
!= ERROR_SUCCESS
)
2354 if (dwStartType
== SERVICE_BOOT_START
||
2355 dwStartType
== SERVICE_SYSTEM_START
)
2357 /* Unlock the service database */
2358 ScmUnlockDatabase();
2360 return ERROR_INVALID_PARAMETER
;
2364 /* Allocate a new service entry */
2365 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2369 if (dwError
!= ERROR_SUCCESS
)
2372 /* Fill the new service entry */
2373 lpService
->dwErrorControl
= dwErrorControl
;
2375 /* Fill the display name */
2376 if (lpDisplayName
!= NULL
&&
2377 *lpDisplayName
!= 0 &&
2378 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2380 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(),
2382 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2383 if (lpService
->lpDisplayName
== NULL
)
2385 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2388 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2391 /* Assign the service to a group */
2392 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2394 dwError
= ScmSetServiceGroup(lpService
,
2396 if (dwError
!= ERROR_SUCCESS
)
2400 /* Assign a new tag */
2401 if (lpdwTagId
!= NULL
)
2403 dwError
= ScmAssignNewTag(lpService
);
2404 if (dwError
!= ERROR_SUCCESS
)
2408 /* Assign the default security descriptor */
2409 if (dwServiceType
& SERVICE_WIN32
)
2411 dwError
= ScmCreateDefaultServiceSD(&lpService
->pSecurityDescriptor
);
2412 if (dwError
!= ERROR_SUCCESS
)
2416 /* Write service data to the registry */
2417 /* Create the service key */
2418 dwError
= ScmCreateServiceKey(lpServiceName
,
2421 if (dwError
!= ERROR_SUCCESS
)
2424 /* Set the display name */
2425 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2427 RegSetValueExW(hServiceKey
,
2431 (LPBYTE
)lpDisplayName
,
2432 (DWORD
)((wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
)));
2435 /* Set the service type */
2436 dwError
= RegSetValueExW(hServiceKey
,
2440 (LPBYTE
)&dwServiceType
,
2442 if (dwError
!= ERROR_SUCCESS
)
2445 /* Set the start value */
2446 dwError
= RegSetValueExW(hServiceKey
,
2450 (LPBYTE
)&dwStartType
,
2452 if (dwError
!= ERROR_SUCCESS
)
2455 /* Set the error control value */
2456 dwError
= RegSetValueExW(hServiceKey
,
2460 (LPBYTE
)&dwErrorControl
,
2462 if (dwError
!= ERROR_SUCCESS
)
2465 /* Set the image path */
2466 if (dwServiceType
& SERVICE_WIN32
)
2468 dwError
= RegSetValueExW(hServiceKey
,
2472 (LPBYTE
)lpBinaryPathName
,
2473 (DWORD
)((wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
)));
2474 if (dwError
!= ERROR_SUCCESS
)
2477 else if (dwServiceType
& SERVICE_DRIVER
)
2479 dwError
= RegSetValueExW(hServiceKey
,
2483 (LPBYTE
)lpImagePath
,
2484 (DWORD
)((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
)));
2485 if (dwError
!= ERROR_SUCCESS
)
2489 /* Set the group name */
2490 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2492 dwError
= RegSetValueExW(hServiceKey
,
2496 (LPBYTE
)lpLoadOrderGroup
,
2497 (DWORD
)((wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
)));
2498 if (dwError
!= ERROR_SUCCESS
)
2502 /* Set the service tag */
2503 if (lpdwTagId
!= NULL
)
2505 dwError
= RegSetValueExW(hServiceKey
,
2509 (LPBYTE
)&lpService
->dwTag
,
2511 if (dwError
!= ERROR_SUCCESS
)
2515 /* Write dependencies */
2516 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2518 dwError
= ScmWriteDependencies(hServiceKey
,
2519 (LPCWSTR
)lpDependencies
,
2521 if (dwError
!= ERROR_SUCCESS
)
2525 /* Start name and password are only used by Win32 services */
2526 if (dwServiceType
& SERVICE_WIN32
)
2528 /* Write service start name */
2529 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2530 dwError
= RegSetValueExW(hServiceKey
,
2534 (LPBYTE
)lpObjectName
,
2535 (DWORD
)((wcslen(lpObjectName
) + 1) * sizeof(WCHAR
)));
2536 if (dwError
!= ERROR_SUCCESS
)
2539 if (lpPassword
!= NULL
&& wcslen((LPWSTR
)lpPassword
) != 0)
2541 /* FIXME: Decrypt the password */
2543 /* Write the password */
2544 dwError
= ScmSetServicePassword(lpServiceName
,
2545 (LPCWSTR
)lpPassword
);
2546 if (dwError
!= ERROR_SUCCESS
)
2550 /* Write the security descriptor */
2551 dwError
= ScmWriteSecurityDescriptor(hServiceKey
,
2552 lpService
->pSecurityDescriptor
);
2553 if (dwError
!= ERROR_SUCCESS
)
2557 dwError
= ScmCreateServiceHandle(lpService
,
2559 if (dwError
!= ERROR_SUCCESS
)
2562 dwError
= ScmCheckAccess(hServiceHandle
,
2564 if (dwError
!= ERROR_SUCCESS
)
2567 lpService
->dwRefCount
= 1;
2568 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2571 /* Unlock the service database */
2572 ScmUnlockDatabase();
2574 if (hServiceKey
!= NULL
)
2575 RegCloseKey(hServiceKey
);
2577 if (dwError
== ERROR_SUCCESS
)
2579 DPRINT("hService %p\n", hServiceHandle
);
2580 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2582 if (lpdwTagId
!= NULL
)
2583 *lpdwTagId
= lpService
->dwTag
;
2587 if (lpService
!= NULL
&&
2588 lpService
->lpServiceName
!= NULL
)
2590 /* Release the display name buffer */
2591 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2596 /* Remove the service handle */
2597 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2600 if (lpService
!= NULL
)
2602 /* FIXME: remove the service entry */
2606 if (lpImagePath
!= NULL
)
2607 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2609 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2618 REnumDependentServicesW(
2619 SC_RPC_HANDLE hService
,
2620 DWORD dwServiceState
,
2623 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2624 LPBOUNDED_DWORD_256K lpServicesReturned
)
2626 DWORD dwError
= ERROR_SUCCESS
;
2627 DWORD dwServicesReturned
= 0;
2628 DWORD dwServiceCount
;
2629 HKEY hServicesKey
= NULL
;
2630 PSERVICE_HANDLE hSvc
;
2631 PSERVICE lpService
= NULL
;
2632 PSERVICE
*lpServicesArray
= NULL
;
2633 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2636 *pcbBytesNeeded
= 0;
2637 *lpServicesReturned
= 0;
2639 DPRINT("REnumDependentServicesW() called\n");
2641 hSvc
= ScmGetServiceFromHandle(hService
);
2644 DPRINT1("Invalid service handle!\n");
2645 return ERROR_INVALID_HANDLE
;
2648 lpService
= hSvc
->ServiceEntry
;
2650 /* Check access rights */
2651 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2652 SC_MANAGER_ENUMERATE_SERVICE
))
2654 DPRINT("Insufficient access rights! 0x%lx\n",
2655 hSvc
->Handle
.DesiredAccess
);
2656 return ERROR_ACCESS_DENIED
;
2659 /* Open the Services Reg key */
2660 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2661 L
"System\\CurrentControlSet\\Services",
2665 if (dwError
!= ERROR_SUCCESS
)
2668 /* First determine the bytes needed and get the number of dependent services */
2669 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2674 &dwServicesReturned
);
2675 if (dwError
!= ERROR_SUCCESS
)
2678 /* If buffer size is less than the bytes needed or pointer is null */
2679 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2681 dwError
= ERROR_MORE_DATA
;
2685 /* Allocate memory for array of service pointers */
2686 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2688 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2689 if (!lpServicesArray
)
2691 DPRINT1("Could not allocate a buffer!!\n");
2692 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2696 dwServicesReturned
= 0;
2697 *pcbBytesNeeded
= 0;
2699 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2704 &dwServicesReturned
);
2705 if (dwError
!= ERROR_SUCCESS
)
2710 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
)lpServices
;
2711 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2713 /* Copy EnumDepenedentService to Buffer */
2714 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2716 lpService
= lpServicesArray
[dwServiceCount
];
2718 /* Copy status info */
2719 memcpy(&lpServicesPtr
->ServiceStatus
,
2721 sizeof(SERVICE_STATUS
));
2723 /* Copy display name */
2724 wcscpy(lpStr
, lpService
->lpDisplayName
);
2725 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2726 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2728 /* Copy service name */
2729 wcscpy(lpStr
, lpService
->lpServiceName
);
2730 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2731 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2736 *lpServicesReturned
= dwServicesReturned
;
2739 if (lpServicesArray
!= NULL
)
2740 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2742 RegCloseKey(hServicesKey
);
2744 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2753 REnumServicesStatusW(
2754 SC_RPC_HANDLE hSCManager
,
2755 DWORD dwServiceType
,
2756 DWORD dwServiceState
,
2759 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2760 LPBOUNDED_DWORD_256K lpServicesReturned
,
2761 LPBOUNDED_DWORD_256K lpResumeHandle
)
2763 /* Enumerate all the services, not regarding of their group */
2764 return REnumServiceGroupW(hSCManager
,
2780 LPWSTR lpMachineName
,
2781 LPWSTR lpDatabaseName
,
2782 DWORD dwDesiredAccess
,
2783 LPSC_RPC_HANDLE lpScHandle
)
2788 DPRINT("ROpenSCManagerW() called\n");
2789 DPRINT("lpMachineName = %p\n", lpMachineName
);
2790 DPRINT("lpMachineName: %S\n", lpMachineName
);
2791 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2792 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2793 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2796 return ERROR_SHUTDOWN_IN_PROGRESS
;
2799 return ERROR_INVALID_PARAMETER
;
2801 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2803 if (dwError
!= ERROR_SUCCESS
)
2805 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2809 /* Check the desired access */
2810 dwError
= ScmCheckAccess(hHandle
,
2811 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2812 if (dwError
!= ERROR_SUCCESS
)
2814 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2815 HeapFree(GetProcessHeap(), 0, hHandle
);
2819 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2820 DPRINT("*hScm = %p\n", *lpScHandle
);
2822 DPRINT("ROpenSCManagerW() done\n");
2824 return ERROR_SUCCESS
;
2832 SC_RPC_HANDLE hSCManager
,
2833 LPWSTR lpServiceName
,
2834 DWORD dwDesiredAccess
,
2835 LPSC_RPC_HANDLE lpServiceHandle
)
2838 PMANAGER_HANDLE hManager
;
2840 DWORD dwError
= ERROR_SUCCESS
;
2842 DPRINT("ROpenServiceW() called\n");
2843 DPRINT("hSCManager = %p\n", hSCManager
);
2844 DPRINT("lpServiceName = %p\n", lpServiceName
);
2845 DPRINT("lpServiceName: %S\n", lpServiceName
);
2846 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2849 return ERROR_SHUTDOWN_IN_PROGRESS
;
2851 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2852 if (hManager
== NULL
)
2854 DPRINT1("Invalid service manager handle!\n");
2855 return ERROR_INVALID_HANDLE
;
2858 if (!lpServiceHandle
)
2859 return ERROR_INVALID_PARAMETER
;
2862 return ERROR_INVALID_ADDRESS
;
2864 /* Lock the service database exclusive */
2865 ScmLockDatabaseExclusive();
2867 /* Get service database entry */
2868 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2869 if (lpService
== NULL
)
2871 DPRINT("Could not find a service!\n");
2872 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2876 /* Create a service handle */
2877 dwError
= ScmCreateServiceHandle(lpService
,
2879 if (dwError
!= ERROR_SUCCESS
)
2881 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2885 /* Check the desired access */
2886 dwError
= ScmCheckAccess(hHandle
,
2888 if (dwError
!= ERROR_SUCCESS
)
2890 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2891 HeapFree(GetProcessHeap(), 0, hHandle
);
2895 lpService
->dwRefCount
++;
2896 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2898 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2899 DPRINT("*hService = %p\n", *lpServiceHandle
);
2902 /* Unlock the service database */
2903 ScmUnlockDatabase();
2905 DPRINT("ROpenServiceW() done\n");
2914 RQueryServiceConfigW(
2915 SC_RPC_HANDLE hService
,
2916 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2918 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2920 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2921 DWORD dwError
= ERROR_SUCCESS
;
2922 PSERVICE_HANDLE hSvc
;
2923 PSERVICE lpService
= NULL
;
2924 HKEY hServiceKey
= NULL
;
2925 LPWSTR lpImagePath
= NULL
;
2926 LPWSTR lpServiceStartName
= NULL
;
2927 LPWSTR lpDependencies
= NULL
;
2928 DWORD dwDependenciesLength
= 0;
2929 DWORD dwRequiredSize
;
2930 WCHAR lpEmptyString
[] = {0,0};
2933 DPRINT("RQueryServiceConfigW() called\n");
2936 return ERROR_SHUTDOWN_IN_PROGRESS
;
2938 hSvc
= ScmGetServiceFromHandle(hService
);
2941 DPRINT1("Invalid service handle!\n");
2942 return ERROR_INVALID_HANDLE
;
2945 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2946 SERVICE_QUERY_CONFIG
))
2948 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2949 return ERROR_ACCESS_DENIED
;
2952 lpService
= hSvc
->ServiceEntry
;
2953 if (lpService
== NULL
)
2955 DPRINT("lpService == NULL!\n");
2956 return ERROR_INVALID_HANDLE
;
2959 /* Lock the service database shared */
2960 ScmLockDatabaseShared();
2962 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2965 if (dwError
!= ERROR_SUCCESS
)
2968 /* Read the image path */
2969 dwError
= ScmReadString(hServiceKey
,
2972 if (dwError
!= ERROR_SUCCESS
)
2975 /* Read the service start name */
2976 ScmReadString(hServiceKey
,
2978 &lpServiceStartName
);
2980 /* Read the dependencies */
2981 ScmReadDependencies(hServiceKey
,
2983 &dwDependenciesLength
);
2985 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2987 if (lpImagePath
!= NULL
)
2988 dwRequiredSize
+= (DWORD
)((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2990 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2992 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
2993 dwRequiredSize
+= (DWORD
)((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2995 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2997 if (lpDependencies
!= NULL
)
2998 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
3000 dwRequiredSize
+= 2 * sizeof(WCHAR
);
3002 if (lpServiceStartName
!= NULL
)
3003 dwRequiredSize
+= (DWORD
)((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
3005 dwRequiredSize
+= 2 * sizeof(WCHAR
);
3007 if (lpService
->lpDisplayName
!= NULL
)
3008 dwRequiredSize
+= (DWORD
)((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
3010 dwRequiredSize
+= 2 * sizeof(WCHAR
);
3012 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3014 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3018 lpServiceConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3019 lpServiceConfig
->dwStartType
= lpService
->dwStartType
;
3020 lpServiceConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3021 lpServiceConfig
->dwTagId
= lpService
->dwTag
;
3023 lpStr
= (LPWSTR
)(lpServiceConfig
+ 1);
3025 /* Append the image path */
3026 if (lpImagePath
!= NULL
)
3028 wcscpy(lpStr
, lpImagePath
);
3032 wcscpy(lpStr
, lpEmptyString
);
3035 lpServiceConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3036 lpStr
+= (wcslen(lpStr
) + 1);
3038 /* Append the group name */
3039 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3041 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
3045 wcscpy(lpStr
, lpEmptyString
);
3048 lpServiceConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3049 lpStr
+= (wcslen(lpStr
) + 1);
3051 /* Append Dependencies */
3052 if (lpDependencies
!= NULL
)
3056 dwDependenciesLength
* sizeof(WCHAR
));
3060 wcscpy(lpStr
, lpEmptyString
);
3063 lpServiceConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3064 if (lpDependencies
!= NULL
)
3065 lpStr
+= dwDependenciesLength
;
3067 lpStr
+= (wcslen(lpStr
) + 1);
3069 /* Append the service start name */
3070 if (lpServiceStartName
!= NULL
)
3072 wcscpy(lpStr
, lpServiceStartName
);
3076 wcscpy(lpStr
, lpEmptyString
);
3079 lpServiceConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3080 lpStr
+= (wcslen(lpStr
) + 1);
3082 /* Append the display name */
3083 if (lpService
->lpDisplayName
!= NULL
)
3085 wcscpy(lpStr
, lpService
->lpDisplayName
);
3089 wcscpy(lpStr
, lpEmptyString
);
3092 lpServiceConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3095 if (pcbBytesNeeded
!= NULL
)
3096 *pcbBytesNeeded
= dwRequiredSize
;
3099 /* Unlock the service database */
3100 ScmUnlockDatabase();
3102 if (lpImagePath
!= NULL
)
3103 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3105 if (lpServiceStartName
!= NULL
)
3106 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3108 if (lpDependencies
!= NULL
)
3109 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3111 if (hServiceKey
!= NULL
)
3112 RegCloseKey(hServiceKey
);
3114 DPRINT("RQueryServiceConfigW() done\n");
3123 RQueryServiceLockStatusW(
3124 SC_RPC_HANDLE hSCManager
,
3125 LPBYTE lpBuf
, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
3127 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3129 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
= (LPQUERY_SERVICE_LOCK_STATUSW
)lpBuf
;
3130 PMANAGER_HANDLE hMgr
;
3131 DWORD dwRequiredSize
;
3133 if (!lpLockStatus
|| !pcbBytesNeeded
)
3134 return ERROR_INVALID_PARAMETER
;
3136 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
3139 DPRINT1("Invalid service manager handle!\n");
3140 return ERROR_INVALID_HANDLE
;
3143 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
3144 SC_MANAGER_QUERY_LOCK_STATUS
))
3146 DPRINT("Insufficient access rights! 0x%lx\n", hMgr
->Handle
.DesiredAccess
);
3147 return ERROR_ACCESS_DENIED
;
3150 /* FIXME: we need to compute instead the real length of the owner name */
3151 dwRequiredSize
= sizeof(QUERY_SERVICE_LOCK_STATUSW
) + sizeof(WCHAR
);
3152 *pcbBytesNeeded
= dwRequiredSize
;
3154 if (cbBufSize
< dwRequiredSize
)
3155 return ERROR_INSUFFICIENT_BUFFER
;
3157 ScmQueryServiceLockStatusW(lpLockStatus
);
3159 return ERROR_SUCCESS
;
3167 SC_RPC_HANDLE hService
,
3169 LPSTRING_PTRSW argv
)
3171 DWORD dwError
= ERROR_SUCCESS
;
3172 PSERVICE_HANDLE hSvc
;
3173 PSERVICE lpService
= NULL
;
3178 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3179 DPRINT(" argc: %lu\n", argc
);
3182 for (i
= 0; i
< argc
; i
++)
3184 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
].StringPtr
);
3190 return ERROR_SHUTDOWN_IN_PROGRESS
;
3192 hSvc
= ScmGetServiceFromHandle(hService
);
3195 DPRINT1("Invalid service handle!\n");
3196 return ERROR_INVALID_HANDLE
;
3199 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3202 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3203 return ERROR_ACCESS_DENIED
;
3206 lpService
= hSvc
->ServiceEntry
;
3207 if (lpService
== NULL
)
3209 DPRINT("lpService == NULL!\n");
3210 return ERROR_INVALID_HANDLE
;
3213 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3214 return ERROR_SERVICE_DISABLED
;
3216 if (lpService
->bDeleted
)
3217 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3219 /* Start the service */
3220 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3229 RGetServiceDisplayNameW(
3230 SC_RPC_HANDLE hSCManager
,
3231 LPCWSTR lpServiceName
,
3232 LPWSTR lpDisplayName
,
3235 // PMANAGER_HANDLE hManager;
3240 DPRINT("RGetServiceDisplayNameW() called\n");
3241 DPRINT("hSCManager = %p\n", hSCManager
);
3242 DPRINT("lpServiceName: %S\n", lpServiceName
);
3243 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3244 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3246 // hManager = (PMANAGER_HANDLE)hSCManager;
3247 // if (hManager->Handle.Tag != MANAGER_TAG)
3249 // DPRINT("Invalid manager handle!\n");
3250 // return ERROR_INVALID_HANDLE;
3253 /* Get service database entry */
3254 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3255 if (lpService
== NULL
)
3257 DPRINT("Could not find a service!\n");
3259 /* If the service could not be found and lpcchBuffer is less than 2, windows
3260 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3261 if (*lpcchBuffer
< 2)
3264 if (lpDisplayName
!= NULL
)
3270 return ERROR_SERVICE_DOES_NOT_EXIST
;
3273 if (!lpService
->lpDisplayName
)
3275 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
3277 if (lpDisplayName
!= NULL
&&
3278 *lpcchBuffer
> dwLength
)
3280 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3285 dwLength
= (DWORD
)wcslen(lpService
->lpDisplayName
);
3287 if (lpDisplayName
!= NULL
&&
3288 *lpcchBuffer
> dwLength
)
3290 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3294 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3296 *lpcchBuffer
= dwLength
;
3305 RGetServiceKeyNameW(
3306 SC_RPC_HANDLE hSCManager
,
3307 LPCWSTR lpDisplayName
,
3308 LPWSTR lpServiceName
,
3311 // PMANAGER_HANDLE hManager;
3316 DPRINT("RGetServiceKeyNameW() called\n");
3317 DPRINT("hSCManager = %p\n", hSCManager
);
3318 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3319 DPRINT("lpServiceName: %p\n", lpServiceName
);
3320 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3322 // hManager = (PMANAGER_HANDLE)hSCManager;
3323 // if (hManager->Handle.Tag != MANAGER_TAG)
3325 // DPRINT("Invalid manager handle!\n");
3326 // return ERROR_INVALID_HANDLE;
3329 /* Get service database entry */
3330 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3331 if (lpService
== NULL
)
3333 DPRINT("Could not find a service!\n");
3335 /* If the service could not be found and lpcchBuffer is less than 2, windows
3336 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3337 if (*lpcchBuffer
< 2)
3340 if (lpServiceName
!= NULL
)
3346 return ERROR_SERVICE_DOES_NOT_EXIST
;
3349 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
3351 if (lpServiceName
!= NULL
&&
3352 *lpcchBuffer
> dwLength
)
3354 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3355 *lpcchBuffer
= dwLength
;
3356 return ERROR_SUCCESS
;
3359 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3361 *lpcchBuffer
= dwLength
;
3370 RI_ScSetServiceBitsA(
3371 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3372 DWORD dwServiceBits
,
3374 int bUpdateImmediately
,
3378 return ERROR_SHUTDOWN_IN_PROGRESS
;
3380 if (lpString
!= NULL
)
3381 return ERROR_INVALID_PARAMETER
;
3383 return RI_ScSetServiceBitsW(hServiceStatus
,
3394 RChangeServiceConfigA(
3395 SC_RPC_HANDLE hService
,
3396 DWORD dwServiceType
,
3398 DWORD dwErrorControl
,
3399 LPSTR lpBinaryPathName
,
3400 LPSTR lpLoadOrderGroup
,
3402 LPBYTE lpDependencies
,
3404 LPSTR lpServiceStartName
,
3407 LPSTR lpDisplayName
)
3409 DWORD dwError
= ERROR_SUCCESS
;
3410 PSERVICE_HANDLE hSvc
;
3411 PSERVICE lpService
= NULL
;
3412 HKEY hServiceKey
= NULL
;
3413 LPWSTR lpDisplayNameW
= NULL
;
3414 LPWSTR lpBinaryPathNameW
= NULL
;
3415 LPWSTR lpCanonicalImagePathW
= NULL
;
3416 LPWSTR lpLoadOrderGroupW
= NULL
;
3417 LPWSTR lpDependenciesW
= NULL
;
3419 DPRINT("RChangeServiceConfigA() called\n");
3420 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3421 DPRINT("dwStartType = %lu\n", dwStartType
);
3422 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3423 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3424 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3425 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3428 return ERROR_SHUTDOWN_IN_PROGRESS
;
3430 hSvc
= ScmGetServiceFromHandle(hService
);
3433 DPRINT1("Invalid service handle!\n");
3434 return ERROR_INVALID_HANDLE
;
3437 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3438 SERVICE_CHANGE_CONFIG
))
3440 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3441 return ERROR_ACCESS_DENIED
;
3444 lpService
= hSvc
->ServiceEntry
;
3445 if (lpService
== NULL
)
3447 DPRINT("lpService == NULL!\n");
3448 return ERROR_INVALID_HANDLE
;
3451 /* Lock the service database exclusively */
3452 ScmLockDatabaseExclusive();
3454 if (lpService
->bDeleted
)
3456 DPRINT("The service has already been marked for delete!\n");
3457 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3461 /* Open the service key */
3462 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3465 if (dwError
!= ERROR_SUCCESS
)
3468 /* Write service data to the registry */
3470 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3472 /* Set the display name */
3473 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3475 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3476 if (lpDisplayNameW
== NULL
)
3478 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3482 MultiByteToWideChar(CP_ACP
,
3487 (int)(strlen(lpDisplayName
) + 1));
3489 RegSetValueExW(hServiceKey
,
3493 (LPBYTE
)lpDisplayNameW
,
3494 (DWORD
)((wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
)));
3496 /* Update lpService->lpDisplayName */
3497 if (lpService
->lpDisplayName
)
3498 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3500 lpService
->lpDisplayName
= lpDisplayNameW
;
3503 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3505 /* Set the service type */
3506 dwError
= RegSetValueExW(hServiceKey
,
3510 (LPBYTE
)&dwServiceType
,
3512 if (dwError
!= ERROR_SUCCESS
)
3515 lpService
->Status
.dwServiceType
= dwServiceType
;
3518 if (dwStartType
!= SERVICE_NO_CHANGE
)
3520 /* Set the start value */
3521 dwError
= RegSetValueExW(hServiceKey
,
3525 (LPBYTE
)&dwStartType
,
3527 if (dwError
!= ERROR_SUCCESS
)
3530 lpService
->dwStartType
= dwStartType
;
3533 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3535 /* Set the error control value */
3536 dwError
= RegSetValueExW(hServiceKey
,
3540 (LPBYTE
)&dwErrorControl
,
3542 if (dwError
!= ERROR_SUCCESS
)
3545 lpService
->dwErrorControl
= dwErrorControl
;
3548 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3550 /* Set the image path */
3551 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(),
3553 (strlen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
3554 if (lpBinaryPathNameW
== NULL
)
3556 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3560 MultiByteToWideChar(CP_ACP
,
3565 (int)(strlen(lpBinaryPathName
) + 1));
3567 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
3569 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
3571 &lpCanonicalImagePathW
);
3573 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3575 if (dwError
!= ERROR_SUCCESS
)
3578 lpBinaryPathNameW
= lpCanonicalImagePathW
;
3581 dwError
= RegSetValueExW(hServiceKey
,
3585 (LPBYTE
)lpBinaryPathNameW
,
3586 (DWORD
)((wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
)));
3588 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3590 if (dwError
!= ERROR_SUCCESS
)
3594 /* Set the group name */
3595 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3597 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3599 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3600 if (lpLoadOrderGroupW
== NULL
)
3602 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3606 MultiByteToWideChar(CP_ACP
,
3611 (int)(strlen(lpLoadOrderGroup
) + 1));
3613 dwError
= RegSetValueExW(hServiceKey
,
3617 (LPBYTE
)lpLoadOrderGroupW
,
3618 (DWORD
)((wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
)));
3619 if (dwError
!= ERROR_SUCCESS
)
3621 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3625 dwError
= ScmSetServiceGroup(lpService
,
3628 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3630 if (dwError
!= ERROR_SUCCESS
)
3634 if (lpdwTagId
!= NULL
)
3636 dwError
= ScmAssignNewTag(lpService
);
3637 if (dwError
!= ERROR_SUCCESS
)
3640 dwError
= RegSetValueExW(hServiceKey
,
3644 (LPBYTE
)&lpService
->dwTag
,
3646 if (dwError
!= ERROR_SUCCESS
)
3649 *lpdwTagId
= lpService
->dwTag
;
3652 /* Write dependencies */
3653 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3655 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3657 (strlen((LPSTR
)lpDependencies
) + 1) * sizeof(WCHAR
));
3658 if (lpDependenciesW
== NULL
)
3660 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3664 MultiByteToWideChar(CP_ACP
,
3666 (LPSTR
)lpDependencies
,
3669 (int)(strlen((LPSTR
)lpDependencies
) + 1));
3671 dwError
= ScmWriteDependencies(hServiceKey
,
3672 (LPWSTR
)lpDependenciesW
,
3675 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3677 if (dwError
!= ERROR_SUCCESS
)
3681 if (lpPassword
!= NULL
)
3683 if (wcslen((LPWSTR
)lpPassword
) != 0)
3685 /* FIXME: Decrypt the password */
3687 /* Write the password */
3688 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
3689 (LPCWSTR
)lpPassword
);
3690 if (dwError
!= ERROR_SUCCESS
)
3695 /* Delete the password */
3696 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
3698 if (dwError
== ERROR_FILE_NOT_FOUND
)
3699 dwError
= ERROR_SUCCESS
;
3701 if (dwError
!= ERROR_SUCCESS
)
3707 /* Unlock the service database */
3708 ScmUnlockDatabase();
3710 if (hServiceKey
!= NULL
)
3711 RegCloseKey(hServiceKey
);
3713 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3723 SC_RPC_HANDLE hSCManager
,
3724 LPSTR lpServiceName
,
3725 LPSTR lpDisplayName
,
3726 DWORD dwDesiredAccess
,
3727 DWORD dwServiceType
,
3729 DWORD dwErrorControl
,
3730 LPSTR lpBinaryPathName
,
3731 LPSTR lpLoadOrderGroup
,
3733 LPBYTE lpDependencies
,
3735 LPSTR lpServiceStartName
,
3738 LPSC_RPC_HANDLE lpServiceHandle
)
3740 DWORD dwError
= ERROR_SUCCESS
;
3741 LPWSTR lpServiceNameW
= NULL
;
3742 LPWSTR lpDisplayNameW
= NULL
;
3743 LPWSTR lpBinaryPathNameW
= NULL
;
3744 LPWSTR lpLoadOrderGroupW
= NULL
;
3745 LPWSTR lpDependenciesW
= NULL
;
3746 LPWSTR lpServiceStartNameW
= NULL
;
3747 DWORD dwDependenciesLength
= 0;
3754 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3755 lpServiceNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3756 if (!lpServiceNameW
)
3758 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3761 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3766 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3767 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3768 if (!lpDisplayNameW
)
3770 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3773 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3776 if (lpBinaryPathName
)
3778 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3779 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3780 if (!lpBinaryPathNameW
)
3782 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3785 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3788 if (lpLoadOrderGroup
)
3790 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3791 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3792 if (!lpLoadOrderGroupW
)
3794 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3797 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3802 lpStr
= (LPCSTR
)lpDependencies
;
3805 cchLength
= strlen(lpStr
) + 1;
3806 dwDependenciesLength
+= (DWORD
)cchLength
;
3807 lpStr
= lpStr
+ cchLength
;
3809 dwDependenciesLength
++;
3811 lpDependenciesW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDependenciesLength
* sizeof(WCHAR
));
3812 if (!lpDependenciesW
)
3814 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3817 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3820 if (lpServiceStartName
)
3822 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3823 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3824 if (!lpServiceStartNameW
)
3826 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3829 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3832 dwError
= RCreateServiceW(hSCManager
,
3842 (LPBYTE
)lpDependenciesW
,
3843 dwDependenciesLength
,
3844 lpServiceStartNameW
,
3850 if (lpServiceNameW
!=NULL
)
3851 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3853 if (lpDisplayNameW
!= NULL
)
3854 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3856 if (lpBinaryPathNameW
!= NULL
)
3857 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3859 if (lpLoadOrderGroupW
!= NULL
)
3860 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3862 if (lpDependenciesW
!= NULL
)
3863 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3865 if (lpServiceStartNameW
!= NULL
)
3866 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3875 REnumDependentServicesA(
3876 SC_RPC_HANDLE hService
,
3877 DWORD dwServiceState
,
3880 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3881 LPBOUNDED_DWORD_256K lpServicesReturned
)
3883 DWORD dwError
= ERROR_SUCCESS
;
3884 DWORD dwServicesReturned
= 0;
3885 DWORD dwServiceCount
;
3886 HKEY hServicesKey
= NULL
;
3887 PSERVICE_HANDLE hSvc
;
3888 PSERVICE lpService
= NULL
;
3889 PSERVICE
*lpServicesArray
= NULL
;
3890 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3893 *pcbBytesNeeded
= 0;
3894 *lpServicesReturned
= 0;
3896 DPRINT("REnumDependentServicesA() called\n");
3898 hSvc
= ScmGetServiceFromHandle(hService
);
3901 DPRINT1("Invalid service handle!\n");
3902 return ERROR_INVALID_HANDLE
;
3905 lpService
= hSvc
->ServiceEntry
;
3907 /* Check access rights */
3908 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3909 SC_MANAGER_ENUMERATE_SERVICE
))
3911 DPRINT("Insufficient access rights! 0x%lx\n",
3912 hSvc
->Handle
.DesiredAccess
);
3913 return ERROR_ACCESS_DENIED
;
3916 /* Open the Services Reg key */
3917 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3918 L
"System\\CurrentControlSet\\Services",
3923 if (dwError
!= ERROR_SUCCESS
)
3926 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3927 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3928 are the same for both. Verified in WINXP. */
3930 /* First determine the bytes needed and get the number of dependent services*/
3931 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3936 &dwServicesReturned
);
3937 if (dwError
!= ERROR_SUCCESS
)
3940 /* If buffer size is less than the bytes needed or pointer is null*/
3941 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3943 dwError
= ERROR_MORE_DATA
;
3947 /* Allocate memory for array of service pointers */
3948 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3950 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3951 if (!lpServicesArray
)
3953 DPRINT("Could not allocate a buffer!!\n");
3954 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3958 dwServicesReturned
= 0;
3959 *pcbBytesNeeded
= 0;
3961 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3966 &dwServicesReturned
);
3967 if (dwError
!= ERROR_SUCCESS
)
3972 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3973 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3975 /* Copy EnumDepenedentService to Buffer */
3976 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3978 lpService
= lpServicesArray
[dwServiceCount
];
3980 /* Copy the status info */
3981 memcpy(&lpServicesPtr
->ServiceStatus
,
3983 sizeof(SERVICE_STATUS
));
3985 /* Copy display name */
3986 WideCharToMultiByte(CP_ACP
,
3988 lpService
->lpDisplayName
,
3991 (int)wcslen(lpService
->lpDisplayName
),
3994 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3995 lpStr
+= strlen(lpStr
) + 1;
3997 /* Copy service name */
3998 WideCharToMultiByte(CP_ACP
,
4000 lpService
->lpServiceName
,
4003 (int)wcslen(lpService
->lpServiceName
),
4006 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
4007 lpStr
+= strlen(lpStr
) + 1;
4012 *lpServicesReturned
= dwServicesReturned
;
4015 if (lpServicesArray
)
4016 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
4018 RegCloseKey(hServicesKey
);
4020 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
4029 REnumServicesStatusA(
4030 SC_RPC_HANDLE hSCManager
,
4031 DWORD dwServiceType
,
4032 DWORD dwServiceState
,
4035 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4036 LPBOUNDED_DWORD_256K lpServicesReturned
,
4037 LPBOUNDED_DWORD_256K lpResumeHandle
)
4039 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
4040 LPENUM_SERVICE_STATUSW lpStatusPtrIncrW
;
4041 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
4042 LPWSTR lpStringPtrW
;
4045 DWORD dwServiceCount
;
4047 DPRINT("REnumServicesStatusA() called\n");
4049 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
4051 return ERROR_INVALID_ADDRESS
;
4054 if ((dwBufSize
> 0) && (lpBuffer
))
4056 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
4059 DPRINT("Failed to allocate buffer!\n");
4060 return ERROR_NOT_ENOUGH_MEMORY
;
4064 dwError
= REnumServicesStatusW(hSCManager
,
4067 (LPBYTE
)lpStatusPtrW
,
4073 /* if no services were returned then we are Done */
4074 if (*lpServicesReturned
== 0)
4077 lpStatusPtrIncrW
= lpStatusPtrW
;
4078 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
4079 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4080 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
4081 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4082 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
4084 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4086 /* Copy the service name */
4087 WideCharToMultiByte(CP_ACP
,
4092 (int)wcslen(lpStringPtrW
),
4096 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4097 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4098 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4100 /* Copy the display name */
4101 WideCharToMultiByte(CP_ACP
,
4106 (int)wcslen(lpStringPtrW
),
4110 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4111 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4112 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4114 /* Copy the status information */
4115 memcpy(&lpStatusPtrA
->ServiceStatus
,
4116 &lpStatusPtrIncrW
->ServiceStatus
,
4117 sizeof(SERVICE_STATUS
));
4125 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4127 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
4137 LPSTR lpMachineName
,
4138 LPSTR lpDatabaseName
,
4139 DWORD dwDesiredAccess
,
4140 LPSC_RPC_HANDLE lpScHandle
)
4142 UNICODE_STRING MachineName
;
4143 UNICODE_STRING DatabaseName
;
4146 DPRINT("ROpenSCManagerA() called\n");
4149 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
4153 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
4156 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
4157 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
4162 RtlFreeUnicodeString(&MachineName
);
4165 RtlFreeUnicodeString(&DatabaseName
);
4175 SC_RPC_HANDLE hSCManager
,
4176 LPSTR lpServiceName
,
4177 DWORD dwDesiredAccess
,
4178 LPSC_RPC_HANDLE lpServiceHandle
)
4180 UNICODE_STRING ServiceName
;
4183 DPRINT("ROpenServiceA() called\n");
4186 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
4189 dwError
= ROpenServiceW(hSCManager
,
4190 lpServiceName
? ServiceName
.Buffer
: NULL
,
4195 RtlFreeUnicodeString(&ServiceName
);
4204 RQueryServiceConfigA(
4205 SC_RPC_HANDLE hService
,
4206 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4208 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4210 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
4211 DWORD dwError
= ERROR_SUCCESS
;
4212 PSERVICE_HANDLE hSvc
;
4213 PSERVICE lpService
= NULL
;
4214 HKEY hServiceKey
= NULL
;
4215 LPWSTR lpImagePath
= NULL
;
4216 LPWSTR lpServiceStartName
= NULL
;
4217 LPWSTR lpDependencies
= NULL
;
4218 DWORD dwDependenciesLength
= 0;
4219 DWORD dwRequiredSize
;
4220 CHAR lpEmptyString
[]={0,0};
4223 DPRINT("RQueryServiceConfigA() called\n");
4226 return ERROR_SHUTDOWN_IN_PROGRESS
;
4228 hSvc
= ScmGetServiceFromHandle(hService
);
4231 DPRINT1("Invalid service handle!\n");
4232 return ERROR_INVALID_HANDLE
;
4235 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4236 SERVICE_QUERY_CONFIG
))
4238 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4239 return ERROR_ACCESS_DENIED
;
4242 lpService
= hSvc
->ServiceEntry
;
4243 if (lpService
== NULL
)
4245 DPRINT("lpService == NULL!\n");
4246 return ERROR_INVALID_HANDLE
;
4249 /* Lock the service database shared */
4250 ScmLockDatabaseShared();
4252 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4255 if (dwError
!= ERROR_SUCCESS
)
4258 /* Read the image path */
4259 dwError
= ScmReadString(hServiceKey
,
4262 if (dwError
!= ERROR_SUCCESS
)
4265 /* Read the service start name */
4266 ScmReadString(hServiceKey
,
4268 &lpServiceStartName
);
4270 /* Read the dependencies */
4271 ScmReadDependencies(hServiceKey
,
4273 &dwDependenciesLength
);
4275 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGA
);
4277 if (lpImagePath
!= NULL
)
4278 dwRequiredSize
+= (DWORD
)(wcslen(lpImagePath
) + 1);
4280 dwRequiredSize
+= 2;
4282 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
4283 dwRequiredSize
+= (DWORD
)(wcslen(lpService
->lpGroup
->lpGroupName
) + 1);
4285 dwRequiredSize
+= 2;
4287 /* Add Dependencies length */
4288 if (lpDependencies
!= NULL
)
4289 dwRequiredSize
+= dwDependenciesLength
;
4291 dwRequiredSize
+= 2;
4293 if (lpServiceStartName
!= NULL
)
4294 dwRequiredSize
+= (DWORD
)(wcslen(lpServiceStartName
) + 1);
4296 dwRequiredSize
+= 2;
4298 if (lpService
->lpDisplayName
!= NULL
)
4299 dwRequiredSize
+= (DWORD
)(wcslen(lpService
->lpDisplayName
) + 1);
4301 dwRequiredSize
+= 2;
4303 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
4305 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4309 lpServiceConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
4310 lpServiceConfig
->dwStartType
= lpService
->dwStartType
;
4311 lpServiceConfig
->dwErrorControl
= lpService
->dwErrorControl
;
4312 lpServiceConfig
->dwTagId
= lpService
->dwTag
;
4314 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
4316 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4317 Verified in WINXP */
4321 WideCharToMultiByte(CP_ACP
,
4326 (int)(wcslen(lpImagePath
) + 1),
4332 strcpy(lpStr
, lpEmptyString
);
4335 lpServiceConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4336 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4338 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4340 WideCharToMultiByte(CP_ACP
,
4342 lpService
->lpGroup
->lpGroupName
,
4345 (int)(wcslen(lpService
->lpGroup
->lpGroupName
) + 1),
4351 strcpy(lpStr
, lpEmptyString
);
4354 lpServiceConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4355 lpStr
+= (strlen(lpStr
) + 1);
4357 /* Append Dependencies */
4360 WideCharToMultiByte(CP_ACP
,
4363 dwDependenciesLength
,
4365 dwDependenciesLength
,
4371 strcpy(lpStr
, lpEmptyString
);
4374 lpServiceConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4376 lpStr
+= dwDependenciesLength
;
4378 lpStr
+= (strlen(lpStr
) + 1);
4380 if (lpServiceStartName
)
4382 WideCharToMultiByte(CP_ACP
,
4387 (int)(wcslen(lpServiceStartName
) + 1),
4393 strcpy(lpStr
, lpEmptyString
);
4396 lpServiceConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4397 lpStr
+= (strlen(lpStr
) + 1);
4399 if (lpService
->lpDisplayName
)
4401 WideCharToMultiByte(CP_ACP
,
4403 lpService
->lpDisplayName
,
4406 (int)(wcslen(lpService
->lpDisplayName
) + 1),
4412 strcpy(lpStr
, lpEmptyString
);
4415 lpServiceConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4418 if (pcbBytesNeeded
!= NULL
)
4419 *pcbBytesNeeded
= dwRequiredSize
;
4422 /* Unlock the service database */
4423 ScmUnlockDatabase();
4425 if (lpImagePath
!= NULL
)
4426 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4428 if (lpServiceStartName
!= NULL
)
4429 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4431 if (lpDependencies
!= NULL
)
4432 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4434 if (hServiceKey
!= NULL
)
4435 RegCloseKey(hServiceKey
);
4437 DPRINT("RQueryServiceConfigA() done\n");
4446 RQueryServiceLockStatusA(
4447 SC_RPC_HANDLE hSCManager
,
4448 LPBYTE lpBuf
, // LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
4450 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4452 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
= (LPQUERY_SERVICE_LOCK_STATUSA
)lpBuf
;
4453 PMANAGER_HANDLE hMgr
;
4454 DWORD dwRequiredSize
;
4456 if (!lpLockStatus
|| !pcbBytesNeeded
)
4457 return ERROR_INVALID_PARAMETER
;
4459 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
4462 DPRINT1("Invalid service manager handle!\n");
4463 return ERROR_INVALID_HANDLE
;
4466 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
4467 SC_MANAGER_QUERY_LOCK_STATUS
))
4469 DPRINT("Insufficient access rights! 0x%lx\n", hMgr
->Handle
.DesiredAccess
);
4470 return ERROR_ACCESS_DENIED
;
4473 /* FIXME: we need to compute instead the real length of the owner name */
4474 dwRequiredSize
= sizeof(QUERY_SERVICE_LOCK_STATUSA
) + sizeof(CHAR
);
4475 *pcbBytesNeeded
= dwRequiredSize
;
4477 if (cbBufSize
< dwRequiredSize
)
4478 return ERROR_INSUFFICIENT_BUFFER
;
4480 ScmQueryServiceLockStatusA(lpLockStatus
);
4482 return ERROR_SUCCESS
;
4490 SC_RPC_HANDLE hService
,
4492 LPSTRING_PTRSA argv
)
4494 DWORD dwError
= ERROR_SUCCESS
;
4495 PSERVICE_HANDLE hSvc
;
4496 PSERVICE lpService
= NULL
;
4497 LPWSTR
*lpVector
= NULL
;
4501 DPRINT("RStartServiceA() called\n");
4504 return ERROR_SHUTDOWN_IN_PROGRESS
;
4506 hSvc
= ScmGetServiceFromHandle(hService
);
4509 DPRINT1("Invalid service handle!\n");
4510 return ERROR_INVALID_HANDLE
;
4513 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4516 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4517 return ERROR_ACCESS_DENIED
;
4520 lpService
= hSvc
->ServiceEntry
;
4521 if (lpService
== NULL
)
4523 DPRINT("lpService == NULL!\n");
4524 return ERROR_INVALID_HANDLE
;
4527 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4528 return ERROR_SERVICE_DISABLED
;
4530 if (lpService
->bDeleted
)
4531 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4533 /* Build a Unicode argument vector */
4536 lpVector
= HeapAlloc(GetProcessHeap(),
4538 argc
* sizeof(LPWSTR
));
4539 if (lpVector
== NULL
)
4540 return ERROR_NOT_ENOUGH_MEMORY
;
4542 for (i
= 0; i
< argc
; i
++)
4544 dwLength
= MultiByteToWideChar(CP_ACP
,
4551 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4553 dwLength
* sizeof(WCHAR
));
4554 if (lpVector
[i
] == NULL
)
4556 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4560 MultiByteToWideChar(CP_ACP
,
4569 /* Start the service */
4570 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4573 /* Free the Unicode argument vector */
4574 if (lpVector
!= NULL
)
4576 for (i
= 0; i
< argc
; i
++)
4578 if (lpVector
[i
] != NULL
)
4579 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4581 HeapFree(GetProcessHeap(), 0, lpVector
);
4591 RGetServiceDisplayNameA(
4592 SC_RPC_HANDLE hSCManager
,
4593 LPCSTR lpServiceName
,
4594 LPSTR lpDisplayName
,
4595 LPBOUNDED_DWORD_4K lpcchBuffer
)
4597 // PMANAGER_HANDLE hManager;
4598 PSERVICE lpService
= NULL
;
4601 LPWSTR lpServiceNameW
;
4603 DPRINT("RGetServiceDisplayNameA() called\n");
4604 DPRINT("hSCManager = %p\n", hSCManager
);
4605 DPRINT("lpServiceName: %s\n", lpServiceName
);
4606 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4607 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4609 // hManager = (PMANAGER_HANDLE)hSCManager;
4610 // if (hManager->Handle.Tag != MANAGER_TAG)
4612 // DPRINT("Invalid manager handle!\n");
4613 // return ERROR_INVALID_HANDLE;
4616 if (lpServiceName
!= NULL
)
4618 dwLength
= (DWORD
)(strlen(lpServiceName
) + 1);
4619 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4621 dwLength
* sizeof(WCHAR
));
4622 if (!lpServiceNameW
)
4623 return ERROR_NOT_ENOUGH_MEMORY
;
4625 MultiByteToWideChar(CP_ACP
,
4632 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4634 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4637 if (lpService
== NULL
)
4639 DPRINT("Could not find a service!\n");
4641 /* If the service could not be found and lpcchBuffer is 0, windows
4642 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4643 if (*lpcchBuffer
== 0)
4646 if (lpDisplayName
!= NULL
)
4651 return ERROR_SERVICE_DOES_NOT_EXIST
;
4654 if (!lpService
->lpDisplayName
)
4656 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
4657 if (lpDisplayName
!= NULL
&&
4658 *lpcchBuffer
> dwLength
)
4660 WideCharToMultiByte(CP_ACP
,
4662 lpService
->lpServiceName
,
4663 (int)wcslen(lpService
->lpServiceName
),
4668 return ERROR_SUCCESS
;
4673 dwLength
= (DWORD
)wcslen(lpService
->lpDisplayName
);
4674 if (lpDisplayName
!= NULL
&&
4675 *lpcchBuffer
> dwLength
)
4677 WideCharToMultiByte(CP_ACP
,
4679 lpService
->lpDisplayName
,
4680 (int)wcslen(lpService
->lpDisplayName
),
4685 return ERROR_SUCCESS
;
4689 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4691 *lpcchBuffer
= dwLength
* 2;
4700 RGetServiceKeyNameA(
4701 SC_RPC_HANDLE hSCManager
,
4702 LPCSTR lpDisplayName
,
4703 LPSTR lpServiceName
,
4704 LPBOUNDED_DWORD_4K lpcchBuffer
)
4709 LPWSTR lpDisplayNameW
;
4711 DPRINT("RGetServiceKeyNameA() called\n");
4712 DPRINT("hSCManager = %p\n", hSCManager
);
4713 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4714 DPRINT("lpServiceName: %p\n", lpServiceName
);
4715 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4717 dwLength
= (DWORD
)(strlen(lpDisplayName
) + 1);
4718 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4720 dwLength
* sizeof(WCHAR
));
4721 if (!lpDisplayNameW
)
4722 return ERROR_NOT_ENOUGH_MEMORY
;
4724 MultiByteToWideChar(CP_ACP
,
4731 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4733 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4735 if (lpService
== NULL
)
4737 DPRINT("Could not find the service!\n");
4739 /* If the service could not be found and lpcchBuffer is 0,
4740 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4741 if (*lpcchBuffer
== 0)
4744 if (lpServiceName
!= NULL
)
4750 return ERROR_SERVICE_DOES_NOT_EXIST
;
4753 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
4754 if (lpServiceName
!= NULL
&&
4755 *lpcchBuffer
> dwLength
)
4757 WideCharToMultiByte(CP_ACP
,
4759 lpService
->lpServiceName
,
4760 (int)wcslen(lpService
->lpServiceName
),
4765 return ERROR_SUCCESS
;
4768 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4770 *lpcchBuffer
= dwLength
* 2;
4779 RI_ScGetCurrentGroupStateW(
4780 SC_RPC_HANDLE hSCManager
,
4781 LPWSTR lpLoadOrderGroup
,
4784 PMANAGER_HANDLE hManager
;
4785 PSERVICE_GROUP pServiceGroup
;
4786 DWORD dwError
= ERROR_SUCCESS
;
4788 DPRINT("RI_ScGetCurrentGroupStateW() called\n");
4791 return ERROR_SHUTDOWN_IN_PROGRESS
;
4793 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
4794 if (hManager
== NULL
)
4796 DPRINT1("Invalid service manager handle!\n");
4797 return ERROR_INVALID_HANDLE
;
4800 /* Check for SC_MANAGER_ENUMERATE_SERVICE access right */
4801 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4802 SC_MANAGER_ENUMERATE_SERVICE
))
4804 DPRINT("Insufficient access rights! 0x%lx\n",
4805 hManager
->Handle
.DesiredAccess
);
4806 return ERROR_ACCESS_DENIED
;
4809 /* Lock the service database shared */
4810 ScmLockDatabaseShared();
4812 /* Get the group list entry */
4813 pServiceGroup
= ScmGetServiceGroupByName(lpLoadOrderGroup
);
4814 if (pServiceGroup
== NULL
)
4816 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
4820 /* FIXME: Return the group state */
4824 /* Unlock the service database */
4825 ScmUnlockDatabase();
4827 DPRINT("RI_ScGetCurrentGroupStateW() done (Error %lu)\n", dwError
);
4837 SC_RPC_HANDLE hSCManager
,
4838 DWORD dwServiceType
,
4839 DWORD dwServiceState
,
4842 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4843 LPBOUNDED_DWORD_256K lpServicesReturned
,
4844 LPBOUNDED_DWORD_256K lpResumeIndex
,
4845 LPCWSTR pszGroupName
)
4847 PMANAGER_HANDLE hManager
;
4849 DWORD dwError
= ERROR_SUCCESS
;
4850 PLIST_ENTRY ServiceEntry
;
4851 PSERVICE CurrentService
;
4853 DWORD dwRequiredSize
;
4854 DWORD dwServiceCount
;
4856 DWORD dwLastResumeCount
= 0;
4857 LPENUM_SERVICE_STATUSW lpStatusPtr
;
4860 DPRINT("REnumServiceGroupW() called\n");
4863 return ERROR_SHUTDOWN_IN_PROGRESS
;
4865 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
4866 if (hManager
== NULL
)
4868 DPRINT1("Invalid service manager handle!\n");
4869 return ERROR_INVALID_HANDLE
;
4872 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
4874 return ERROR_INVALID_ADDRESS
;
4877 *pcbBytesNeeded
= 0;
4878 *lpServicesReturned
= 0;
4880 if ((dwServiceType
== 0) ||
4881 ((dwServiceType
& ~SERVICE_TYPE_ALL
) != 0))
4883 DPRINT("Not a valid Service Type!\n");
4884 return ERROR_INVALID_PARAMETER
;
4887 if ((dwServiceState
== 0) ||
4888 ((dwServiceState
& ~SERVICE_STATE_ALL
) != 0))
4890 DPRINT("Not a valid Service State!\n");
4891 return ERROR_INVALID_PARAMETER
;
4894 /* Check access rights */
4895 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4896 SC_MANAGER_ENUMERATE_SERVICE
))
4898 DPRINT("Insufficient access rights! 0x%lx\n",
4899 hManager
->Handle
.DesiredAccess
);
4900 return ERROR_ACCESS_DENIED
;
4904 dwLastResumeCount
= *lpResumeIndex
;
4906 /* Lock the service database shared */
4907 ScmLockDatabaseShared();
4909 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4910 if (lpService
== NULL
)
4912 dwError
= ERROR_SUCCESS
;
4919 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4920 ServiceEntry
!= &ServiceListHead
;
4921 ServiceEntry
= ServiceEntry
->Flink
)
4923 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4927 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4930 dwState
= SERVICE_ACTIVE
;
4931 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4932 dwState
= SERVICE_INACTIVE
;
4934 if ((dwState
& dwServiceState
) == 0)
4939 if (*pszGroupName
== 0)
4941 if (CurrentService
->lpGroup
!= NULL
)
4946 if ((CurrentService
->lpGroup
== NULL
) ||
4947 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4952 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
4953 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4954 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4956 if (dwRequiredSize
+ dwSize
> cbBufSize
)
4958 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4962 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4963 dwRequiredSize
+= dwSize
;
4965 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4968 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4969 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4972 ServiceEntry
!= &ServiceListHead
;
4973 ServiceEntry
= ServiceEntry
->Flink
)
4975 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4979 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4982 dwState
= SERVICE_ACTIVE
;
4983 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4984 dwState
= SERVICE_INACTIVE
;
4986 if ((dwState
& dwServiceState
) == 0)
4991 if (*pszGroupName
== 0)
4993 if (CurrentService
->lpGroup
!= NULL
)
4998 if ((CurrentService
->lpGroup
== NULL
) ||
4999 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
5004 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
5005 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5006 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5008 dwError
= ERROR_MORE_DATA
;
5011 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5014 *lpResumeIndex
= dwLastResumeCount
;
5016 *lpServicesReturned
= dwServiceCount
;
5017 *pcbBytesNeeded
= dwRequiredSize
;
5019 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
5020 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5021 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
5024 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5025 ServiceEntry
!= &ServiceListHead
;
5026 ServiceEntry
= ServiceEntry
->Flink
)
5028 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5032 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5035 dwState
= SERVICE_ACTIVE
;
5036 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5037 dwState
= SERVICE_INACTIVE
;
5039 if ((dwState
& dwServiceState
) == 0)
5044 if (*pszGroupName
== 0)
5046 if (CurrentService
->lpGroup
!= NULL
)
5051 if ((CurrentService
->lpGroup
== NULL
) ||
5052 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
5057 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
5058 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5059 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5061 if (dwRequiredSize
+ dwSize
> cbBufSize
)
5064 /* Copy the service name */
5065 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
5066 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5067 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5069 /* Copy the display name */
5070 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
5071 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5072 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5074 /* Copy the status information */
5075 memcpy(&lpStatusPtr
->ServiceStatus
,
5076 &CurrentService
->Status
,
5077 sizeof(SERVICE_STATUS
));
5080 dwRequiredSize
+= dwSize
;
5083 if (dwError
== ERROR_SUCCESS
)
5085 *pcbBytesNeeded
= 0;
5086 if (lpResumeIndex
) *lpResumeIndex
= 0;
5090 /* Unlock the service database */
5091 ScmUnlockDatabase();
5093 DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError
);
5102 RChangeServiceConfig2A(
5103 SC_RPC_HANDLE hService
,
5104 SC_RPC_CONFIG_INFOA Info
)
5106 SC_RPC_CONFIG_INFOW InfoW
= { 0 };
5107 DWORD dwRet
, dwLength
;
5110 DPRINT("RChangeServiceConfig2A() called\n");
5111 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
5113 if ((Info
.dwInfoLevel
< SERVICE_CONFIG_DESCRIPTION
) ||
5114 (Info
.dwInfoLevel
> SERVICE_CONFIG_FAILURE_ACTIONS
))
5115 return ERROR_INVALID_LEVEL
;
5117 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
5119 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5121 LPSERVICE_DESCRIPTIONW lpServiceDescriptionW
;
5122 LPSERVICE_DESCRIPTIONA lpServiceDescriptionA
;
5124 lpServiceDescriptionA
= Info
.psd
;
5126 if (lpServiceDescriptionA
&&
5127 lpServiceDescriptionA
->lpDescription
)
5129 dwLength
= (DWORD
)((strlen(lpServiceDescriptionA
->lpDescription
) + 1) * sizeof(WCHAR
));
5131 lpServiceDescriptionW
= HeapAlloc(GetProcessHeap(),
5133 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
5134 if (!lpServiceDescriptionW
)
5136 return ERROR_NOT_ENOUGH_MEMORY
;
5139 lpServiceDescriptionW
->lpDescription
= (LPWSTR
)(lpServiceDescriptionW
+ 1);
5141 MultiByteToWideChar(CP_ACP
,
5143 lpServiceDescriptionA
->lpDescription
,
5145 lpServiceDescriptionW
->lpDescription
,
5148 ptr
= lpServiceDescriptionW
;
5149 InfoW
.psd
= lpServiceDescriptionW
;
5152 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5154 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
5155 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
5156 DWORD dwRebootLen
= 0;
5157 DWORD dwCommandLen
= 0;
5158 DWORD dwActionArrayLen
= 0;
5159 LPWSTR lpStr
= NULL
;
5161 lpServiceFailureActionsA
= Info
.psfa
;
5163 if (lpServiceFailureActionsA
)
5166 * The following code is inspired by the
5167 * SERVICE_CONFIG_FAILURE_ACTIONS case of
5168 * the RQueryServiceConfig2W function.
5171 /* Retrieve the needed length for the two data strings */
5172 if (lpServiceFailureActionsA
->lpRebootMsg
)
5174 dwRebootLen
= (DWORD
)((strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
));
5176 if (lpServiceFailureActionsA
->lpCommand
)
5178 dwCommandLen
= (DWORD
)((strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
));
5182 * Retrieve the size of the lpsaActions array if needed.
5183 * We will copy the lpsaActions array only if there is at
5184 * least one action AND that the original array is valid.
5186 if (lpServiceFailureActionsA
->cActions
> 0 && lpServiceFailureActionsA
->lpsaActions
)
5188 dwActionArrayLen
= lpServiceFailureActionsA
->cActions
* sizeof(SC_ACTION
);
5191 /* Compute the total length for the UNICODE structure, including data */
5192 dwLength
= sizeof(SERVICE_FAILURE_ACTIONSW
) +
5193 dwActionArrayLen
+ dwRebootLen
+ dwCommandLen
;
5195 /* Allocate the structure */
5196 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
5199 if (!lpServiceFailureActionsW
)
5201 return ERROR_NOT_ENOUGH_MEMORY
;
5204 /* Copy the members */
5205 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
5206 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
5208 /* Copy the lpsaActions array if needed */
5209 if (dwActionArrayLen
> 0)
5211 /* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */
5212 lpServiceFailureActionsW
->lpsaActions
= (LPSC_ACTION
)((ULONG_PTR
)(lpServiceFailureActionsW
+ 1));
5214 /* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */
5215 RtlCopyMemory(lpServiceFailureActionsW
->lpsaActions
,
5216 lpServiceFailureActionsA
->lpsaActions
,
5221 /* No lpsaActions array */
5222 lpServiceFailureActionsW
->lpsaActions
= NULL
;
5224 /* The data strings are stored just after the lpsaActions array */
5225 lpStr
= (LPWSTR
)((ULONG_PTR
)(lpServiceFailureActionsW
+ 1) + dwActionArrayLen
);
5228 * Convert the data strings to UNICODE
5231 lpServiceFailureActionsW
->lpRebootMsg
= NULL
;
5232 lpServiceFailureActionsW
->lpCommand
= NULL
;
5236 /* lpRebootMsg points just after the lpsaActions array */
5237 lpServiceFailureActionsW
->lpRebootMsg
= lpStr
;
5239 MultiByteToWideChar(CP_ACP
,
5241 lpServiceFailureActionsA
->lpRebootMsg
,
5243 lpServiceFailureActionsW
->lpRebootMsg
,
5246 lpStr
+= dwRebootLen
/ sizeof(WCHAR
);
5251 /* lpRebootMsg points just after the lpRebootMsg data string */
5252 lpServiceFailureActionsW
->lpCommand
= lpStr
;
5254 MultiByteToWideChar(CP_ACP
,
5256 lpServiceFailureActionsA
->lpCommand
,
5258 lpServiceFailureActionsW
->lpCommand
,
5262 /* Set the pointers */
5263 ptr
= lpServiceFailureActionsW
;
5264 InfoW
.psfa
= lpServiceFailureActionsW
;
5268 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
5270 HeapFree(GetProcessHeap(), 0, ptr
);
5277 ScmSetFailureActions(HKEY hServiceKey
,
5278 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
)
5280 LPSERVICE_FAILURE_ACTIONSW lpReadBuffer
= NULL
;
5281 LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer
= NULL
;
5282 DWORD dwRequiredSize
= 0;
5286 /* There is nothing to be done if we have no failure actions */
5287 if (lpFailureActions
== NULL
)
5288 return ERROR_SUCCESS
;
5291 * 1- Retrieve the original value of FailureActions.
5294 /* Query value length */
5295 dwError
= RegQueryValueExW(hServiceKey
,
5301 if (dwError
!= ERROR_SUCCESS
&&
5302 dwError
!= ERROR_MORE_DATA
&&
5303 dwError
!= ERROR_FILE_NOT_FOUND
)
5306 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSW
), dwRequiredSize
)
5307 : sizeof(SERVICE_FAILURE_ACTIONSW
);
5309 /* Initialize the read buffer */
5310 lpReadBuffer
= HeapAlloc(GetProcessHeap(),
5313 if (lpReadBuffer
== NULL
)
5314 return ERROR_NOT_ENOUGH_MEMORY
;
5316 /* Now we can fill the read buffer */
5317 if (dwError
!= ERROR_FILE_NOT_FOUND
&&
5318 dwType
== REG_BINARY
)
5320 dwError
= RegQueryValueExW(hServiceKey
,
5324 (LPBYTE
)lpReadBuffer
,
5326 if (dwError
!= ERROR_SUCCESS
&&
5327 dwError
!= ERROR_FILE_NOT_FOUND
)
5330 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSW
))
5331 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5336 * The value of the error doesn't really matter, the only
5337 * important thing is that it must be != ERROR_SUCCESS.
5339 dwError
= ERROR_INVALID_DATA
;
5342 if (dwError
== ERROR_SUCCESS
)
5344 lpReadBuffer
->cActions
= min(lpReadBuffer
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSW
)) / sizeof(SC_ACTION
));
5345 lpReadBuffer
->lpsaActions
= (lpReadBuffer
->cActions
> 0 ? (LPSC_ACTION
)(lpReadBuffer
+ 1) : NULL
);
5349 lpReadBuffer
->dwResetPeriod
= 0;
5350 lpReadBuffer
->cActions
= 0;
5351 lpReadBuffer
->lpsaActions
= NULL
;
5354 lpReadBuffer
->lpRebootMsg
= NULL
;
5355 lpReadBuffer
->lpCommand
= NULL
;
5358 * 2- Initialize the new value to set.
5361 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5363 if (lpFailureActions
->lpsaActions
== NULL
)
5366 * lpFailureActions->cActions is ignored.
5367 * Therefore we use the original values
5368 * of cActions and lpsaActions.
5370 dwRequiredSize
+= lpReadBuffer
->cActions
* sizeof(SC_ACTION
);
5375 * The reset period and array of failure actions
5376 * are deleted if lpFailureActions->cActions == 0 .
5378 dwRequiredSize
+= lpFailureActions
->cActions
* sizeof(SC_ACTION
);
5381 lpWriteBuffer
= HeapAlloc(GetProcessHeap(),
5384 if (lpWriteBuffer
== NULL
)
5386 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
5390 /* Clean the pointers as they have no meaning when the structure is stored in the registry */
5391 lpWriteBuffer
->lpRebootMsg
= NULL
;
5392 lpWriteBuffer
->lpCommand
= NULL
;
5393 lpWriteBuffer
->lpsaActions
= NULL
;
5395 /* Set the members */
5396 if (lpFailureActions
->lpsaActions
== NULL
)
5399 * lpFailureActions->dwResetPeriod and lpFailureActions->cActions are ignored.
5400 * Therefore we use the original values of dwResetPeriod, cActions and lpsaActions.
5402 lpWriteBuffer
->dwResetPeriod
= lpReadBuffer
->dwResetPeriod
;
5403 lpWriteBuffer
->cActions
= lpReadBuffer
->cActions
;
5405 if (lpReadBuffer
->lpsaActions
!= NULL
)
5407 memmove(lpWriteBuffer
+ 1,
5408 lpReadBuffer
->lpsaActions
,
5409 lpReadBuffer
->cActions
* sizeof(SC_ACTION
));
5414 if (lpFailureActions
->cActions
> 0)
5416 lpWriteBuffer
->dwResetPeriod
= lpFailureActions
->dwResetPeriod
;
5417 lpWriteBuffer
->cActions
= lpFailureActions
->cActions
;
5419 memmove(lpWriteBuffer
+ 1,
5420 lpFailureActions
->lpsaActions
,
5421 lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5425 /* The reset period and array of failure actions are deleted */
5426 lpWriteBuffer
->dwResetPeriod
= 0;
5427 lpWriteBuffer
->cActions
= 0;
5431 /* Save the new failure actions into the registry */
5432 dwError
= RegSetValueExW(hServiceKey
,
5436 (LPBYTE
)lpWriteBuffer
,
5439 /* We modify the strings only in case of success.*/
5440 if (dwError
== ERROR_SUCCESS
)
5442 /* Modify the Reboot Message value, if specified */
5443 if (lpFailureActions
->lpRebootMsg
!= NULL
)
5445 /* If the Reboot Message is "" then we delete it */
5446 if (*lpFailureActions
->lpRebootMsg
== 0)
5448 DPRINT("Delete Reboot Message value\n");
5449 RegDeleteValueW(hServiceKey
, L
"RebootMessage");
5453 DPRINT("Setting Reboot Message value %S\n", lpFailureActions
->lpRebootMsg
);
5454 RegSetValueExW(hServiceKey
,
5458 (LPBYTE
)lpFailureActions
->lpRebootMsg
,
5459 (DWORD
)((wcslen(lpFailureActions
->lpRebootMsg
) + 1) * sizeof(WCHAR
)));
5463 /* Modify the Failure Command value, if specified */
5464 if (lpFailureActions
->lpCommand
!= NULL
)
5466 /* If the FailureCommand string is an empty string, delete the value */
5467 if (*lpFailureActions
->lpCommand
== 0)
5469 DPRINT("Delete Failure Command value\n");
5470 RegDeleteValueW(hServiceKey
, L
"FailureCommand");
5474 DPRINT("Setting Failure Command value %S\n", lpFailureActions
->lpCommand
);
5475 RegSetValueExW(hServiceKey
,
5479 (LPBYTE
)lpFailureActions
->lpCommand
,
5480 (DWORD
)((wcslen(lpFailureActions
->lpCommand
) + 1) * sizeof(WCHAR
)));
5486 if (lpWriteBuffer
!= NULL
)
5487 HeapFree(GetProcessHeap(), 0, lpWriteBuffer
);
5489 if (lpReadBuffer
!= NULL
)
5490 HeapFree(GetProcessHeap(), 0, lpReadBuffer
);
5499 RChangeServiceConfig2W(
5500 SC_RPC_HANDLE hService
,
5501 SC_RPC_CONFIG_INFOW Info
)
5503 DWORD dwError
= ERROR_SUCCESS
;
5504 PSERVICE_HANDLE hSvc
;
5505 PSERVICE lpService
= NULL
;
5506 HKEY hServiceKey
= NULL
;
5507 ACCESS_MASK RequiredAccess
= SERVICE_CHANGE_CONFIG
;
5509 DPRINT("RChangeServiceConfig2W() called\n");
5510 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
5513 return ERROR_SHUTDOWN_IN_PROGRESS
;
5515 if ((Info
.dwInfoLevel
< SERVICE_CONFIG_DESCRIPTION
) ||
5516 (Info
.dwInfoLevel
> SERVICE_CONFIG_FAILURE_ACTIONS
))
5517 return ERROR_INVALID_LEVEL
;
5519 hSvc
= ScmGetServiceFromHandle(hService
);
5522 DPRINT("Invalid service handle!\n");
5523 return ERROR_INVALID_HANDLE
;
5526 if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5527 RequiredAccess
|= SERVICE_START
;
5529 /* Check the access rights */
5530 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5533 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5534 return ERROR_ACCESS_DENIED
;
5537 if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5539 /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */
5543 lpService
= hSvc
->ServiceEntry
;
5544 if (lpService
== NULL
)
5546 DPRINT("lpService == NULL!\n");
5547 return ERROR_INVALID_HANDLE
;
5550 /* Failure actions can only be set for Win32 services, not for drivers */
5551 if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5553 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
5554 return ERROR_CANNOT_DETECT_DRIVER_FAILURE
;
5557 /* Lock the service database exclusively */
5558 ScmLockDatabaseExclusive();
5560 if (lpService
->bDeleted
)
5562 DPRINT("The service has already been marked for delete!\n");
5563 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
5567 /* Open the service key */
5568 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
5569 KEY_READ
| KEY_SET_VALUE
,
5571 if (dwError
!= ERROR_SUCCESS
)
5574 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5576 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
5578 /* Modify the service description, if specified */
5579 if (lpServiceDescription
!= NULL
&&
5580 lpServiceDescription
->lpDescription
!= NULL
)
5582 /* If the description is "" then we delete it */
5583 if (*lpServiceDescription
->lpDescription
== 0)
5585 DPRINT("Delete service description\n");
5586 dwError
= RegDeleteValueW(hServiceKey
, L
"Description");
5588 if (dwError
== ERROR_FILE_NOT_FOUND
)
5589 dwError
= ERROR_SUCCESS
;
5593 DPRINT("Setting service description value %S\n", lpServiceDescription
->lpDescription
);
5594 dwError
= RegSetValueExW(hServiceKey
,
5598 (LPBYTE
)lpServiceDescription
->lpDescription
,
5599 (DWORD
)((wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
)));
5604 dwError
= ERROR_SUCCESS
;
5607 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5609 dwError
= ScmSetFailureActions(hServiceKey
,
5610 (LPSERVICE_FAILURE_ACTIONSW
)Info
.psfa
);
5614 if (hServiceKey
!= NULL
)
5615 RegCloseKey(hServiceKey
);
5617 /* Unlock the service database */
5618 ScmUnlockDatabase();
5620 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
5629 RQueryServiceConfig2A(
5630 SC_RPC_HANDLE hService
,
5634 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5636 DWORD dwError
= ERROR_SUCCESS
;
5637 PSERVICE_HANDLE hSvc
;
5638 PSERVICE lpService
= NULL
;
5639 HKEY hServiceKey
= NULL
;
5640 DWORD dwRequiredSize
= 0;
5642 LPWSTR lpDescriptionW
= NULL
;
5643 LPWSTR lpRebootMessageW
= NULL
;
5644 LPWSTR lpFailureCommandW
= NULL
;
5646 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
5647 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
5650 return ERROR_INVALID_ADDRESS
;
5653 return ERROR_SHUTDOWN_IN_PROGRESS
;
5655 if ((dwInfoLevel
< SERVICE_CONFIG_DESCRIPTION
) ||
5656 (dwInfoLevel
> SERVICE_CONFIG_FAILURE_ACTIONS
))
5657 return ERROR_INVALID_LEVEL
;
5659 hSvc
= ScmGetServiceFromHandle(hService
);
5662 DPRINT1("Invalid service handle!\n");
5663 return ERROR_INVALID_HANDLE
;
5666 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5667 SERVICE_QUERY_CONFIG
))
5669 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5670 return ERROR_ACCESS_DENIED
;
5673 lpService
= hSvc
->ServiceEntry
;
5674 if (lpService
== NULL
)
5676 DPRINT("lpService == NULL!\n");
5677 return ERROR_INVALID_HANDLE
;
5680 /* Lock the service database shared */
5681 ScmLockDatabaseShared();
5683 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
5686 if (dwError
!= ERROR_SUCCESS
)
5689 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5691 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
5694 dwError
= ScmReadString(hServiceKey
,
5697 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5700 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
5701 if (dwError
== ERROR_SUCCESS
)
5702 *pcbBytesNeeded
+= (DWORD
)((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
5704 if (cbBufSize
< *pcbBytesNeeded
)
5706 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5710 if (dwError
== ERROR_SUCCESS
)
5712 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
5714 WideCharToMultiByte(CP_ACP
,
5719 (int)wcslen(lpDescriptionW
),
5722 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
5726 lpServiceDescription
->lpDescription
= NULL
;
5727 dwError
= ERROR_SUCCESS
;
5730 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5732 LPSERVICE_FAILURE_ACTIONSA lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSA
)lpBuffer
;
5735 /* Query value length */
5736 dwError
= RegQueryValueExW(hServiceKey
,
5742 if (dwError
!= ERROR_SUCCESS
&&
5743 dwError
!= ERROR_MORE_DATA
&&
5744 dwError
!= ERROR_FILE_NOT_FOUND
)
5747 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSA
), dwRequiredSize
)
5748 : sizeof(SERVICE_FAILURE_ACTIONSA
);
5750 /* Get the strings */
5751 ScmReadString(hServiceKey
,
5753 &lpFailureCommandW
);
5755 ScmReadString(hServiceKey
,
5759 if (lpRebootMessageW
)
5760 dwRequiredSize
+= (DWORD
)((wcslen(lpRebootMessageW
) + 1) * sizeof(WCHAR
));
5762 if (lpFailureCommandW
)
5763 dwRequiredSize
+= (DWORD
)((wcslen(lpFailureCommandW
) + 1) * sizeof(WCHAR
));
5765 if (cbBufSize
< dwRequiredSize
)
5767 *pcbBytesNeeded
= dwRequiredSize
;
5768 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5772 /* Now we can fill the buffer */
5773 if (dwError
!= ERROR_FILE_NOT_FOUND
&& dwType
== REG_BINARY
)
5775 dwError
= RegQueryValueExW(hServiceKey
,
5779 (LPBYTE
)lpFailureActions
,
5781 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5784 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSA
))
5785 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSA
);
5790 * The value of the error doesn't really matter, the only
5791 * important thing is that it must be != ERROR_SUCCESS .
5793 dwError
= ERROR_INVALID_DATA
;
5796 if (dwError
== ERROR_SUCCESS
)
5798 lpFailureActions
->cActions
= min(lpFailureActions
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSA
)) / sizeof(SC_ACTION
));
5800 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5801 lpFailureActions
->lpsaActions
= (lpFailureActions
->cActions
> 0 ? (LPSC_ACTION
)(ULONG_PTR
)sizeof(SERVICE_FAILURE_ACTIONSA
) : NULL
);
5803 lpStr
= (LPSTR
)((ULONG_PTR
)(lpFailureActions
+ 1) + lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5807 lpFailureActions
->dwResetPeriod
= 0;
5808 lpFailureActions
->cActions
= 0;
5809 lpFailureActions
->lpsaActions
= NULL
;
5810 lpStr
= (LPSTR
)(lpFailureActions
+ 1);
5813 lpFailureActions
->lpRebootMsg
= NULL
;
5814 lpFailureActions
->lpCommand
= NULL
;
5816 if (lpRebootMessageW
)
5818 WideCharToMultiByte(CP_ACP
,
5823 (int)wcslen(lpRebootMessageW
),
5826 lpFailureActions
->lpRebootMsg
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5827 lpStr
+= strlen(lpStr
) + 1;
5830 if (lpFailureCommandW
)
5832 WideCharToMultiByte(CP_ACP
,
5837 (int)wcslen(lpFailureCommandW
),
5840 lpFailureActions
->lpCommand
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5841 /* lpStr += strlen(lpStr) + 1; */
5844 dwError
= ERROR_SUCCESS
;
5848 /* Unlock the service database */
5849 ScmUnlockDatabase();
5851 if (lpDescriptionW
!= NULL
)
5852 HeapFree(GetProcessHeap(), 0, lpDescriptionW
);
5854 if (lpRebootMessageW
!= NULL
)
5855 HeapFree(GetProcessHeap(), 0, lpRebootMessageW
);
5857 if (lpFailureCommandW
!= NULL
)
5858 HeapFree(GetProcessHeap(), 0, lpFailureCommandW
);
5860 if (hServiceKey
!= NULL
)
5861 RegCloseKey(hServiceKey
);
5863 DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError
);
5872 RQueryServiceConfig2W(
5873 SC_RPC_HANDLE hService
,
5877 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5879 DWORD dwError
= ERROR_SUCCESS
;
5880 PSERVICE_HANDLE hSvc
;
5881 PSERVICE lpService
= NULL
;
5882 HKEY hServiceKey
= NULL
;
5883 DWORD dwRequiredSize
= 0;
5885 LPWSTR lpDescription
= NULL
;
5886 LPWSTR lpRebootMessage
= NULL
;
5887 LPWSTR lpFailureCommand
= NULL
;
5889 DPRINT("RQueryServiceConfig2W() called\n");
5892 return ERROR_INVALID_ADDRESS
;
5895 return ERROR_SHUTDOWN_IN_PROGRESS
;
5897 if ((dwInfoLevel
< SERVICE_CONFIG_DESCRIPTION
) ||
5898 (dwInfoLevel
> SERVICE_CONFIG_FAILURE_ACTIONS
))
5899 return ERROR_INVALID_LEVEL
;
5901 hSvc
= ScmGetServiceFromHandle(hService
);
5904 DPRINT1("Invalid service handle!\n");
5905 return ERROR_INVALID_HANDLE
;
5908 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5909 SERVICE_QUERY_CONFIG
))
5911 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5912 return ERROR_ACCESS_DENIED
;
5915 lpService
= hSvc
->ServiceEntry
;
5916 if (lpService
== NULL
)
5918 DPRINT("lpService == NULL!\n");
5919 return ERROR_INVALID_HANDLE
;
5922 /* Lock the service database shared */
5923 ScmLockDatabaseShared();
5925 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
5928 if (dwError
!= ERROR_SUCCESS
)
5931 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5933 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
5936 dwError
= ScmReadString(hServiceKey
,
5939 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5942 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
5943 if (dwError
== ERROR_SUCCESS
)
5944 *pcbBytesNeeded
+= (DWORD
)((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
5946 if (cbBufSize
< *pcbBytesNeeded
)
5948 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5952 if (dwError
== ERROR_SUCCESS
)
5954 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
5955 wcscpy(lpStr
, lpDescription
);
5956 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
5960 lpServiceDescription
->lpDescription
= NULL
;
5961 dwError
= ERROR_SUCCESS
;
5964 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5966 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
5967 LPWSTR lpStr
= NULL
;
5969 /* Query value length */
5970 dwError
= RegQueryValueExW(hServiceKey
,
5976 if (dwError
!= ERROR_SUCCESS
&&
5977 dwError
!= ERROR_MORE_DATA
&&
5978 dwError
!= ERROR_FILE_NOT_FOUND
)
5981 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSW
), dwRequiredSize
)
5982 : sizeof(SERVICE_FAILURE_ACTIONSW
);
5984 /* Get the strings */
5985 ScmReadString(hServiceKey
,
5989 ScmReadString(hServiceKey
,
5993 if (lpRebootMessage
)
5994 dwRequiredSize
+= (DWORD
)((wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
));
5996 if (lpFailureCommand
)
5997 dwRequiredSize
+= (DWORD
)((wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
));
5999 if (cbBufSize
< dwRequiredSize
)
6001 *pcbBytesNeeded
= dwRequiredSize
;
6002 dwError
= ERROR_INSUFFICIENT_BUFFER
;
6006 /* Now we can fill the buffer */
6007 if (dwError
!= ERROR_FILE_NOT_FOUND
&& dwType
== REG_BINARY
)
6009 dwError
= RegQueryValueExW(hServiceKey
,
6013 (LPBYTE
)lpFailureActions
,
6015 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
6018 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSW
))
6019 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
6024 * The value of the error doesn't really matter, the only
6025 * important thing is that it must be != ERROR_SUCCESS .
6027 dwError
= ERROR_INVALID_DATA
;
6030 if (dwError
== ERROR_SUCCESS
)
6032 lpFailureActions
->cActions
= min(lpFailureActions
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSW
)) / sizeof(SC_ACTION
));
6034 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
6035 lpFailureActions
->lpsaActions
= (lpFailureActions
->cActions
> 0 ? (LPSC_ACTION
)(ULONG_PTR
)sizeof(SERVICE_FAILURE_ACTIONSW
) : NULL
);
6037 lpStr
= (LPWSTR
)((ULONG_PTR
)(lpFailureActions
+ 1) + lpFailureActions
->cActions
* sizeof(SC_ACTION
));
6041 lpFailureActions
->dwResetPeriod
= 0;
6042 lpFailureActions
->cActions
= 0;
6043 lpFailureActions
->lpsaActions
= NULL
;
6044 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
6047 lpFailureActions
->lpRebootMsg
= NULL
;
6048 lpFailureActions
->lpCommand
= NULL
;
6050 if (lpRebootMessage
)
6052 wcscpy(lpStr
, lpRebootMessage
);
6053 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
6054 lpStr
+= wcslen(lpStr
) + 1;
6057 if (lpFailureCommand
)
6059 wcscpy(lpStr
, lpFailureCommand
);
6060 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
6061 /* lpStr += wcslen(lpStr) + 1; */
6064 dwError
= ERROR_SUCCESS
;
6068 /* Unlock the service database */
6069 ScmUnlockDatabase();
6071 if (lpDescription
!= NULL
)
6072 HeapFree(GetProcessHeap(), 0, lpDescription
);
6074 if (lpRebootMessage
!= NULL
)
6075 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
6077 if (lpFailureCommand
!= NULL
)
6078 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
6080 if (hServiceKey
!= NULL
)
6081 RegCloseKey(hServiceKey
);
6083 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
6092 RQueryServiceStatusEx(
6093 SC_RPC_HANDLE hService
,
6094 SC_STATUS_TYPE InfoLevel
,
6097 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
6099 LPSERVICE_STATUS_PROCESS lpStatus
;
6100 PSERVICE_HANDLE hSvc
;
6103 DPRINT("RQueryServiceStatusEx() called\n");
6106 return ERROR_SHUTDOWN_IN_PROGRESS
;
6108 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
6109 return ERROR_INVALID_LEVEL
;
6111 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
6113 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
6114 return ERROR_INSUFFICIENT_BUFFER
;
6116 hSvc
= ScmGetServiceFromHandle(hService
);
6119 DPRINT1("Invalid service handle!\n");
6120 return ERROR_INVALID_HANDLE
;
6123 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
6124 SERVICE_QUERY_STATUS
))
6126 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
6127 return ERROR_ACCESS_DENIED
;
6130 lpService
= hSvc
->ServiceEntry
;
6131 if (lpService
== NULL
)
6133 DPRINT("lpService == NULL!\n");
6134 return ERROR_INVALID_HANDLE
;
6137 /* Lock the service database shared */
6138 ScmLockDatabaseShared();
6140 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
6142 /* Return service status information */
6143 RtlCopyMemory(lpStatus
,
6145 sizeof(SERVICE_STATUS
));
6147 /* Copy the service process ID */
6148 if ((lpService
->Status
.dwCurrentState
== SERVICE_STOPPED
) || (lpService
->lpImage
== NULL
))
6149 lpStatus
->dwProcessId
= 0;
6151 lpStatus
->dwProcessId
= lpService
->lpImage
->dwProcessId
;
6153 lpStatus
->dwServiceFlags
= 0; /* FIXME */
6155 /* Unlock the service database */
6156 ScmUnlockDatabase();
6158 return ERROR_SUCCESS
;
6165 REnumServicesStatusExA(
6166 SC_RPC_HANDLE hSCManager
,
6167 SC_ENUM_TYPE InfoLevel
,
6168 DWORD dwServiceType
,
6169 DWORD dwServiceState
,
6172 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
6173 LPBOUNDED_DWORD_256K lpServicesReturned
,
6174 LPBOUNDED_DWORD_256K lpResumeIndex
,
6175 LPCSTR pszGroupName
)
6177 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
6178 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW
;
6179 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
6180 LPWSTR lpStringPtrW
;
6182 LPWSTR pszGroupNameW
= NULL
;
6184 DWORD dwServiceCount
;
6186 DPRINT("REnumServicesStatusExA() called\n");
6188 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
6190 return ERROR_INVALID_ADDRESS
;
6195 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
6198 DPRINT("Failed to allocate buffer!\n");
6199 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
6203 MultiByteToWideChar(CP_ACP
,
6208 (int)(strlen(pszGroupName
) + 1));
6211 if ((cbBufSize
> 0) && (lpBuffer
))
6213 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
6216 DPRINT("Failed to allocate buffer!\n");
6217 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
6222 dwError
= REnumServicesStatusExW(hSCManager
,
6226 (LPBYTE
)lpStatusPtrW
,
6233 /* if no services were returned then we are Done */
6234 if (*lpServicesReturned
== 0)
6237 lpStatusPtrIncrW
= lpStatusPtrW
;
6238 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
6239 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
6240 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
6241 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
6242 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
6244 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
6246 /* Copy the service name */
6247 WideCharToMultiByte(CP_ACP
,
6252 (int)wcslen(lpStringPtrW
),
6256 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
6257 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
6258 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
6260 /* Copy the display name */
6261 WideCharToMultiByte(CP_ACP
,
6266 (int)wcslen(lpStringPtrW
),
6270 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
6271 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
6272 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
6274 /* Copy the status information */
6275 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
6276 &lpStatusPtrIncrW
->ServiceStatusProcess
,
6277 sizeof(SERVICE_STATUS
));
6279 /* Copy the service process ID */
6280 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrIncrW
->ServiceStatusProcess
.dwProcessId
;
6282 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
6290 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
6293 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
6295 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
6304 REnumServicesStatusExW(
6305 SC_RPC_HANDLE hSCManager
,
6306 SC_ENUM_TYPE InfoLevel
,
6307 DWORD dwServiceType
,
6308 DWORD dwServiceState
,
6311 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
6312 LPBOUNDED_DWORD_256K lpServicesReturned
,
6313 LPBOUNDED_DWORD_256K lpResumeIndex
,
6314 LPCWSTR pszGroupName
)
6316 PMANAGER_HANDLE hManager
;
6318 DWORD dwError
= ERROR_SUCCESS
;
6319 PLIST_ENTRY ServiceEntry
;
6320 PSERVICE CurrentService
;
6322 DWORD dwRequiredSize
;
6323 DWORD dwServiceCount
;
6325 DWORD dwLastResumeCount
= 0;
6326 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
6329 DPRINT("REnumServicesStatusExW() called\n");
6332 return ERROR_SHUTDOWN_IN_PROGRESS
;
6334 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
6335 return ERROR_INVALID_LEVEL
;
6337 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
6338 if (hManager
== NULL
)
6340 DPRINT1("Invalid service manager handle!\n");
6341 return ERROR_INVALID_HANDLE
;
6344 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
6346 return ERROR_INVALID_ADDRESS
;
6349 *pcbBytesNeeded
= 0;
6350 *lpServicesReturned
= 0;
6352 if ((dwServiceType
== 0) ||
6353 ((dwServiceType
& ~SERVICE_TYPE_ALL
) != 0))
6355 DPRINT("Not a valid Service Type!\n");
6356 return ERROR_INVALID_PARAMETER
;
6359 if ((dwServiceState
== 0) ||
6360 ((dwServiceState
& ~SERVICE_STATE_ALL
) != 0))
6362 DPRINT("Not a valid Service State!\n");
6363 return ERROR_INVALID_PARAMETER
;
6366 /* Check access rights */
6367 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
6368 SC_MANAGER_ENUMERATE_SERVICE
))
6370 DPRINT("Insufficient access rights! 0x%lx\n",
6371 hManager
->Handle
.DesiredAccess
);
6372 return ERROR_ACCESS_DENIED
;
6376 dwLastResumeCount
= *lpResumeIndex
;
6378 /* Lock the service database shared */
6379 ScmLockDatabaseShared();
6381 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
6382 if (lpService
== NULL
)
6384 dwError
= ERROR_SUCCESS
;
6391 for (ServiceEntry
= &lpService
->ServiceListEntry
;
6392 ServiceEntry
!= &ServiceListHead
;
6393 ServiceEntry
= ServiceEntry
->Flink
)
6395 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
6399 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
6402 dwState
= SERVICE_ACTIVE
;
6403 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
6404 dwState
= SERVICE_INACTIVE
;
6406 if ((dwState
& dwServiceState
) == 0)
6411 if (*pszGroupName
== 0)
6413 if (CurrentService
->lpGroup
!= NULL
)
6418 if ((CurrentService
->lpGroup
== NULL
) ||
6419 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
6424 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
6425 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
6426 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
6428 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
6430 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
6431 dwRequiredSize
+= dwSize
;
6433 dwLastResumeCount
= CurrentService
->dwResumeCount
;
6437 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
6443 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
6444 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
6447 ServiceEntry
!= &ServiceListHead
;
6448 ServiceEntry
= ServiceEntry
->Flink
)
6450 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
6454 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
6457 dwState
= SERVICE_ACTIVE
;
6458 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
6459 dwState
= SERVICE_INACTIVE
;
6461 if ((dwState
& dwServiceState
) == 0)
6466 if (*pszGroupName
== 0)
6468 if (CurrentService
->lpGroup
!= NULL
)
6473 if ((CurrentService
->lpGroup
== NULL
) ||
6474 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
6479 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
6480 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
6481 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
6483 dwError
= ERROR_MORE_DATA
;
6486 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
6489 *lpResumeIndex
= dwLastResumeCount
;
6491 *lpServicesReturned
= dwServiceCount
;
6492 *pcbBytesNeeded
= dwRequiredSize
;
6494 /* If there was no services that matched */
6495 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
6497 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
6501 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
6502 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
6503 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
6506 for (ServiceEntry
= &lpService
->ServiceListEntry
;
6507 ServiceEntry
!= &ServiceListHead
;
6508 ServiceEntry
= ServiceEntry
->Flink
)
6510 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
6514 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
6517 dwState
= SERVICE_ACTIVE
;
6518 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
6519 dwState
= SERVICE_INACTIVE
;
6521 if ((dwState
& dwServiceState
) == 0)
6526 if (*pszGroupName
== 0)
6528 if (CurrentService
->lpGroup
!= NULL
)
6533 if ((CurrentService
->lpGroup
== NULL
) ||
6534 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
6539 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
6540 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
6541 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
6543 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
6545 /* Copy the service name */
6547 CurrentService
->lpServiceName
);
6548 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
6549 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
6551 /* Copy the display name */
6553 CurrentService
->lpDisplayName
);
6554 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
6555 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
6557 /* Copy the status information */
6558 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
6559 &CurrentService
->Status
,
6560 sizeof(SERVICE_STATUS
));
6562 /* Copy the service process ID */
6563 if ((CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
) || (CurrentService
->lpImage
== NULL
))
6564 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= 0;
6566 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->lpImage
->dwProcessId
;
6568 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
6571 dwRequiredSize
+= dwSize
;
6581 *pcbBytesNeeded
= 0;
6587 /* Unlock the service database */
6588 ScmUnlockDatabase();
6590 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
6600 handle_t BindingHandle
) /* FIXME */
6603 return ERROR_CALL_NOT_IMPLEMENTED
;
6610 RCreateServiceWOW64A(
6611 handle_t BindingHandle
,
6612 LPSTR lpServiceName
,
6613 LPSTR lpDisplayName
,
6614 DWORD dwDesiredAccess
,
6615 DWORD dwServiceType
,
6617 DWORD dwErrorControl
,
6618 LPSTR lpBinaryPathName
,
6619 LPSTR lpLoadOrderGroup
,
6621 LPBYTE lpDependencies
,
6623 LPSTR lpServiceStartName
,
6626 LPSC_RPC_HANDLE lpServiceHandle
)
6629 return ERROR_CALL_NOT_IMPLEMENTED
;
6636 RCreateServiceWOW64W(
6637 handle_t BindingHandle
,
6638 LPWSTR lpServiceName
,
6639 LPWSTR lpDisplayName
,
6640 DWORD dwDesiredAccess
,
6641 DWORD dwServiceType
,
6643 DWORD dwErrorControl
,
6644 LPWSTR lpBinaryPathName
,
6645 LPWSTR lpLoadOrderGroup
,
6647 LPBYTE lpDependencies
,
6649 LPWSTR lpServiceStartName
,
6652 LPSC_RPC_HANDLE lpServiceHandle
)
6655 return ERROR_CALL_NOT_IMPLEMENTED
;
6662 RQueryServiceTagInfo(
6663 handle_t BindingHandle
) /* FIXME */
6666 return ERROR_CALL_NOT_IMPLEMENTED
;
6673 RNotifyServiceStatusChange(
6674 SC_RPC_HANDLE hService
,
6675 SC_RPC_NOTIFY_PARAMS NotifyParams
,
6676 GUID
*pClientProcessGuid
,
6677 GUID
*pSCMProcessGuid
,
6678 PBOOL pfCreateRemoteQueue
,
6679 LPSC_NOTIFY_RPC_HANDLE phNotify
)
6682 return ERROR_CALL_NOT_IMPLEMENTED
;
6690 SC_NOTIFY_RPC_HANDLE hNotify
,
6691 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
6694 return ERROR_CALL_NOT_IMPLEMENTED
;
6702 LPSC_NOTIFY_RPC_HANDLE phNotify
,
6706 return ERROR_CALL_NOT_IMPLEMENTED
;
6714 SC_RPC_HANDLE hService
,
6719 return ERROR_CALL_NOT_IMPLEMENTED
;
6727 SC_RPC_HANDLE hService
,
6732 return ERROR_CALL_NOT_IMPLEMENTED
;
6740 handle_t BindingHandle
) /* FIXME */
6743 return ERROR_CALL_NOT_IMPLEMENTED
;
6750 RValidatePnPService(
6751 handle_t BindingHandle
) /* FIXME */
6754 return ERROR_CALL_NOT_IMPLEMENTED
;
6761 ROpenServiceStatusHandle(
6762 handle_t BindingHandle
) /* FIXME */
6765 return ERROR_CALL_NOT_IMPLEMENTED
;
6773 handle_t BindingHandle
) /* FIXME */
6776 return ERROR_CALL_NOT_IMPLEMENTED
;
6780 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
6782 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
6786 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
6788 HeapFree(GetProcessHeap(), 0, ptr
);
6792 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
6794 /* Close the handle */
6795 RCloseServiceHandle(&hSCObject
);
6799 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
6801 /* Unlock the database */
6802 RUnlockServiceDatabase(&Lock
);
6806 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)