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 ****************************************************************/
18 /* GLOBALS *****************************************************************/
20 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
21 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
23 typedef struct _SCMGR_HANDLE
30 typedef struct _MANAGER_HANDLE
33 WCHAR DatabaseName
[1];
34 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
37 typedef struct _SERVICE_HANDLE
40 PSERVICE ServiceEntry
;
41 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
44 #define SC_MANAGER_READ \
45 (STANDARD_RIGHTS_READ | \
46 SC_MANAGER_QUERY_LOCK_STATUS | \
47 SC_MANAGER_ENUMERATE_SERVICE)
49 #define SC_MANAGER_WRITE \
50 (STANDARD_RIGHTS_WRITE | \
51 SC_MANAGER_MODIFY_BOOT_CONFIG | \
52 SC_MANAGER_CREATE_SERVICE)
54 #define SC_MANAGER_EXECUTE \
55 (STANDARD_RIGHTS_EXECUTE | \
57 SC_MANAGER_ENUMERATE_SERVICE | \
58 SC_MANAGER_CONNECT | \
59 SC_MANAGER_CREATE_SERVICE)
62 #define SERVICE_READ \
63 (STANDARD_RIGHTS_READ | \
64 SERVICE_INTERROGATE | \
65 SERVICE_ENUMERATE_DEPENDENTS | \
66 SERVICE_QUERY_STATUS | \
69 #define SERVICE_WRITE \
70 (STANDARD_RIGHTS_WRITE | \
71 SERVICE_CHANGE_CONFIG)
73 #define SERVICE_EXECUTE \
74 (STANDARD_RIGHTS_EXECUTE | \
75 SERVICE_USER_DEFINED_CONTROL | \
76 SERVICE_PAUSE_CONTINUE | \
80 #define TAG_ARRAY_SIZE 32
82 /* VARIABLES ***************************************************************/
84 static GENERIC_MAPPING
85 ScmManagerMapping
= {SC_MANAGER_READ
,
88 SC_MANAGER_ALL_ACCESS
};
90 static GENERIC_MAPPING
91 ScmServiceMapping
= {SERVICE_READ
,
97 /* FUNCTIONS ***************************************************************/
100 ScmStartRpcServer(VOID
)
104 DPRINT("ScmStartRpcServer() called\n");
106 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
110 if (Status
!= RPC_S_OK
)
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
116 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
125 Status
= RpcServerListen(1, 20, TRUE
);
126 if (Status
!= RPC_S_OK
)
128 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
132 DPRINT("ScmStartRpcServer() done\n");
137 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
142 if (lpDatabaseName
== NULL
)
143 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
145 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
147 DPRINT("Database %S, does not exist\n", lpDatabaseName
);
148 return ERROR_DATABASE_DOES_NOT_EXIST
;
150 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
152 DPRINT("Invalid Database name %S.\n", lpDatabaseName
);
153 return ERROR_INVALID_NAME
;
156 Ptr
= HeapAlloc(GetProcessHeap(),
158 FIELD_OFFSET(MANAGER_HANDLE
, DatabaseName
[wcslen(lpDatabaseName
) + 1]));
160 return ERROR_NOT_ENOUGH_MEMORY
;
162 Ptr
->Handle
.Tag
= MANAGER_TAG
;
164 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
166 *Handle
= (SC_HANDLE
)Ptr
;
168 return ERROR_SUCCESS
;
173 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
178 Ptr
= HeapAlloc(GetProcessHeap(),
180 sizeof(SERVICE_HANDLE
));
182 return ERROR_NOT_ENOUGH_MEMORY
;
184 Ptr
->Handle
.Tag
= SERVICE_TAG
;
186 Ptr
->ServiceEntry
= lpServiceEntry
;
188 *Handle
= (SC_HANDLE
)Ptr
;
190 return ERROR_SUCCESS
;
194 static PMANAGER_HANDLE
195 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
197 PMANAGER_HANDLE pManager
= NULL
;
201 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
202 pManager
= (PMANAGER_HANDLE
)Handle
;
204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
206 DPRINT1("Exception: Invalid Service Manager handle!\n");
214 static PSERVICE_HANDLE
215 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
217 PSERVICE_HANDLE pService
= NULL
;
221 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
222 pService
= (PSERVICE_HANDLE
)Handle
;
224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
226 DPRINT1("Exception: Invalid Service handle!\n");
235 ScmCheckAccess(SC_HANDLE Handle
,
236 DWORD dwDesiredAccess
)
238 PMANAGER_HANDLE hMgr
;
240 hMgr
= (PMANAGER_HANDLE
)Handle
;
241 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
243 RtlMapGenericMask(&dwDesiredAccess
,
246 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
248 return ERROR_SUCCESS
;
250 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
252 RtlMapGenericMask(&dwDesiredAccess
,
255 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
257 return ERROR_SUCCESS
;
260 return ERROR_INVALID_HANDLE
;
265 ScmAssignNewTag(PSERVICE lpService
)
269 DWORD dwGroupTagCount
= 0;
270 PDWORD pdwGroupTags
= NULL
;
272 DWORD dwTagUsedBase
= 1;
273 BOOLEAN TagUsed
[TAG_ARRAY_SIZE
];
277 PLIST_ENTRY ServiceEntry
;
278 PSERVICE CurrentService
;
280 ASSERT(lpService
!= NULL
);
281 ASSERT(lpService
->lpGroup
!= NULL
);
283 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
284 L
"System\\CurrentControlSet\\Control\\GroupOrderList",
289 if (dwError
!= ERROR_SUCCESS
)
292 /* query value length */
294 dwError
= RegQueryValueExW(hKey
,
295 lpService
->lpGroup
->szGroupName
,
301 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_MORE_DATA
)
304 pdwGroupTags
= HeapAlloc(GetProcessHeap(), 0, cbDataSize
);
307 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
311 dwError
= RegQueryValueExW(hKey
,
312 lpService
->lpGroup
->szGroupName
,
315 (LPBYTE
)pdwGroupTags
,
318 if (dwError
!= ERROR_SUCCESS
)
321 if (cbDataSize
< sizeof(pdwGroupTags
[0]))
324 dwGroupTagCount
= min(pdwGroupTags
[0], cbDataSize
/ sizeof(pdwGroupTags
[0]) - 1);
329 /* mark all tags as unused */
330 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
333 /* mark tags in GroupOrderList as used */
334 for (i
= 1; i
<= dwGroupTagCount
; i
++)
336 dwTagOffset
= pdwGroupTags
[i
] - dwTagUsedBase
;
337 if (dwTagOffset
>= 0 && dwTagOffset
< TAG_ARRAY_SIZE
)
338 TagUsed
[dwTagOffset
] = TRUE
;
341 /* mark tags in service list as used */
342 ServiceEntry
= lpService
->ServiceListEntry
.Flink
;
343 while (ServiceEntry
!= &lpService
->ServiceListEntry
)
345 ASSERT(ServiceEntry
!= NULL
);
346 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
347 if (CurrentService
->lpGroup
== lpService
->lpGroup
)
349 dwTagOffset
= CurrentService
->dwTag
- dwTagUsedBase
;
350 if (dwTagOffset
>= 0 && dwTagOffset
< TAG_ARRAY_SIZE
)
351 TagUsed
[dwTagOffset
] = TRUE
;
354 ServiceEntry
= ServiceEntry
->Flink
;
357 /* find unused tag, if any */
358 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
362 dwFreeTag
= dwTagUsedBase
+ i
;
367 dwTagUsedBase
+= TAG_ARRAY_SIZE
;
373 HeapFree(GetProcessHeap(), 0, pdwGroupTags
);
380 lpService
->dwTag
= dwFreeTag
;
381 DPRINT("Assigning new tag %lu to service %S in group %S\n",
382 lpService
->dwTag
, lpService
->lpServiceName
, lpService
->lpGroup
->szGroupName
);
383 dwError
= ERROR_SUCCESS
;
387 DPRINT1("Failed to assign new tag to service %S, error=%lu\n",
388 lpService
->lpServiceName
, dwError
);
395 /* Create a path suitable for the bootloader out of the full path */
397 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
399 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
402 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
403 OBJECT_ATTRIBUTES ObjectAttributes
;
405 HANDLE SymbolicLinkHandle
;
407 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
409 ServiceNameLen
= wcslen(CanonName
);
411 /* First check, if it's already good */
412 if (ServiceNameLen
> 12 &&
413 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
415 *RelativeName
= HeapAlloc(GetProcessHeap(),
417 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
418 if (*RelativeName
== NULL
)
420 DPRINT("Error allocating memory for boot driver name!\n");
421 return ERROR_NOT_ENOUGH_MEMORY
;
425 wcscpy(*RelativeName
, CanonName
);
427 DPRINT("Bootdriver name %S\n", *RelativeName
);
428 return ERROR_SUCCESS
;
431 /* If it has %SystemRoot% prefix, substitute it to \System*/
432 if (ServiceNameLen
> 13 &&
433 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
435 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
436 *RelativeName
= HeapAlloc(GetProcessHeap(),
438 ServiceNameLen
* sizeof(WCHAR
));
440 if (*RelativeName
== NULL
)
442 DPRINT("Error allocating memory for boot driver name!\n");
443 return ERROR_NOT_ENOUGH_MEMORY
;
447 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
448 wcscat(*RelativeName
, CanonName
+ 13);
450 DPRINT("Bootdriver name %S\n", *RelativeName
);
451 return ERROR_SUCCESS
;
454 /* Get buffer size needed for expanding env strings */
455 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
459 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
460 return ERROR_INVALID_ENVIRONMENT
;
463 /* Allocate memory, since the size is known now */
464 Expanded
= HeapAlloc(GetProcessHeap(),
466 (BufferSize
+ 1) * sizeof(WCHAR
));
469 DPRINT("Error allocating memory for boot driver name!\n");
470 return ERROR_NOT_ENOUGH_MEMORY
;
474 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
477 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
478 HeapFree(GetProcessHeap(), 0, Expanded
);
479 return ERROR_NOT_ENOUGH_MEMORY
;
482 /* Convert to NY-style path */
483 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
485 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
486 return ERROR_INVALID_ENVIRONMENT
;
489 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
491 /* No need to keep the dos-path anymore */
492 HeapFree(GetProcessHeap(), 0, Expanded
);
494 /* Copy it to the allocated place */
495 Expanded
= HeapAlloc(GetProcessHeap(),
497 NtPathName
.Length
+ sizeof(UNICODE_NULL
));
500 DPRINT("Error allocating memory for boot driver name!\n");
501 return ERROR_NOT_ENOUGH_MEMORY
;
504 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
505 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
506 Expanded
[ExpandedLen
] = UNICODE_NULL
;
508 if (ServiceNameLen
> ExpandedLen
&&
509 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
511 /* Only \SystemRoot\ is missing */
512 *RelativeName
= HeapAlloc(GetProcessHeap(),
514 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
515 if (*RelativeName
== NULL
)
517 DPRINT("Error allocating memory for boot driver name!\n");
518 HeapFree(GetProcessHeap(), 0, Expanded
);
519 return ERROR_NOT_ENOUGH_MEMORY
;
522 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
523 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
525 RtlFreeUnicodeString(&NtPathName
);
526 return ERROR_SUCCESS
;
529 /* The most complex case starts here */
530 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
531 InitializeObjectAttributes(&ObjectAttributes
,
533 OBJ_CASE_INSENSITIVE
,
537 /* Open this symlink */
538 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
540 if (NT_SUCCESS(Status
))
542 LinkTarget
.Length
= 0;
543 LinkTarget
.MaximumLength
= 0;
545 DPRINT("Opened symbolic link object\n");
547 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
548 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
550 /* Check if required buffer size is sane */
551 if (BufferSize
> 0xFFFD)
553 DPRINT("Too large buffer required\n");
556 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
557 HeapFree(GetProcessHeap(), 0, Expanded
);
558 return ERROR_NOT_ENOUGH_MEMORY
;
561 /* Alloc the string */
562 LinkTarget
.Length
= (USHORT
)BufferSize
;
563 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(UNICODE_NULL
);
564 LinkTarget
.Buffer
= HeapAlloc(GetProcessHeap(),
566 LinkTarget
.MaximumLength
);
567 if (!LinkTarget
.Buffer
)
569 DPRINT("Unable to alloc buffer\n");
570 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
571 HeapFree(GetProcessHeap(), 0, Expanded
);
572 return ERROR_NOT_ENOUGH_MEMORY
;
575 /* Do a real query now */
576 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
577 if (NT_SUCCESS(Status
))
579 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
581 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
582 if ((ServiceNameLen
> ExpandedLen
) &&
583 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
585 *RelativeName
= HeapAlloc(GetProcessHeap(),
587 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
589 if (*RelativeName
== NULL
)
591 DPRINT("Unable to alloc buffer\n");
592 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
593 HeapFree(GetProcessHeap(), 0, Expanded
);
594 RtlFreeUnicodeString(&NtPathName
);
595 return ERROR_NOT_ENOUGH_MEMORY
;
598 /* Copy it over, substituting the first part
600 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
601 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
604 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
605 HeapFree(GetProcessHeap(), 0, Expanded
);
606 RtlFreeUnicodeString(&NtPathName
);
609 return ERROR_SUCCESS
;
613 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
614 HeapFree(GetProcessHeap(), 0, Expanded
);
615 RtlFreeUnicodeString(&NtPathName
);
616 return ERROR_INVALID_PARAMETER
;
621 DPRINT("Error, Status = %08X\n", Status
);
622 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
623 HeapFree(GetProcessHeap(), 0, Expanded
);
624 RtlFreeUnicodeString(&NtPathName
);
625 return ERROR_INVALID_PARAMETER
;
630 DPRINT("Error, Status = %08X\n", Status
);
631 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
632 HeapFree(GetProcessHeap(), 0, Expanded
);
633 RtlFreeUnicodeString(&NtPathName
);
634 return ERROR_INVALID_PARAMETER
;
639 DPRINT("Error, Status = %08X\n", Status
);
640 HeapFree(GetProcessHeap(), 0, Expanded
);
641 return ERROR_INVALID_PARAMETER
;
645 *RelativeName
= NULL
;
646 return ERROR_INVALID_PARAMETER
;
651 ScmCanonDriverImagePath(DWORD dwStartType
,
652 const wchar_t *lpServiceName
,
653 wchar_t **lpCanonName
)
655 DWORD ServiceNameLen
, Result
;
656 UNICODE_STRING NtServiceName
;
658 const WCHAR
*SourceName
= lpServiceName
;
660 /* Calculate the length of the service's name */
661 ServiceNameLen
= wcslen(lpServiceName
);
663 /* 12 is wcslen(L"\\SystemRoot\\") */
664 if (ServiceNameLen
> 12 &&
665 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
667 /* SystemRoot prefix is already included */
668 *lpCanonName
= HeapAlloc(GetProcessHeap(),
670 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
672 if (*lpCanonName
== NULL
)
674 DPRINT("Error allocating memory for canonized service name!\n");
675 return ERROR_NOT_ENOUGH_MEMORY
;
678 /* If it's a boot-time driver, it must be systemroot relative */
679 if (dwStartType
== SERVICE_BOOT_START
)
683 wcscpy(*lpCanonName
, SourceName
);
685 DPRINT("Canonicalized name %S\n", *lpCanonName
);
689 /* Check if it has %SystemRoot% (len=13) */
690 if (ServiceNameLen
> 13 &&
691 !_wcsnicmp(L
"%SystemRoot%\\", lpServiceName
, 13))
693 /* Substitute %SystemRoot% with \\SystemRoot\\ */
694 *lpCanonName
= HeapAlloc(GetProcessHeap(),
696 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
698 if (*lpCanonName
== NULL
)
700 DPRINT("Error allocating memory for canonized service name!\n");
701 return ERROR_NOT_ENOUGH_MEMORY
;
704 /* If it's a boot-time driver, it must be systemroot relative */
705 if (dwStartType
== SERVICE_BOOT_START
)
706 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
708 wcscat(*lpCanonName
, lpServiceName
+ 13);
710 DPRINT("Canonicalized name %S\n", *lpCanonName
);
714 /* Check if it's a relative path name */
715 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
717 *lpCanonName
= HeapAlloc(GetProcessHeap(),
719 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
721 if (*lpCanonName
== NULL
)
723 DPRINT("Error allocating memory for canonized service name!\n");
724 return ERROR_NOT_ENOUGH_MEMORY
;
727 /* Just copy it over without changing */
728 wcscpy(*lpCanonName
, lpServiceName
);
733 /* It seems to be a DOS path, convert it */
734 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
736 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
737 return ERROR_INVALID_PARAMETER
;
740 *lpCanonName
= HeapAlloc(GetProcessHeap(),
742 NtServiceName
.Length
+ sizeof(WCHAR
));
744 if (*lpCanonName
== NULL
)
746 DPRINT("Error allocating memory for canonized service name!\n");
747 RtlFreeUnicodeString(&NtServiceName
);
748 return ERROR_NOT_ENOUGH_MEMORY
;
751 /* Copy the string */
752 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
754 /* The unicode string is not needed anymore */
755 RtlFreeUnicodeString(&NtServiceName
);
757 if (dwStartType
!= SERVICE_BOOT_START
)
759 DPRINT("Canonicalized name %S\n", *lpCanonName
);
763 /* The service is boot-started, so must be relative */
764 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
767 /* There is a problem, free name and return */
768 HeapFree(GetProcessHeap(), 0, *lpCanonName
);
769 DPRINT("Error converting named!\n");
773 ASSERT(RelativeName
);
775 /* Copy that string */
776 wcscpy(*lpCanonName
, RelativeName
+ 12);
778 /* Free the allocated buffer */
779 HeapFree(GetProcessHeap(), 0, RelativeName
);
781 DPRINT("Canonicalized name %S\n", *lpCanonName
);
788 /* Internal recursive function */
789 /* Need to search for every dependency on every service */
791 Int_EnumDependentServicesW(HKEY hServicesKey
,
793 DWORD dwServiceState
,
794 PSERVICE
*lpServices
,
795 LPDWORD pcbBytesNeeded
,
796 LPDWORD lpServicesReturned
)
798 DWORD dwError
= ERROR_SUCCESS
;
799 WCHAR szNameBuf
[MAX_PATH
];
800 WCHAR szValueBuf
[MAX_PATH
];
801 WCHAR
*lpszNameBuf
= szNameBuf
;
802 WCHAR
*lpszValueBuf
= szValueBuf
;
806 PSERVICE lpCurrentService
;
807 HKEY hServiceEnumKey
;
808 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
809 DWORD dwDependServiceStrPtr
= 0;
810 DWORD dwRequiredSize
= 0;
812 /* Get the number of service keys */
813 dwError
= RegQueryInfoKeyW(hServicesKey
,
825 if (dwError
!= ERROR_SUCCESS
)
827 DPRINT("ERROR! Unable to get number of services keys.\n");
831 /* Iterate the service keys to see if another service depends on the this service */
832 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
835 dwError
= RegEnumKeyExW(hServicesKey
,
843 if (dwError
!= ERROR_SUCCESS
)
846 /* Open the Service key */
847 dwError
= RegOpenKeyExW(hServicesKey
,
852 if (dwError
!= ERROR_SUCCESS
)
857 /* Check for the DependOnService Value */
858 dwError
= RegQueryValueExW(hServiceEnumKey
,
862 (LPBYTE
)lpszValueBuf
,
865 /* FIXME: Handle load order. */
867 /* If the service found has a DependOnService value */
868 if (dwError
== ERROR_SUCCESS
)
870 dwDependServiceStrPtr
= 0;
872 /* Can be more than one Dependencies in the DependOnService string */
873 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
875 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
877 /* Get the current enumed service pointer */
878 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
880 /* Check for valid Service */
881 if (!lpCurrentService
)
883 /* This should never happen! */
884 DPRINT("This should not happen at this point, report to Developer\n");
885 return ERROR_NOT_FOUND
;
888 /* Determine state the service is in */
889 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
890 dwCurrentServiceState
= SERVICE_INACTIVE
;
892 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
893 if ((dwCurrentServiceState
== dwServiceState
) ||
894 (dwServiceState
== SERVICE_STATE_ALL
))
896 /* Calculate the required size */
897 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
898 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
899 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
901 /* Add the size for service name and display name pointers */
902 dwRequiredSize
+= (2 * sizeof(PVOID
));
904 /* increase the BytesNeeded size */
905 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
907 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
910 /* Recursive call to check for its dependencies */
911 Int_EnumDependentServicesW(hServicesKey
,
918 /* If the lpServices is valid set the service pointer */
920 lpServices
[*lpServicesReturned
] = lpCurrentService
;
922 *lpServicesReturned
= *lpServicesReturned
+ 1;
926 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
929 else if (*pcbBytesNeeded
)
931 dwError
= ERROR_SUCCESS
;
934 RegCloseKey(hServiceEnumKey
);
942 DWORD
RCloseServiceHandle(
943 LPSC_RPC_HANDLE hSCObject
)
945 PMANAGER_HANDLE hManager
;
946 PSERVICE_HANDLE hService
;
950 DWORD pcbBytesNeeded
= 0;
951 DWORD dwServicesReturned
= 0;
953 DPRINT("RCloseServiceHandle() called\n");
955 DPRINT("hSCObject = %p\n", *hSCObject
);
958 return ERROR_INVALID_HANDLE
;
960 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
961 hService
= ScmGetServiceFromHandle(*hSCObject
);
963 if (hManager
!= NULL
)
965 DPRINT("Found manager handle\n");
967 /* FIXME: add handle cleanup code */
969 HeapFree(GetProcessHeap(), 0, hManager
);
974 DPRINT("RCloseServiceHandle() done\n");
975 return ERROR_SUCCESS
;
977 else if (hService
!= NULL
)
979 DPRINT("Found service handle\n");
981 /* Lock the service database exlusively */
982 ScmLockDatabaseExclusive();
984 /* Get the pointer to the service record */
985 lpService
= hService
->ServiceEntry
;
987 /* FIXME: add handle cleanup code */
989 /* Free the handle */
990 HeapFree(GetProcessHeap(), 0, hService
);
993 ASSERT(lpService
->dwRefCount
> 0);
995 lpService
->dwRefCount
--;
996 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
997 lpService
->dwRefCount
);
999 if (lpService
->dwRefCount
== 0)
1001 /* If this service has been marked for deletion */
1002 if (lpService
->bDeleted
)
1004 /* Open the Services Reg key */
1005 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1006 L
"System\\CurrentControlSet\\Services",
1008 KEY_SET_VALUE
| KEY_READ
,
1010 if (dwError
!= ERROR_SUCCESS
)
1012 DPRINT("Failed to open services key\n");
1013 ScmUnlockDatabase();
1017 /* Call the internal function with NULL, just to get bytes we need */
1018 Int_EnumDependentServicesW(hServicesKey
,
1023 &dwServicesReturned
);
1025 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */
1028 DPRINT("Deletion failed due to running dependencies.\n");
1029 RegCloseKey(hServicesKey
);
1030 ScmUnlockDatabase();
1031 return ERROR_SUCCESS
;
1034 /* There are no references and no runnning dependencies,
1035 it is now safe to delete the service */
1037 /* Delete the Service Key */
1038 dwError
= RegDeleteKeyW(hServicesKey
,
1039 lpService
->lpServiceName
);
1041 RegCloseKey(hServicesKey
);
1043 if (dwError
!= ERROR_SUCCESS
)
1045 DPRINT("Failed to Delete the Service Registry key\n");
1046 ScmUnlockDatabase();
1050 /* Delete the Service */
1051 ScmDeleteServiceRecord(lpService
);
1055 ScmUnlockDatabase();
1059 DPRINT("RCloseServiceHandle() done\n");
1060 return ERROR_SUCCESS
;
1063 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
1065 return ERROR_INVALID_HANDLE
;
1070 DWORD
RControlService(
1071 SC_RPC_HANDLE hService
,
1073 LPSERVICE_STATUS lpServiceStatus
)
1075 PSERVICE_HANDLE hSvc
;
1077 ACCESS_MASK DesiredAccess
;
1078 DWORD dwError
= ERROR_SUCCESS
;
1079 DWORD pcbBytesNeeded
= 0;
1080 DWORD dwServicesReturned
= 0;
1081 DWORD dwControlsAccepted
;
1082 DWORD dwCurrentState
;
1083 HKEY hServicesKey
= NULL
;
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 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
1118 case SERVICE_INTERROGATE
:
1119 DesiredAccess
= SERVICE_INTERROGATE
;
1123 if (dwControl
>= 128 && dwControl
<= 255)
1124 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
1126 return ERROR_INVALID_PARAMETER
;
1130 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1132 return ERROR_ACCESS_DENIED
;
1134 /* Return the current service status information */
1135 RtlCopyMemory(lpServiceStatus
,
1137 sizeof(SERVICE_STATUS
));
1139 if (dwControl
== SERVICE_CONTROL_STOP
)
1141 /* Check if the service has dependencies running as windows
1142 doesn't stop a service that does */
1144 /* Open the Services Reg key */
1145 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1146 L
"System\\CurrentControlSet\\Services",
1150 if (dwError
!= ERROR_SUCCESS
)
1152 DPRINT("Failed to open services key\n");
1156 /* Call the internal function with NULL, just to get bytes we need */
1157 Int_EnumDependentServicesW(hServicesKey
,
1162 &dwServicesReturned
);
1164 RegCloseKey(hServicesKey
);
1166 /* If pcbBytesNeeded is not zero then there are services running that
1167 are dependent on this service */
1168 if (pcbBytesNeeded
!= 0)
1170 DPRINT("Service has running dependencies. Failed to stop service.\n");
1171 return ERROR_DEPENDENT_SERVICES_RUNNING
;
1175 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1177 /* Send control code to the driver */
1178 dwError
= ScmControlDriver(lpService
,
1184 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
1185 dwCurrentState
= lpService
->Status
.dwCurrentState
;
1187 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1188 if (lpService
->lpImage
== NULL
|| dwCurrentState
== SERVICE_STOPPED
)
1189 return ERROR_SERVICE_NOT_ACTIVE
;
1191 /* Check the current state before sending a control request */
1192 switch (dwCurrentState
)
1194 case SERVICE_STOP_PENDING
:
1195 case SERVICE_STOPPED
:
1196 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1198 case SERVICE_START_PENDING
:
1201 case SERVICE_CONTROL_STOP
:
1204 case SERVICE_CONTROL_INTERROGATE
:
1205 RtlCopyMemory(lpServiceStatus
,
1207 sizeof(SERVICE_STATUS
));
1208 return ERROR_SUCCESS
;
1211 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1216 /* Check if the control code is acceptable to the service */
1219 case SERVICE_CONTROL_STOP
:
1220 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
1221 return ERROR_INVALID_SERVICE_CONTROL
;
1224 case SERVICE_CONTROL_PAUSE
:
1225 case SERVICE_CONTROL_CONTINUE
:
1226 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
1227 return ERROR_INVALID_SERVICE_CONTROL
;
1231 /* Send control code to the service */
1232 dwError
= ScmControlService(lpService
,
1235 /* Return service status information */
1236 RtlCopyMemory(lpServiceStatus
,
1238 sizeof(SERVICE_STATUS
));
1241 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
1242 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
1249 DWORD
RDeleteService(
1250 SC_RPC_HANDLE hService
)
1252 PSERVICE_HANDLE hSvc
;
1256 DPRINT("RDeleteService() called\n");
1259 return ERROR_SHUTDOWN_IN_PROGRESS
;
1261 hSvc
= ScmGetServiceFromHandle(hService
);
1264 DPRINT1("Invalid service handle!\n");
1265 return ERROR_INVALID_HANDLE
;
1268 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1270 return ERROR_ACCESS_DENIED
;
1272 lpService
= hSvc
->ServiceEntry
;
1273 if (lpService
== NULL
)
1275 DPRINT("lpService == NULL!\n");
1276 return ERROR_INVALID_HANDLE
;
1279 /* Lock the service database exclusively */
1280 ScmLockDatabaseExclusive();
1282 if (lpService
->bDeleted
)
1284 DPRINT("The service has already been marked for delete!\n");
1285 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1289 /* Mark service for delete */
1290 lpService
->bDeleted
= TRUE
;
1292 dwError
= ScmMarkServiceForDelete(lpService
);
1295 /* Unlock the service database */
1296 ScmUnlockDatabase();
1298 DPRINT("RDeleteService() done\n");
1305 DWORD
RLockServiceDatabase(
1306 SC_RPC_HANDLE hSCManager
,
1307 LPSC_RPC_LOCK lpLock
)
1309 PMANAGER_HANDLE hMgr
;
1311 DPRINT("RLockServiceDatabase() called\n");
1315 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
1318 DPRINT1("Invalid service manager handle!\n");
1319 return ERROR_INVALID_HANDLE
;
1322 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
1324 return ERROR_ACCESS_DENIED
;
1326 // return ScmLockDatabase(0, hMgr->0xC, hLock);
1328 /* FIXME: Lock the database */
1329 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
1331 return ERROR_SUCCESS
;
1336 DWORD
RQueryServiceObjectSecurity(
1337 SC_RPC_HANDLE hService
,
1338 SECURITY_INFORMATION dwSecurityInformation
,
1339 LPBYTE lpSecurityDescriptor
,
1341 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1343 PSERVICE_HANDLE hSvc
;
1345 ULONG DesiredAccess
= 0;
1347 DWORD dwBytesNeeded
;
1351 SECURITY_DESCRIPTOR ObjectDescriptor
;
1353 DPRINT("RQueryServiceObjectSecurity() called\n");
1355 hSvc
= ScmGetServiceFromHandle(hService
);
1358 DPRINT1("Invalid service handle!\n");
1359 return ERROR_INVALID_HANDLE
;
1362 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1363 GROUP_SECURITY_INFORMATION
|
1364 OWNER_SECURITY_INFORMATION
))
1365 DesiredAccess
|= READ_CONTROL
;
1367 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1368 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1370 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1373 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1374 return ERROR_ACCESS_DENIED
;
1377 lpService
= hSvc
->ServiceEntry
;
1378 if (lpService
== NULL
)
1380 DPRINT("lpService == NULL!\n");
1381 return ERROR_INVALID_HANDLE
;
1384 /* Lock the service database */
1385 ScmLockDatabaseShared();
1389 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
1391 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
1392 dwSecurityInformation
,
1393 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1397 /* Unlock the service database */
1398 ScmUnlockDatabase();
1400 if (NT_SUCCESS(Status
))
1402 *pcbBytesNeeded
= dwBytesNeeded
;
1403 dwError
= STATUS_SUCCESS
;
1405 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1407 *pcbBytesNeeded
= dwBytesNeeded
;
1408 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1410 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1412 dwError
= ERROR_GEN_FAILURE
;
1416 dwError
= RtlNtStatusToDosError(Status
);
1424 DWORD
RSetServiceObjectSecurity(
1425 SC_RPC_HANDLE hService
,
1426 DWORD dwSecurityInformation
,
1427 LPBYTE lpSecurityDescriptor
,
1428 DWORD dwSecuityDescriptorSize
)
1430 PSERVICE_HANDLE hSvc
;
1432 ULONG DesiredAccess
= 0;
1433 /* HANDLE hToken = NULL; */
1435 /* NTSTATUS Status; */
1438 DPRINT("RSetServiceObjectSecurity() called\n");
1440 hSvc
= ScmGetServiceFromHandle(hService
);
1443 DPRINT1("Invalid service handle!\n");
1444 return ERROR_INVALID_HANDLE
;
1447 if (dwSecurityInformation
== 0 ||
1448 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1449 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1450 return ERROR_INVALID_PARAMETER
;
1452 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1453 return ERROR_INVALID_PARAMETER
;
1455 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1456 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1458 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1459 DesiredAccess
|= WRITE_DAC
;
1461 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1462 DesiredAccess
|= WRITE_OWNER
;
1464 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1465 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1466 return ERROR_INVALID_PARAMETER
;
1468 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1469 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1470 return ERROR_INVALID_PARAMETER
;
1472 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1475 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1476 return ERROR_ACCESS_DENIED
;
1479 lpService
= hSvc
->ServiceEntry
;
1480 if (lpService
== NULL
)
1482 DPRINT("lpService == NULL!\n");
1483 return ERROR_INVALID_HANDLE
;
1486 if (lpService
->bDeleted
)
1487 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1490 RpcImpersonateClient(NULL
);
1492 Status
= NtOpenThreadToken(NtCurrentThread(),
1496 if (!NT_SUCCESS(Status
))
1497 return RtlNtStatusToDosError(Status
);
1502 /* Lock the service database exclusive */
1503 ScmLockDatabaseExclusive();
1506 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1507 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1508 &lpService
->lpSecurityDescriptor
,
1511 if (!NT_SUCCESS(Status
))
1513 dwError
= RtlNtStatusToDosError(Status
);
1518 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1519 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1521 if (dwError
!= ERROR_SUCCESS
)
1525 dwError
= ERROR_SUCCESS
;
1526 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1527 // lpService->lpSecurityDescriptor);
1529 RegFlushKey(hServiceKey
);
1530 RegCloseKey(hServiceKey
);
1539 /* Unlock service database */
1540 ScmUnlockDatabase();
1542 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1549 DWORD
RQueryServiceStatus(
1550 SC_RPC_HANDLE hService
,
1551 LPSERVICE_STATUS lpServiceStatus
)
1553 PSERVICE_HANDLE hSvc
;
1556 DPRINT("RQueryServiceStatus() called\n");
1559 return ERROR_SHUTDOWN_IN_PROGRESS
;
1561 hSvc
= ScmGetServiceFromHandle(hService
);
1564 DPRINT1("Invalid service handle!\n");
1565 return ERROR_INVALID_HANDLE
;
1568 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1569 SERVICE_QUERY_STATUS
))
1571 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1572 return ERROR_ACCESS_DENIED
;
1575 lpService
= hSvc
->ServiceEntry
;
1576 if (lpService
== NULL
)
1578 DPRINT("lpService == NULL!\n");
1579 return ERROR_INVALID_HANDLE
;
1582 /* Lock the service database shared */
1583 ScmLockDatabaseShared();
1585 /* Return service status information */
1586 RtlCopyMemory(lpServiceStatus
,
1588 sizeof(SERVICE_STATUS
));
1590 /* Unlock the service database */
1591 ScmUnlockDatabase();
1593 return ERROR_SUCCESS
;
1598 ScmIsValidServiceState(DWORD dwCurrentState
)
1600 switch (dwCurrentState
)
1602 case SERVICE_STOPPED
:
1603 case SERVICE_START_PENDING
:
1604 case SERVICE_STOP_PENDING
:
1605 case SERVICE_RUNNING
:
1606 case SERVICE_CONTINUE_PENDING
:
1607 case SERVICE_PAUSE_PENDING
:
1608 case SERVICE_PAUSED
:
1618 DWORD
RSetServiceStatus(
1619 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1620 LPSERVICE_STATUS lpServiceStatus
)
1624 DPRINT("RSetServiceStatus() called\n");
1625 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1626 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1627 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1628 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1629 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1630 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1631 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1632 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1634 if (hServiceStatus
== 0)
1636 DPRINT("hServiceStatus == NULL!\n");
1637 return ERROR_INVALID_HANDLE
;
1640 lpService
= (PSERVICE
)hServiceStatus
;
1641 if (lpService
== NULL
)
1643 DPRINT("lpService == NULL!\n");
1644 return ERROR_INVALID_HANDLE
;
1647 /* Check current state */
1648 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1650 DPRINT("Invalid service state!\n");
1651 return ERROR_INVALID_DATA
;
1654 /* Check service type */
1655 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1656 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1658 DPRINT("Invalid service type!\n");
1659 return ERROR_INVALID_DATA
;
1662 /* Check accepted controls */
1663 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1665 DPRINT("Invalid controls accepted!\n");
1666 return ERROR_INVALID_DATA
;
1669 /* Lock the service database exclusively */
1670 ScmLockDatabaseExclusive();
1672 RtlCopyMemory(&lpService
->Status
,
1674 sizeof(SERVICE_STATUS
));
1676 /* Unlock the service database */
1677 ScmUnlockDatabase();
1679 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1680 DPRINT("RSetServiceStatus() done\n");
1682 return ERROR_SUCCESS
;
1687 DWORD
RUnlockServiceDatabase(
1691 return ERROR_SUCCESS
;
1696 DWORD
RNotifyBootConfigStatus(
1697 SVCCTL_HANDLEW lpMachineName
,
1698 DWORD BootAcceptable
)
1700 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1701 return ERROR_SUCCESS
;
1704 // return ERROR_CALL_NOT_IMPLEMENTED;
1709 DWORD
RI_ScSetServiceBitsW(
1710 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1711 DWORD dwServiceBits
,
1713 int bUpdateImmediately
,
1717 return ERROR_CALL_NOT_IMPLEMENTED
;
1722 DWORD
RChangeServiceConfigW(
1723 SC_RPC_HANDLE hService
,
1724 DWORD dwServiceType
,
1726 DWORD dwErrorControl
,
1727 LPWSTR lpBinaryPathName
,
1728 LPWSTR lpLoadOrderGroup
,
1730 LPBYTE lpDependencies
,
1732 LPWSTR lpServiceStartName
,
1735 LPWSTR lpDisplayName
)
1737 DWORD dwError
= ERROR_SUCCESS
;
1738 PSERVICE_HANDLE hSvc
;
1739 PSERVICE lpService
= NULL
;
1740 HKEY hServiceKey
= NULL
;
1741 LPWSTR lpDisplayNameW
= NULL
;
1742 LPWSTR lpImagePathW
= NULL
;
1744 DPRINT("RChangeServiceConfigW() called\n");
1745 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1746 DPRINT("dwStartType = %lu\n", dwStartType
);
1747 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1748 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1749 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1750 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1753 return ERROR_SHUTDOWN_IN_PROGRESS
;
1755 hSvc
= ScmGetServiceFromHandle(hService
);
1758 DPRINT1("Invalid service handle!\n");
1759 return ERROR_INVALID_HANDLE
;
1762 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1763 SERVICE_CHANGE_CONFIG
))
1765 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1766 return ERROR_ACCESS_DENIED
;
1769 lpService
= hSvc
->ServiceEntry
;
1770 if (lpService
== NULL
)
1772 DPRINT("lpService == NULL!\n");
1773 return ERROR_INVALID_HANDLE
;
1776 /* Lock the service database exclusively */
1777 ScmLockDatabaseExclusive();
1779 if (lpService
->bDeleted
)
1781 DPRINT("The service has already been marked for delete!\n");
1782 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1786 /* Open the service key */
1787 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1790 if (dwError
!= ERROR_SUCCESS
)
1793 /* Write service data to the registry */
1794 /* Set the display name */
1795 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1797 RegSetValueExW(hServiceKey
,
1801 (LPBYTE
)lpDisplayName
,
1802 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1804 /* Update the display name */
1805 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
1807 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1808 if (lpDisplayNameW
== NULL
)
1810 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1814 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1815 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1817 lpService
->lpDisplayName
= lpDisplayNameW
;
1820 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1822 /* Set the service type */
1823 dwError
= RegSetValueExW(hServiceKey
,
1827 (LPBYTE
)&dwServiceType
,
1829 if (dwError
!= ERROR_SUCCESS
)
1832 lpService
->Status
.dwServiceType
= dwServiceType
;
1835 if (dwStartType
!= SERVICE_NO_CHANGE
)
1837 /* Set the start value */
1838 dwError
= RegSetValueExW(hServiceKey
,
1842 (LPBYTE
)&dwStartType
,
1844 if (dwError
!= ERROR_SUCCESS
)
1847 lpService
->dwStartType
= dwStartType
;
1850 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1852 /* Set the error control value */
1853 dwError
= RegSetValueExW(hServiceKey
,
1857 (LPBYTE
)&dwErrorControl
,
1859 if (dwError
!= ERROR_SUCCESS
)
1862 lpService
->dwErrorControl
= dwErrorControl
;
1865 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1867 /* Set the image path */
1868 lpImagePathW
= lpBinaryPathName
;
1870 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1872 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
1876 if (dwError
!= ERROR_SUCCESS
)
1880 dwError
= RegSetValueExW(hServiceKey
,
1884 (LPBYTE
)lpImagePathW
,
1885 (wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
));
1887 if (lpImagePathW
!= lpBinaryPathName
)
1888 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
1890 if (dwError
!= ERROR_SUCCESS
)
1894 /* Set the group name */
1895 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1897 dwError
= RegSetValueExW(hServiceKey
,
1901 (LPBYTE
)lpLoadOrderGroup
,
1902 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1903 if (dwError
!= ERROR_SUCCESS
)
1906 dwError
= ScmSetServiceGroup(lpService
,
1908 if (dwError
!= ERROR_SUCCESS
)
1912 if (lpdwTagId
!= NULL
)
1914 dwError
= ScmAssignNewTag(lpService
);
1915 if (dwError
!= ERROR_SUCCESS
)
1918 dwError
= RegSetValueExW(hServiceKey
,
1922 (LPBYTE
)&lpService
->dwTag
,
1924 if (dwError
!= ERROR_SUCCESS
)
1927 *lpdwTagId
= lpService
->dwTag
;
1930 /* Write dependencies */
1931 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1933 dwError
= ScmWriteDependencies(hServiceKey
,
1934 (LPWSTR
)lpDependencies
,
1936 if (dwError
!= ERROR_SUCCESS
)
1940 if (lpPassword
!= NULL
)
1942 /* FIXME: Write password */
1946 if (hServiceKey
!= NULL
)
1947 RegCloseKey(hServiceKey
);
1949 /* Unlock the service database */
1950 ScmUnlockDatabase();
1952 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1959 DWORD
RCreateServiceW(
1960 SC_RPC_HANDLE hSCManager
,
1961 LPCWSTR lpServiceName
,
1962 LPCWSTR lpDisplayName
,
1963 DWORD dwDesiredAccess
,
1964 DWORD dwServiceType
,
1966 DWORD dwErrorControl
,
1967 LPCWSTR lpBinaryPathName
,
1968 LPCWSTR lpLoadOrderGroup
,
1970 LPBYTE lpDependencies
,
1972 LPCWSTR lpServiceStartName
,
1975 LPSC_RPC_HANDLE lpServiceHandle
)
1977 PMANAGER_HANDLE hManager
;
1978 DWORD dwError
= ERROR_SUCCESS
;
1979 PSERVICE lpService
= NULL
;
1980 SC_HANDLE hServiceHandle
= NULL
;
1981 LPWSTR lpImagePath
= NULL
;
1982 HKEY hServiceKey
= NULL
;
1983 LPWSTR lpObjectName
;
1985 DPRINT("RCreateServiceW() called\n");
1986 DPRINT("lpServiceName = %S\n", lpServiceName
);
1987 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1988 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1989 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1990 DPRINT("dwStartType = %lu\n", dwStartType
);
1991 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1992 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1993 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1994 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
1997 return ERROR_SHUTDOWN_IN_PROGRESS
;
1999 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2000 if (hManager
== NULL
)
2002 DPRINT1("Invalid service manager handle!\n");
2003 return ERROR_INVALID_HANDLE
;
2006 /* Check access rights */
2007 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2008 SC_MANAGER_CREATE_SERVICE
))
2010 DPRINT("Insufficient access rights! 0x%lx\n",
2011 hManager
->Handle
.DesiredAccess
);
2012 return ERROR_ACCESS_DENIED
;
2015 if (wcslen(lpServiceName
) == 0)
2017 return ERROR_INVALID_NAME
;
2020 if (wcslen(lpBinaryPathName
) == 0)
2022 return ERROR_INVALID_PARAMETER
;
2025 /* Check for invalid service type value */
2026 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2027 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2028 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2029 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2030 return ERROR_INVALID_PARAMETER
;
2032 /* Check for invalid start type value */
2033 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2034 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2035 (dwStartType
!= SERVICE_AUTO_START
) &&
2036 (dwStartType
!= SERVICE_DEMAND_START
) &&
2037 (dwStartType
!= SERVICE_DISABLED
))
2038 return ERROR_INVALID_PARAMETER
;
2040 /* Only drivers can be boot start or system start services */
2041 if ((dwStartType
== SERVICE_BOOT_START
) ||
2042 (dwStartType
== SERVICE_SYSTEM_START
))
2044 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2045 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2046 return ERROR_INVALID_PARAMETER
;
2049 /* Check for invalid error control value */
2050 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2051 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2052 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2053 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2054 return ERROR_INVALID_PARAMETER
;
2056 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2057 (lpServiceStartName
))
2059 return ERROR_INVALID_PARAMETER
;
2062 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2064 return ERROR_INVALID_PARAMETER
;
2067 /* Lock the service database exclusively */
2068 ScmLockDatabaseExclusive();
2070 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2073 /* Unlock the service database */
2074 ScmUnlockDatabase();
2076 /* Check if it is marked for deletion */
2077 if (lpService
->bDeleted
)
2078 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2080 /* Return Error exist */
2081 return ERROR_SERVICE_EXISTS
;
2084 if (lpDisplayName
!= NULL
&&
2085 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2087 /* Unlock the service database */
2088 ScmUnlockDatabase();
2090 return ERROR_DUPLICATE_SERVICE_NAME
;
2093 if (dwServiceType
& SERVICE_DRIVER
)
2095 dwError
= ScmCanonDriverImagePath(dwStartType
,
2098 if (dwError
!= ERROR_SUCCESS
)
2103 if (dwStartType
== SERVICE_BOOT_START
||
2104 dwStartType
== SERVICE_SYSTEM_START
)
2106 /* Unlock the service database */
2107 ScmUnlockDatabase();
2109 return ERROR_INVALID_PARAMETER
;
2113 /* Allocate a new service entry */
2114 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2116 if (dwError
!= ERROR_SUCCESS
)
2119 /* Fill the new service entry */
2120 lpService
->Status
.dwServiceType
= dwServiceType
;
2121 lpService
->dwStartType
= dwStartType
;
2122 lpService
->dwErrorControl
= dwErrorControl
;
2124 /* Fill the display name */
2125 if (lpDisplayName
!= NULL
&&
2126 *lpDisplayName
!= 0 &&
2127 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2129 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(), 0,
2130 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2131 if (lpService
->lpDisplayName
== NULL
)
2133 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2136 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2139 /* Assign the service to a group */
2140 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2142 dwError
= ScmSetServiceGroup(lpService
,
2144 if (dwError
!= ERROR_SUCCESS
)
2148 /* Assign a new tag */
2149 if (lpdwTagId
!= NULL
)
2151 dwError
= ScmAssignNewTag(lpService
);
2152 if (dwError
!= ERROR_SUCCESS
)
2156 /* Write service data to the registry */
2157 /* Create the service key */
2158 dwError
= ScmCreateServiceKey(lpServiceName
,
2161 if (dwError
!= ERROR_SUCCESS
)
2164 /* Set the display name */
2165 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2167 RegSetValueExW(hServiceKey
,
2171 (LPBYTE
)lpDisplayName
,
2172 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2175 /* Set the service type */
2176 dwError
= RegSetValueExW(hServiceKey
,
2180 (LPBYTE
)&dwServiceType
,
2182 if (dwError
!= ERROR_SUCCESS
)
2185 /* Set the start value */
2186 dwError
= RegSetValueExW(hServiceKey
,
2190 (LPBYTE
)&dwStartType
,
2192 if (dwError
!= ERROR_SUCCESS
)
2195 /* Set the error control value */
2196 dwError
= RegSetValueExW(hServiceKey
,
2200 (LPBYTE
)&dwErrorControl
,
2202 if (dwError
!= ERROR_SUCCESS
)
2205 /* Set the image path */
2206 if (dwServiceType
& SERVICE_WIN32
)
2208 dwError
= RegSetValueExW(hServiceKey
,
2212 (LPBYTE
)lpBinaryPathName
,
2213 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2214 if (dwError
!= ERROR_SUCCESS
)
2217 else if (dwServiceType
& SERVICE_DRIVER
)
2219 dwError
= RegSetValueExW(hServiceKey
,
2223 (LPBYTE
)lpImagePath
,
2224 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2225 if (dwError
!= ERROR_SUCCESS
)
2229 /* Set the group name */
2230 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2232 dwError
= RegSetValueExW(hServiceKey
,
2236 (LPBYTE
)lpLoadOrderGroup
,
2237 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2238 if (dwError
!= ERROR_SUCCESS
)
2242 if (lpdwTagId
!= NULL
)
2244 dwError
= RegSetValueExW(hServiceKey
,
2248 (LPBYTE
)&lpService
->dwTag
,
2250 if (dwError
!= ERROR_SUCCESS
)
2254 /* Write dependencies */
2255 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2257 dwError
= ScmWriteDependencies(hServiceKey
,
2258 (LPCWSTR
)lpDependencies
,
2260 if (dwError
!= ERROR_SUCCESS
)
2264 /* Write service start name */
2265 if (dwServiceType
& SERVICE_WIN32
)
2267 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2268 dwError
= RegSetValueExW(hServiceKey
,
2272 (LPBYTE
)lpObjectName
,
2273 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2274 if (dwError
!= ERROR_SUCCESS
)
2278 if (lpPassword
!= NULL
)
2280 /* FIXME: Write password */
2283 dwError
= ScmCreateServiceHandle(lpService
,
2285 if (dwError
!= ERROR_SUCCESS
)
2288 dwError
= ScmCheckAccess(hServiceHandle
,
2290 if (dwError
!= ERROR_SUCCESS
)
2293 lpService
->dwRefCount
= 1;
2294 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2297 /* Unlock the service database */
2298 ScmUnlockDatabase();
2300 if (hServiceKey
!= NULL
)
2301 RegCloseKey(hServiceKey
);
2303 if (dwError
== ERROR_SUCCESS
)
2305 DPRINT("hService %p\n", hServiceHandle
);
2306 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2308 if (lpdwTagId
!= NULL
)
2309 *lpdwTagId
= lpService
->dwTag
;
2313 if (lpService
!= NULL
&&
2314 lpService
->lpServiceName
!= NULL
)
2316 /* Release the display name buffer */
2317 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2322 /* Remove the service handle */
2323 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2326 if (lpService
!= NULL
)
2328 /* FIXME: remove the service entry */
2332 if (lpImagePath
!= NULL
)
2333 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2335 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2342 DWORD
REnumDependentServicesW(
2343 SC_RPC_HANDLE hService
,
2344 DWORD dwServiceState
,
2347 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2348 LPBOUNDED_DWORD_256K lpServicesReturned
)
2350 DWORD dwError
= ERROR_SUCCESS
;
2351 DWORD dwServicesReturned
= 0;
2352 DWORD dwServiceCount
;
2353 HKEY hServicesKey
= NULL
;
2354 PSERVICE_HANDLE hSvc
;
2355 PSERVICE lpService
= NULL
;
2356 PSERVICE
*lpServicesArray
= NULL
;
2357 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2360 *pcbBytesNeeded
= 0;
2361 *lpServicesReturned
= 0;
2363 DPRINT("REnumDependentServicesW() called\n");
2365 hSvc
= ScmGetServiceFromHandle(hService
);
2368 DPRINT1("Invalid service handle!\n");
2369 return ERROR_INVALID_HANDLE
;
2372 lpService
= hSvc
->ServiceEntry
;
2374 /* Check access rights */
2375 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2376 SC_MANAGER_ENUMERATE_SERVICE
))
2378 DPRINT("Insufficient access rights! 0x%lx\n",
2379 hSvc
->Handle
.DesiredAccess
);
2380 return ERROR_ACCESS_DENIED
;
2383 /* Open the Services Reg key */
2384 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2385 L
"System\\CurrentControlSet\\Services",
2389 if (dwError
!= ERROR_SUCCESS
)
2392 /* First determine the bytes needed and get the number of dependent services */
2393 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2398 &dwServicesReturned
);
2399 if (dwError
!= ERROR_SUCCESS
)
2402 /* If buffer size is less than the bytes needed or pointer is null */
2403 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2405 dwError
= ERROR_MORE_DATA
;
2409 /* Allocate memory for array of service pointers */
2410 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2412 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2413 if (!lpServicesArray
)
2415 DPRINT1("Could not allocate a buffer!!\n");
2416 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2420 dwServicesReturned
= 0;
2421 *pcbBytesNeeded
= 0;
2423 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2428 &dwServicesReturned
);
2429 if (dwError
!= ERROR_SUCCESS
)
2434 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2435 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2437 /* Copy EnumDepenedentService to Buffer */
2438 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2440 lpService
= lpServicesArray
[dwServiceCount
];
2442 /* Copy status info */
2443 memcpy(&lpServicesPtr
->ServiceStatus
,
2445 sizeof(SERVICE_STATUS
));
2447 /* Copy display name */
2448 wcscpy(lpStr
, lpService
->lpDisplayName
);
2449 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2450 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2452 /* Copy service name */
2453 wcscpy(lpStr
, lpService
->lpServiceName
);
2454 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2455 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2460 *lpServicesReturned
= dwServicesReturned
;
2463 if (lpServicesArray
!= NULL
)
2464 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2466 RegCloseKey(hServicesKey
);
2468 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2475 DWORD
REnumServicesStatusW(
2476 SC_RPC_HANDLE hSCManager
,
2477 DWORD dwServiceType
,
2478 DWORD dwServiceState
,
2481 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2482 LPBOUNDED_DWORD_256K lpServicesReturned
,
2483 LPBOUNDED_DWORD_256K lpResumeHandle
)
2485 PMANAGER_HANDLE hManager
;
2487 DWORD dwError
= ERROR_SUCCESS
;
2488 PLIST_ENTRY ServiceEntry
;
2489 PSERVICE CurrentService
;
2491 DWORD dwRequiredSize
;
2492 DWORD dwServiceCount
;
2494 DWORD dwLastResumeCount
= 0;
2495 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2498 DPRINT("REnumServicesStatusW() called\n");
2501 return ERROR_SHUTDOWN_IN_PROGRESS
;
2503 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2504 if (hManager
== NULL
)
2506 DPRINT1("Invalid service manager handle!\n");
2507 return ERROR_INVALID_HANDLE
;
2511 *pcbBytesNeeded
= 0;
2512 *lpServicesReturned
= 0;
2514 if ((dwServiceType
== 0) ||
2515 ((dwServiceType
& ~(SERVICE_DRIVER
| SERVICE_WIN32
)) != 0))
2517 DPRINT("Not a valid Service Type!\n");
2518 return ERROR_INVALID_PARAMETER
;
2521 if ((dwServiceState
!= SERVICE_ACTIVE
) &&
2522 (dwServiceState
!= SERVICE_INACTIVE
) &&
2523 (dwServiceState
!= SERVICE_STATE_ALL
))
2525 DPRINT("Not a valid Service State!\n");
2526 return ERROR_INVALID_PARAMETER
;
2529 /* Check access rights */
2530 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2531 SC_MANAGER_ENUMERATE_SERVICE
))
2533 DPRINT("Insufficient access rights! 0x%lx\n",
2534 hManager
->Handle
.DesiredAccess
);
2535 return ERROR_ACCESS_DENIED
;
2539 dwLastResumeCount
= *lpResumeHandle
;
2541 /* Lock the service database shared */
2542 ScmLockDatabaseShared();
2544 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2545 if (lpService
== NULL
)
2547 dwError
= ERROR_SUCCESS
;
2554 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2555 ServiceEntry
!= &ServiceListHead
;
2556 ServiceEntry
= ServiceEntry
->Flink
)
2558 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2562 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2565 dwState
= SERVICE_ACTIVE
;
2566 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2567 dwState
= SERVICE_INACTIVE
;
2569 if ((dwState
& dwServiceState
) == 0)
2572 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2573 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2574 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2576 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2578 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2582 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2583 dwRequiredSize
+= dwSize
;
2585 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2588 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2589 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2592 ServiceEntry
!= &ServiceListHead
;
2593 ServiceEntry
= ServiceEntry
->Flink
)
2595 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2599 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2602 dwState
= SERVICE_ACTIVE
;
2603 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2604 dwState
= SERVICE_INACTIVE
;
2606 if ((dwState
& dwServiceState
) == 0)
2609 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2610 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2611 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2613 dwError
= ERROR_MORE_DATA
;
2616 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2619 *lpResumeHandle
= dwLastResumeCount
;
2621 *lpServicesReturned
= dwServiceCount
;
2622 *pcbBytesNeeded
= dwRequiredSize
;
2624 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2625 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2626 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2629 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2630 ServiceEntry
!= &ServiceListHead
;
2631 ServiceEntry
= ServiceEntry
->Flink
)
2633 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2637 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2640 dwState
= SERVICE_ACTIVE
;
2641 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2642 dwState
= SERVICE_INACTIVE
;
2644 if ((dwState
& dwServiceState
) == 0)
2647 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2648 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2649 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2651 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2654 /* Copy the service name */
2655 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2656 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2657 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2659 /* Copy the display name */
2660 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2661 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2662 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2664 /* Copy the status information */
2665 memcpy(&lpStatusPtr
->ServiceStatus
,
2666 &CurrentService
->Status
,
2667 sizeof(SERVICE_STATUS
));
2670 dwRequiredSize
+= dwSize
;
2673 if (dwError
== ERROR_SUCCESS
)
2675 *pcbBytesNeeded
= 0;
2676 if (lpResumeHandle
) *lpResumeHandle
= 0;
2680 /* Unlock the service database */
2681 ScmUnlockDatabase();
2683 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2690 DWORD
ROpenSCManagerW(
2691 LPWSTR lpMachineName
,
2692 LPWSTR lpDatabaseName
,
2693 DWORD dwDesiredAccess
,
2694 LPSC_RPC_HANDLE lpScHandle
)
2699 DPRINT("ROpenSCManagerW() called\n");
2700 DPRINT("lpMachineName = %p\n", lpMachineName
);
2701 DPRINT("lpMachineName: %S\n", lpMachineName
);
2702 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2703 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2704 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2707 return ERROR_SHUTDOWN_IN_PROGRESS
;
2710 return ERROR_INVALID_PARAMETER
;
2712 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2714 if (dwError
!= ERROR_SUCCESS
)
2716 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2720 /* Check the desired access */
2721 dwError
= ScmCheckAccess(hHandle
,
2722 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2723 if (dwError
!= ERROR_SUCCESS
)
2725 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2726 HeapFree(GetProcessHeap(), 0, hHandle
);
2730 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2731 DPRINT("*hScm = %p\n", *lpScHandle
);
2733 DPRINT("ROpenSCManagerW() done\n");
2735 return ERROR_SUCCESS
;
2740 DWORD
ROpenServiceW(
2741 SC_RPC_HANDLE hSCManager
,
2742 LPWSTR lpServiceName
,
2743 DWORD dwDesiredAccess
,
2744 LPSC_RPC_HANDLE lpServiceHandle
)
2747 PMANAGER_HANDLE hManager
;
2749 DWORD dwError
= ERROR_SUCCESS
;
2751 DPRINT("ROpenServiceW() called\n");
2752 DPRINT("hSCManager = %p\n", hSCManager
);
2753 DPRINT("lpServiceName = %p\n", lpServiceName
);
2754 DPRINT("lpServiceName: %S\n", lpServiceName
);
2755 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2758 return ERROR_SHUTDOWN_IN_PROGRESS
;
2760 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2761 if (hManager
== NULL
)
2763 DPRINT1("Invalid service manager handle!\n");
2764 return ERROR_INVALID_HANDLE
;
2767 if (!lpServiceHandle
)
2768 return ERROR_INVALID_PARAMETER
;
2771 return ERROR_INVALID_ADDRESS
;
2773 /* Lock the service database exclusive */
2774 ScmLockDatabaseExclusive();
2776 /* Get service database entry */
2777 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2778 if (lpService
== NULL
)
2780 DPRINT("Could not find a service!\n");
2781 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2785 /* Create a service handle */
2786 dwError
= ScmCreateServiceHandle(lpService
,
2788 if (dwError
!= ERROR_SUCCESS
)
2790 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2794 /* Check the desired access */
2795 dwError
= ScmCheckAccess(hHandle
,
2797 if (dwError
!= ERROR_SUCCESS
)
2799 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2800 HeapFree(GetProcessHeap(), 0, hHandle
);
2804 lpService
->dwRefCount
++;
2805 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2807 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2808 DPRINT("*hService = %p\n", *lpServiceHandle
);
2811 /* Unlock the service database */
2812 ScmUnlockDatabase();
2814 DPRINT("ROpenServiceW() done\n");
2821 DWORD
RQueryServiceConfigW(
2822 SC_RPC_HANDLE hService
,
2823 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2825 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2827 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2828 DWORD dwError
= ERROR_SUCCESS
;
2829 PSERVICE_HANDLE hSvc
;
2830 PSERVICE lpService
= NULL
;
2831 HKEY hServiceKey
= NULL
;
2832 LPWSTR lpImagePath
= NULL
;
2833 LPWSTR lpServiceStartName
= NULL
;
2834 LPWSTR lpDependencies
= NULL
;
2835 DWORD dwDependenciesLength
= 0;
2836 DWORD dwRequiredSize
;
2837 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2838 WCHAR lpEmptyString
[] = {0,0};
2841 DPRINT("RQueryServiceConfigW() called\n");
2844 return ERROR_SHUTDOWN_IN_PROGRESS
;
2846 hSvc
= ScmGetServiceFromHandle(hService
);
2849 DPRINT1("Invalid service handle!\n");
2850 return ERROR_INVALID_HANDLE
;
2853 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2854 SERVICE_QUERY_CONFIG
))
2856 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2857 return ERROR_ACCESS_DENIED
;
2860 lpService
= hSvc
->ServiceEntry
;
2861 if (lpService
== NULL
)
2863 DPRINT("lpService == NULL!\n");
2864 return ERROR_INVALID_HANDLE
;
2867 /* Lock the service database shared */
2868 ScmLockDatabaseShared();
2870 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2873 if (dwError
!= ERROR_SUCCESS
)
2876 /* Read the image path */
2877 dwError
= ScmReadString(hServiceKey
,
2880 if (dwError
!= ERROR_SUCCESS
)
2883 /* Read the service start name */
2884 ScmReadString(hServiceKey
,
2886 &lpServiceStartName
);
2888 /* Read the dependencies */
2889 ScmReadDependencies(hServiceKey
,
2891 &dwDependenciesLength
);
2893 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2895 if (lpImagePath
!= NULL
)
2896 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2898 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2900 if (lpService
->lpGroup
!= NULL
)
2901 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2903 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2905 if (lpDependencies
!= NULL
)
2906 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2908 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2910 if (lpServiceStartName
!= NULL
)
2911 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2913 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2915 if (lpService
->lpDisplayName
!= NULL
)
2916 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2918 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2920 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2922 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2926 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2927 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2928 lpConfig
->dwStartType
= lpService
->dwStartType
;
2929 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2930 lpConfig
->dwTagId
= lpService
->dwTag
;
2932 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2934 /* Append the image path */
2935 if (lpImagePath
!= NULL
)
2937 wcscpy(lpStr
, lpImagePath
);
2941 wcscpy(lpStr
, lpEmptyString
);
2944 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2945 lpStr
+= (wcslen(lpStr
) + 1);
2947 /* Append the group name */
2948 if (lpService
->lpGroup
!= NULL
)
2950 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2954 wcscpy(lpStr
, lpEmptyString
);
2957 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2958 lpStr
+= (wcslen(lpStr
) + 1);
2960 /* Append Dependencies */
2961 if (lpDependencies
!= NULL
)
2965 dwDependenciesLength
* sizeof(WCHAR
));
2969 wcscpy(lpStr
, lpEmptyString
);
2972 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2973 if (lpDependencies
!= NULL
)
2974 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2976 lpStr
+= (wcslen(lpStr
) + 1);
2978 /* Append the service start name */
2979 if (lpServiceStartName
!= NULL
)
2981 wcscpy(lpStr
, lpServiceStartName
);
2985 wcscpy(lpStr
, lpEmptyString
);
2988 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2989 lpStr
+= (wcslen(lpStr
) + 1);
2991 /* Append the display name */
2992 if (lpService
->lpDisplayName
!= NULL
)
2994 wcscpy(lpStr
, lpService
->lpDisplayName
);
2998 wcscpy(lpStr
, lpEmptyString
);
3001 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3004 if (pcbBytesNeeded
!= NULL
)
3005 *pcbBytesNeeded
= dwRequiredSize
;
3008 /* Unlock the service database */
3009 ScmUnlockDatabase();
3011 if (lpImagePath
!= NULL
)
3012 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3014 if (lpServiceStartName
!= NULL
)
3015 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3017 if (lpDependencies
!= NULL
)
3018 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3020 if (hServiceKey
!= NULL
)
3021 RegCloseKey(hServiceKey
);
3023 DPRINT("RQueryServiceConfigW() done\n");
3030 DWORD
RQueryServiceLockStatusW(
3031 SC_RPC_HANDLE hSCManager
,
3032 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
3034 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3037 return ERROR_CALL_NOT_IMPLEMENTED
;
3042 DWORD
RStartServiceW(
3043 SC_RPC_HANDLE hService
,
3045 LPSTRING_PTRSW argv
)
3047 DWORD dwError
= ERROR_SUCCESS
;
3048 PSERVICE_HANDLE hSvc
;
3049 PSERVICE lpService
= NULL
;
3052 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3053 DPRINT(" argc: %lu\n", argc
);
3056 for (i
= 0; i
< argc
; i
++)
3058 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
]);
3063 return ERROR_SHUTDOWN_IN_PROGRESS
;
3065 hSvc
= ScmGetServiceFromHandle(hService
);
3068 DPRINT1("Invalid service handle!\n");
3069 return ERROR_INVALID_HANDLE
;
3072 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3075 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3076 return ERROR_ACCESS_DENIED
;
3079 lpService
= hSvc
->ServiceEntry
;
3080 if (lpService
== NULL
)
3082 DPRINT("lpService == NULL!\n");
3083 return ERROR_INVALID_HANDLE
;
3086 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3087 return ERROR_SERVICE_DISABLED
;
3089 if (lpService
->bDeleted
)
3090 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3092 /* Start the service */
3093 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3100 DWORD
RGetServiceDisplayNameW(
3101 SC_RPC_HANDLE hSCManager
,
3102 LPCWSTR lpServiceName
,
3103 LPWSTR lpDisplayName
,
3106 // PMANAGER_HANDLE hManager;
3111 DPRINT("RGetServiceDisplayNameW() called\n");
3112 DPRINT("hSCManager = %p\n", hSCManager
);
3113 DPRINT("lpServiceName: %S\n", lpServiceName
);
3114 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3115 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3117 // hManager = (PMANAGER_HANDLE)hSCManager;
3118 // if (hManager->Handle.Tag != MANAGER_TAG)
3120 // DPRINT("Invalid manager handle!\n");
3121 // return ERROR_INVALID_HANDLE;
3124 /* Get service database entry */
3125 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3126 if (lpService
== NULL
)
3128 DPRINT("Could not find a service!\n");
3130 /* If the service could not be found and lpcchBuffer is less than 2, windows
3131 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3132 if (*lpcchBuffer
< 2)
3135 if (lpDisplayName
!= NULL
)
3137 *lpDisplayName
= '\0';
3141 return ERROR_SERVICE_DOES_NOT_EXIST
;
3144 if (!lpService
->lpDisplayName
)
3146 dwLength
= wcslen(lpService
->lpServiceName
);
3148 if (lpDisplayName
!= NULL
&&
3149 *lpcchBuffer
> dwLength
)
3151 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3156 dwLength
= wcslen(lpService
->lpDisplayName
);
3158 if (lpDisplayName
!= NULL
&&
3159 *lpcchBuffer
> dwLength
)
3161 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3165 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3167 *lpcchBuffer
= dwLength
;
3174 DWORD
RGetServiceKeyNameW(
3175 SC_RPC_HANDLE hSCManager
,
3176 LPCWSTR lpDisplayName
,
3177 LPWSTR lpServiceName
,
3180 // PMANAGER_HANDLE hManager;
3185 DPRINT("RGetServiceKeyNameW() called\n");
3186 DPRINT("hSCManager = %p\n", hSCManager
);
3187 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3188 DPRINT("lpServiceName: %p\n", lpServiceName
);
3189 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3191 // hManager = (PMANAGER_HANDLE)hSCManager;
3192 // if (hManager->Handle.Tag != MANAGER_TAG)
3194 // DPRINT("Invalid manager handle!\n");
3195 // return ERROR_INVALID_HANDLE;
3198 /* Get service database entry */
3199 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3200 if (lpService
== NULL
)
3202 DPRINT("Could not find a service!\n");
3204 /* If the service could not be found and lpcchBuffer is less than 2, windows
3205 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3206 if (*lpcchBuffer
< 2)
3209 if (lpServiceName
!= NULL
)
3211 *lpServiceName
= '\0';
3215 return ERROR_SERVICE_DOES_NOT_EXIST
;
3218 dwLength
= wcslen(lpService
->lpServiceName
);
3220 if (lpServiceName
!= NULL
&&
3221 *lpcchBuffer
> dwLength
)
3223 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3224 *lpcchBuffer
= dwLength
;
3225 return ERROR_SUCCESS
;
3228 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3230 *lpcchBuffer
= dwLength
;
3237 DWORD
RI_ScSetServiceBitsA(
3238 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3239 DWORD dwServiceBits
,
3241 int bUpdateImmediately
,
3245 return ERROR_CALL_NOT_IMPLEMENTED
;
3250 DWORD
RChangeServiceConfigA(
3251 SC_RPC_HANDLE hService
,
3252 DWORD dwServiceType
,
3254 DWORD dwErrorControl
,
3255 LPSTR lpBinaryPathName
,
3256 LPSTR lpLoadOrderGroup
,
3258 LPSTR lpDependencies
,
3260 LPSTR lpServiceStartName
,
3263 LPSTR lpDisplayName
)
3265 DWORD dwError
= ERROR_SUCCESS
;
3266 PSERVICE_HANDLE hSvc
;
3267 PSERVICE lpService
= NULL
;
3268 HKEY hServiceKey
= NULL
;
3269 LPWSTR lpDisplayNameW
= NULL
;
3270 LPWSTR lpBinaryPathNameW
= NULL
;
3271 LPWSTR lpCanonicalImagePathW
= NULL
;
3272 LPWSTR lpLoadOrderGroupW
= NULL
;
3273 LPWSTR lpDependenciesW
= NULL
;
3274 // LPWSTR lpPasswordW = NULL;
3276 DPRINT("RChangeServiceConfigA() called\n");
3277 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3278 DPRINT("dwStartType = %lu\n", dwStartType
);
3279 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3280 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3281 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3282 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3285 return ERROR_SHUTDOWN_IN_PROGRESS
;
3287 hSvc
= ScmGetServiceFromHandle(hService
);
3290 DPRINT1("Invalid service handle!\n");
3291 return ERROR_INVALID_HANDLE
;
3294 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3295 SERVICE_CHANGE_CONFIG
))
3297 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3298 return ERROR_ACCESS_DENIED
;
3301 lpService
= hSvc
->ServiceEntry
;
3302 if (lpService
== NULL
)
3304 DPRINT("lpService == NULL!\n");
3305 return ERROR_INVALID_HANDLE
;
3308 /* Lock the service database exclusively */
3309 ScmLockDatabaseExclusive();
3311 if (lpService
->bDeleted
)
3313 DPRINT("The service has already been marked for delete!\n");
3314 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3318 /* Open the service key */
3319 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3322 if (dwError
!= ERROR_SUCCESS
)
3325 /* Write service data to the registry */
3327 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3329 /* Set the display name */
3330 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3332 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3333 if (lpDisplayNameW
== NULL
)
3335 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3339 MultiByteToWideChar(CP_ACP
,
3344 strlen(lpDisplayName
) + 1);
3346 RegSetValueExW(hServiceKey
,
3350 (LPBYTE
)lpDisplayNameW
,
3351 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3353 /* Update lpService->lpDisplayName */
3354 if (lpService
->lpDisplayName
)
3355 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3357 lpService
->lpDisplayName
= lpDisplayNameW
;
3360 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3362 /* Set the service type */
3363 dwError
= RegSetValueExW(hServiceKey
,
3367 (LPBYTE
)&dwServiceType
,
3369 if (dwError
!= ERROR_SUCCESS
)
3372 lpService
->Status
.dwServiceType
= dwServiceType
;
3375 if (dwStartType
!= SERVICE_NO_CHANGE
)
3377 /* Set the start value */
3378 dwError
= RegSetValueExW(hServiceKey
,
3382 (LPBYTE
)&dwStartType
,
3384 if (dwError
!= ERROR_SUCCESS
)
3387 lpService
->dwStartType
= dwStartType
;
3390 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3392 /* Set the error control value */
3393 dwError
= RegSetValueExW(hServiceKey
,
3397 (LPBYTE
)&dwErrorControl
,
3399 if (dwError
!= ERROR_SUCCESS
)
3402 lpService
->dwErrorControl
= dwErrorControl
;
3405 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3407 /* Set the image path */
3408 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(),
3410 (strlen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
3411 if (lpBinaryPathNameW
== NULL
)
3413 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3417 MultiByteToWideChar(CP_ACP
,
3422 strlen(lpBinaryPathName
) + 1);
3424 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
3426 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
3428 &lpCanonicalImagePathW
);
3430 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3432 if (dwError
!= ERROR_SUCCESS
)
3435 lpBinaryPathNameW
= lpCanonicalImagePathW
;
3438 dwError
= RegSetValueExW(hServiceKey
,
3442 (LPBYTE
)lpBinaryPathNameW
,
3443 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3445 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3447 if (dwError
!= ERROR_SUCCESS
)
3451 /* Set the group name */
3452 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3454 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3456 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3457 if (lpLoadOrderGroupW
== NULL
)
3459 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3463 MultiByteToWideChar(CP_ACP
,
3468 strlen(lpLoadOrderGroup
) + 1);
3470 dwError
= RegSetValueExW(hServiceKey
,
3474 (LPBYTE
)lpLoadOrderGroupW
,
3475 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3476 if (dwError
!= ERROR_SUCCESS
)
3478 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3482 dwError
= ScmSetServiceGroup(lpService
,
3485 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3487 if (dwError
!= ERROR_SUCCESS
)
3491 if (lpdwTagId
!= NULL
)
3493 dwError
= ScmAssignNewTag(lpService
);
3494 if (dwError
!= ERROR_SUCCESS
)
3497 dwError
= RegSetValueExW(hServiceKey
,
3501 (LPBYTE
)&lpService
->dwTag
,
3503 if (dwError
!= ERROR_SUCCESS
)
3506 *lpdwTagId
= lpService
->dwTag
;
3509 /* Write dependencies */
3510 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3512 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3514 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3515 if (lpDependenciesW
== NULL
)
3517 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3521 MultiByteToWideChar(CP_ACP
,
3526 strlen(lpDependencies
) + 1);
3528 dwError
= ScmWriteDependencies(hServiceKey
,
3529 (LPWSTR
)lpDependenciesW
,
3532 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3535 if (lpPassword
!= NULL
)
3537 /* FIXME: Write password */
3541 /* Unlock the service database */
3542 ScmUnlockDatabase();
3544 if (hServiceKey
!= NULL
)
3545 RegCloseKey(hServiceKey
);
3547 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3554 DWORD
RCreateServiceA(
3555 SC_RPC_HANDLE hSCManager
,
3556 LPSTR lpServiceName
,
3557 LPSTR lpDisplayName
,
3558 DWORD dwDesiredAccess
,
3559 DWORD dwServiceType
,
3561 DWORD dwErrorControl
,
3562 LPSTR lpBinaryPathName
,
3563 LPSTR lpLoadOrderGroup
,
3565 LPBYTE lpDependencies
,
3567 LPSTR lpServiceStartName
,
3570 LPSC_RPC_HANDLE lpServiceHandle
)
3572 DWORD dwError
= ERROR_SUCCESS
;
3573 LPWSTR lpServiceNameW
= NULL
;
3574 LPWSTR lpDisplayNameW
= NULL
;
3575 LPWSTR lpBinaryPathNameW
= NULL
;
3576 LPWSTR lpLoadOrderGroupW
= NULL
;
3577 LPWSTR lpDependenciesW
= NULL
;
3578 LPWSTR lpServiceStartNameW
= NULL
;
3579 DWORD dwDependenciesLength
= 0;
3586 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3587 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3588 if (!lpServiceNameW
)
3590 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3593 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3598 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3599 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3600 if (!lpDisplayNameW
)
3602 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3605 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3608 if (lpBinaryPathName
)
3610 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3611 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3612 if (!lpBinaryPathNameW
)
3614 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3617 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3620 if (lpLoadOrderGroup
)
3622 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3623 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3624 if (!lpLoadOrderGroupW
)
3626 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3629 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3634 lpStr
= (LPCSTR
)lpDependencies
;
3637 dwLength
= strlen(lpStr
) + 1;
3638 dwDependenciesLength
+= dwLength
;
3639 lpStr
= lpStr
+ dwLength
;
3641 dwDependenciesLength
++;
3643 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3644 if (!lpDependenciesW
)
3646 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3649 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3652 if (lpServiceStartName
)
3654 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3655 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3656 if (!lpServiceStartNameW
)
3658 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3661 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3664 dwError
= RCreateServiceW(hSCManager
,
3674 (LPBYTE
)lpDependenciesW
,
3675 dwDependenciesLength
,
3676 lpServiceStartNameW
,
3682 if (lpServiceNameW
!=NULL
)
3683 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3685 if (lpDisplayNameW
!= NULL
)
3686 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3688 if (lpBinaryPathNameW
!= NULL
)
3689 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3691 if (lpLoadOrderGroupW
!= NULL
)
3692 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3694 if (lpDependenciesW
!= NULL
)
3695 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3697 if (lpServiceStartNameW
!= NULL
)
3698 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3705 DWORD
REnumDependentServicesA(
3706 SC_RPC_HANDLE hService
,
3707 DWORD dwServiceState
,
3710 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3711 LPBOUNDED_DWORD_256K lpServicesReturned
)
3713 DWORD dwError
= ERROR_SUCCESS
;
3714 DWORD dwServicesReturned
= 0;
3715 DWORD dwServiceCount
;
3716 HKEY hServicesKey
= NULL
;
3717 PSERVICE_HANDLE hSvc
;
3718 PSERVICE lpService
= NULL
;
3719 PSERVICE
*lpServicesArray
= NULL
;
3720 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3723 *pcbBytesNeeded
= 0;
3724 *lpServicesReturned
= 0;
3726 DPRINT("REnumDependentServicesA() called\n");
3728 hSvc
= ScmGetServiceFromHandle(hService
);
3731 DPRINT1("Invalid service handle!\n");
3732 return ERROR_INVALID_HANDLE
;
3735 lpService
= hSvc
->ServiceEntry
;
3737 /* Check access rights */
3738 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3739 SC_MANAGER_ENUMERATE_SERVICE
))
3741 DPRINT("Insufficient access rights! 0x%lx\n",
3742 hSvc
->Handle
.DesiredAccess
);
3743 return ERROR_ACCESS_DENIED
;
3746 /* Open the Services Reg key */
3747 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3748 L
"System\\CurrentControlSet\\Services",
3753 if (dwError
!= ERROR_SUCCESS
)
3756 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3757 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3758 are the same for both. Verified in WINXP. */
3760 /* First determine the bytes needed and get the number of dependent services*/
3761 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3766 &dwServicesReturned
);
3767 if (dwError
!= ERROR_SUCCESS
)
3770 /* If buffer size is less than the bytes needed or pointer is null*/
3771 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3773 dwError
= ERROR_MORE_DATA
;
3777 /* Allocate memory for array of service pointers */
3778 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3780 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3781 if (!lpServicesArray
)
3783 DPRINT("Could not allocate a buffer!!\n");
3784 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3788 dwServicesReturned
= 0;
3789 *pcbBytesNeeded
= 0;
3791 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3796 &dwServicesReturned
);
3797 if (dwError
!= ERROR_SUCCESS
)
3802 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3803 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3805 /* Copy EnumDepenedentService to Buffer */
3806 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3808 lpService
= lpServicesArray
[dwServiceCount
];
3810 /* Copy the status info */
3811 memcpy(&lpServicesPtr
->ServiceStatus
,
3813 sizeof(SERVICE_STATUS
));
3815 /* Copy display name */
3816 WideCharToMultiByte(CP_ACP
,
3818 lpService
->lpDisplayName
,
3821 wcslen(lpService
->lpDisplayName
),
3824 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3825 lpStr
+= strlen(lpStr
) + 1;
3827 /* Copy service name */
3828 WideCharToMultiByte(CP_ACP
,
3830 lpService
->lpServiceName
,
3833 wcslen(lpService
->lpServiceName
),
3836 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3837 lpStr
+= strlen(lpStr
) + 1;
3842 *lpServicesReturned
= dwServicesReturned
;
3845 if (lpServicesArray
)
3846 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3848 RegCloseKey(hServicesKey
);
3850 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3857 DWORD
REnumServicesStatusA(
3858 SC_RPC_HANDLE hSCManager
,
3859 DWORD dwServiceType
,
3860 DWORD dwServiceState
,
3863 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3864 LPBOUNDED_DWORD_256K lpServicesReturned
,
3865 LPBOUNDED_DWORD_256K lpResumeHandle
)
3867 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3868 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3869 LPWSTR lpStringPtrW
;
3872 DWORD dwServiceCount
;
3874 DPRINT("REnumServicesStatusA() called\n");
3876 if ((dwBufSize
> 0) && (lpBuffer
))
3878 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3881 DPRINT("Failed to allocate buffer!\n");
3882 return ERROR_NOT_ENOUGH_MEMORY
;
3886 dwError
= REnumServicesStatusW(hSCManager
,
3889 (LPBYTE
)lpStatusPtrW
,
3895 /* if no services were returned then we are Done */
3896 if (*lpServicesReturned
== 0)
3899 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3900 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3901 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3902 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3903 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3905 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3907 /* Copy the service name */
3908 WideCharToMultiByte(CP_ACP
,
3913 wcslen(lpStringPtrW
),
3917 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3918 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3919 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3921 /* Copy the display name */
3922 WideCharToMultiByte(CP_ACP
,
3927 wcslen(lpStringPtrW
),
3931 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3932 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3933 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3935 /* Copy the status information */
3936 memcpy(&lpStatusPtrA
->ServiceStatus
,
3937 &lpStatusPtrW
->ServiceStatus
,
3938 sizeof(SERVICE_STATUS
));
3945 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3947 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3954 DWORD
ROpenSCManagerA(
3955 LPSTR lpMachineName
,
3956 LPSTR lpDatabaseName
,
3957 DWORD dwDesiredAccess
,
3958 LPSC_RPC_HANDLE lpScHandle
)
3960 UNICODE_STRING MachineName
;
3961 UNICODE_STRING DatabaseName
;
3964 DPRINT("ROpenSCManagerA() called\n");
3967 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3971 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3974 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3975 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3980 RtlFreeUnicodeString(&MachineName
);
3983 RtlFreeUnicodeString(&DatabaseName
);
3990 DWORD
ROpenServiceA(
3991 SC_RPC_HANDLE hSCManager
,
3992 LPSTR lpServiceName
,
3993 DWORD dwDesiredAccess
,
3994 LPSC_RPC_HANDLE lpServiceHandle
)
3996 UNICODE_STRING ServiceName
;
3999 DPRINT("ROpenServiceA() called\n");
4002 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
4005 dwError
= ROpenServiceW(hSCManager
,
4006 lpServiceName
? ServiceName
.Buffer
: NULL
,
4011 RtlFreeUnicodeString(&ServiceName
);
4018 DWORD
RQueryServiceConfigA(
4019 SC_RPC_HANDLE hService
,
4020 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4022 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4024 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
4025 DWORD dwError
= ERROR_SUCCESS
;
4026 PSERVICE_HANDLE hSvc
;
4027 PSERVICE lpService
= NULL
;
4028 HKEY hServiceKey
= NULL
;
4029 LPWSTR lpImagePath
= NULL
;
4030 LPWSTR lpServiceStartName
= NULL
;
4031 LPWSTR lpDependencies
= NULL
;
4032 DWORD dwDependenciesLength
= 0;
4033 DWORD dwRequiredSize
;
4034 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
4035 CHAR lpEmptyString
[]={0,0};
4038 DPRINT("RQueryServiceConfigA() called\n");
4041 return ERROR_SHUTDOWN_IN_PROGRESS
;
4043 hSvc
= ScmGetServiceFromHandle(hService
);
4046 DPRINT1("Invalid service handle!\n");
4047 return ERROR_INVALID_HANDLE
;
4050 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4051 SERVICE_QUERY_CONFIG
))
4053 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4054 return ERROR_ACCESS_DENIED
;
4057 lpService
= hSvc
->ServiceEntry
;
4058 if (lpService
== NULL
)
4060 DPRINT("lpService == NULL!\n");
4061 return ERROR_INVALID_HANDLE
;
4064 /* Lock the service database shared */
4065 ScmLockDatabaseShared();
4067 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4070 if (dwError
!= ERROR_SUCCESS
)
4073 /* Read the image path */
4074 dwError
= ScmReadString(hServiceKey
,
4077 if (dwError
!= ERROR_SUCCESS
)
4080 /* Read the service start name */
4081 ScmReadString(hServiceKey
,
4083 &lpServiceStartName
);
4085 /* Read the dependencies */
4086 ScmReadDependencies(hServiceKey
,
4088 &dwDependenciesLength
);
4090 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
4092 if (lpImagePath
!= NULL
)
4093 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
4095 dwRequiredSize
+= 2;
4097 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
4098 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
4100 dwRequiredSize
+= 2;
4102 /* Add Dependencies length */
4103 if (lpDependencies
!= NULL
)
4104 dwRequiredSize
+= dwDependenciesLength
;
4106 dwRequiredSize
+= 2;
4108 if (lpServiceStartName
!= NULL
)
4109 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
4111 dwRequiredSize
+= 2;
4113 if (lpService
->lpDisplayName
!= NULL
)
4114 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
4116 dwRequiredSize
+= 2;
4118 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
4120 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4124 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
4125 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
4126 lpConfig
->dwStartType
= lpService
->dwStartType
;
4127 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
4128 lpConfig
->dwTagId
= lpService
->dwTag
;
4130 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
4132 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4137 WideCharToMultiByte(CP_ACP
,
4142 wcslen(lpImagePath
) + 1,
4148 strcpy(lpStr
, lpEmptyString
);
4151 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4152 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4154 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4156 WideCharToMultiByte(CP_ACP
,
4158 lpService
->lpGroup
->lpGroupName
,
4161 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
4167 strcpy(lpStr
, lpEmptyString
);
4170 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4171 lpStr
+= (strlen(lpStr
) + 1);
4173 /* Append Dependencies */
4176 WideCharToMultiByte(CP_ACP
,
4179 dwDependenciesLength
,
4181 dwDependenciesLength
,
4187 strcpy(lpStr
, lpEmptyString
);
4190 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4192 lpStr
+= dwDependenciesLength
;
4194 lpStr
+= (strlen(lpStr
) + 1);
4196 if (lpServiceStartName
)
4198 WideCharToMultiByte(CP_ACP
,
4203 wcslen(lpServiceStartName
) + 1,
4209 strcpy(lpStr
, lpEmptyString
);
4212 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4213 lpStr
+= (strlen(lpStr
) + 1);
4215 if (lpService
->lpDisplayName
)
4217 WideCharToMultiByte(CP_ACP
,
4219 lpService
->lpDisplayName
,
4222 wcslen(lpService
->lpDisplayName
) + 1,
4228 strcpy(lpStr
, lpEmptyString
);
4231 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4234 if (pcbBytesNeeded
!= NULL
)
4235 *pcbBytesNeeded
= dwRequiredSize
;
4238 /* Unlock the service database */
4239 ScmUnlockDatabase();
4241 if (lpImagePath
!= NULL
)
4242 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4244 if (lpServiceStartName
!= NULL
)
4245 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4247 if (lpDependencies
!= NULL
)
4248 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4250 if (hServiceKey
!= NULL
)
4251 RegCloseKey(hServiceKey
);
4253 DPRINT("RQueryServiceConfigA() done\n");
4260 DWORD
RQueryServiceLockStatusA(
4261 SC_RPC_HANDLE hSCManager
,
4262 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4264 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4267 return ERROR_CALL_NOT_IMPLEMENTED
;
4272 DWORD
RStartServiceA(
4273 SC_RPC_HANDLE hService
,
4275 LPSTRING_PTRSA argv
)
4277 DWORD dwError
= ERROR_SUCCESS
;
4278 PSERVICE_HANDLE hSvc
;
4279 PSERVICE lpService
= NULL
;
4280 LPWSTR
*lpVector
= NULL
;
4284 DPRINT("RStartServiceA() called\n");
4287 return ERROR_SHUTDOWN_IN_PROGRESS
;
4289 hSvc
= ScmGetServiceFromHandle(hService
);
4292 DPRINT1("Invalid service handle!\n");
4293 return ERROR_INVALID_HANDLE
;
4296 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4299 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4300 return ERROR_ACCESS_DENIED
;
4303 lpService
= hSvc
->ServiceEntry
;
4304 if (lpService
== NULL
)
4306 DPRINT("lpService == NULL!\n");
4307 return ERROR_INVALID_HANDLE
;
4310 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4311 return ERROR_SERVICE_DISABLED
;
4313 if (lpService
->bDeleted
)
4314 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4316 /* Build a Unicode argument vector */
4319 lpVector
= HeapAlloc(GetProcessHeap(),
4321 argc
* sizeof(LPWSTR
));
4322 if (lpVector
== NULL
)
4323 return ERROR_NOT_ENOUGH_MEMORY
;
4325 for (i
= 0; i
< argc
; i
++)
4327 dwLength
= MultiByteToWideChar(CP_ACP
,
4334 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4336 dwLength
* sizeof(WCHAR
));
4337 if (lpVector
[i
] == NULL
)
4339 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4343 MultiByteToWideChar(CP_ACP
,
4352 /* Start the service */
4353 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4356 /* Free the Unicode argument vector */
4357 if (lpVector
!= NULL
)
4359 for (i
= 0; i
< argc
; i
++)
4361 if (lpVector
[i
] != NULL
)
4362 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4364 HeapFree(GetProcessHeap(), 0, lpVector
);
4372 DWORD
RGetServiceDisplayNameA(
4373 SC_RPC_HANDLE hSCManager
,
4374 LPCSTR lpServiceName
,
4375 LPSTR lpDisplayName
,
4376 LPBOUNDED_DWORD_4K lpcchBuffer
)
4378 // PMANAGER_HANDLE hManager;
4379 PSERVICE lpService
= NULL
;
4382 LPWSTR lpServiceNameW
;
4384 DPRINT("RGetServiceDisplayNameA() called\n");
4385 DPRINT("hSCManager = %p\n", hSCManager
);
4386 DPRINT("lpServiceName: %s\n", lpServiceName
);
4387 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4388 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4390 // hManager = (PMANAGER_HANDLE)hSCManager;
4391 // if (hManager->Handle.Tag != MANAGER_TAG)
4393 // DPRINT("Invalid manager handle!\n");
4394 // return ERROR_INVALID_HANDLE;
4397 if (lpServiceName
!= NULL
)
4399 dwLength
= strlen(lpServiceName
) + 1;
4400 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4402 dwLength
* sizeof(WCHAR
));
4403 if (!lpServiceNameW
)
4404 return ERROR_NOT_ENOUGH_MEMORY
;
4406 MultiByteToWideChar(CP_ACP
,
4413 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4415 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4418 if (lpService
== NULL
)
4420 DPRINT("Could not find a service!\n");
4422 /* If the service could not be found and lpcchBuffer is 0, windows
4423 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4424 if (*lpcchBuffer
== 0)
4427 if (lpDisplayName
!= NULL
)
4429 *lpDisplayName
= '\0';
4432 return ERROR_SERVICE_DOES_NOT_EXIST
;
4435 if (!lpService
->lpDisplayName
)
4437 dwLength
= wcslen(lpService
->lpServiceName
);
4438 if (lpDisplayName
!= NULL
&&
4439 *lpcchBuffer
> dwLength
)
4441 WideCharToMultiByte(CP_ACP
,
4443 lpService
->lpServiceName
,
4444 wcslen(lpService
->lpServiceName
),
4449 return ERROR_SUCCESS
;
4454 dwLength
= wcslen(lpService
->lpDisplayName
);
4455 if (lpDisplayName
!= NULL
&&
4456 *lpcchBuffer
> dwLength
)
4458 WideCharToMultiByte(CP_ACP
,
4460 lpService
->lpDisplayName
,
4461 wcslen(lpService
->lpDisplayName
),
4466 return ERROR_SUCCESS
;
4470 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4472 *lpcchBuffer
= dwLength
* 2;
4479 DWORD
RGetServiceKeyNameA(
4480 SC_RPC_HANDLE hSCManager
,
4481 LPCSTR lpDisplayName
,
4482 LPSTR lpServiceName
,
4483 LPBOUNDED_DWORD_4K lpcchBuffer
)
4488 LPWSTR lpDisplayNameW
;
4490 DPRINT("RGetServiceKeyNameA() called\n");
4491 DPRINT("hSCManager = %p\n", hSCManager
);
4492 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4493 DPRINT("lpServiceName: %p\n", lpServiceName
);
4494 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4496 dwLength
= strlen(lpDisplayName
) + 1;
4497 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4499 dwLength
* sizeof(WCHAR
));
4500 if (!lpDisplayNameW
)
4501 return ERROR_NOT_ENOUGH_MEMORY
;
4503 MultiByteToWideChar(CP_ACP
,
4510 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4512 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4514 if (lpService
== NULL
)
4516 DPRINT("Could not find the service!\n");
4518 /* If the service could not be found and lpcchBuffer is 0,
4519 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4520 if (*lpcchBuffer
== 0)
4523 if (lpServiceName
!= NULL
)
4525 *lpServiceName
= '\0';
4529 return ERROR_SERVICE_DOES_NOT_EXIST
;
4532 dwLength
= wcslen(lpService
->lpServiceName
);
4533 if (lpServiceName
!= NULL
&&
4534 *lpcchBuffer
> dwLength
)
4536 WideCharToMultiByte(CP_ACP
,
4538 lpService
->lpServiceName
,
4539 wcslen(lpService
->lpServiceName
),
4544 return ERROR_SUCCESS
;
4547 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4549 *lpcchBuffer
= dwLength
* 2;
4556 DWORD
RI_ScGetCurrentGroupStateW(
4557 SC_RPC_HANDLE hSCManager
,
4558 LPWSTR lpLoadOrderGroup
,
4562 return ERROR_CALL_NOT_IMPLEMENTED
;
4567 DWORD
REnumServiceGroupW(
4568 SC_RPC_HANDLE hSCManager
,
4569 DWORD dwServiceType
,
4570 DWORD dwServiceState
,
4573 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4574 LPBOUNDED_DWORD_256K lpServicesReturned
,
4575 LPBOUNDED_DWORD_256K lpResumeIndex
,
4576 LPCWSTR pszGroupName
)
4579 return ERROR_CALL_NOT_IMPLEMENTED
;
4584 // WARNING: This function is untested
4587 DWORD
RChangeServiceConfig2A(
4588 SC_RPC_HANDLE hService
,
4589 SC_RPC_CONFIG_INFOA Info
)
4591 SC_RPC_CONFIG_INFOW InfoW
;
4592 DWORD dwRet
, dwLength
;
4595 DPRINT("RChangeServiceConfig2A() called\n");
4596 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4598 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4600 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4602 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4603 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4605 //lpServiceDescriptonA = Info.psd;
4607 ///if (lpServiceDescriptonA &&
4608 ///lpServiceDescriptonA->lpDescription)
4610 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4612 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4614 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4615 if (!lpServiceDescriptonW
)
4617 return ERROR_NOT_ENOUGH_MEMORY
;
4620 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4622 MultiByteToWideChar(CP_ACP
,
4626 lpServiceDescriptonW
->lpDescription
,
4629 ptr
= lpServiceDescriptonW
;
4630 InfoW
.psd
= lpServiceDescriptonW
;
4633 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4635 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4636 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4637 DWORD dwRebootLen
= 0;
4638 DWORD dwCommandLen
= 0;
4640 lpServiceFailureActionsA
= Info
.psfa
;
4642 if (lpServiceFailureActionsA
)
4644 if (lpServiceFailureActionsA
->lpRebootMsg
)
4646 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4648 if (lpServiceFailureActionsA
->lpCommand
)
4650 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4652 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4654 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4657 if (!lpServiceFailureActionsW
)
4659 return ERROR_NOT_ENOUGH_MEMORY
;
4662 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4663 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4664 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4666 if (lpServiceFailureActionsA
->lpRebootMsg
)
4668 MultiByteToWideChar(CP_ACP
,
4670 lpServiceFailureActionsA
->lpRebootMsg
,
4672 lpServiceFailureActionsW
->lpRebootMsg
,
4676 if (lpServiceFailureActionsA
->lpCommand
)
4678 MultiByteToWideChar(CP_ACP
,
4680 lpServiceFailureActionsA
->lpCommand
,
4682 lpServiceFailureActionsW
->lpCommand
,
4686 ptr
= lpServiceFailureActionsW
;
4690 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4692 HeapFree(GetProcessHeap(), 0, ptr
);
4699 DWORD
RChangeServiceConfig2W(
4700 SC_RPC_HANDLE hService
,
4701 SC_RPC_CONFIG_INFOW Info
)
4703 DWORD dwError
= ERROR_SUCCESS
;
4704 PSERVICE_HANDLE hSvc
;
4705 PSERVICE lpService
= NULL
;
4706 HKEY hServiceKey
= NULL
;
4708 DPRINT("RChangeServiceConfig2W() called\n");
4709 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4712 return ERROR_SHUTDOWN_IN_PROGRESS
;
4714 hSvc
= ScmGetServiceFromHandle(hService
);
4717 DPRINT1("Invalid service handle!\n");
4718 return ERROR_INVALID_HANDLE
;
4721 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4722 SERVICE_CHANGE_CONFIG
))
4724 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4725 return ERROR_ACCESS_DENIED
;
4728 lpService
= hSvc
->ServiceEntry
;
4729 if (lpService
== NULL
)
4731 DPRINT("lpService == NULL!\n");
4732 return ERROR_INVALID_HANDLE
;
4735 /* Lock the service database exclusively */
4736 ScmLockDatabaseExclusive();
4738 if (lpService
->bDeleted
)
4740 DPRINT("The service has already been marked for delete!\n");
4741 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4745 /* Open the service key */
4746 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4749 if (dwError
!= ERROR_SUCCESS
)
4752 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4754 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4756 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4757 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4759 if (lpServiceDescription
!= NULL
&&
4760 lpServiceDescription
->lpDescription
!= NULL
)
4762 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4763 dwError
= RegSetValueExW(hServiceKey
,
4767 (LPBYTE
)lpServiceDescription
->lpDescription
,
4768 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4769 if (dwError
!= ERROR_SUCCESS
)
4773 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4776 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4781 /* Unlock the service database */
4782 ScmUnlockDatabase();
4784 if (hServiceKey
!= NULL
)
4785 RegCloseKey(hServiceKey
);
4787 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4794 DWORD
RQueryServiceConfig2A(
4795 SC_RPC_HANDLE hService
,
4799 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4801 DWORD dwError
= ERROR_SUCCESS
;
4802 PSERVICE_HANDLE hSvc
;
4803 PSERVICE lpService
= NULL
;
4804 HKEY hServiceKey
= NULL
;
4805 LPWSTR lpDescriptionW
= NULL
;
4807 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4808 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4811 return ERROR_INVALID_ADDRESS
;
4814 return ERROR_SHUTDOWN_IN_PROGRESS
;
4816 hSvc
= ScmGetServiceFromHandle(hService
);
4819 DPRINT1("Invalid service handle!\n");
4820 return ERROR_INVALID_HANDLE
;
4823 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4824 SERVICE_QUERY_CONFIG
))
4826 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4827 return ERROR_ACCESS_DENIED
;
4830 lpService
= hSvc
->ServiceEntry
;
4831 if (lpService
== NULL
)
4833 DPRINT("lpService == NULL!\n");
4834 return ERROR_INVALID_HANDLE
;
4837 /* Lock the service database shared */
4838 ScmLockDatabaseShared();
4840 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4843 if (dwError
!= ERROR_SUCCESS
)
4846 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4848 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4851 dwError
= ScmReadString(hServiceKey
,
4854 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4857 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4858 if (dwError
== ERROR_SUCCESS
)
4859 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4861 if (cbBufSize
< *pcbBytesNeeded
)
4863 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4867 if (dwError
== ERROR_SUCCESS
)
4869 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4871 WideCharToMultiByte(CP_ACP
,
4876 wcslen(lpDescriptionW
),
4879 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4883 lpServiceDescription
->lpDescription
= NULL
;
4884 dwError
= ERROR_SUCCESS
;
4888 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4891 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4896 /* Unlock the service database */
4897 ScmUnlockDatabase();
4899 if (lpDescriptionW
!= NULL
)
4900 HeapFree(GetProcessHeap(), 0, lpDescriptionW
);
4902 if (hServiceKey
!= NULL
)
4903 RegCloseKey(hServiceKey
);
4905 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4912 DWORD
RQueryServiceConfig2W(
4913 SC_RPC_HANDLE hService
,
4917 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4919 DWORD dwError
= ERROR_SUCCESS
;
4920 PSERVICE_HANDLE hSvc
;
4921 PSERVICE lpService
= NULL
;
4922 HKEY hServiceKey
= NULL
;
4923 DWORD dwRequiredSize
;
4924 LPWSTR lpDescription
= NULL
;
4925 LPWSTR lpFailureCommand
= NULL
;
4926 LPWSTR lpRebootMessage
= NULL
;
4928 DPRINT("RQueryServiceConfig2W() called\n");
4931 return ERROR_INVALID_ADDRESS
;
4934 return ERROR_SHUTDOWN_IN_PROGRESS
;
4936 hSvc
= ScmGetServiceFromHandle(hService
);
4939 DPRINT1("Invalid service handle!\n");
4940 return ERROR_INVALID_HANDLE
;
4943 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4944 SERVICE_QUERY_CONFIG
))
4946 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4947 return ERROR_ACCESS_DENIED
;
4950 lpService
= hSvc
->ServiceEntry
;
4951 if (lpService
== NULL
)
4953 DPRINT("lpService == NULL!\n");
4954 return ERROR_INVALID_HANDLE
;
4957 /* Lock the service database shared */
4958 ScmLockDatabaseShared();
4960 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4963 if (dwError
!= ERROR_SUCCESS
)
4966 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4968 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4971 dwError
= ScmReadString(hServiceKey
,
4974 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4977 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4978 if (dwError
== ERROR_SUCCESS
)
4979 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4981 if (cbBufSize
< *pcbBytesNeeded
)
4983 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4987 if (dwError
== ERROR_SUCCESS
)
4989 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4990 wcscpy(lpStr
, lpDescription
);
4991 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4995 lpServiceDescription
->lpDescription
= NULL
;
4996 dwError
= ERROR_SUCCESS
;
4999 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5002 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
5006 dwError
= ScmReadString(hServiceKey
,
5010 dwError
= ScmReadString(hServiceKey
,
5014 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5016 if (lpFailureCommand
)
5017 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
5019 if (lpRebootMessage
)
5020 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
5022 if (cbBufSize
< dwRequiredSize
)
5024 *pcbBytesNeeded
= dwRequiredSize
;
5025 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5029 lpFailureActions
->cActions
= 0;
5030 lpFailureActions
->dwResetPeriod
= 0;
5031 lpFailureActions
->lpCommand
= NULL
;
5032 lpFailureActions
->lpRebootMsg
= NULL
;
5033 lpFailureActions
->lpsaActions
= NULL
;
5035 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
5036 if (lpRebootMessage
)
5038 wcscpy(lpStr
, lpRebootMessage
);
5039 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
5040 lpStr
+= wcslen(lpRebootMessage
) + 1;
5043 if (lpFailureCommand
)
5045 wcscpy(lpStr
, lpFailureCommand
);
5046 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
5047 lpStr
+= wcslen(lpRebootMessage
) + 1;
5049 dwError
= STATUS_SUCCESS
;
5054 /* Unlock the service database */
5055 ScmUnlockDatabase();
5057 if (lpDescription
!= NULL
)
5058 HeapFree(GetProcessHeap(), 0, lpDescription
);
5060 if (lpRebootMessage
!= NULL
)
5061 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5063 if (lpFailureCommand
!= NULL
)
5064 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5066 if (hServiceKey
!= NULL
)
5067 RegCloseKey(hServiceKey
);
5069 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5076 DWORD
RQueryServiceStatusEx(
5077 SC_RPC_HANDLE hService
,
5078 SC_STATUS_TYPE InfoLevel
,
5081 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5083 LPSERVICE_STATUS_PROCESS lpStatus
;
5084 PSERVICE_HANDLE hSvc
;
5087 DPRINT("RQueryServiceStatusEx() called\n");
5090 return ERROR_SHUTDOWN_IN_PROGRESS
;
5092 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
5093 return ERROR_INVALID_LEVEL
;
5095 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
5097 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
5098 return ERROR_INSUFFICIENT_BUFFER
;
5100 hSvc
= ScmGetServiceFromHandle(hService
);
5103 DPRINT1("Invalid service handle!\n");
5104 return ERROR_INVALID_HANDLE
;
5107 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5108 SERVICE_QUERY_STATUS
))
5110 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5111 return ERROR_ACCESS_DENIED
;
5114 lpService
= hSvc
->ServiceEntry
;
5115 if (lpService
== NULL
)
5117 DPRINT("lpService == NULL!\n");
5118 return ERROR_INVALID_HANDLE
;
5121 /* Lock the service database shared */
5122 ScmLockDatabaseShared();
5124 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
5126 /* Return service status information */
5127 RtlCopyMemory(lpStatus
,
5129 sizeof(SERVICE_STATUS
));
5131 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
5132 lpStatus
->dwServiceFlags
= 0; /* FIXME */
5134 /* Unlock the service database */
5135 ScmUnlockDatabase();
5137 return ERROR_SUCCESS
;
5142 DWORD
REnumServicesStatusExA(
5143 SC_RPC_HANDLE hSCManager
,
5144 SC_ENUM_TYPE InfoLevel
,
5145 DWORD dwServiceType
,
5146 DWORD dwServiceState
,
5149 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5150 LPBOUNDED_DWORD_256K lpServicesReturned
,
5151 LPBOUNDED_DWORD_256K lpResumeIndex
,
5152 LPCSTR pszGroupName
)
5154 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
5155 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
5156 LPWSTR lpStringPtrW
;
5158 LPWSTR pszGroupNameW
= NULL
;
5160 DWORD dwServiceCount
;
5162 DPRINT("REnumServicesStatusExA() called\n");
5166 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
5169 DPRINT("Failed to allocate buffer!\n");
5170 return ERROR_NOT_ENOUGH_MEMORY
;
5173 MultiByteToWideChar(CP_ACP
,
5178 strlen(pszGroupName
) + 1);
5181 if ((cbBufSize
> 0) && (lpBuffer
))
5183 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
5186 DPRINT("Failed to allocate buffer!\n");
5187 return ERROR_NOT_ENOUGH_MEMORY
;
5191 dwError
= REnumServicesStatusExW(hSCManager
,
5195 (LPBYTE
)lpStatusPtrW
,
5202 /* if no services were returned then we are Done */
5203 if (*lpServicesReturned
== 0)
5206 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5207 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5208 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5209 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5210 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5212 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5214 /* Copy the service name */
5215 WideCharToMultiByte(CP_ACP
,
5220 wcslen(lpStringPtrW
),
5224 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5225 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5226 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5228 /* Copy the display name */
5229 WideCharToMultiByte(CP_ACP
,
5234 wcslen(lpStringPtrW
),
5238 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5239 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5240 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5242 /* Copy the status information */
5243 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5244 &lpStatusPtrW
->ServiceStatusProcess
,
5245 sizeof(SERVICE_STATUS
));
5247 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5248 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5254 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5257 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5259 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5266 DWORD
REnumServicesStatusExW(
5267 SC_RPC_HANDLE hSCManager
,
5268 SC_ENUM_TYPE InfoLevel
,
5269 DWORD dwServiceType
,
5270 DWORD dwServiceState
,
5273 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5274 LPBOUNDED_DWORD_256K lpServicesReturned
,
5275 LPBOUNDED_DWORD_256K lpResumeIndex
,
5276 LPCWSTR pszGroupName
)
5278 PMANAGER_HANDLE hManager
;
5280 DWORD dwError
= ERROR_SUCCESS
;
5281 PLIST_ENTRY ServiceEntry
;
5282 PSERVICE CurrentService
;
5284 DWORD dwRequiredSize
;
5285 DWORD dwServiceCount
;
5287 DWORD dwLastResumeCount
= 0;
5288 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5291 DPRINT("REnumServicesStatusExW() called\n");
5294 return ERROR_SHUTDOWN_IN_PROGRESS
;
5296 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5297 return ERROR_INVALID_LEVEL
;
5299 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5300 if (hManager
== NULL
)
5302 DPRINT1("Invalid service manager handle!\n");
5303 return ERROR_INVALID_HANDLE
;
5306 *pcbBytesNeeded
= 0;
5307 *lpServicesReturned
= 0;
5309 if ((dwServiceType
== 0) ||
5310 ((dwServiceType
& ~(SERVICE_DRIVER
| SERVICE_WIN32
)) != 0))
5312 DPRINT("Not a valid Service Type!\n");
5313 return ERROR_INVALID_PARAMETER
;
5316 if ((dwServiceState
!= SERVICE_ACTIVE
) &&
5317 (dwServiceState
!= SERVICE_INACTIVE
) &&
5318 (dwServiceState
!= SERVICE_STATE_ALL
))
5320 DPRINT("Not a valid Service State!\n");
5321 return ERROR_INVALID_PARAMETER
;
5324 /* Check access rights */
5325 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5326 SC_MANAGER_ENUMERATE_SERVICE
))
5328 DPRINT("Insufficient access rights! 0x%lx\n",
5329 hManager
->Handle
.DesiredAccess
);
5330 return ERROR_ACCESS_DENIED
;
5334 dwLastResumeCount
= *lpResumeIndex
;
5336 /* Lock the service database shared */
5337 ScmLockDatabaseShared();
5339 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5340 if (lpService
== NULL
)
5342 dwError
= ERROR_SUCCESS
;
5349 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5350 ServiceEntry
!= &ServiceListHead
;
5351 ServiceEntry
= ServiceEntry
->Flink
)
5353 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5357 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5360 dwState
= SERVICE_ACTIVE
;
5361 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5362 dwState
= SERVICE_INACTIVE
;
5364 if ((dwState
& dwServiceState
) == 0)
5369 if (*pszGroupName
== 0)
5371 if (CurrentService
->lpGroup
!= NULL
)
5376 if ((CurrentService
->lpGroup
== NULL
) ||
5377 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5382 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5383 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5384 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5386 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5388 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5389 dwRequiredSize
+= dwSize
;
5391 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5395 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5401 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5402 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5405 ServiceEntry
!= &ServiceListHead
;
5406 ServiceEntry
= ServiceEntry
->Flink
)
5408 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5412 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5415 dwState
= SERVICE_ACTIVE
;
5416 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5417 dwState
= SERVICE_INACTIVE
;
5419 if ((dwState
& dwServiceState
) == 0)
5424 if (*pszGroupName
== 0)
5426 if (CurrentService
->lpGroup
!= NULL
)
5431 if ((CurrentService
->lpGroup
== NULL
) ||
5432 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5437 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5438 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5439 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5441 dwError
= ERROR_MORE_DATA
;
5444 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5447 *lpResumeIndex
= dwLastResumeCount
;
5449 *lpServicesReturned
= dwServiceCount
;
5450 *pcbBytesNeeded
= dwRequiredSize
;
5452 /* If there was no services that matched */
5453 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5455 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5459 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5460 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5461 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5464 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5465 ServiceEntry
!= &ServiceListHead
;
5466 ServiceEntry
= ServiceEntry
->Flink
)
5468 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5472 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5475 dwState
= SERVICE_ACTIVE
;
5476 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5477 dwState
= SERVICE_INACTIVE
;
5479 if ((dwState
& dwServiceState
) == 0)
5484 if (*pszGroupName
== 0)
5486 if (CurrentService
->lpGroup
!= NULL
)
5491 if ((CurrentService
->lpGroup
== NULL
) ||
5492 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5497 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5498 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5499 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5501 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5503 /* Copy the service name */
5505 CurrentService
->lpServiceName
);
5506 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5507 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5509 /* Copy the display name */
5511 CurrentService
->lpDisplayName
);
5512 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5513 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5515 /* Copy the status information */
5516 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5517 &CurrentService
->Status
,
5518 sizeof(SERVICE_STATUS
));
5519 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5520 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5521 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5524 dwRequiredSize
+= dwSize
;
5534 *pcbBytesNeeded
= 0;
5540 /* Unlock the service database */
5541 ScmUnlockDatabase();
5543 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5550 DWORD
RSendTSMessage(
5551 handle_t BindingHandle
) /* FIXME */
5554 return ERROR_CALL_NOT_IMPLEMENTED
;
5559 DWORD
RCreateServiceWOW64A(
5560 handle_t BindingHandle
,
5561 LPSTR lpServiceName
,
5562 LPSTR lpDisplayName
,
5563 DWORD dwDesiredAccess
,
5564 DWORD dwServiceType
,
5566 DWORD dwErrorControl
,
5567 LPSTR lpBinaryPathName
,
5568 LPSTR lpLoadOrderGroup
,
5570 LPBYTE lpDependencies
,
5572 LPSTR lpServiceStartName
,
5575 LPSC_RPC_HANDLE lpServiceHandle
)
5578 return ERROR_CALL_NOT_IMPLEMENTED
;
5583 DWORD
RCreateServiceWOW64W(
5584 handle_t BindingHandle
,
5585 LPWSTR lpServiceName
,
5586 LPWSTR lpDisplayName
,
5587 DWORD dwDesiredAccess
,
5588 DWORD dwServiceType
,
5590 DWORD dwErrorControl
,
5591 LPWSTR lpBinaryPathName
,
5592 LPWSTR lpLoadOrderGroup
,
5594 LPBYTE lpDependencies
,
5596 LPWSTR lpServiceStartName
,
5599 LPSC_RPC_HANDLE lpServiceHandle
)
5602 return ERROR_CALL_NOT_IMPLEMENTED
;
5607 DWORD
RQueryServiceTagInfo(
5608 handle_t BindingHandle
) /* FIXME */
5611 return ERROR_CALL_NOT_IMPLEMENTED
;
5616 DWORD
RNotifyServiceStatusChange(
5617 SC_RPC_HANDLE hService
,
5618 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5619 GUID
*pClientProcessGuid
,
5620 GUID
*pSCMProcessGuid
,
5621 PBOOL pfCreateRemoteQueue
,
5622 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5625 return ERROR_CALL_NOT_IMPLEMENTED
;
5630 DWORD
RGetNotifyResults(
5631 SC_NOTIFY_RPC_HANDLE hNotify
,
5632 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5635 return ERROR_CALL_NOT_IMPLEMENTED
;
5640 DWORD
RCloseNotifyHandle(
5641 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5645 return ERROR_CALL_NOT_IMPLEMENTED
;
5650 DWORD
RControlServiceExA(
5651 SC_RPC_HANDLE hService
,
5656 return ERROR_CALL_NOT_IMPLEMENTED
;
5661 DWORD
RControlServiceExW(
5662 SC_RPC_HANDLE hService
,
5667 return ERROR_CALL_NOT_IMPLEMENTED
;
5672 DWORD
RSendPnPMessage(
5673 handle_t BindingHandle
) /* FIXME */
5676 return ERROR_CALL_NOT_IMPLEMENTED
;
5681 DWORD
RValidatePnPService(
5682 handle_t BindingHandle
) /* FIXME */
5685 return ERROR_CALL_NOT_IMPLEMENTED
;
5690 DWORD
ROpenServiceStatusHandle(
5691 handle_t BindingHandle
) /* FIXME */
5694 return ERROR_CALL_NOT_IMPLEMENTED
;
5700 handle_t BindingHandle
) /* FIXME */
5703 return ERROR_CALL_NOT_IMPLEMENTED
;
5707 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5709 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5713 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5715 HeapFree(GetProcessHeap(), 0, ptr
);
5719 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5724 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5729 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)