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);
468 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
469 return ERROR_INVALID_ENVIRONMENT
;
472 /* Allocate memory, since the size is known now */
473 Expanded
= HeapAlloc(GetProcessHeap(),
475 (BufferSize
+ 1) * sizeof(WCHAR
));
478 DPRINT("Error allocating memory for boot driver name!\n");
479 return ERROR_NOT_ENOUGH_MEMORY
;
483 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
486 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
487 HeapFree(GetProcessHeap(), 0, Expanded
);
488 return ERROR_NOT_ENOUGH_MEMORY
;
491 /* Convert to NT-style path */
492 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
494 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
495 return ERROR_INVALID_ENVIRONMENT
;
498 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
500 /* No need to keep the dos-path anymore */
501 HeapFree(GetProcessHeap(), 0, Expanded
);
503 /* Copy it to the allocated place */
504 Expanded
= HeapAlloc(GetProcessHeap(),
506 NtPathName
.Length
+ sizeof(UNICODE_NULL
));
509 DPRINT("Error allocating memory for boot driver name!\n");
510 RtlFreeUnicodeString(&NtPathName
);
511 return ERROR_NOT_ENOUGH_MEMORY
;
514 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
515 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
516 Expanded
[ExpandedLen
] = UNICODE_NULL
;
517 RtlFreeUnicodeString(&NtPathName
);
519 if (ServiceNameLen
> ExpandedLen
&&
520 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
522 HeapFree(GetProcessHeap(), 0, Expanded
);
524 /* Only \SystemRoot\ is missing */
525 *RelativeName
= HeapAlloc(GetProcessHeap(),
527 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
528 if (*RelativeName
== NULL
)
530 DPRINT("Error allocating memory for boot driver name!\n");
531 return ERROR_NOT_ENOUGH_MEMORY
;
534 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
535 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
537 return ERROR_SUCCESS
;
540 /* No longer need this */
541 HeapFree(GetProcessHeap(), 0, Expanded
);
543 /* The most complex case starts here */
544 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
545 InitializeObjectAttributes(&ObjectAttributes
,
547 OBJ_CASE_INSENSITIVE
,
551 /* Open this symlink */
552 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
553 if (NT_SUCCESS(Status
))
555 DPRINT("Opened symbolic link object\n");
557 RtlInitEmptyUnicodeString(&LinkTarget
, NULL
, 0);
558 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
559 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
561 /* Check if required buffer size is sane */
562 if (BufferSize
> UNICODE_STRING_MAX_BYTES
- sizeof(UNICODE_NULL
))
564 DPRINT("Too large buffer required\n");
566 NtClose(SymbolicLinkHandle
);
567 return ERROR_NOT_ENOUGH_MEMORY
;
570 /* Alloc the string */
571 LinkTarget
.Length
= (USHORT
)BufferSize
;
572 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(UNICODE_NULL
);
573 LinkTarget
.Buffer
= HeapAlloc(GetProcessHeap(),
575 LinkTarget
.MaximumLength
);
576 if (!LinkTarget
.Buffer
)
578 DPRINT("Unable to alloc buffer\n");
579 NtClose(SymbolicLinkHandle
);
580 return ERROR_NOT_ENOUGH_MEMORY
;
583 /* Do a real query now */
584 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
585 NtClose(SymbolicLinkHandle
);
586 if (NT_SUCCESS(Status
))
588 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
590 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
591 if ((ServiceNameLen
> ExpandedLen
) &&
592 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
594 *RelativeName
= HeapAlloc(GetProcessHeap(),
596 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
598 if (*RelativeName
== NULL
)
600 DPRINT("Unable to alloc buffer\n");
601 return ERROR_NOT_ENOUGH_MEMORY
;
604 /* Copy it over, substituting the first part
606 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
607 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
610 return ERROR_SUCCESS
;
614 return ERROR_INVALID_PARAMETER
;
619 DPRINT("Error, Status = %08X\n", Status
);
620 return ERROR_INVALID_PARAMETER
;
625 DPRINT("Error, Status = %08X\n", Status
);
626 NtClose(SymbolicLinkHandle
);
627 return ERROR_INVALID_PARAMETER
;
633 DPRINT("Error, Status = %08X\n", Status
);
634 return ERROR_INVALID_PARAMETER
;
640 ScmCanonDriverImagePath(DWORD dwStartType
,
641 const wchar_t *lpServiceName
,
642 wchar_t **lpCanonName
)
645 SIZE_T ServiceNameLen
;
646 UNICODE_STRING NtServiceName
;
648 const WCHAR
*SourceName
= lpServiceName
;
650 /* Calculate the length of the service's name */
651 ServiceNameLen
= wcslen(lpServiceName
);
653 /* 12 is wcslen(L"\\SystemRoot\\") */
654 if (ServiceNameLen
> 12 &&
655 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
657 /* SystemRoot prefix is already included */
658 *lpCanonName
= HeapAlloc(GetProcessHeap(),
660 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
662 if (*lpCanonName
== NULL
)
664 DPRINT("Error allocating memory for canonized service name!\n");
665 return ERROR_NOT_ENOUGH_MEMORY
;
668 /* If it's a boot-time driver, it must be systemroot relative */
669 if (dwStartType
== SERVICE_BOOT_START
)
673 wcscpy(*lpCanonName
, SourceName
);
675 DPRINT("Canonicalized name %S\n", *lpCanonName
);
679 /* Check if it has %SystemRoot% (len=13) */
680 if (ServiceNameLen
> 13 &&
681 !_wcsnicmp(L
"%SystemRoot%\\", lpServiceName
, 13))
683 /* Substitute %SystemRoot% with \\SystemRoot\\ */
684 *lpCanonName
= HeapAlloc(GetProcessHeap(),
686 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
688 if (*lpCanonName
== NULL
)
690 DPRINT("Error allocating memory for canonized service name!\n");
691 return ERROR_NOT_ENOUGH_MEMORY
;
694 /* If it's a boot-time driver, it must be systemroot relative */
695 if (dwStartType
== SERVICE_BOOT_START
)
696 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
698 wcscat(*lpCanonName
, lpServiceName
+ 13);
700 DPRINT("Canonicalized name %S\n", *lpCanonName
);
704 /* Check if it's a relative path name */
705 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
707 *lpCanonName
= HeapAlloc(GetProcessHeap(),
709 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
711 if (*lpCanonName
== NULL
)
713 DPRINT("Error allocating memory for canonized service name!\n");
714 return ERROR_NOT_ENOUGH_MEMORY
;
717 /* Just copy it over without changing */
718 wcscpy(*lpCanonName
, lpServiceName
);
723 /* It seems to be a DOS path, convert it */
724 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
726 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
727 return ERROR_INVALID_PARAMETER
;
730 *lpCanonName
= HeapAlloc(GetProcessHeap(),
732 NtServiceName
.Length
+ sizeof(WCHAR
));
734 if (*lpCanonName
== NULL
)
736 DPRINT("Error allocating memory for canonized service name!\n");
737 RtlFreeUnicodeString(&NtServiceName
);
738 return ERROR_NOT_ENOUGH_MEMORY
;
741 /* Copy the string */
742 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
744 /* The unicode string is not needed anymore */
745 RtlFreeUnicodeString(&NtServiceName
);
747 if (dwStartType
!= SERVICE_BOOT_START
)
749 DPRINT("Canonicalized name %S\n", *lpCanonName
);
753 /* The service is boot-started, so must be relative */
754 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
757 /* There is a problem, free name and return */
758 HeapFree(GetProcessHeap(), 0, *lpCanonName
);
759 DPRINT("Error converting named!\n");
763 ASSERT(RelativeName
);
765 /* Copy that string */
766 wcscpy(*lpCanonName
, RelativeName
+ 12);
768 /* Free the allocated buffer */
769 HeapFree(GetProcessHeap(), 0, RelativeName
);
771 DPRINT("Canonicalized name %S\n", *lpCanonName
);
778 /* Internal recursive function */
779 /* Need to search for every dependency on every service */
781 Int_EnumDependentServicesW(HKEY hServicesKey
,
783 DWORD dwServiceState
,
784 PSERVICE
*lpServices
,
785 LPDWORD pcbBytesNeeded
,
786 LPDWORD lpServicesReturned
)
788 DWORD dwError
= ERROR_SUCCESS
;
789 WCHAR szNameBuf
[MAX_PATH
];
790 WCHAR szValueBuf
[MAX_PATH
];
791 WCHAR
*lpszNameBuf
= szNameBuf
;
792 WCHAR
*lpszValueBuf
= szValueBuf
;
796 PSERVICE lpCurrentService
;
797 HKEY hServiceEnumKey
;
798 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
799 DWORD dwDependServiceStrPtr
= 0;
800 DWORD dwRequiredSize
= 0;
802 /* Get the number of service keys */
803 dwError
= RegQueryInfoKeyW(hServicesKey
,
815 if (dwError
!= ERROR_SUCCESS
)
817 DPRINT("ERROR! Unable to get number of services keys.\n");
821 /* Iterate the service keys to see if another service depends on the this service */
822 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
825 dwError
= RegEnumKeyExW(hServicesKey
,
833 if (dwError
!= ERROR_SUCCESS
)
836 /* Open the Service key */
837 dwError
= RegOpenKeyExW(hServicesKey
,
842 if (dwError
!= ERROR_SUCCESS
)
845 dwSize
= MAX_PATH
* sizeof(WCHAR
);
847 /* Check for the DependOnService Value */
848 dwError
= RegQueryValueExW(hServiceEnumKey
,
852 (LPBYTE
)lpszValueBuf
,
855 /* FIXME: Handle load order. */
857 /* If the service found has a DependOnService value */
858 if (dwError
== ERROR_SUCCESS
)
860 dwDependServiceStrPtr
= 0;
862 /* Can be more than one Dependencies in the DependOnService string */
863 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
865 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
867 /* Get the current enumed service pointer */
868 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
870 /* Check for valid Service */
871 if (!lpCurrentService
)
873 /* This should never happen! */
874 DPRINT("This should not happen at this point, report to Developer\n");
875 return ERROR_NOT_FOUND
;
878 /* Determine state the service is in */
879 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
880 dwCurrentServiceState
= SERVICE_INACTIVE
;
882 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
883 if ((dwCurrentServiceState
== dwServiceState
) ||
884 (dwServiceState
== SERVICE_STATE_ALL
))
886 /* Calculate the required size */
887 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
888 dwRequiredSize
+= (DWORD
)((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
889 dwRequiredSize
+= (DWORD
)((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
891 /* Add the size for service name and display name pointers */
892 dwRequiredSize
+= (2 * sizeof(PVOID
));
894 /* increase the BytesNeeded size */
895 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
897 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
900 /* Recursive call to check for its dependencies */
901 Int_EnumDependentServicesW(hServicesKey
,
908 /* If the lpServices is valid set the service pointer */
910 lpServices
[*lpServicesReturned
] = lpCurrentService
;
912 *lpServicesReturned
= *lpServicesReturned
+ 1;
916 dwDependServiceStrPtr
+= (DWORD
)(wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
919 else if (*pcbBytesNeeded
)
921 dwError
= ERROR_SUCCESS
;
924 RegCloseKey(hServiceEnumKey
);
935 LPSC_RPC_HANDLE hSCObject
)
937 PMANAGER_HANDLE hManager
;
938 PSERVICE_HANDLE hService
;
942 DWORD pcbBytesNeeded
= 0;
943 DWORD dwServicesReturned
= 0;
945 DPRINT("RCloseServiceHandle() called\n");
947 DPRINT("hSCObject = %p\n", *hSCObject
);
950 return ERROR_INVALID_HANDLE
;
952 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
953 hService
= ScmGetServiceFromHandle(*hSCObject
);
955 if (hManager
!= NULL
)
957 DPRINT("Found manager handle\n");
959 /* Make sure we don't access stale memory if someone tries to use this handle again. */
960 hManager
->Handle
.Tag
= INVALID_TAG
;
962 HeapFree(GetProcessHeap(), 0, hManager
);
967 DPRINT("RCloseServiceHandle() done\n");
968 return ERROR_SUCCESS
;
970 else if (hService
!= NULL
)
972 DPRINT("Found service handle\n");
974 /* Lock the service database exclusively */
975 ScmLockDatabaseExclusive();
977 /* Get the pointer to the service record */
978 lpService
= hService
->ServiceEntry
;
980 /* Make sure we don't access stale memory if someone tries to use this handle again. */
981 hService
->Handle
.Tag
= INVALID_TAG
;
983 /* Free the handle */
984 HeapFree(GetProcessHeap(), 0, hService
);
987 ASSERT(lpService
->dwRefCount
> 0);
989 lpService
->dwRefCount
--;
990 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
991 lpService
->dwRefCount
);
993 if (lpService
->dwRefCount
== 0)
995 /* If this service has been marked for deletion */
996 if (lpService
->bDeleted
&&
997 lpService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
999 /* Open the Services Reg key */
1000 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1001 L
"System\\CurrentControlSet\\Services",
1003 KEY_SET_VALUE
| KEY_READ
,
1005 if (dwError
!= ERROR_SUCCESS
)
1007 DPRINT("Failed to open services key\n");
1008 ScmUnlockDatabase();
1012 /* Call the internal function with NULL, just to get bytes we need */
1013 Int_EnumDependentServicesW(hServicesKey
,
1018 &dwServicesReturned
);
1020 /* If pcbBytesNeeded returned a value then there are services running that are dependent on this service */
1023 DPRINT("Deletion failed due to running dependencies.\n");
1024 RegCloseKey(hServicesKey
);
1025 ScmUnlockDatabase();
1026 return ERROR_SUCCESS
;
1029 /* There are no references and no running dependencies,
1030 it is now safe to delete the service */
1032 /* Delete the Service Key */
1033 dwError
= ScmDeleteRegKey(hServicesKey
,
1034 lpService
->lpServiceName
);
1036 RegCloseKey(hServicesKey
);
1038 if (dwError
!= ERROR_SUCCESS
)
1040 DPRINT("Failed to Delete the Service Registry key\n");
1041 ScmUnlockDatabase();
1045 /* Delete the Service */
1046 ScmDeleteServiceRecord(lpService
);
1050 ScmUnlockDatabase();
1054 DPRINT("RCloseServiceHandle() done\n");
1055 return ERROR_SUCCESS
;
1058 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
1060 return ERROR_INVALID_HANDLE
;
1068 SC_RPC_HANDLE hService
,
1070 LPSERVICE_STATUS lpServiceStatus
)
1072 PSERVICE_HANDLE hSvc
;
1074 ACCESS_MASK DesiredAccess
;
1075 DWORD dwError
= ERROR_SUCCESS
;
1076 DWORD pcbBytesNeeded
= 0;
1077 DWORD dwServicesReturned
= 0;
1078 DWORD dwControlsAccepted
;
1079 DWORD dwCurrentState
;
1080 HKEY hServicesKey
= NULL
;
1081 LPCWSTR lpLogStrings
[2];
1082 WCHAR szLogBuffer
[80];
1085 DPRINT("RControlService() called\n");
1088 return ERROR_SHUTDOWN_IN_PROGRESS
;
1090 /* Check the service handle */
1091 hSvc
= ScmGetServiceFromHandle(hService
);
1094 DPRINT1("Invalid service handle!\n");
1095 return ERROR_INVALID_HANDLE
;
1098 /* Check the service entry point */
1099 lpService
= hSvc
->ServiceEntry
;
1100 if (lpService
== NULL
)
1102 DPRINT1("lpService == NULL!\n");
1103 return ERROR_INVALID_HANDLE
;
1106 /* Check access rights */
1109 case SERVICE_CONTROL_STOP
:
1110 DesiredAccess
= SERVICE_STOP
;
1113 case SERVICE_CONTROL_PAUSE
:
1114 case SERVICE_CONTROL_CONTINUE
:
1115 case SERVICE_CONTROL_PARAMCHANGE
:
1116 case SERVICE_CONTROL_NETBINDADD
:
1117 case SERVICE_CONTROL_NETBINDREMOVE
:
1118 case SERVICE_CONTROL_NETBINDENABLE
:
1119 case SERVICE_CONTROL_NETBINDDISABLE
:
1120 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
1123 case SERVICE_CONTROL_INTERROGATE
:
1124 DesiredAccess
= SERVICE_INTERROGATE
;
1128 if (dwControl
>= 128 && dwControl
<= 255)
1129 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
1131 return ERROR_INVALID_PARAMETER
;
1135 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1137 return ERROR_ACCESS_DENIED
;
1139 /* Return the current service status information */
1140 RtlCopyMemory(lpServiceStatus
,
1142 sizeof(SERVICE_STATUS
));
1144 if (dwControl
== SERVICE_CONTROL_STOP
)
1146 /* Check if the service has dependencies running as windows
1147 doesn't stop a service that does */
1149 /* Open the Services Reg key */
1150 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1151 L
"System\\CurrentControlSet\\Services",
1155 if (dwError
!= ERROR_SUCCESS
)
1157 DPRINT("Failed to open services key\n");
1161 /* Call the internal function with NULL, just to get bytes we need */
1162 Int_EnumDependentServicesW(hServicesKey
,
1167 &dwServicesReturned
);
1169 RegCloseKey(hServicesKey
);
1171 /* If pcbBytesNeeded is not zero then there are services running that
1172 are dependent on this service */
1173 if (pcbBytesNeeded
!= 0)
1175 DPRINT("Service has running dependencies. Failed to stop service.\n");
1176 return ERROR_DEPENDENT_SERVICES_RUNNING
;
1180 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1182 /* Send control code to the driver */
1183 dwError
= ScmControlDriver(lpService
,
1189 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
1190 dwCurrentState
= lpService
->Status
.dwCurrentState
;
1192 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1193 if (lpService
->lpImage
== NULL
|| dwCurrentState
== SERVICE_STOPPED
)
1194 return ERROR_SERVICE_NOT_ACTIVE
;
1196 /* Check the current state before sending a control request */
1197 switch (dwCurrentState
)
1199 case SERVICE_STOP_PENDING
:
1200 case SERVICE_STOPPED
:
1201 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1203 case SERVICE_START_PENDING
:
1206 case SERVICE_CONTROL_STOP
:
1209 case SERVICE_CONTROL_INTERROGATE
:
1210 RtlCopyMemory(lpServiceStatus
,
1212 sizeof(SERVICE_STATUS
));
1213 return ERROR_SUCCESS
;
1216 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1221 /* Check if the control code is acceptable to the service */
1224 case SERVICE_CONTROL_STOP
:
1225 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
1226 return ERROR_INVALID_SERVICE_CONTROL
;
1229 case SERVICE_CONTROL_PAUSE
:
1230 case SERVICE_CONTROL_CONTINUE
:
1231 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
1232 return ERROR_INVALID_SERVICE_CONTROL
;
1235 case SERVICE_CONTROL_PARAMCHANGE
:
1236 if ((dwControlsAccepted
& SERVICE_ACCEPT_PARAMCHANGE
) == 0)
1237 return ERROR_INVALID_SERVICE_CONTROL
;
1240 case SERVICE_CONTROL_NETBINDADD
:
1241 case SERVICE_CONTROL_NETBINDREMOVE
:
1242 case SERVICE_CONTROL_NETBINDENABLE
:
1243 case SERVICE_CONTROL_NETBINDDISABLE
:
1244 if ((dwControlsAccepted
& SERVICE_ACCEPT_NETBINDCHANGE
) == 0)
1245 return ERROR_INVALID_SERVICE_CONTROL
;
1249 /* Send control code to the service */
1250 dwError
= ScmControlService(lpService
->lpImage
->hControlPipe
,
1251 lpService
->lpServiceName
,
1252 (SERVICE_STATUS_HANDLE
)lpService
,
1255 /* Return service status information */
1256 RtlCopyMemory(lpServiceStatus
,
1258 sizeof(SERVICE_STATUS
));
1261 if (dwError
== ERROR_SUCCESS
)
1263 if (dwControl
== SERVICE_CONTROL_STOP
||
1264 dwControl
== SERVICE_CONTROL_PAUSE
||
1265 dwControl
== SERVICE_CONTROL_CONTINUE
)
1267 /* Log a successful send control */
1271 case SERVICE_CONTROL_STOP
:
1272 uID
= IDS_SERVICE_STOP
;
1275 case SERVICE_CONTROL_PAUSE
:
1276 uID
= IDS_SERVICE_PAUSE
;
1279 case SERVICE_CONTROL_CONTINUE
:
1280 uID
= IDS_SERVICE_RESUME
;
1283 LoadStringW(GetModuleHandle(NULL
), uID
, szLogBuffer
, ARRAYSIZE(szLogBuffer
));
1285 lpLogStrings
[0] = lpService
->lpDisplayName
;
1286 lpLogStrings
[1] = szLogBuffer
;
1288 ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS
,
1289 EVENTLOG_INFORMATION_TYPE
,
1303 SC_RPC_HANDLE hService
)
1305 PSERVICE_HANDLE hSvc
;
1309 DPRINT("RDeleteService() called\n");
1312 return ERROR_SHUTDOWN_IN_PROGRESS
;
1314 hSvc
= ScmGetServiceFromHandle(hService
);
1317 DPRINT1("Invalid service handle!\n");
1318 return ERROR_INVALID_HANDLE
;
1321 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1323 return ERROR_ACCESS_DENIED
;
1325 lpService
= hSvc
->ServiceEntry
;
1326 if (lpService
== NULL
)
1328 DPRINT("lpService == NULL!\n");
1329 return ERROR_INVALID_HANDLE
;
1332 /* Lock the service database exclusively */
1333 ScmLockDatabaseExclusive();
1335 if (lpService
->bDeleted
)
1337 DPRINT("The service has already been marked for delete!\n");
1338 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1342 /* Mark service for delete */
1343 lpService
->bDeleted
= TRUE
;
1345 dwError
= ScmMarkServiceForDelete(lpService
);
1348 /* Unlock the service database */
1349 ScmUnlockDatabase();
1351 DPRINT("RDeleteService() done\n");
1360 RLockServiceDatabase(
1361 SC_RPC_HANDLE hSCManager
,
1362 LPSC_RPC_LOCK lpLock
)
1364 PMANAGER_HANDLE hMgr
;
1366 DPRINT("RLockServiceDatabase() called\n");
1370 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
1373 DPRINT1("Invalid service manager handle!\n");
1374 return ERROR_INVALID_HANDLE
;
1377 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
1379 return ERROR_ACCESS_DENIED
;
1381 return ScmAcquireServiceStartLock(FALSE
, lpLock
);
1388 RQueryServiceObjectSecurity(
1389 SC_RPC_HANDLE hService
,
1390 SECURITY_INFORMATION dwSecurityInformation
,
1391 LPBYTE lpSecurityDescriptor
,
1393 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1395 PSERVICE_HANDLE hSvc
;
1397 ULONG DesiredAccess
= 0;
1399 DWORD dwBytesNeeded
;
1402 DPRINT("RQueryServiceObjectSecurity() called\n");
1404 hSvc
= ScmGetServiceFromHandle(hService
);
1407 DPRINT1("Invalid service handle!\n");
1408 return ERROR_INVALID_HANDLE
;
1411 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1412 GROUP_SECURITY_INFORMATION
|
1413 OWNER_SECURITY_INFORMATION
))
1414 DesiredAccess
|= READ_CONTROL
;
1416 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1417 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1419 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1422 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1423 return ERROR_ACCESS_DENIED
;
1426 lpService
= hSvc
->ServiceEntry
;
1427 if (lpService
== NULL
)
1429 DPRINT("lpService == NULL!\n");
1430 return ERROR_INVALID_HANDLE
;
1433 /* Lock the service database */
1434 ScmLockDatabaseShared();
1436 /* Retrieve the security descriptor */
1437 Status
= RtlQuerySecurityObject(lpService
->pSecurityDescriptor
,
1438 dwSecurityInformation
,
1439 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1443 /* Unlock the service database */
1444 ScmUnlockDatabase();
1446 if (NT_SUCCESS(Status
))
1448 *pcbBytesNeeded
= dwBytesNeeded
;
1449 dwError
= STATUS_SUCCESS
;
1451 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1453 *pcbBytesNeeded
= dwBytesNeeded
;
1454 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1456 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1458 dwError
= ERROR_GEN_FAILURE
;
1462 dwError
= RtlNtStatusToDosError(Status
);
1472 RSetServiceObjectSecurity(
1473 SC_RPC_HANDLE hService
,
1474 DWORD dwSecurityInformation
,
1475 LPBYTE lpSecurityDescriptor
,
1476 DWORD dwSecurityDescriptorSize
)
1478 PSERVICE_HANDLE hSvc
;
1480 ACCESS_MASK DesiredAccess
= 0;
1481 HANDLE hToken
= NULL
;
1482 HKEY hServiceKey
= NULL
;
1483 BOOL bDatabaseLocked
= FALSE
;
1487 DPRINT("RSetServiceObjectSecurity() called\n");
1489 hSvc
= ScmGetServiceFromHandle(hService
);
1492 DPRINT1("Invalid service handle!\n");
1493 return ERROR_INVALID_HANDLE
;
1496 if (dwSecurityInformation
== 0 ||
1497 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1498 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1500 return ERROR_INVALID_PARAMETER
;
1503 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1504 return ERROR_INVALID_PARAMETER
;
1506 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1507 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1509 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1510 DesiredAccess
|= WRITE_DAC
;
1512 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1513 DesiredAccess
|= WRITE_OWNER
;
1515 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1516 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1518 return ERROR_INVALID_PARAMETER
;
1521 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1522 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1524 return ERROR_INVALID_PARAMETER
;
1527 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1530 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1531 return ERROR_ACCESS_DENIED
;
1534 lpService
= hSvc
->ServiceEntry
;
1535 if (lpService
== NULL
)
1537 DPRINT1("lpService == NULL!\n");
1538 return ERROR_INVALID_HANDLE
;
1541 if (lpService
->bDeleted
)
1542 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1545 RpcImpersonateClient(NULL
);
1547 Status
= NtOpenThreadToken(NtCurrentThread(),
1551 if (!NT_SUCCESS(Status
))
1552 return RtlNtStatusToDosError(Status
);
1557 /* Build the new security descriptor */
1558 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1559 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1560 &lpService
->pSecurityDescriptor
,
1563 if (!NT_SUCCESS(Status
))
1565 dwError
= RtlNtStatusToDosError(Status
);
1569 /* Lock the service database exclusive */
1570 ScmLockDatabaseExclusive();
1571 bDatabaseLocked
= TRUE
;
1573 /* Open the service key */
1574 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1575 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1577 if (dwError
!= ERROR_SUCCESS
)
1580 /* Store the new security descriptor */
1581 dwError
= ScmWriteSecurityDescriptor(hServiceKey
,
1582 lpService
->pSecurityDescriptor
);
1584 RegFlushKey(hServiceKey
);
1587 if (hServiceKey
!= NULL
)
1588 RegCloseKey(hServiceKey
);
1590 /* Unlock service database */
1591 if (bDatabaseLocked
== TRUE
)
1592 ScmUnlockDatabase();
1597 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1606 RQueryServiceStatus(
1607 SC_RPC_HANDLE hService
,
1608 LPSERVICE_STATUS lpServiceStatus
)
1610 PSERVICE_HANDLE hSvc
;
1613 DPRINT("RQueryServiceStatus() called\n");
1616 return ERROR_SHUTDOWN_IN_PROGRESS
;
1618 hSvc
= ScmGetServiceFromHandle(hService
);
1621 DPRINT1("Invalid service handle!\n");
1622 return ERROR_INVALID_HANDLE
;
1625 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1626 SERVICE_QUERY_STATUS
))
1628 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1629 return ERROR_ACCESS_DENIED
;
1632 lpService
= hSvc
->ServiceEntry
;
1633 if (lpService
== NULL
)
1635 DPRINT("lpService == NULL!\n");
1636 return ERROR_INVALID_HANDLE
;
1639 /* Lock the service database shared */
1640 ScmLockDatabaseShared();
1642 /* Return service status information */
1643 RtlCopyMemory(lpServiceStatus
,
1645 sizeof(SERVICE_STATUS
));
1647 /* Unlock the service database */
1648 ScmUnlockDatabase();
1650 return ERROR_SUCCESS
;
1655 ScmIsValidServiceState(DWORD dwCurrentState
)
1657 switch (dwCurrentState
)
1659 case SERVICE_STOPPED
:
1660 case SERVICE_START_PENDING
:
1661 case SERVICE_STOP_PENDING
:
1662 case SERVICE_RUNNING
:
1663 case SERVICE_CONTINUE_PENDING
:
1664 case SERVICE_PAUSE_PENDING
:
1665 case SERVICE_PAUSED
:
1678 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1679 LPSERVICE_STATUS lpServiceStatus
)
1682 DWORD dwPreviousState
;
1683 DWORD dwPreviousType
;
1684 LPCWSTR lpLogStrings
[2];
1685 WCHAR szLogBuffer
[80];
1688 DPRINT("RSetServiceStatus() called\n");
1689 DPRINT("hServiceStatus = %lu\n", hServiceStatus
);
1690 DPRINT("dwServiceType = 0x%lx\n", lpServiceStatus
->dwServiceType
);
1691 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1692 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1693 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1694 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1695 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1696 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1698 if (hServiceStatus
== 0)
1700 DPRINT("hServiceStatus == NULL!\n");
1701 return ERROR_INVALID_HANDLE
;
1704 lpService
= (PSERVICE
)hServiceStatus
;
1706 /* Check current state */
1707 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1709 DPRINT("Invalid service state!\n");
1710 return ERROR_INVALID_DATA
;
1713 /* Check service type */
1714 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1715 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1717 DPRINT("Invalid service type!\n");
1718 return ERROR_INVALID_DATA
;
1721 /* Check accepted controls */
1722 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1724 DPRINT("Invalid controls accepted!\n");
1725 return ERROR_INVALID_DATA
;
1728 /* Set the wait hint and check point only if the service is in a pending state,
1729 otherwise they should be 0 */
1730 if (lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
||
1731 lpServiceStatus
->dwCurrentState
== SERVICE_PAUSED
||
1732 lpServiceStatus
->dwCurrentState
== SERVICE_RUNNING
)
1734 lpServiceStatus
->dwWaitHint
= 0;
1735 lpServiceStatus
->dwCheckPoint
= 0;
1738 /* Lock the service database exclusively */
1739 ScmLockDatabaseExclusive();
1741 /* Save the current service state */
1742 dwPreviousState
= lpService
->Status
.dwCurrentState
;
1744 /* Save the current service type */
1745 dwPreviousType
= lpService
->Status
.dwServiceType
;
1747 /* Update the service status */
1748 RtlCopyMemory(&lpService
->Status
,
1750 sizeof(SERVICE_STATUS
));
1752 /* Restore the previous service type */
1753 lpService
->Status
.dwServiceType
= dwPreviousType
;
1755 /* Dereference a stopped service */
1756 if ((lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1757 (lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
))
1759 /* Decrement the image run counter */
1760 lpService
->lpImage
->dwImageRunCount
--;
1762 /* If we just stopped the last running service... */
1763 if (lpService
->lpImage
->dwImageRunCount
== 0)
1765 /* Stop the dispatcher thread */
1766 ScmControlService(lpService
->lpImage
->hControlPipe
,
1768 (SERVICE_STATUS_HANDLE
)lpService
,
1769 SERVICE_CONTROL_STOP
);
1771 /* Remove the service image */
1772 ScmRemoveServiceImage(lpService
->lpImage
);
1773 lpService
->lpImage
= NULL
;
1777 /* Unlock the service database */
1778 ScmUnlockDatabase();
1780 if ((lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
) &&
1781 (dwPreviousState
!= SERVICE_STOPPED
) &&
1782 (lpServiceStatus
->dwWin32ExitCode
!= ERROR_SUCCESS
))
1784 /* Log a failed service stop */
1785 StringCchPrintfW(szLogBuffer
, ARRAYSIZE(szLogBuffer
),
1786 L
"%lu", lpServiceStatus
->dwWin32ExitCode
);
1787 lpLogStrings
[0] = lpService
->lpDisplayName
;
1788 lpLogStrings
[1] = szLogBuffer
;
1790 ScmLogEvent(EVENT_SERVICE_EXIT_FAILED
,
1791 EVENTLOG_ERROR_TYPE
,
1795 else if (lpServiceStatus
->dwCurrentState
!= dwPreviousState
&&
1796 (lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
||
1797 lpServiceStatus
->dwCurrentState
== SERVICE_RUNNING
||
1798 lpServiceStatus
->dwCurrentState
== SERVICE_PAUSED
))
1800 /* Log a successful service status change */
1801 switch(lpServiceStatus
->dwCurrentState
)
1803 case SERVICE_STOPPED
:
1804 uID
= IDS_SERVICE_STOPPED
;
1807 case SERVICE_RUNNING
:
1808 uID
= IDS_SERVICE_RUNNING
;
1811 case SERVICE_PAUSED
:
1812 uID
= IDS_SERVICE_PAUSED
;
1816 LoadStringW(GetModuleHandle(NULL
), uID
, szLogBuffer
, ARRAYSIZE(szLogBuffer
));
1817 lpLogStrings
[0] = lpService
->lpDisplayName
;
1818 lpLogStrings
[1] = szLogBuffer
;
1820 ScmLogEvent(EVENT_SERVICE_STATUS_SUCCESS
,
1821 EVENTLOG_INFORMATION_TYPE
,
1826 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1827 DPRINT("RSetServiceStatus() done\n");
1829 return ERROR_SUCCESS
;
1836 RUnlockServiceDatabase(
1839 DPRINT("RUnlockServiceDatabase(%p)\n", Lock
);
1840 return ScmReleaseServiceStartLock(Lock
);
1847 RNotifyBootConfigStatus(
1848 SVCCTL_HANDLEW lpMachineName
,
1849 DWORD BootAcceptable
)
1851 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1852 return ERROR_SUCCESS
;
1855 // return ERROR_CALL_NOT_IMPLEMENTED;
1862 RI_ScSetServiceBitsW(
1863 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1864 DWORD dwServiceBits
,
1866 int bUpdateImmediately
,
1871 DPRINT("RI_ScSetServiceBitsW(%p %lx %d %d %S)\n",
1872 hServiceStatus
, dwServiceBits
, bSetBitsOn
,
1873 bUpdateImmediately
, lpString
);
1876 return ERROR_SHUTDOWN_IN_PROGRESS
;
1878 if (lpString
!= NULL
)
1879 return ERROR_INVALID_PARAMETER
;
1881 if (hServiceStatus
== 0)
1883 DPRINT("hServiceStatus == NULL!\n");
1884 return ERROR_INVALID_HANDLE
;
1887 // FIXME: Validate the status handle
1888 pService
= (PSERVICE
)hServiceStatus
;
1892 DPRINT("Old service bits: %08lx\n", pService
->dwServiceBits
);
1893 DPRINT("Old global service bits: %08lx\n", g_dwServiceBits
);
1894 pService
->dwServiceBits
|= dwServiceBits
;
1895 g_dwServiceBits
|= dwServiceBits
;
1896 DPRINT("New service bits: %08lx\n", pService
->dwServiceBits
);
1897 DPRINT("New global service bits: %08lx\n", g_dwServiceBits
);
1901 DPRINT("Old service bits: %08lx\n", pService
->dwServiceBits
);
1902 DPRINT("Old global service bits: %08lx\n", g_dwServiceBits
);
1903 pService
->dwServiceBits
&= ~dwServiceBits
;
1904 g_dwServiceBits
&= ~dwServiceBits
;
1905 DPRINT("New service bits: %08lx\n", pService
->dwServiceBits
);
1906 DPRINT("New global service bits: %08lx\n", g_dwServiceBits
);
1909 return ERROR_SUCCESS
;
1916 RChangeServiceConfigW(
1917 SC_RPC_HANDLE hService
,
1918 DWORD dwServiceType
,
1920 DWORD dwErrorControl
,
1921 LPWSTR lpBinaryPathName
,
1922 LPWSTR lpLoadOrderGroup
,
1924 LPBYTE lpDependencies
,
1926 LPWSTR lpServiceStartName
,
1929 LPWSTR lpDisplayName
)
1931 DWORD dwError
= ERROR_SUCCESS
;
1932 PSERVICE_HANDLE hSvc
;
1933 PSERVICE lpService
= NULL
;
1934 HKEY hServiceKey
= NULL
;
1935 LPWSTR lpDisplayNameW
= NULL
;
1936 LPWSTR lpImagePathW
= NULL
;
1937 LPWSTR lpClearTextPassword
= NULL
;
1939 DPRINT("RChangeServiceConfigW() called\n");
1940 DPRINT("dwServiceType = 0x%lx\n", dwServiceType
);
1941 DPRINT("dwStartType = %lu\n", dwStartType
);
1942 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1943 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1944 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1945 DPRINT("lpServiceStartName = %S\n", lpServiceStartName
);
1946 DPRINT("lpPassword = %p\n", lpPassword
);
1947 DPRINT("dwPwSite = %lu\n", dwPwSize
);
1948 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1951 return ERROR_SHUTDOWN_IN_PROGRESS
;
1953 hSvc
= ScmGetServiceFromHandle(hService
);
1956 DPRINT1("Invalid service handle!\n");
1957 return ERROR_INVALID_HANDLE
;
1960 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1961 SERVICE_CHANGE_CONFIG
))
1963 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1964 return ERROR_ACCESS_DENIED
;
1967 /* Check for invalid service type value */
1968 if ((dwServiceType
!= SERVICE_NO_CHANGE
) &&
1969 (dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
1970 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
1971 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
1972 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
1974 return ERROR_INVALID_PARAMETER
;
1977 /* Check for invalid start type value */
1978 if ((dwStartType
!= SERVICE_NO_CHANGE
) &&
1979 (dwStartType
!= SERVICE_BOOT_START
) &&
1980 (dwStartType
!= SERVICE_SYSTEM_START
) &&
1981 (dwStartType
!= SERVICE_AUTO_START
) &&
1982 (dwStartType
!= SERVICE_DEMAND_START
) &&
1983 (dwStartType
!= SERVICE_DISABLED
))
1985 return ERROR_INVALID_PARAMETER
;
1988 /* Only drivers can be boot start or system start services */
1989 if ((dwStartType
== SERVICE_BOOT_START
) ||
1990 (dwStartType
== SERVICE_SYSTEM_START
))
1992 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
1993 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
1994 return ERROR_INVALID_PARAMETER
;
1997 /* Check for invalid error control value */
1998 if ((dwErrorControl
!= SERVICE_NO_CHANGE
) &&
1999 (dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2000 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2001 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2002 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2004 return ERROR_INVALID_PARAMETER
;
2007 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2009 return ERROR_INVALID_PARAMETER
;
2012 lpService
= hSvc
->ServiceEntry
;
2013 if (lpService
== NULL
)
2015 DPRINT("lpService == NULL!\n");
2016 return ERROR_INVALID_HANDLE
;
2019 /* Lock the service database exclusively */
2020 ScmLockDatabaseExclusive();
2022 if (lpService
->bDeleted
)
2024 DPRINT("The service has already been marked for delete!\n");
2025 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
2029 /* Open the service key */
2030 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2033 if (dwError
!= ERROR_SUCCESS
)
2036 /* Write service data to the registry */
2038 /* Set the display name */
2039 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2041 RegSetValueExW(hServiceKey
,
2045 (LPBYTE
)lpDisplayName
,
2046 (DWORD
)((wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
)));
2048 /* Update the display name */
2049 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2051 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2052 if (lpDisplayNameW
== NULL
)
2054 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2058 wcscpy(lpDisplayNameW
, lpDisplayName
);
2059 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
2060 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2062 lpService
->lpDisplayName
= lpDisplayNameW
;
2065 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2067 /* Set the service type */
2068 dwError
= RegSetValueExW(hServiceKey
,
2072 (LPBYTE
)&dwServiceType
,
2074 if (dwError
!= ERROR_SUCCESS
)
2077 lpService
->Status
.dwServiceType
= dwServiceType
;
2080 if (dwStartType
!= SERVICE_NO_CHANGE
)
2082 /* Set the start value */
2083 dwError
= RegSetValueExW(hServiceKey
,
2087 (LPBYTE
)&dwStartType
,
2089 if (dwError
!= ERROR_SUCCESS
)
2092 lpService
->dwStartType
= dwStartType
;
2095 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
2097 /* Set the error control value */
2098 dwError
= RegSetValueExW(hServiceKey
,
2102 (LPBYTE
)&dwErrorControl
,
2104 if (dwError
!= ERROR_SUCCESS
)
2107 lpService
->dwErrorControl
= dwErrorControl
;
2110 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2112 /* Set the image path */
2113 lpImagePathW
= lpBinaryPathName
;
2115 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
2117 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
2121 if (dwError
!= ERROR_SUCCESS
)
2125 dwError
= RegSetValueExW(hServiceKey
,
2129 (LPBYTE
)lpImagePathW
,
2130 (DWORD
)((wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
)));
2132 if (lpImagePathW
!= lpBinaryPathName
)
2133 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
2135 if (dwError
!= ERROR_SUCCESS
)
2139 /* Set the group name */
2140 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2142 dwError
= RegSetValueExW(hServiceKey
,
2146 (LPBYTE
)lpLoadOrderGroup
,
2147 (DWORD
)((wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
)));
2148 if (dwError
!= ERROR_SUCCESS
)
2151 dwError
= ScmSetServiceGroup(lpService
,
2153 if (dwError
!= ERROR_SUCCESS
)
2158 if (lpdwTagId
!= NULL
)
2160 dwError
= ScmAssignNewTag(lpService
);
2161 if (dwError
!= ERROR_SUCCESS
)
2164 dwError
= RegSetValueExW(hServiceKey
,
2168 (LPBYTE
)&lpService
->dwTag
,
2170 if (dwError
!= ERROR_SUCCESS
)
2173 *lpdwTagId
= lpService
->dwTag
;
2176 /* Write dependencies */
2177 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2179 dwError
= ScmWriteDependencies(hServiceKey
,
2180 (LPWSTR
)lpDependencies
,
2182 if (dwError
!= ERROR_SUCCESS
)
2186 /* Start name and password are only used by Win32 services */
2187 if (lpService
->Status
.dwServiceType
& SERVICE_WIN32
)
2189 /* Write service start name */
2190 if (lpServiceStartName
!= NULL
&& *lpServiceStartName
!= 0)
2192 dwError
= RegSetValueExW(hServiceKey
,
2196 (LPBYTE
)lpServiceStartName
,
2197 (DWORD
)((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
)));
2198 if (dwError
!= ERROR_SUCCESS
)
2202 if (lpPassword
!= NULL
)
2204 if (*(LPWSTR
)lpPassword
!= 0)
2206 /* Decrypt the password */
2207 dwError
= ScmDecryptPassword(lpPassword
,
2209 &lpClearTextPassword
);
2210 if (dwError
!= ERROR_SUCCESS
)
2212 DPRINT1("ScmDecryptPassword failed (Error %lu)\n", dwError
);
2215 DPRINT1("Clear text password: %S\n", lpClearTextPassword
);
2217 /* Write the password */
2218 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
2219 lpClearTextPassword
);
2220 if (dwError
!= ERROR_SUCCESS
)
2222 DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError
);
2228 /* Delete the password */
2229 dwError
= ScmSetServicePassword(lpService
->szServiceName
,
2231 if (dwError
== ERROR_FILE_NOT_FOUND
)
2232 dwError
= ERROR_SUCCESS
;
2234 if (dwError
!= ERROR_SUCCESS
)
2236 DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError
);
2244 if (lpClearTextPassword
!= NULL
)
2246 /* Wipe and release the password buffer */
2247 SecureZeroMemory(lpClearTextPassword
,
2248 (wcslen(lpClearTextPassword
) + 1) * sizeof(WCHAR
));
2249 HeapFree(GetProcessHeap(), 0, lpClearTextPassword
);
2252 if (hServiceKey
!= NULL
)
2253 RegCloseKey(hServiceKey
);
2255 /* Unlock the service database */
2256 ScmUnlockDatabase();
2258 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
2268 SC_RPC_HANDLE hSCManager
,
2269 LPCWSTR lpServiceName
,
2270 LPCWSTR lpDisplayName
,
2271 DWORD dwDesiredAccess
,
2272 DWORD dwServiceType
,
2274 DWORD dwErrorControl
,
2275 LPCWSTR lpBinaryPathName
,
2276 LPCWSTR lpLoadOrderGroup
,
2278 LPBYTE lpDependencies
,
2280 LPCWSTR lpServiceStartName
,
2283 LPSC_RPC_HANDLE lpServiceHandle
)
2285 PMANAGER_HANDLE hManager
;
2286 DWORD dwError
= ERROR_SUCCESS
;
2287 PSERVICE lpService
= NULL
;
2288 SC_HANDLE hServiceHandle
= NULL
;
2289 LPWSTR lpImagePath
= NULL
;
2290 LPWSTR lpClearTextPassword
= NULL
;
2291 HKEY hServiceKey
= NULL
;
2292 LPWSTR lpObjectName
;
2294 DPRINT("RCreateServiceW() called\n");
2295 DPRINT("lpServiceName = %S\n", lpServiceName
);
2296 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
2297 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
2298 DPRINT("dwServiceType = 0x%lx\n", dwServiceType
);
2299 DPRINT("dwStartType = %lu\n", dwStartType
);
2300 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2301 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
2302 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
2303 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
2306 return ERROR_SHUTDOWN_IN_PROGRESS
;
2308 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2309 if (hManager
== NULL
)
2311 DPRINT1("Invalid service manager handle!\n");
2312 return ERROR_INVALID_HANDLE
;
2315 /* Check access rights */
2316 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2317 SC_MANAGER_CREATE_SERVICE
))
2319 DPRINT("Insufficient access rights! 0x%lx\n",
2320 hManager
->Handle
.DesiredAccess
);
2321 return ERROR_ACCESS_DENIED
;
2324 if (*lpServiceName
== 0)
2325 return ERROR_INVALID_NAME
;
2327 if (*lpBinaryPathName
== 0)
2328 return ERROR_INVALID_PARAMETER
;
2330 /* Check for invalid service type value */
2331 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2332 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2333 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2334 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2336 return ERROR_INVALID_PARAMETER
;
2339 /* Check for invalid start type value */
2340 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2341 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2342 (dwStartType
!= SERVICE_AUTO_START
) &&
2343 (dwStartType
!= SERVICE_DEMAND_START
) &&
2344 (dwStartType
!= SERVICE_DISABLED
))
2346 return ERROR_INVALID_PARAMETER
;
2349 /* Only drivers can be boot start or system start services */
2350 if ((dwStartType
== SERVICE_BOOT_START
) ||
2351 (dwStartType
== SERVICE_SYSTEM_START
))
2353 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2354 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2356 return ERROR_INVALID_PARAMETER
;
2360 /* Check for invalid error control value */
2361 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2362 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2363 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2364 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2366 return ERROR_INVALID_PARAMETER
;
2369 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2370 (lpServiceStartName
))
2372 /* We allow LocalSystem to run interactive. */
2373 if (wcsicmp(lpServiceStartName
, L
"LocalSystem"))
2375 return ERROR_INVALID_PARAMETER
;
2379 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2381 return ERROR_INVALID_PARAMETER
;
2384 /* Lock the service database exclusively */
2385 ScmLockDatabaseExclusive();
2387 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2390 /* Unlock the service database */
2391 ScmUnlockDatabase();
2393 /* Check if it is marked for deletion */
2394 if (lpService
->bDeleted
)
2395 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2397 /* Return service-exists error */
2398 return ERROR_SERVICE_EXISTS
;
2401 if (lpDisplayName
!= NULL
&&
2402 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2404 /* Unlock the service database */
2405 ScmUnlockDatabase();
2407 return ERROR_DUPLICATE_SERVICE_NAME
;
2410 if (dwServiceType
& SERVICE_DRIVER
)
2412 dwError
= ScmCanonDriverImagePath(dwStartType
,
2415 if (dwError
!= ERROR_SUCCESS
)
2420 if (dwStartType
== SERVICE_BOOT_START
||
2421 dwStartType
== SERVICE_SYSTEM_START
)
2423 /* Unlock the service database */
2424 ScmUnlockDatabase();
2426 return ERROR_INVALID_PARAMETER
;
2430 /* Allocate a new service entry */
2431 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2435 if (dwError
!= ERROR_SUCCESS
)
2438 /* Fill the new service entry */
2439 lpService
->dwErrorControl
= dwErrorControl
;
2441 /* Fill the display name */
2442 if (lpDisplayName
!= NULL
&&
2443 *lpDisplayName
!= 0 &&
2444 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2446 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(),
2448 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2449 if (lpService
->lpDisplayName
== NULL
)
2451 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2454 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2457 /* Assign the service to a group */
2458 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2460 dwError
= ScmSetServiceGroup(lpService
,
2462 if (dwError
!= ERROR_SUCCESS
)
2466 /* Assign a new tag */
2467 if (lpdwTagId
!= NULL
)
2469 dwError
= ScmAssignNewTag(lpService
);
2470 if (dwError
!= ERROR_SUCCESS
)
2474 /* Assign the default security descriptor */
2475 if (dwServiceType
& SERVICE_WIN32
)
2477 dwError
= ScmCreateDefaultServiceSD(&lpService
->pSecurityDescriptor
);
2478 if (dwError
!= ERROR_SUCCESS
)
2482 /* Write service data to the registry */
2483 /* Create the service key */
2484 dwError
= ScmCreateServiceKey(lpServiceName
,
2487 if (dwError
!= ERROR_SUCCESS
)
2490 /* Set the display name */
2491 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2493 RegSetValueExW(hServiceKey
,
2497 (LPBYTE
)lpDisplayName
,
2498 (DWORD
)((wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
)));
2501 /* Set the service type */
2502 dwError
= RegSetValueExW(hServiceKey
,
2506 (LPBYTE
)&dwServiceType
,
2508 if (dwError
!= ERROR_SUCCESS
)
2511 /* Set the start value */
2512 dwError
= RegSetValueExW(hServiceKey
,
2516 (LPBYTE
)&dwStartType
,
2518 if (dwError
!= ERROR_SUCCESS
)
2521 /* Set the error control value */
2522 dwError
= RegSetValueExW(hServiceKey
,
2526 (LPBYTE
)&dwErrorControl
,
2528 if (dwError
!= ERROR_SUCCESS
)
2531 /* Set the image path */
2532 if (dwServiceType
& SERVICE_WIN32
)
2534 dwError
= RegSetValueExW(hServiceKey
,
2538 (LPBYTE
)lpBinaryPathName
,
2539 (DWORD
)((wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
)));
2540 if (dwError
!= ERROR_SUCCESS
)
2543 else if (dwServiceType
& SERVICE_DRIVER
)
2545 dwError
= RegSetValueExW(hServiceKey
,
2549 (LPBYTE
)lpImagePath
,
2550 (DWORD
)((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
)));
2551 if (dwError
!= ERROR_SUCCESS
)
2555 /* Set the group name */
2556 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2558 dwError
= RegSetValueExW(hServiceKey
,
2562 (LPBYTE
)lpLoadOrderGroup
,
2563 (DWORD
)((wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
)));
2564 if (dwError
!= ERROR_SUCCESS
)
2568 /* Set the service tag */
2569 if (lpdwTagId
!= NULL
)
2571 dwError
= RegSetValueExW(hServiceKey
,
2575 (LPBYTE
)&lpService
->dwTag
,
2577 if (dwError
!= ERROR_SUCCESS
)
2581 /* Write dependencies */
2582 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2584 dwError
= ScmWriteDependencies(hServiceKey
,
2585 (LPCWSTR
)lpDependencies
,
2587 if (dwError
!= ERROR_SUCCESS
)
2591 /* Start name and password are only used by Win32 services */
2592 if (dwServiceType
& SERVICE_WIN32
)
2594 /* Write service start name */
2595 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2596 dwError
= RegSetValueExW(hServiceKey
,
2600 (LPBYTE
)lpObjectName
,
2601 (DWORD
)((wcslen(lpObjectName
) + 1) * sizeof(WCHAR
)));
2602 if (dwError
!= ERROR_SUCCESS
)
2605 if (lpPassword
!= NULL
&& *(LPWSTR
)lpPassword
!= 0)
2607 /* Decrypt the password */
2608 dwError
= ScmDecryptPassword(lpPassword
,
2610 &lpClearTextPassword
);
2611 if (dwError
!= ERROR_SUCCESS
)
2614 /* Write the password */
2615 dwError
= ScmSetServicePassword(lpServiceName
,
2616 lpClearTextPassword
);
2617 if (dwError
!= ERROR_SUCCESS
)
2621 /* Write the security descriptor */
2622 dwError
= ScmWriteSecurityDescriptor(hServiceKey
,
2623 lpService
->pSecurityDescriptor
);
2624 if (dwError
!= ERROR_SUCCESS
)
2628 dwError
= ScmCreateServiceHandle(lpService
,
2630 if (dwError
!= ERROR_SUCCESS
)
2633 dwError
= ScmCheckAccess(hServiceHandle
,
2635 if (dwError
!= ERROR_SUCCESS
)
2638 lpService
->dwRefCount
= 1;
2639 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2642 /* Unlock the service database */
2643 ScmUnlockDatabase();
2645 if (hServiceKey
!= NULL
)
2646 RegCloseKey(hServiceKey
);
2648 if (lpClearTextPassword
!= NULL
)
2650 /* Wipe and release the password buffer */
2651 SecureZeroMemory(lpClearTextPassword
,
2652 (wcslen(lpClearTextPassword
) + 1) * sizeof(WCHAR
));
2653 HeapFree(GetProcessHeap(), 0, lpClearTextPassword
);
2656 if (dwError
== ERROR_SUCCESS
)
2658 DPRINT("hService %p\n", hServiceHandle
);
2659 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2661 if (lpdwTagId
!= NULL
)
2662 *lpdwTagId
= lpService
->dwTag
;
2666 if (lpService
!= NULL
&&
2667 lpService
->lpServiceName
!= NULL
)
2669 /* Release the display name buffer */
2670 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2675 /* Remove the service handle */
2676 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2679 if (lpService
!= NULL
)
2681 /* FIXME: remove the service entry */
2685 if (lpImagePath
!= NULL
)
2686 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2688 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2697 REnumDependentServicesW(
2698 SC_RPC_HANDLE hService
,
2699 DWORD dwServiceState
,
2702 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2703 LPBOUNDED_DWORD_256K lpServicesReturned
)
2705 DWORD dwError
= ERROR_SUCCESS
;
2706 DWORD dwServicesReturned
= 0;
2707 DWORD dwServiceCount
;
2708 HKEY hServicesKey
= NULL
;
2709 PSERVICE_HANDLE hSvc
;
2710 PSERVICE lpService
= NULL
;
2711 PSERVICE
*lpServicesArray
= NULL
;
2712 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2715 *pcbBytesNeeded
= 0;
2716 *lpServicesReturned
= 0;
2718 DPRINT("REnumDependentServicesW() called\n");
2720 hSvc
= ScmGetServiceFromHandle(hService
);
2723 DPRINT1("Invalid service handle!\n");
2724 return ERROR_INVALID_HANDLE
;
2727 lpService
= hSvc
->ServiceEntry
;
2729 /* Check access rights */
2730 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2731 SC_MANAGER_ENUMERATE_SERVICE
))
2733 DPRINT("Insufficient access rights! 0x%lx\n",
2734 hSvc
->Handle
.DesiredAccess
);
2735 return ERROR_ACCESS_DENIED
;
2738 /* Open the Services Reg key */
2739 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2740 L
"System\\CurrentControlSet\\Services",
2744 if (dwError
!= ERROR_SUCCESS
)
2747 /* First determine the bytes needed and get the number of dependent services */
2748 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2753 &dwServicesReturned
);
2754 if (dwError
!= ERROR_SUCCESS
)
2757 /* If buffer size is less than the bytes needed or pointer is null */
2758 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2760 dwError
= ERROR_MORE_DATA
;
2764 /* Allocate memory for array of service pointers */
2765 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2767 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2768 if (!lpServicesArray
)
2770 DPRINT1("Could not allocate a buffer!!\n");
2771 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2775 dwServicesReturned
= 0;
2776 *pcbBytesNeeded
= 0;
2778 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2783 &dwServicesReturned
);
2784 if (dwError
!= ERROR_SUCCESS
)
2789 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
)lpServices
;
2790 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2792 /* Copy EnumDepenedentService to Buffer */
2793 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2795 lpService
= lpServicesArray
[dwServiceCount
];
2797 /* Copy status info */
2798 memcpy(&lpServicesPtr
->ServiceStatus
,
2800 sizeof(SERVICE_STATUS
));
2802 /* Copy display name */
2803 wcscpy(lpStr
, lpService
->lpDisplayName
);
2804 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2805 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2807 /* Copy service name */
2808 wcscpy(lpStr
, lpService
->lpServiceName
);
2809 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2810 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2815 *lpServicesReturned
= dwServicesReturned
;
2818 if (lpServicesArray
!= NULL
)
2819 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2821 RegCloseKey(hServicesKey
);
2823 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2832 REnumServicesStatusW(
2833 SC_RPC_HANDLE hSCManager
,
2834 DWORD dwServiceType
,
2835 DWORD dwServiceState
,
2838 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2839 LPBOUNDED_DWORD_256K lpServicesReturned
,
2840 LPBOUNDED_DWORD_256K lpResumeHandle
)
2842 /* Enumerate all the services, not regarding of their group */
2843 return REnumServiceGroupW(hSCManager
,
2859 LPWSTR lpMachineName
,
2860 LPWSTR lpDatabaseName
,
2861 DWORD dwDesiredAccess
,
2862 LPSC_RPC_HANDLE lpScHandle
)
2867 DPRINT("ROpenSCManagerW() called\n");
2868 DPRINT("lpMachineName = %p\n", lpMachineName
);
2869 DPRINT("lpMachineName: %S\n", lpMachineName
);
2870 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2871 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2872 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2875 return ERROR_SHUTDOWN_IN_PROGRESS
;
2878 return ERROR_INVALID_PARAMETER
;
2880 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2882 if (dwError
!= ERROR_SUCCESS
)
2884 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2888 /* Check the desired access */
2889 dwError
= ScmCheckAccess(hHandle
,
2890 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2891 if (dwError
!= ERROR_SUCCESS
)
2893 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2894 HeapFree(GetProcessHeap(), 0, hHandle
);
2898 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2899 DPRINT("*hScm = %p\n", *lpScHandle
);
2901 DPRINT("ROpenSCManagerW() done\n");
2903 return ERROR_SUCCESS
;
2911 SC_RPC_HANDLE hSCManager
,
2912 LPWSTR lpServiceName
,
2913 DWORD dwDesiredAccess
,
2914 LPSC_RPC_HANDLE lpServiceHandle
)
2917 PMANAGER_HANDLE hManager
;
2919 DWORD dwError
= ERROR_SUCCESS
;
2921 DPRINT("ROpenServiceW() called\n");
2922 DPRINT("hSCManager = %p\n", hSCManager
);
2923 DPRINT("lpServiceName = %p\n", lpServiceName
);
2924 DPRINT("lpServiceName: %S\n", lpServiceName
);
2925 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2928 return ERROR_SHUTDOWN_IN_PROGRESS
;
2930 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2931 if (hManager
== NULL
)
2933 DPRINT1("Invalid service manager handle!\n");
2934 return ERROR_INVALID_HANDLE
;
2937 if (!lpServiceHandle
)
2938 return ERROR_INVALID_PARAMETER
;
2941 return ERROR_INVALID_ADDRESS
;
2943 /* Lock the service database exclusive */
2944 ScmLockDatabaseExclusive();
2946 /* Get service database entry */
2947 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2948 if (lpService
== NULL
)
2950 DPRINT("Could not find the service!\n");
2951 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2955 /* Create a service handle */
2956 dwError
= ScmCreateServiceHandle(lpService
,
2958 if (dwError
!= ERROR_SUCCESS
)
2960 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2964 /* Check the desired access */
2965 dwError
= ScmCheckAccess(hHandle
,
2967 if (dwError
!= ERROR_SUCCESS
)
2969 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2970 HeapFree(GetProcessHeap(), 0, hHandle
);
2974 lpService
->dwRefCount
++;
2975 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2977 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2978 DPRINT("*hService = %p\n", *lpServiceHandle
);
2981 /* Unlock the service database */
2982 ScmUnlockDatabase();
2984 DPRINT("ROpenServiceW() done\n");
2993 RQueryServiceConfigW(
2994 SC_RPC_HANDLE hService
,
2995 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2997 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2999 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
3000 DWORD dwError
= ERROR_SUCCESS
;
3001 PSERVICE_HANDLE hSvc
;
3002 PSERVICE lpService
= NULL
;
3003 HKEY hServiceKey
= NULL
;
3004 LPWSTR lpImagePath
= NULL
;
3005 LPWSTR lpServiceStartName
= NULL
;
3006 LPWSTR lpDependencies
= NULL
;
3007 DWORD dwDependenciesLength
= 0;
3008 DWORD dwRequiredSize
;
3011 DPRINT("RQueryServiceConfigW() called\n");
3014 return ERROR_SHUTDOWN_IN_PROGRESS
;
3016 hSvc
= ScmGetServiceFromHandle(hService
);
3019 DPRINT1("Invalid service handle!\n");
3020 return ERROR_INVALID_HANDLE
;
3023 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3024 SERVICE_QUERY_CONFIG
))
3026 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3027 return ERROR_ACCESS_DENIED
;
3030 lpService
= hSvc
->ServiceEntry
;
3031 if (lpService
== NULL
)
3033 DPRINT("lpService == NULL!\n");
3034 return ERROR_INVALID_HANDLE
;
3037 /* Lock the service database shared */
3038 ScmLockDatabaseShared();
3040 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3043 if (dwError
!= ERROR_SUCCESS
)
3046 /* Read the image path */
3047 dwError
= ScmReadString(hServiceKey
,
3050 if (dwError
!= ERROR_SUCCESS
)
3053 /* Read the service start name */
3054 ScmReadString(hServiceKey
,
3056 &lpServiceStartName
);
3058 /* Read the dependencies */
3059 ScmReadDependencies(hServiceKey
,
3061 &dwDependenciesLength
);
3063 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3065 if (lpImagePath
!= NULL
)
3066 dwRequiredSize
+= (DWORD
)((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
3068 dwRequiredSize
+= 2 * sizeof(WCHAR
);
3070 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3071 dwRequiredSize
+= (DWORD
)((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
3073 dwRequiredSize
+= 2 * sizeof(WCHAR
);
3075 if (lpDependencies
!= NULL
)
3076 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
3078 dwRequiredSize
+= 2 * sizeof(WCHAR
);
3080 if (lpServiceStartName
!= NULL
)
3081 dwRequiredSize
+= (DWORD
)((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
3083 dwRequiredSize
+= 2 * sizeof(WCHAR
);
3085 if (lpService
->lpDisplayName
!= NULL
)
3086 dwRequiredSize
+= (DWORD
)((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
3088 dwRequiredSize
+= 2 * sizeof(WCHAR
);
3090 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3092 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3096 lpServiceConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3097 lpServiceConfig
->dwStartType
= lpService
->dwStartType
;
3098 lpServiceConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3099 lpServiceConfig
->dwTagId
= lpService
->dwTag
;
3101 lpStr
= (LPWSTR
)(lpServiceConfig
+ 1);
3103 /* Append the image path */
3104 if (lpImagePath
!= NULL
)
3106 wcscpy(lpStr
, lpImagePath
);
3113 lpServiceConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3114 lpStr
+= (wcslen(lpStr
) + 1);
3116 /* Append the group name */
3117 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3119 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
3126 lpServiceConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3127 lpStr
+= (wcslen(lpStr
) + 1);
3129 /* Append Dependencies */
3130 if (lpDependencies
!= NULL
)
3134 dwDependenciesLength
* sizeof(WCHAR
));
3141 lpServiceConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3142 if (lpDependencies
!= NULL
)
3143 lpStr
+= dwDependenciesLength
;
3145 lpStr
+= (wcslen(lpStr
) + 1);
3147 /* Append the service start name */
3148 if (lpServiceStartName
!= NULL
)
3150 wcscpy(lpStr
, lpServiceStartName
);
3157 lpServiceConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3158 lpStr
+= (wcslen(lpStr
) + 1);
3160 /* Append the display name */
3161 if (lpService
->lpDisplayName
!= NULL
)
3163 wcscpy(lpStr
, lpService
->lpDisplayName
);
3170 lpServiceConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
3173 if (pcbBytesNeeded
!= NULL
)
3174 *pcbBytesNeeded
= dwRequiredSize
;
3177 /* Unlock the service database */
3178 ScmUnlockDatabase();
3180 if (lpImagePath
!= NULL
)
3181 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3183 if (lpServiceStartName
!= NULL
)
3184 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3186 if (lpDependencies
!= NULL
)
3187 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3189 if (hServiceKey
!= NULL
)
3190 RegCloseKey(hServiceKey
);
3192 DPRINT("RQueryServiceConfigW() done\n");
3201 RQueryServiceLockStatusW(
3202 SC_RPC_HANDLE hSCManager
,
3203 LPBYTE lpBuf
, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
3205 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3207 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
= (LPQUERY_SERVICE_LOCK_STATUSW
)lpBuf
;
3208 PMANAGER_HANDLE hMgr
;
3209 DWORD dwRequiredSize
;
3211 if (!lpLockStatus
|| !pcbBytesNeeded
)
3212 return ERROR_INVALID_PARAMETER
;
3214 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
3217 DPRINT1("Invalid service manager handle!\n");
3218 return ERROR_INVALID_HANDLE
;
3221 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
3222 SC_MANAGER_QUERY_LOCK_STATUS
))
3224 DPRINT("Insufficient access rights! 0x%lx\n", hMgr
->Handle
.DesiredAccess
);
3225 return ERROR_ACCESS_DENIED
;
3228 /* FIXME: we need to compute instead the real length of the owner name */
3229 dwRequiredSize
= sizeof(QUERY_SERVICE_LOCK_STATUSW
) + sizeof(WCHAR
);
3230 *pcbBytesNeeded
= dwRequiredSize
;
3232 if (cbBufSize
< dwRequiredSize
)
3233 return ERROR_INSUFFICIENT_BUFFER
;
3235 ScmQueryServiceLockStatusW(lpLockStatus
);
3237 return ERROR_SUCCESS
;
3245 SC_RPC_HANDLE hService
,
3247 LPSTRING_PTRSW argv
)
3249 DWORD dwError
= ERROR_SUCCESS
;
3250 PSERVICE_HANDLE hSvc
;
3251 PSERVICE lpService
= NULL
;
3256 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3257 DPRINT(" argc: %lu\n", argc
);
3260 for (i
= 0; i
< argc
; i
++)
3262 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
].StringPtr
);
3268 return ERROR_SHUTDOWN_IN_PROGRESS
;
3270 hSvc
= ScmGetServiceFromHandle(hService
);
3273 DPRINT1("Invalid service handle!\n");
3274 return ERROR_INVALID_HANDLE
;
3277 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3280 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3281 return ERROR_ACCESS_DENIED
;
3284 lpService
= hSvc
->ServiceEntry
;
3285 if (lpService
== NULL
)
3287 DPRINT("lpService == NULL!\n");
3288 return ERROR_INVALID_HANDLE
;
3291 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3292 return ERROR_SERVICE_DISABLED
;
3294 if (lpService
->bDeleted
)
3295 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3297 /* Start the service */
3298 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3307 RGetServiceDisplayNameW(
3308 SC_RPC_HANDLE hSCManager
,
3309 LPCWSTR lpServiceName
,
3310 LPWSTR lpDisplayName
,
3313 // PMANAGER_HANDLE hManager;
3315 LPCWSTR lpSvcDisplayName
;
3319 DPRINT("RGetServiceDisplayNameW() called\n");
3320 DPRINT("hSCManager = %p\n", hSCManager
);
3321 DPRINT("lpServiceName: %S\n", lpServiceName
);
3322 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3323 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3326 hManager
= (PMANAGER_HANDLE
)hSCManager
;
3327 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
3329 DPRINT("Invalid manager handle!\n");
3330 return ERROR_INVALID_HANDLE
;
3334 /* Get service database entry */
3335 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3336 if (lpService
== NULL
)
3338 DPRINT("Could not find the service!\n");
3339 return ERROR_SERVICE_DOES_NOT_EXIST
;
3342 if (lpService
->lpDisplayName
)
3343 lpSvcDisplayName
= lpService
->lpDisplayName
;
3345 lpSvcDisplayName
= lpService
->lpServiceName
;
3347 dwLength
= (DWORD
)wcslen(lpSvcDisplayName
);
3349 if (*lpcchBuffer
> dwLength
)
3351 if (lpDisplayName
!= NULL
)
3352 wcscpy(lpDisplayName
, lpSvcDisplayName
);
3354 dwError
= ERROR_SUCCESS
;