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
;
1099 /* Check the service entry point */
1100 lpService
= hSvc
->ServiceEntry
;
1101 if (lpService
== NULL
)
1103 DPRINT1("lpService == NULL!\n");
1104 return ERROR_INVALID_HANDLE
;
1107 /* Check access rights */
1110 case SERVICE_CONTROL_STOP
:
1111 DesiredAccess
= SERVICE_STOP
;
1114 case SERVICE_CONTROL_PAUSE
:
1115 case SERVICE_CONTROL_CONTINUE
:
1116 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
1119 case SERVICE_INTERROGATE
:
1120 DesiredAccess
= SERVICE_INTERROGATE
;
1124 if (dwControl
>= 128 && dwControl
<= 255)
1125 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
1127 return ERROR_INVALID_PARAMETER
;
1131 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1133 return ERROR_ACCESS_DENIED
;
1135 if (dwControl
== SERVICE_CONTROL_STOP
)
1137 /* Check if the service has dependencies running as windows
1138 doesn't stop a service that does */
1140 /* Open the Services Reg key */
1141 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1142 L
"System\\CurrentControlSet\\Services",
1146 if (dwError
!= ERROR_SUCCESS
)
1148 DPRINT("Failed to open services key\n");
1152 /* Call the internal function with NULL, just to get bytes we need */
1153 Int_EnumDependentServicesW(hServicesKey
,
1158 &dwServicesReturned
);
1160 RegCloseKey(hServicesKey
);
1162 /* If pcbBytesNeeded is not zero then there are services running that
1163 are dependent on this service */
1164 if (pcbBytesNeeded
!= 0)
1166 DPRINT("Service has running dependencies. Failed to stop service.\n");
1167 return ERROR_DEPENDENT_SERVICES_RUNNING
;
1171 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1173 /* Send control code to the driver */
1174 dwError
= ScmControlDriver(lpService
,
1180 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
1181 dwCurrentState
= lpService
->Status
.dwCurrentState
;
1183 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1184 if (lpService
->lpImage
== NULL
|| dwCurrentState
== SERVICE_STOPPED
)
1185 return ERROR_SERVICE_NOT_ACTIVE
;
1187 /* Check the current state before sending a control request */
1188 switch (dwCurrentState
)
1190 case SERVICE_STOP_PENDING
:
1191 case SERVICE_STOPPED
:
1192 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1194 case SERVICE_START_PENDING
:
1197 case SERVICE_CONTROL_STOP
:
1200 case SERVICE_CONTROL_INTERROGATE
:
1201 RtlCopyMemory(lpServiceStatus
,
1203 sizeof(SERVICE_STATUS
));
1204 return ERROR_SUCCESS
;
1207 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1212 /* Check if the control code is acceptable to the service */
1215 case SERVICE_CONTROL_STOP
:
1216 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
1217 return ERROR_INVALID_SERVICE_CONTROL
;
1220 case SERVICE_CONTROL_PAUSE
:
1221 case SERVICE_CONTROL_CONTINUE
:
1222 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
1223 return ERROR_INVALID_SERVICE_CONTROL
;
1227 /* Send control code to the service */
1228 dwError
= ScmControlService(lpService
,
1231 /* Return service status information */
1232 RtlCopyMemory(lpServiceStatus
,
1234 sizeof(SERVICE_STATUS
));
1237 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
1238 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
1245 DWORD
RDeleteService(
1246 SC_RPC_HANDLE hService
)
1248 PSERVICE_HANDLE hSvc
;
1252 DPRINT("RDeleteService() called\n");
1255 return ERROR_SHUTDOWN_IN_PROGRESS
;
1257 hSvc
= ScmGetServiceFromHandle(hService
);
1260 DPRINT1("Invalid service handle!\n");
1261 return ERROR_INVALID_HANDLE
;
1264 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1266 return ERROR_ACCESS_DENIED
;
1268 lpService
= hSvc
->ServiceEntry
;
1269 if (lpService
== NULL
)
1271 DPRINT("lpService == NULL!\n");
1272 return ERROR_INVALID_HANDLE
;
1275 /* Lock the service database exclusively */
1276 ScmLockDatabaseExclusive();
1278 if (lpService
->bDeleted
)
1280 DPRINT("The service has already been marked for delete!\n");
1281 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1285 /* Mark service for delete */
1286 lpService
->bDeleted
= TRUE
;
1288 dwError
= ScmMarkServiceForDelete(lpService
);
1291 /* Unlock the service database */
1292 ScmUnlockDatabase();
1294 DPRINT("RDeleteService() done\n");
1301 DWORD
RLockServiceDatabase(
1302 SC_RPC_HANDLE hSCManager
,
1303 LPSC_RPC_LOCK lpLock
)
1305 PMANAGER_HANDLE hMgr
;
1307 DPRINT("RLockServiceDatabase() called\n");
1311 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
1314 DPRINT1("Invalid service manager handle!\n");
1315 return ERROR_INVALID_HANDLE
;
1318 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
1320 return ERROR_ACCESS_DENIED
;
1322 // return ScmLockDatabase(0, hMgr->0xC, hLock);
1324 /* FIXME: Lock the database */
1325 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
1327 return ERROR_SUCCESS
;
1332 DWORD
RQueryServiceObjectSecurity(
1333 SC_RPC_HANDLE hService
,
1334 SECURITY_INFORMATION dwSecurityInformation
,
1335 LPBYTE lpSecurityDescriptor
,
1337 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1339 PSERVICE_HANDLE hSvc
;
1341 ULONG DesiredAccess
= 0;
1343 DWORD dwBytesNeeded
;
1347 SECURITY_DESCRIPTOR ObjectDescriptor
;
1349 DPRINT("RQueryServiceObjectSecurity() called\n");
1351 hSvc
= ScmGetServiceFromHandle(hService
);
1354 DPRINT1("Invalid service handle!\n");
1355 return ERROR_INVALID_HANDLE
;
1358 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1359 GROUP_SECURITY_INFORMATION
|
1360 OWNER_SECURITY_INFORMATION
))
1361 DesiredAccess
|= READ_CONTROL
;
1363 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1364 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1366 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1369 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1370 return ERROR_ACCESS_DENIED
;
1373 lpService
= hSvc
->ServiceEntry
;
1374 if (lpService
== NULL
)
1376 DPRINT("lpService == NULL!\n");
1377 return ERROR_INVALID_HANDLE
;
1380 /* Lock the service database */
1381 ScmLockDatabaseShared();
1385 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
1387 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
1388 dwSecurityInformation
,
1389 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1393 /* Unlock the service database */
1394 ScmUnlockDatabase();
1396 if (NT_SUCCESS(Status
))
1398 *pcbBytesNeeded
= dwBytesNeeded
;
1399 dwError
= STATUS_SUCCESS
;
1401 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1403 *pcbBytesNeeded
= dwBytesNeeded
;
1404 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1406 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1408 dwError
= ERROR_GEN_FAILURE
;
1412 dwError
= RtlNtStatusToDosError(Status
);
1420 DWORD
RSetServiceObjectSecurity(
1421 SC_RPC_HANDLE hService
,
1422 DWORD dwSecurityInformation
,
1423 LPBYTE lpSecurityDescriptor
,
1424 DWORD dwSecuityDescriptorSize
)
1426 PSERVICE_HANDLE hSvc
;
1428 ULONG DesiredAccess
= 0;
1429 /* HANDLE hToken = NULL; */
1431 /* NTSTATUS Status; */
1434 DPRINT("RSetServiceObjectSecurity() called\n");
1436 hSvc
= ScmGetServiceFromHandle(hService
);
1439 DPRINT1("Invalid service handle!\n");
1440 return ERROR_INVALID_HANDLE
;
1443 if (dwSecurityInformation
== 0 ||
1444 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1445 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1446 return ERROR_INVALID_PARAMETER
;
1448 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1449 return ERROR_INVALID_PARAMETER
;
1451 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1452 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1454 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1455 DesiredAccess
|= WRITE_DAC
;
1457 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1458 DesiredAccess
|= WRITE_OWNER
;
1460 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1461 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1462 return ERROR_INVALID_PARAMETER
;
1464 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1465 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1466 return ERROR_INVALID_PARAMETER
;
1468 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1471 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1472 return ERROR_ACCESS_DENIED
;
1475 lpService
= hSvc
->ServiceEntry
;
1476 if (lpService
== NULL
)
1478 DPRINT("lpService == NULL!\n");
1479 return ERROR_INVALID_HANDLE
;
1482 if (lpService
->bDeleted
)
1483 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1486 RpcImpersonateClient(NULL
);
1488 Status
= NtOpenThreadToken(NtCurrentThread(),
1492 if (!NT_SUCCESS(Status
))
1493 return RtlNtStatusToDosError(Status
);
1498 /* Lock the service database exclusive */
1499 ScmLockDatabaseExclusive();
1502 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1503 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1504 &lpService
->lpSecurityDescriptor
,
1507 if (!NT_SUCCESS(Status
))
1509 dwError
= RtlNtStatusToDosError(Status
);
1514 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1515 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1517 if (dwError
!= ERROR_SUCCESS
)
1521 dwError
= ERROR_SUCCESS
;
1522 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1523 // lpService->lpSecurityDescriptor);
1525 RegFlushKey(hServiceKey
);
1526 RegCloseKey(hServiceKey
);
1535 /* Unlock service database */
1536 ScmUnlockDatabase();
1538 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1545 DWORD
RQueryServiceStatus(
1546 SC_RPC_HANDLE hService
,
1547 LPSERVICE_STATUS lpServiceStatus
)
1549 PSERVICE_HANDLE hSvc
;
1552 DPRINT("RQueryServiceStatus() called\n");
1555 return ERROR_SHUTDOWN_IN_PROGRESS
;
1557 hSvc
= ScmGetServiceFromHandle(hService
);
1560 DPRINT1("Invalid service handle!\n");
1561 return ERROR_INVALID_HANDLE
;
1564 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1565 SERVICE_QUERY_STATUS
))
1567 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1568 return ERROR_ACCESS_DENIED
;
1571 lpService
= hSvc
->ServiceEntry
;
1572 if (lpService
== NULL
)
1574 DPRINT("lpService == NULL!\n");
1575 return ERROR_INVALID_HANDLE
;
1578 /* Lock the service database shared */
1579 ScmLockDatabaseShared();
1581 /* Return service status information */
1582 RtlCopyMemory(lpServiceStatus
,
1584 sizeof(SERVICE_STATUS
));
1586 /* Unlock the service database */
1587 ScmUnlockDatabase();
1589 return ERROR_SUCCESS
;
1594 ScmIsValidServiceState(DWORD dwCurrentState
)
1596 switch (dwCurrentState
)
1598 case SERVICE_STOPPED
:
1599 case SERVICE_START_PENDING
:
1600 case SERVICE_STOP_PENDING
:
1601 case SERVICE_RUNNING
:
1602 case SERVICE_CONTINUE_PENDING
:
1603 case SERVICE_PAUSE_PENDING
:
1604 case SERVICE_PAUSED
:
1614 DWORD
RSetServiceStatus(
1615 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1616 LPSERVICE_STATUS lpServiceStatus
)
1620 DPRINT("RSetServiceStatus() called\n");
1621 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1622 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1623 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1624 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1625 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1626 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1627 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1628 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1630 if (hServiceStatus
== 0)
1632 DPRINT("hServiceStatus == NULL!\n");
1633 return ERROR_INVALID_HANDLE
;
1636 lpService
= (PSERVICE
)hServiceStatus
;
1637 if (lpService
== NULL
)
1639 DPRINT("lpService == NULL!\n");
1640 return ERROR_INVALID_HANDLE
;
1643 /* Check current state */
1644 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1646 DPRINT("Invalid service state!\n");
1647 return ERROR_INVALID_DATA
;
1650 /* Check service type */
1651 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1652 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1654 DPRINT("Invalid service type!\n");
1655 return ERROR_INVALID_DATA
;
1658 /* Check accepted controls */
1659 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1661 DPRINT("Invalid controls accepted!\n");
1662 return ERROR_INVALID_DATA
;
1665 /* Lock the service database exclusively */
1666 ScmLockDatabaseExclusive();
1668 RtlCopyMemory(&lpService
->Status
,
1670 sizeof(SERVICE_STATUS
));
1672 /* Unlock the service database */
1673 ScmUnlockDatabase();
1675 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1676 DPRINT("RSetServiceStatus() done\n");
1678 return ERROR_SUCCESS
;
1683 DWORD
RUnlockServiceDatabase(
1687 return ERROR_SUCCESS
;
1692 DWORD
RNotifyBootConfigStatus(
1693 SVCCTL_HANDLEW lpMachineName
,
1694 DWORD BootAcceptable
)
1696 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1697 return ERROR_SUCCESS
;
1700 // return ERROR_CALL_NOT_IMPLEMENTED;
1705 DWORD
RI_ScSetServiceBitsW(
1706 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1707 DWORD dwServiceBits
,
1709 int bUpdateImmediately
,
1713 return ERROR_CALL_NOT_IMPLEMENTED
;
1718 DWORD
RChangeServiceConfigW(
1719 SC_RPC_HANDLE hService
,
1720 DWORD dwServiceType
,
1722 DWORD dwErrorControl
,
1723 LPWSTR lpBinaryPathName
,
1724 LPWSTR lpLoadOrderGroup
,
1726 LPBYTE lpDependencies
,
1728 LPWSTR lpServiceStartName
,
1731 LPWSTR lpDisplayName
)
1733 DWORD dwError
= ERROR_SUCCESS
;
1734 PSERVICE_HANDLE hSvc
;
1735 PSERVICE lpService
= NULL
;
1736 HKEY hServiceKey
= NULL
;
1737 LPWSTR lpDisplayNameW
= NULL
;
1738 LPWSTR lpImagePathW
= NULL
;
1740 DPRINT("RChangeServiceConfigW() called\n");
1741 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1742 DPRINT("dwStartType = %lu\n", dwStartType
);
1743 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1744 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1745 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1746 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1749 return ERROR_SHUTDOWN_IN_PROGRESS
;
1751 hSvc
= ScmGetServiceFromHandle(hService
);
1754 DPRINT1("Invalid service handle!\n");
1755 return ERROR_INVALID_HANDLE
;
1758 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1759 SERVICE_CHANGE_CONFIG
))
1761 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1762 return ERROR_ACCESS_DENIED
;
1765 lpService
= hSvc
->ServiceEntry
;
1766 if (lpService
== NULL
)
1768 DPRINT("lpService == NULL!\n");
1769 return ERROR_INVALID_HANDLE
;
1772 /* Lock the service database exclusively */
1773 ScmLockDatabaseExclusive();
1775 if (lpService
->bDeleted
)
1777 DPRINT("The service has already been marked for delete!\n");
1778 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1782 /* Open the service key */
1783 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1786 if (dwError
!= ERROR_SUCCESS
)
1789 /* Write service data to the registry */
1790 /* Set the display name */
1791 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1793 RegSetValueExW(hServiceKey
,
1797 (LPBYTE
)lpDisplayName
,
1798 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1800 /* Update the display name */
1801 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
1803 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1804 if (lpDisplayNameW
== NULL
)
1806 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1810 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1811 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1813 lpService
->lpDisplayName
= lpDisplayNameW
;
1816 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1818 /* Set the service type */
1819 dwError
= RegSetValueExW(hServiceKey
,
1823 (LPBYTE
)&dwServiceType
,
1825 if (dwError
!= ERROR_SUCCESS
)
1828 lpService
->Status
.dwServiceType
= dwServiceType
;
1831 if (dwStartType
!= SERVICE_NO_CHANGE
)
1833 /* Set the start value */
1834 dwError
= RegSetValueExW(hServiceKey
,
1838 (LPBYTE
)&dwStartType
,
1840 if (dwError
!= ERROR_SUCCESS
)
1843 lpService
->dwStartType
= dwStartType
;
1846 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1848 /* Set the error control value */
1849 dwError
= RegSetValueExW(hServiceKey
,
1853 (LPBYTE
)&dwErrorControl
,
1855 if (dwError
!= ERROR_SUCCESS
)
1858 lpService
->dwErrorControl
= dwErrorControl
;
1861 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1863 /* Set the image path */
1864 lpImagePathW
= lpBinaryPathName
;
1866 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1868 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
1872 if (dwError
!= ERROR_SUCCESS
)
1876 dwError
= RegSetValueExW(hServiceKey
,
1880 (LPBYTE
)lpImagePathW
,
1881 (wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
));
1883 if (lpImagePathW
!= lpBinaryPathName
)
1884 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
1886 if (dwError
!= ERROR_SUCCESS
)
1890 /* Set the group name */
1891 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1893 dwError
= RegSetValueExW(hServiceKey
,
1897 (LPBYTE
)lpLoadOrderGroup
,
1898 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1899 if (dwError
!= ERROR_SUCCESS
)
1902 dwError
= ScmSetServiceGroup(lpService
,
1904 if (dwError
!= ERROR_SUCCESS
)
1908 if (lpdwTagId
!= NULL
)
1910 dwError
= ScmAssignNewTag(lpService
);
1911 if (dwError
!= ERROR_SUCCESS
)
1914 dwError
= RegSetValueExW(hServiceKey
,
1918 (LPBYTE
)&lpService
->dwTag
,
1920 if (dwError
!= ERROR_SUCCESS
)
1923 *lpdwTagId
= lpService
->dwTag
;
1926 /* Write dependencies */
1927 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1929 dwError
= ScmWriteDependencies(hServiceKey
,
1930 (LPWSTR
)lpDependencies
,
1932 if (dwError
!= ERROR_SUCCESS
)
1936 if (lpPassword
!= NULL
)
1938 /* FIXME: Write password */
1942 if (hServiceKey
!= NULL
)
1943 RegCloseKey(hServiceKey
);
1945 /* Unlock the service database */
1946 ScmUnlockDatabase();
1948 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1955 DWORD
RCreateServiceW(
1956 SC_RPC_HANDLE hSCManager
,
1957 LPCWSTR lpServiceName
,
1958 LPCWSTR lpDisplayName
,
1959 DWORD dwDesiredAccess
,
1960 DWORD dwServiceType
,
1962 DWORD dwErrorControl
,
1963 LPCWSTR lpBinaryPathName
,
1964 LPCWSTR lpLoadOrderGroup
,
1966 LPBYTE lpDependencies
,
1968 LPCWSTR lpServiceStartName
,
1971 LPSC_RPC_HANDLE lpServiceHandle
)
1973 PMANAGER_HANDLE hManager
;
1974 DWORD dwError
= ERROR_SUCCESS
;
1975 PSERVICE lpService
= NULL
;
1976 SC_HANDLE hServiceHandle
= NULL
;
1977 LPWSTR lpImagePath
= NULL
;
1978 HKEY hServiceKey
= NULL
;
1979 LPWSTR lpObjectName
;
1981 DPRINT("RCreateServiceW() called\n");
1982 DPRINT("lpServiceName = %S\n", lpServiceName
);
1983 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1984 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1985 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1986 DPRINT("dwStartType = %lu\n", dwStartType
);
1987 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1988 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1989 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1990 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
1993 return ERROR_SHUTDOWN_IN_PROGRESS
;
1995 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1996 if (hManager
== NULL
)
1998 DPRINT1("Invalid service manager handle!\n");
1999 return ERROR_INVALID_HANDLE
;
2002 /* Check access rights */
2003 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2004 SC_MANAGER_CREATE_SERVICE
))
2006 DPRINT("Insufficient access rights! 0x%lx\n",
2007 hManager
->Handle
.DesiredAccess
);
2008 return ERROR_ACCESS_DENIED
;
2011 if (wcslen(lpServiceName
) == 0)
2013 return ERROR_INVALID_NAME
;
2016 if (wcslen(lpBinaryPathName
) == 0)
2018 return ERROR_INVALID_PARAMETER
;
2021 /* Check for invalid service type value */
2022 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2023 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2024 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2025 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2026 return ERROR_INVALID_PARAMETER
;
2028 /* Check for invalid start type value */
2029 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2030 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2031 (dwStartType
!= SERVICE_AUTO_START
) &&
2032 (dwStartType
!= SERVICE_DEMAND_START
) &&
2033 (dwStartType
!= SERVICE_DISABLED
))
2034 return ERROR_INVALID_PARAMETER
;
2036 /* Only drivers can be boot start or system start services */
2037 if ((dwStartType
== SERVICE_BOOT_START
) ||
2038 (dwStartType
== SERVICE_SYSTEM_START
))
2040 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2041 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2042 return ERROR_INVALID_PARAMETER
;
2045 /* Check for invalid error control value */
2046 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2047 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2048 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2049 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2050 return ERROR_INVALID_PARAMETER
;
2052 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2053 (lpServiceStartName
))
2055 return ERROR_INVALID_PARAMETER
;
2058 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2060 return ERROR_INVALID_PARAMETER
;
2063 /* Lock the service database exclusively */
2064 ScmLockDatabaseExclusive();
2066 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2069 /* Unlock the service database */
2070 ScmUnlockDatabase();
2072 /* Check if it is marked for deletion */
2073 if (lpService
->bDeleted
)
2074 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2076 /* Return Error exist */
2077 return ERROR_SERVICE_EXISTS
;
2080 if (lpDisplayName
!= NULL
&&
2081 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2083 /* Unlock the service database */
2084 ScmUnlockDatabase();
2086 return ERROR_DUPLICATE_SERVICE_NAME
;
2089 if (dwServiceType
& SERVICE_DRIVER
)
2091 dwError
= ScmCanonDriverImagePath(dwStartType
,
2094 if (dwError
!= ERROR_SUCCESS
)
2099 if (dwStartType
== SERVICE_BOOT_START
||
2100 dwStartType
== SERVICE_SYSTEM_START
)
2102 /* Unlock the service database */
2103 ScmUnlockDatabase();
2105 return ERROR_INVALID_PARAMETER
;
2109 /* Allocate a new service entry */
2110 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2112 if (dwError
!= ERROR_SUCCESS
)
2115 /* Fill the new service entry */
2116 lpService
->Status
.dwServiceType
= dwServiceType
;
2117 lpService
->dwStartType
= dwStartType
;
2118 lpService
->dwErrorControl
= dwErrorControl
;
2120 /* Fill the display name */
2121 if (lpDisplayName
!= NULL
&&
2122 *lpDisplayName
!= 0 &&
2123 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2125 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(), 0,
2126 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2127 if (lpService
->lpDisplayName
== NULL
)
2129 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2132 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2135 /* Assign the service to a group */
2136 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2138 dwError
= ScmSetServiceGroup(lpService
,
2140 if (dwError
!= ERROR_SUCCESS
)
2144 /* Assign a new tag */
2145 if (lpdwTagId
!= NULL
)
2147 dwError
= ScmAssignNewTag(lpService
);
2148 if (dwError
!= ERROR_SUCCESS
)
2152 /* Write service data to the registry */
2153 /* Create the service key */
2154 dwError
= ScmCreateServiceKey(lpServiceName
,
2157 if (dwError
!= ERROR_SUCCESS
)
2160 /* Set the display name */
2161 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2163 RegSetValueExW(hServiceKey
,
2167 (LPBYTE
)lpDisplayName
,
2168 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2171 /* Set the service type */
2172 dwError
= RegSetValueExW(hServiceKey
,
2176 (LPBYTE
)&dwServiceType
,
2178 if (dwError
!= ERROR_SUCCESS
)
2181 /* Set the start value */
2182 dwError
= RegSetValueExW(hServiceKey
,
2186 (LPBYTE
)&dwStartType
,
2188 if (dwError
!= ERROR_SUCCESS
)
2191 /* Set the error control value */
2192 dwError
= RegSetValueExW(hServiceKey
,
2196 (LPBYTE
)&dwErrorControl
,
2198 if (dwError
!= ERROR_SUCCESS
)
2201 /* Set the image path */
2202 if (dwServiceType
& SERVICE_WIN32
)
2204 dwError
= RegSetValueExW(hServiceKey
,
2208 (LPBYTE
)lpBinaryPathName
,
2209 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2210 if (dwError
!= ERROR_SUCCESS
)
2213 else if (dwServiceType
& SERVICE_DRIVER
)
2215 dwError
= RegSetValueExW(hServiceKey
,
2219 (LPBYTE
)lpImagePath
,
2220 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2221 if (dwError
!= ERROR_SUCCESS
)
2225 /* Set the group name */
2226 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2228 dwError
= RegSetValueExW(hServiceKey
,
2232 (LPBYTE
)lpLoadOrderGroup
,
2233 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2234 if (dwError
!= ERROR_SUCCESS
)
2238 if (lpdwTagId
!= NULL
)
2240 dwError
= RegSetValueExW(hServiceKey
,
2244 (LPBYTE
)&lpService
->dwTag
,
2246 if (dwError
!= ERROR_SUCCESS
)
2250 /* Write dependencies */
2251 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2253 dwError
= ScmWriteDependencies(hServiceKey
,
2254 (LPCWSTR
)lpDependencies
,
2256 if (dwError
!= ERROR_SUCCESS
)
2260 /* Write service start name */
2261 if (dwServiceType
& SERVICE_WIN32
)
2263 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2264 dwError
= RegSetValueExW(hServiceKey
,
2268 (LPBYTE
)lpObjectName
,
2269 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2270 if (dwError
!= ERROR_SUCCESS
)
2274 if (lpPassword
!= NULL
)
2276 /* FIXME: Write password */
2279 dwError
= ScmCreateServiceHandle(lpService
,
2281 if (dwError
!= ERROR_SUCCESS
)
2284 dwError
= ScmCheckAccess(hServiceHandle
,
2286 if (dwError
!= ERROR_SUCCESS
)
2289 lpService
->dwRefCount
= 1;
2290 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2293 /* Unlock the service database */
2294 ScmUnlockDatabase();
2296 if (hServiceKey
!= NULL
)
2297 RegCloseKey(hServiceKey
);
2299 if (dwError
== ERROR_SUCCESS
)
2301 DPRINT("hService %p\n", hServiceHandle
);
2302 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2304 if (lpdwTagId
!= NULL
)
2305 *lpdwTagId
= lpService
->dwTag
;
2309 if (lpService
!= NULL
&&
2310 lpService
->lpServiceName
!= NULL
)
2312 /* Release the display name buffer */
2313 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2318 /* Remove the service handle */
2319 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2322 if (lpService
!= NULL
)
2324 /* FIXME: remove the service entry */
2328 if (lpImagePath
!= NULL
)
2329 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2331 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2338 DWORD
REnumDependentServicesW(
2339 SC_RPC_HANDLE hService
,
2340 DWORD dwServiceState
,
2343 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2344 LPBOUNDED_DWORD_256K lpServicesReturned
)
2346 DWORD dwError
= ERROR_SUCCESS
;
2347 DWORD dwServicesReturned
= 0;
2348 DWORD dwServiceCount
;
2349 HKEY hServicesKey
= NULL
;
2350 PSERVICE_HANDLE hSvc
;
2351 PSERVICE lpService
= NULL
;
2352 PSERVICE
*lpServicesArray
= NULL
;
2353 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2356 *pcbBytesNeeded
= 0;
2357 *lpServicesReturned
= 0;
2359 DPRINT("REnumDependentServicesW() called\n");
2361 hSvc
= ScmGetServiceFromHandle(hService
);
2364 DPRINT1("Invalid service handle!\n");
2365 return ERROR_INVALID_HANDLE
;
2368 lpService
= hSvc
->ServiceEntry
;
2370 /* Check access rights */
2371 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2372 SC_MANAGER_ENUMERATE_SERVICE
))
2374 DPRINT("Insufficient access rights! 0x%lx\n",
2375 hSvc
->Handle
.DesiredAccess
);
2376 return ERROR_ACCESS_DENIED
;
2379 /* Open the Services Reg key */
2380 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2381 L
"System\\CurrentControlSet\\Services",
2385 if (dwError
!= ERROR_SUCCESS
)
2388 /* First determine the bytes needed and get the number of dependent services */
2389 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2394 &dwServicesReturned
);
2395 if (dwError
!= ERROR_SUCCESS
)
2398 /* If buffer size is less than the bytes needed or pointer is null */
2399 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2401 dwError
= ERROR_MORE_DATA
;
2405 /* Allocate memory for array of service pointers */
2406 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2408 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2409 if (!lpServicesArray
)
2411 DPRINT1("Could not allocate a buffer!!\n");
2412 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2416 dwServicesReturned
= 0;
2417 *pcbBytesNeeded
= 0;
2419 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2424 &dwServicesReturned
);
2425 if (dwError
!= ERROR_SUCCESS
)
2430 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2431 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2433 /* Copy EnumDepenedentService to Buffer */
2434 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2436 lpService
= lpServicesArray
[dwServiceCount
];
2438 /* Copy status info */
2439 memcpy(&lpServicesPtr
->ServiceStatus
,
2441 sizeof(SERVICE_STATUS
));
2443 /* Copy display name */
2444 wcscpy(lpStr
, lpService
->lpDisplayName
);
2445 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2446 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2448 /* Copy service name */
2449 wcscpy(lpStr
, lpService
->lpServiceName
);
2450 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2451 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2456 *lpServicesReturned
= dwServicesReturned
;
2459 if (lpServicesArray
!= NULL
)
2460 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2462 RegCloseKey(hServicesKey
);
2464 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2471 DWORD
REnumServicesStatusW(
2472 SC_RPC_HANDLE hSCManager
,
2473 DWORD dwServiceType
,
2474 DWORD dwServiceState
,
2477 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2478 LPBOUNDED_DWORD_256K lpServicesReturned
,
2479 LPBOUNDED_DWORD_256K lpResumeHandle
)
2481 PMANAGER_HANDLE hManager
;
2483 DWORD dwError
= ERROR_SUCCESS
;
2484 PLIST_ENTRY ServiceEntry
;
2485 PSERVICE CurrentService
;
2487 DWORD dwRequiredSize
;
2488 DWORD dwServiceCount
;
2490 DWORD dwLastResumeCount
= 0;
2491 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2494 DPRINT("REnumServicesStatusW() called\n");
2497 return ERROR_SHUTDOWN_IN_PROGRESS
;
2499 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2500 if (hManager
== NULL
)
2502 DPRINT1("Invalid service manager handle!\n");
2503 return ERROR_INVALID_HANDLE
;
2507 *pcbBytesNeeded
= 0;
2508 *lpServicesReturned
= 0;
2510 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2512 DPRINT("Not a valid Service Type!\n");
2513 return ERROR_INVALID_PARAMETER
;
2516 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2518 DPRINT("Not a valid Service State!\n");
2519 return ERROR_INVALID_PARAMETER
;
2522 /* Check access rights */
2523 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2524 SC_MANAGER_ENUMERATE_SERVICE
))
2526 DPRINT("Insufficient access rights! 0x%lx\n",
2527 hManager
->Handle
.DesiredAccess
);
2528 return ERROR_ACCESS_DENIED
;
2532 dwLastResumeCount
= *lpResumeHandle
;
2534 /* Lock the service database shared */
2535 ScmLockDatabaseShared();
2537 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2538 if (lpService
== NULL
)
2540 dwError
= ERROR_SUCCESS
;
2547 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2548 ServiceEntry
!= &ServiceListHead
;
2549 ServiceEntry
= ServiceEntry
->Flink
)
2551 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2555 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2558 dwState
= SERVICE_ACTIVE
;
2559 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2560 dwState
= SERVICE_INACTIVE
;
2562 if ((dwState
& dwServiceState
) == 0)
2565 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2566 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2567 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2569 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2571 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2575 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2576 dwRequiredSize
+= dwSize
;
2578 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2581 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2582 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2585 ServiceEntry
!= &ServiceListHead
;
2586 ServiceEntry
= ServiceEntry
->Flink
)
2588 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2592 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2595 dwState
= SERVICE_ACTIVE
;
2596 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2597 dwState
= SERVICE_INACTIVE
;
2599 if ((dwState
& dwServiceState
) == 0)
2602 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2603 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2604 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2606 dwError
= ERROR_MORE_DATA
;
2609 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2612 *lpResumeHandle
= dwLastResumeCount
;
2614 *lpServicesReturned
= dwServiceCount
;
2615 *pcbBytesNeeded
= dwRequiredSize
;
2617 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2618 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2619 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2622 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2623 ServiceEntry
!= &ServiceListHead
;
2624 ServiceEntry
= ServiceEntry
->Flink
)
2626 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2630 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2633 dwState
= SERVICE_ACTIVE
;
2634 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2635 dwState
= SERVICE_INACTIVE
;
2637 if ((dwState
& dwServiceState
) == 0)
2640 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2641 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2642 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2644 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2647 /* Copy the service name */
2648 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2649 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2650 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2652 /* Copy the display name */
2653 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2654 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2655 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2657 /* Copy the status information */
2658 memcpy(&lpStatusPtr
->ServiceStatus
,
2659 &CurrentService
->Status
,
2660 sizeof(SERVICE_STATUS
));
2663 dwRequiredSize
+= dwSize
;
2668 *pcbBytesNeeded
= 0;
2669 if (lpResumeHandle
) *lpResumeHandle
= 0;
2673 /* Unlock the service database */
2674 ScmUnlockDatabase();
2676 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2683 DWORD
ROpenSCManagerW(
2684 LPWSTR lpMachineName
,
2685 LPWSTR lpDatabaseName
,
2686 DWORD dwDesiredAccess
,
2687 LPSC_RPC_HANDLE lpScHandle
)
2692 DPRINT("ROpenSCManagerW() called\n");
2693 DPRINT("lpMachineName = %p\n", lpMachineName
);
2694 DPRINT("lpMachineName: %S\n", lpMachineName
);
2695 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2696 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2697 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2700 return ERROR_SHUTDOWN_IN_PROGRESS
;
2703 return ERROR_INVALID_PARAMETER
;
2705 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2707 if (dwError
!= ERROR_SUCCESS
)
2709 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2713 /* Check the desired access */
2714 dwError
= ScmCheckAccess(hHandle
,
2715 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2716 if (dwError
!= ERROR_SUCCESS
)
2718 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2719 HeapFree(GetProcessHeap(), 0, hHandle
);
2723 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2724 DPRINT("*hScm = %p\n", *lpScHandle
);
2726 DPRINT("ROpenSCManagerW() done\n");
2728 return ERROR_SUCCESS
;
2733 DWORD
ROpenServiceW(
2734 SC_RPC_HANDLE hSCManager
,
2735 LPWSTR lpServiceName
,
2736 DWORD dwDesiredAccess
,
2737 LPSC_RPC_HANDLE lpServiceHandle
)
2740 PMANAGER_HANDLE hManager
;
2742 DWORD dwError
= ERROR_SUCCESS
;
2744 DPRINT("ROpenServiceW() called\n");
2745 DPRINT("hSCManager = %p\n", hSCManager
);
2746 DPRINT("lpServiceName = %p\n", lpServiceName
);
2747 DPRINT("lpServiceName: %S\n", lpServiceName
);
2748 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2751 return ERROR_SHUTDOWN_IN_PROGRESS
;
2753 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2754 if (hManager
== NULL
)
2756 DPRINT1("Invalid service manager handle!\n");
2757 return ERROR_INVALID_HANDLE
;
2760 if (!lpServiceHandle
)
2761 return ERROR_INVALID_PARAMETER
;
2764 return ERROR_INVALID_ADDRESS
;
2766 /* Lock the service database exclusive */
2767 ScmLockDatabaseExclusive();
2769 /* Get service database entry */
2770 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2771 if (lpService
== NULL
)
2773 DPRINT("Could not find a service!\n");
2774 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2778 /* Create a service handle */
2779 dwError
= ScmCreateServiceHandle(lpService
,
2781 if (dwError
!= ERROR_SUCCESS
)
2783 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2787 /* Check the desired access */
2788 dwError
= ScmCheckAccess(hHandle
,
2790 if (dwError
!= ERROR_SUCCESS
)
2792 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2793 HeapFree(GetProcessHeap(), 0, hHandle
);
2797 lpService
->dwRefCount
++;
2798 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2800 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2801 DPRINT("*hService = %p\n", *lpServiceHandle
);
2804 /* Unlock the service database */
2805 ScmUnlockDatabase();
2807 DPRINT("ROpenServiceW() done\n");
2814 DWORD
RQueryServiceConfigW(
2815 SC_RPC_HANDLE hService
,
2816 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2818 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2820 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2821 DWORD dwError
= ERROR_SUCCESS
;
2822 PSERVICE_HANDLE hSvc
;
2823 PSERVICE lpService
= NULL
;
2824 HKEY hServiceKey
= NULL
;
2825 LPWSTR lpImagePath
= NULL
;
2826 LPWSTR lpServiceStartName
= NULL
;
2827 LPWSTR lpDependencies
= NULL
;
2828 DWORD dwDependenciesLength
= 0;
2829 DWORD dwRequiredSize
;
2830 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2831 WCHAR lpEmptyString
[] = {0,0};
2834 DPRINT("RQueryServiceConfigW() called\n");
2837 return ERROR_SHUTDOWN_IN_PROGRESS
;
2839 hSvc
= ScmGetServiceFromHandle(hService
);
2842 DPRINT1("Invalid service handle!\n");
2843 return ERROR_INVALID_HANDLE
;
2846 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2847 SERVICE_QUERY_CONFIG
))
2849 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2850 return ERROR_ACCESS_DENIED
;
2853 lpService
= hSvc
->ServiceEntry
;
2854 if (lpService
== NULL
)
2856 DPRINT("lpService == NULL!\n");
2857 return ERROR_INVALID_HANDLE
;
2860 /* Lock the service database shared */
2861 ScmLockDatabaseShared();
2863 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2866 if (dwError
!= ERROR_SUCCESS
)
2869 /* Read the image path */
2870 dwError
= ScmReadString(hServiceKey
,
2873 if (dwError
!= ERROR_SUCCESS
)
2876 /* Read the service start name */
2877 ScmReadString(hServiceKey
,
2879 &lpServiceStartName
);
2881 /* Read the dependencies */
2882 ScmReadDependencies(hServiceKey
,
2884 &dwDependenciesLength
);
2886 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2888 if (lpImagePath
!= NULL
)
2889 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2891 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2893 if (lpService
->lpGroup
!= NULL
)
2894 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2896 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2898 if (lpDependencies
!= NULL
)
2899 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2901 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2903 if (lpServiceStartName
!= NULL
)
2904 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2906 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2908 if (lpService
->lpDisplayName
!= NULL
)
2909 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2911 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2913 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2915 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2919 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2920 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2921 lpConfig
->dwStartType
= lpService
->dwStartType
;
2922 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2923 lpConfig
->dwTagId
= lpService
->dwTag
;
2925 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2927 /* Append the image path */
2928 if (lpImagePath
!= NULL
)
2930 wcscpy(lpStr
, lpImagePath
);
2934 wcscpy(lpStr
, lpEmptyString
);
2937 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2938 lpStr
+= (wcslen(lpStr
) + 1);
2940 /* Append the group name */
2941 if (lpService
->lpGroup
!= NULL
)
2943 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2947 wcscpy(lpStr
, lpEmptyString
);
2950 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2951 lpStr
+= (wcslen(lpStr
) + 1);
2953 /* Append Dependencies */
2954 if (lpDependencies
!= NULL
)
2958 dwDependenciesLength
* sizeof(WCHAR
));
2962 wcscpy(lpStr
, lpEmptyString
);
2965 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2966 if (lpDependencies
!= NULL
)
2967 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2969 lpStr
+= (wcslen(lpStr
) + 1);
2971 /* Append the service start name */
2972 if (lpServiceStartName
!= NULL
)
2974 wcscpy(lpStr
, lpServiceStartName
);
2978 wcscpy(lpStr
, lpEmptyString
);
2981 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2982 lpStr
+= (wcslen(lpStr
) + 1);
2984 /* Append the display name */
2985 if (lpService
->lpDisplayName
!= NULL
)
2987 wcscpy(lpStr
, lpService
->lpDisplayName
);
2991 wcscpy(lpStr
, lpEmptyString
);
2994 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2997 if (pcbBytesNeeded
!= NULL
)
2998 *pcbBytesNeeded
= dwRequiredSize
;
3001 /* Unlock the service database */
3002 ScmUnlockDatabase();
3004 if (lpImagePath
!= NULL
)
3005 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3007 if (lpServiceStartName
!= NULL
)
3008 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3010 if (lpDependencies
!= NULL
)
3011 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3013 if (hServiceKey
!= NULL
)
3014 RegCloseKey(hServiceKey
);
3016 DPRINT("RQueryServiceConfigW() done\n");
3023 DWORD
RQueryServiceLockStatusW(
3024 SC_RPC_HANDLE hSCManager
,
3025 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
3027 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3030 return ERROR_CALL_NOT_IMPLEMENTED
;
3035 DWORD
RStartServiceW(
3036 SC_RPC_HANDLE hService
,
3038 LPSTRING_PTRSW argv
)
3040 DWORD dwError
= ERROR_SUCCESS
;
3041 PSERVICE_HANDLE hSvc
;
3042 PSERVICE lpService
= NULL
;
3045 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3046 DPRINT(" argc: %lu\n", argc
);
3049 for (i
= 0; i
< argc
; i
++)
3051 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
]);
3056 return ERROR_SHUTDOWN_IN_PROGRESS
;
3058 hSvc
= ScmGetServiceFromHandle(hService
);
3061 DPRINT1("Invalid service handle!\n");
3062 return ERROR_INVALID_HANDLE
;
3065 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3068 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3069 return ERROR_ACCESS_DENIED
;
3072 lpService
= hSvc
->ServiceEntry
;
3073 if (lpService
== NULL
)
3075 DPRINT("lpService == NULL!\n");
3076 return ERROR_INVALID_HANDLE
;
3079 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3080 return ERROR_SERVICE_DISABLED
;
3082 if (lpService
->bDeleted
)
3083 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3085 /* Start the service */
3086 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3093 DWORD
RGetServiceDisplayNameW(
3094 SC_RPC_HANDLE hSCManager
,
3095 LPCWSTR lpServiceName
,
3096 LPWSTR lpDisplayName
,
3099 // PMANAGER_HANDLE hManager;
3104 DPRINT("RGetServiceDisplayNameW() called\n");
3105 DPRINT("hSCManager = %p\n", hSCManager
);
3106 DPRINT("lpServiceName: %S\n", lpServiceName
);
3107 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3108 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3110 // hManager = (PMANAGER_HANDLE)hSCManager;
3111 // if (hManager->Handle.Tag != MANAGER_TAG)
3113 // DPRINT("Invalid manager handle!\n");
3114 // return ERROR_INVALID_HANDLE;
3117 /* Get service database entry */
3118 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3119 if (lpService
== NULL
)
3121 DPRINT("Could not find a service!\n");
3123 /* If the service could not be found and lpcchBuffer is less than 2, windows
3124 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3125 if (*lpcchBuffer
< 2)
3128 if (lpDisplayName
!= NULL
)
3130 *lpDisplayName
= '\0';
3134 return ERROR_SERVICE_DOES_NOT_EXIST
;
3137 if (!lpService
->lpDisplayName
)
3139 dwLength
= wcslen(lpService
->lpServiceName
);
3141 if (lpDisplayName
!= NULL
&&
3142 *lpcchBuffer
> dwLength
)
3144 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3149 dwLength
= wcslen(lpService
->lpDisplayName
);
3151 if (lpDisplayName
!= NULL
&&
3152 *lpcchBuffer
> dwLength
)
3154 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3158 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3160 *lpcchBuffer
= dwLength
;
3167 DWORD
RGetServiceKeyNameW(
3168 SC_RPC_HANDLE hSCManager
,
3169 LPCWSTR lpDisplayName
,
3170 LPWSTR lpServiceName
,
3173 // PMANAGER_HANDLE hManager;
3178 DPRINT("RGetServiceKeyNameW() called\n");
3179 DPRINT("hSCManager = %p\n", hSCManager
);
3180 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3181 DPRINT("lpServiceName: %p\n", lpServiceName
);
3182 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3184 // hManager = (PMANAGER_HANDLE)hSCManager;
3185 // if (hManager->Handle.Tag != MANAGER_TAG)
3187 // DPRINT("Invalid manager handle!\n");
3188 // return ERROR_INVALID_HANDLE;
3191 /* Get service database entry */
3192 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3193 if (lpService
== NULL
)
3195 DPRINT("Could not find a service!\n");
3197 /* If the service could not be found and lpcchBuffer is less than 2, windows
3198 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3199 if (*lpcchBuffer
< 2)
3202 if (lpServiceName
!= NULL
)
3204 *lpServiceName
= '\0';
3208 return ERROR_SERVICE_DOES_NOT_EXIST
;
3211 dwLength
= wcslen(lpService
->lpServiceName
);
3213 if (lpServiceName
!= NULL
&&
3214 *lpcchBuffer
> dwLength
)
3216 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3217 *lpcchBuffer
= dwLength
;
3218 return ERROR_SUCCESS
;
3221 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3223 *lpcchBuffer
= dwLength
;
3230 DWORD
RI_ScSetServiceBitsA(
3231 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3232 DWORD dwServiceBits
,
3234 int bUpdateImmediately
,
3238 return ERROR_CALL_NOT_IMPLEMENTED
;
3243 DWORD
RChangeServiceConfigA(
3244 SC_RPC_HANDLE hService
,
3245 DWORD dwServiceType
,
3247 DWORD dwErrorControl
,
3248 LPSTR lpBinaryPathName
,
3249 LPSTR lpLoadOrderGroup
,
3251 LPSTR lpDependencies
,
3253 LPSTR lpServiceStartName
,
3256 LPSTR lpDisplayName
)
3258 DWORD dwError
= ERROR_SUCCESS
;
3259 PSERVICE_HANDLE hSvc
;
3260 PSERVICE lpService
= NULL
;
3261 HKEY hServiceKey
= NULL
;
3262 LPWSTR lpDisplayNameW
= NULL
;
3263 LPWSTR lpBinaryPathNameW
= NULL
;
3264 LPWSTR lpCanonicalImagePathW
= NULL
;
3265 LPWSTR lpLoadOrderGroupW
= NULL
;
3266 LPWSTR lpDependenciesW
= NULL
;
3267 // LPWSTR lpPasswordW = NULL;
3269 DPRINT("RChangeServiceConfigA() called\n");
3270 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3271 DPRINT("dwStartType = %lu\n", dwStartType
);
3272 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3273 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3274 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3275 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3278 return ERROR_SHUTDOWN_IN_PROGRESS
;
3280 hSvc
= ScmGetServiceFromHandle(hService
);
3283 DPRINT1("Invalid service handle!\n");
3284 return ERROR_INVALID_HANDLE
;
3287 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3288 SERVICE_CHANGE_CONFIG
))
3290 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3291 return ERROR_ACCESS_DENIED
;
3294 lpService
= hSvc
->ServiceEntry
;
3295 if (lpService
== NULL
)
3297 DPRINT("lpService == NULL!\n");
3298 return ERROR_INVALID_HANDLE
;
3301 /* Lock the service database exclusively */
3302 ScmLockDatabaseExclusive();
3304 if (lpService
->bDeleted
)
3306 DPRINT("The service has already been marked for delete!\n");
3307 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3311 /* Open the service key */
3312 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3315 if (dwError
!= ERROR_SUCCESS
)
3318 /* Write service data to the registry */
3320 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3322 /* Set the display name */
3323 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3325 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3326 if (lpDisplayNameW
== NULL
)
3328 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3332 MultiByteToWideChar(CP_ACP
,
3337 strlen(lpDisplayName
) + 1);
3339 RegSetValueExW(hServiceKey
,
3343 (LPBYTE
)lpDisplayNameW
,
3344 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3346 /* Update lpService->lpDisplayName */
3347 if (lpService
->lpDisplayName
)
3348 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3350 lpService
->lpDisplayName
= lpDisplayNameW
;
3353 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3355 /* Set the service type */
3356 dwError
= RegSetValueExW(hServiceKey
,
3360 (LPBYTE
)&dwServiceType
,
3362 if (dwError
!= ERROR_SUCCESS
)
3365 lpService
->Status
.dwServiceType
= dwServiceType
;
3368 if (dwStartType
!= SERVICE_NO_CHANGE
)
3370 /* Set the start value */
3371 dwError
= RegSetValueExW(hServiceKey
,
3375 (LPBYTE
)&dwStartType
,
3377 if (dwError
!= ERROR_SUCCESS
)
3380 lpService
->dwStartType
= dwStartType
;
3383 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3385 /* Set the error control value */
3386 dwError
= RegSetValueExW(hServiceKey
,
3390 (LPBYTE
)&dwErrorControl
,
3392 if (dwError
!= ERROR_SUCCESS
)
3395 lpService
->dwErrorControl
= dwErrorControl
;
3398 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3400 /* Set the image path */
3401 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(),
3403 (strlen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
3404 if (lpBinaryPathNameW
== NULL
)
3406 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3410 MultiByteToWideChar(CP_ACP
,
3415 strlen(lpBinaryPathName
) + 1);
3417 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
3419 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
3421 &lpCanonicalImagePathW
);
3423 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3425 if (dwError
!= ERROR_SUCCESS
)
3428 lpBinaryPathNameW
= lpCanonicalImagePathW
;
3431 dwError
= RegSetValueExW(hServiceKey
,
3435 (LPBYTE
)lpBinaryPathNameW
,
3436 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3438 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3440 if (dwError
!= ERROR_SUCCESS
)
3444 /* Set the group name */
3445 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3447 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3449 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3450 if (lpLoadOrderGroupW
== NULL
)
3452 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3456 MultiByteToWideChar(CP_ACP
,
3461 strlen(lpLoadOrderGroup
) + 1);
3463 dwError
= RegSetValueExW(hServiceKey
,
3467 (LPBYTE
)lpLoadOrderGroupW
,
3468 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3469 if (dwError
!= ERROR_SUCCESS
)
3471 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3475 dwError
= ScmSetServiceGroup(lpService
,
3478 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3480 if (dwError
!= ERROR_SUCCESS
)
3484 if (lpdwTagId
!= NULL
)
3486 dwError
= ScmAssignNewTag(lpService
);
3487 if (dwError
!= ERROR_SUCCESS
)
3490 dwError
= RegSetValueExW(hServiceKey
,
3494 (LPBYTE
)&lpService
->dwTag
,
3496 if (dwError
!= ERROR_SUCCESS
)
3499 *lpdwTagId
= lpService
->dwTag
;
3502 /* Write dependencies */
3503 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3505 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3507 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3508 if (lpDependenciesW
== NULL
)
3510 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3514 MultiByteToWideChar(CP_ACP
,
3519 strlen(lpDependencies
) + 1);
3521 dwError
= ScmWriteDependencies(hServiceKey
,
3522 (LPWSTR
)lpDependenciesW
,
3525 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3528 if (lpPassword
!= NULL
)
3530 /* FIXME: Write password */
3534 /* Unlock the service database */
3535 ScmUnlockDatabase();
3537 if (hServiceKey
!= NULL
)
3538 RegCloseKey(hServiceKey
);
3540 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3547 DWORD
RCreateServiceA(
3548 SC_RPC_HANDLE hSCManager
,
3549 LPSTR lpServiceName
,
3550 LPSTR lpDisplayName
,
3551 DWORD dwDesiredAccess
,
3552 DWORD dwServiceType
,
3554 DWORD dwErrorControl
,
3555 LPSTR lpBinaryPathName
,
3556 LPSTR lpLoadOrderGroup
,
3558 LPBYTE lpDependencies
,
3560 LPSTR lpServiceStartName
,
3563 LPSC_RPC_HANDLE lpServiceHandle
)
3565 DWORD dwError
= ERROR_SUCCESS
;
3566 LPWSTR lpServiceNameW
= NULL
;
3567 LPWSTR lpDisplayNameW
= NULL
;
3568 LPWSTR lpBinaryPathNameW
= NULL
;
3569 LPWSTR lpLoadOrderGroupW
= NULL
;
3570 LPWSTR lpDependenciesW
= NULL
;
3571 LPWSTR lpServiceStartNameW
= NULL
;
3572 DWORD dwDependenciesLength
= 0;
3579 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3580 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3581 if (!lpServiceNameW
)
3583 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3586 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3591 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3592 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3593 if (!lpDisplayNameW
)
3595 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3598 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3601 if (lpBinaryPathName
)
3603 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3604 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3605 if (!lpBinaryPathNameW
)
3607 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3610 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3613 if (lpLoadOrderGroup
)
3615 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3616 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3617 if (!lpLoadOrderGroupW
)
3619 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3622 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3627 lpStr
= (LPCSTR
)lpDependencies
;
3630 dwLength
= strlen(lpStr
) + 1;
3631 dwDependenciesLength
+= dwLength
;
3632 lpStr
= lpStr
+ dwLength
;
3634 dwDependenciesLength
++;
3636 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3637 if (!lpDependenciesW
)
3639 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3642 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3645 if (lpServiceStartName
)
3647 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3648 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3649 if (!lpServiceStartNameW
)
3651 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3654 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3657 dwError
= RCreateServiceW(hSCManager
,
3667 (LPBYTE
)lpDependenciesW
,
3668 dwDependenciesLength
,
3669 lpServiceStartNameW
,
3675 if (lpServiceNameW
!=NULL
)
3676 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3678 if (lpDisplayNameW
!= NULL
)
3679 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3681 if (lpBinaryPathNameW
!= NULL
)
3682 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3684 if (lpLoadOrderGroupW
!= NULL
)
3685 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3687 if (lpDependenciesW
!= NULL
)
3688 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3690 if (lpServiceStartNameW
!= NULL
)
3691 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3698 DWORD
REnumDependentServicesA(
3699 SC_RPC_HANDLE hService
,
3700 DWORD dwServiceState
,
3703 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3704 LPBOUNDED_DWORD_256K lpServicesReturned
)
3706 DWORD dwError
= ERROR_SUCCESS
;
3707 DWORD dwServicesReturned
= 0;
3708 DWORD dwServiceCount
;
3709 HKEY hServicesKey
= NULL
;
3710 PSERVICE_HANDLE hSvc
;
3711 PSERVICE lpService
= NULL
;
3712 PSERVICE
*lpServicesArray
= NULL
;
3713 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3716 *pcbBytesNeeded
= 0;
3717 *lpServicesReturned
= 0;
3719 DPRINT("REnumDependentServicesA() called\n");
3721 hSvc
= ScmGetServiceFromHandle(hService
);
3724 DPRINT1("Invalid service handle!\n");
3725 return ERROR_INVALID_HANDLE
;
3728 lpService
= hSvc
->ServiceEntry
;
3730 /* Check access rights */
3731 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3732 SC_MANAGER_ENUMERATE_SERVICE
))
3734 DPRINT("Insufficient access rights! 0x%lx\n",
3735 hSvc
->Handle
.DesiredAccess
);
3736 return ERROR_ACCESS_DENIED
;
3739 /* Open the Services Reg key */
3740 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3741 L
"System\\CurrentControlSet\\Services",
3746 if (dwError
!= ERROR_SUCCESS
)
3749 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3750 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3751 are the same for both. Verified in WINXP. */
3753 /* First determine the bytes needed and get the number of dependent services*/
3754 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3759 &dwServicesReturned
);
3760 if (dwError
!= ERROR_SUCCESS
)
3763 /* If buffer size is less than the bytes needed or pointer is null*/
3764 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3766 dwError
= ERROR_MORE_DATA
;
3770 /* Allocate memory for array of service pointers */
3771 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3773 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3774 if (!lpServicesArray
)
3776 DPRINT("Could not allocate a buffer!!\n");
3777 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3781 dwServicesReturned
= 0;
3782 *pcbBytesNeeded
= 0;
3784 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3789 &dwServicesReturned
);
3790 if (dwError
!= ERROR_SUCCESS
)
3795 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3796 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3798 /* Copy EnumDepenedentService to Buffer */
3799 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3801 lpService
= lpServicesArray
[dwServiceCount
];
3803 /* Copy the status info */
3804 memcpy(&lpServicesPtr
->ServiceStatus
,
3806 sizeof(SERVICE_STATUS
));
3808 /* Copy display name */
3809 WideCharToMultiByte(CP_ACP
,
3811 lpService
->lpDisplayName
,
3814 wcslen(lpService
->lpDisplayName
),
3817 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3818 lpStr
+= strlen(lpStr
) + 1;
3820 /* Copy service name */
3821 WideCharToMultiByte(CP_ACP
,
3823 lpService
->lpServiceName
,
3826 wcslen(lpService
->lpServiceName
),
3829 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3830 lpStr
+= strlen(lpStr
) + 1;
3835 *lpServicesReturned
= dwServicesReturned
;
3838 if (lpServicesArray
)
3839 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3841 RegCloseKey(hServicesKey
);
3843 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3850 DWORD
REnumServicesStatusA(
3851 SC_RPC_HANDLE hSCManager
,
3852 DWORD dwServiceType
,
3853 DWORD dwServiceState
,
3856 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3857 LPBOUNDED_DWORD_256K lpServicesReturned
,
3858 LPBOUNDED_DWORD_256K lpResumeHandle
)
3860 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3861 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3862 LPWSTR lpStringPtrW
;
3865 DWORD dwServiceCount
;
3867 DPRINT("REnumServicesStatusA() called\n");
3869 if ((dwBufSize
> 0) && (lpBuffer
))
3871 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3874 DPRINT("Failed to allocate buffer!\n");
3875 return ERROR_NOT_ENOUGH_MEMORY
;
3879 dwError
= REnumServicesStatusW(hSCManager
,
3882 (LPBYTE
)lpStatusPtrW
,
3888 /* if no services were returned then we are Done */
3889 if (*lpServicesReturned
== 0)
3892 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3893 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3894 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3895 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3896 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3898 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3900 /* Copy the service name */
3901 WideCharToMultiByte(CP_ACP
,
3906 wcslen(lpStringPtrW
),
3910 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3911 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3912 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3914 /* Copy the display name */
3915 WideCharToMultiByte(CP_ACP
,
3920 wcslen(lpStringPtrW
),
3924 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3925 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3926 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3928 /* Copy the status information */
3929 memcpy(&lpStatusPtrA
->ServiceStatus
,
3930 &lpStatusPtrW
->ServiceStatus
,
3931 sizeof(SERVICE_STATUS
));
3938 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3940 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3947 DWORD
ROpenSCManagerA(
3948 LPSTR lpMachineName
,
3949 LPSTR lpDatabaseName
,
3950 DWORD dwDesiredAccess
,
3951 LPSC_RPC_HANDLE lpScHandle
)
3953 UNICODE_STRING MachineName
;
3954 UNICODE_STRING DatabaseName
;
3957 DPRINT("ROpenSCManagerA() called\n");
3960 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3964 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3967 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3968 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3973 RtlFreeUnicodeString(&MachineName
);
3976 RtlFreeUnicodeString(&DatabaseName
);
3983 DWORD
ROpenServiceA(
3984 SC_RPC_HANDLE hSCManager
,
3985 LPSTR lpServiceName
,
3986 DWORD dwDesiredAccess
,
3987 LPSC_RPC_HANDLE lpServiceHandle
)
3989 UNICODE_STRING ServiceName
;
3992 DPRINT("ROpenServiceA() called\n");
3995 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3998 dwError
= ROpenServiceW(hSCManager
,
3999 lpServiceName
? ServiceName
.Buffer
: NULL
,
4004 RtlFreeUnicodeString(&ServiceName
);
4011 DWORD
RQueryServiceConfigA(
4012 SC_RPC_HANDLE hService
,
4013 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4015 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4017 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
4018 DWORD dwError
= ERROR_SUCCESS
;
4019 PSERVICE_HANDLE hSvc
;
4020 PSERVICE lpService
= NULL
;
4021 HKEY hServiceKey
= NULL
;
4022 LPWSTR lpImagePath
= NULL
;
4023 LPWSTR lpServiceStartName
= NULL
;
4024 LPWSTR lpDependencies
= NULL
;
4025 DWORD dwDependenciesLength
= 0;
4026 DWORD dwRequiredSize
;
4027 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
4028 CHAR lpEmptyString
[]={0,0};
4031 DPRINT("RQueryServiceConfigA() called\n");
4034 return ERROR_SHUTDOWN_IN_PROGRESS
;
4036 hSvc
= ScmGetServiceFromHandle(hService
);
4039 DPRINT1("Invalid service handle!\n");
4040 return ERROR_INVALID_HANDLE
;
4043 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4044 SERVICE_QUERY_CONFIG
))
4046 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4047 return ERROR_ACCESS_DENIED
;
4050 lpService
= hSvc
->ServiceEntry
;
4051 if (lpService
== NULL
)
4053 DPRINT("lpService == NULL!\n");
4054 return ERROR_INVALID_HANDLE
;
4057 /* Lock the service database shared */
4058 ScmLockDatabaseShared();
4060 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4063 if (dwError
!= ERROR_SUCCESS
)
4066 /* Read the image path */
4067 dwError
= ScmReadString(hServiceKey
,
4070 if (dwError
!= ERROR_SUCCESS
)
4073 /* Read the service start name */
4074 ScmReadString(hServiceKey
,
4076 &lpServiceStartName
);
4078 /* Read the dependencies */
4079 ScmReadDependencies(hServiceKey
,
4081 &dwDependenciesLength
);
4083 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
4085 if (lpImagePath
!= NULL
)
4086 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
4088 dwRequiredSize
+= 2;
4090 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
4091 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
4093 dwRequiredSize
+= 2;
4095 /* Add Dependencies length */
4096 if (lpDependencies
!= NULL
)
4097 dwRequiredSize
+= dwDependenciesLength
;
4099 dwRequiredSize
+= 2;
4101 if (lpServiceStartName
!= NULL
)
4102 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
4104 dwRequiredSize
+= 2;
4106 if (lpService
->lpDisplayName
!= NULL
)
4107 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
4109 dwRequiredSize
+= 2;
4111 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
4113 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4117 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
4118 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
4119 lpConfig
->dwStartType
= lpService
->dwStartType
;
4120 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
4121 lpConfig
->dwTagId
= lpService
->dwTag
;
4123 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
4125 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4130 WideCharToMultiByte(CP_ACP
,
4135 wcslen(lpImagePath
) + 1,
4141 strcpy(lpStr
, lpEmptyString
);
4144 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4145 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4147 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4149 WideCharToMultiByte(CP_ACP
,
4151 lpService
->lpGroup
->lpGroupName
,
4154 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
4160 strcpy(lpStr
, lpEmptyString
);
4163 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4164 lpStr
+= (strlen(lpStr
) + 1);
4166 /* Append Dependencies */
4169 WideCharToMultiByte(CP_ACP
,
4172 dwDependenciesLength
,
4174 dwDependenciesLength
,
4180 strcpy(lpStr
, lpEmptyString
);
4183 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4185 lpStr
+= dwDependenciesLength
;
4187 lpStr
+= (strlen(lpStr
) + 1);
4189 if (lpServiceStartName
)
4191 WideCharToMultiByte(CP_ACP
,
4196 wcslen(lpServiceStartName
) + 1,
4202 strcpy(lpStr
, lpEmptyString
);
4205 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4206 lpStr
+= (strlen(lpStr
) + 1);
4208 if (lpService
->lpDisplayName
)
4210 WideCharToMultiByte(CP_ACP
,
4212 lpService
->lpDisplayName
,
4215 wcslen(lpService
->lpDisplayName
) + 1,
4221 strcpy(lpStr
, lpEmptyString
);
4224 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4227 if (pcbBytesNeeded
!= NULL
)
4228 *pcbBytesNeeded
= dwRequiredSize
;
4231 /* Unlock the service database */
4232 ScmUnlockDatabase();
4234 if (lpImagePath
!= NULL
)
4235 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4237 if (lpServiceStartName
!= NULL
)
4238 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4240 if (lpDependencies
!= NULL
)
4241 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4243 if (hServiceKey
!= NULL
)
4244 RegCloseKey(hServiceKey
);
4246 DPRINT("RQueryServiceConfigA() done\n");
4253 DWORD
RQueryServiceLockStatusA(
4254 SC_RPC_HANDLE hSCManager
,
4255 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4257 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4260 return ERROR_CALL_NOT_IMPLEMENTED
;
4265 DWORD
RStartServiceA(
4266 SC_RPC_HANDLE hService
,
4268 LPSTRING_PTRSA argv
)
4270 DWORD dwError
= ERROR_SUCCESS
;
4271 PSERVICE_HANDLE hSvc
;
4272 PSERVICE lpService
= NULL
;
4273 LPWSTR
*lpVector
= NULL
;
4277 DPRINT("RStartServiceA() called\n");
4280 return ERROR_SHUTDOWN_IN_PROGRESS
;
4282 hSvc
= ScmGetServiceFromHandle(hService
);
4285 DPRINT1("Invalid service handle!\n");
4286 return ERROR_INVALID_HANDLE
;
4289 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4292 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4293 return ERROR_ACCESS_DENIED
;
4296 lpService
= hSvc
->ServiceEntry
;
4297 if (lpService
== NULL
)
4299 DPRINT("lpService == NULL!\n");
4300 return ERROR_INVALID_HANDLE
;
4303 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4304 return ERROR_SERVICE_DISABLED
;
4306 if (lpService
->bDeleted
)
4307 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4309 /* Build a Unicode argument vector */
4312 lpVector
= HeapAlloc(GetProcessHeap(),
4314 argc
* sizeof(LPWSTR
));
4315 if (lpVector
== NULL
)
4316 return ERROR_NOT_ENOUGH_MEMORY
;
4318 for (i
= 0; i
< argc
; i
++)
4320 dwLength
= MultiByteToWideChar(CP_ACP
,
4327 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4329 dwLength
* sizeof(WCHAR
));
4330 if (lpVector
[i
] == NULL
)
4332 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4336 MultiByteToWideChar(CP_ACP
,
4345 /* Start the service */
4346 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4349 /* Free the Unicode argument vector */
4350 if (lpVector
!= NULL
)
4352 for (i
= 0; i
< argc
; i
++)
4354 if (lpVector
[i
] != NULL
)
4355 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4357 HeapFree(GetProcessHeap(), 0, lpVector
);
4365 DWORD
RGetServiceDisplayNameA(
4366 SC_RPC_HANDLE hSCManager
,
4367 LPCSTR lpServiceName
,
4368 LPSTR lpDisplayName
,
4369 LPBOUNDED_DWORD_4K lpcchBuffer
)
4371 // PMANAGER_HANDLE hManager;
4372 PSERVICE lpService
= NULL
;
4375 LPWSTR lpServiceNameW
;
4377 DPRINT("RGetServiceDisplayNameA() called\n");
4378 DPRINT("hSCManager = %p\n", hSCManager
);
4379 DPRINT("lpServiceName: %s\n", lpServiceName
);
4380 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4381 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4383 // hManager = (PMANAGER_HANDLE)hSCManager;
4384 // if (hManager->Handle.Tag != MANAGER_TAG)
4386 // DPRINT("Invalid manager handle!\n");
4387 // return ERROR_INVALID_HANDLE;
4390 if (lpServiceName
!= NULL
)
4392 dwLength
= strlen(lpServiceName
) + 1;
4393 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4395 dwLength
* sizeof(WCHAR
));
4396 if (!lpServiceNameW
)
4397 return ERROR_NOT_ENOUGH_MEMORY
;
4399 MultiByteToWideChar(CP_ACP
,
4406 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4408 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4411 if (lpService
== NULL
)
4413 DPRINT("Could not find a service!\n");
4415 /* If the service could not be found and lpcchBuffer is 0, windows
4416 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4417 if (*lpcchBuffer
== 0)
4420 if (lpDisplayName
!= NULL
)
4422 *lpDisplayName
= '\0';
4425 return ERROR_SERVICE_DOES_NOT_EXIST
;
4428 if (!lpService
->lpDisplayName
)
4430 dwLength
= wcslen(lpService
->lpServiceName
);
4431 if (lpDisplayName
!= NULL
&&
4432 *lpcchBuffer
> dwLength
)
4434 WideCharToMultiByte(CP_ACP
,
4436 lpService
->lpServiceName
,
4437 wcslen(lpService
->lpServiceName
),
4442 return ERROR_SUCCESS
;
4447 dwLength
= wcslen(lpService
->lpDisplayName
);
4448 if (lpDisplayName
!= NULL
&&
4449 *lpcchBuffer
> dwLength
)
4451 WideCharToMultiByte(CP_ACP
,
4453 lpService
->lpDisplayName
,
4454 wcslen(lpService
->lpDisplayName
),
4459 return ERROR_SUCCESS
;
4463 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4465 *lpcchBuffer
= dwLength
* 2;
4472 DWORD
RGetServiceKeyNameA(
4473 SC_RPC_HANDLE hSCManager
,
4474 LPCSTR lpDisplayName
,
4475 LPSTR lpServiceName
,
4476 LPBOUNDED_DWORD_4K lpcchBuffer
)
4481 LPWSTR lpDisplayNameW
;
4483 DPRINT("RGetServiceKeyNameA() called\n");
4484 DPRINT("hSCManager = %p\n", hSCManager
);
4485 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4486 DPRINT("lpServiceName: %p\n", lpServiceName
);
4487 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4489 dwLength
= strlen(lpDisplayName
) + 1;
4490 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4492 dwLength
* sizeof(WCHAR
));
4493 if (!lpDisplayNameW
)
4494 return ERROR_NOT_ENOUGH_MEMORY
;
4496 MultiByteToWideChar(CP_ACP
,
4503 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4505 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4507 if (lpService
== NULL
)
4509 DPRINT("Could not find the service!\n");
4511 /* If the service could not be found and lpcchBuffer is 0,
4512 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4513 if (*lpcchBuffer
== 0)
4516 if (lpServiceName
!= NULL
)
4518 *lpServiceName
= '\0';
4522 return ERROR_SERVICE_DOES_NOT_EXIST
;
4525 dwLength
= wcslen(lpService
->lpServiceName
);
4526 if (lpServiceName
!= NULL
&&
4527 *lpcchBuffer
> dwLength
)
4529 WideCharToMultiByte(CP_ACP
,
4531 lpService
->lpServiceName
,
4532 wcslen(lpService
->lpServiceName
),
4537 return ERROR_SUCCESS
;
4540 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4542 *lpcchBuffer
= dwLength
* 2;
4549 DWORD
RI_ScGetCurrentGroupStateW(
4550 SC_RPC_HANDLE hSCManager
,
4551 LPWSTR lpLoadOrderGroup
,
4555 return ERROR_CALL_NOT_IMPLEMENTED
;
4560 DWORD
REnumServiceGroupW(
4561 SC_RPC_HANDLE hSCManager
,
4562 DWORD dwServiceType
,
4563 DWORD dwServiceState
,
4566 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4567 LPBOUNDED_DWORD_256K lpServicesReturned
,
4568 LPBOUNDED_DWORD_256K lpResumeIndex
,
4569 LPCWSTR pszGroupName
)
4572 return ERROR_CALL_NOT_IMPLEMENTED
;
4577 // WARNING: This function is untested
4580 DWORD
RChangeServiceConfig2A(
4581 SC_RPC_HANDLE hService
,
4582 SC_RPC_CONFIG_INFOA Info
)
4584 SC_RPC_CONFIG_INFOW InfoW
;
4585 DWORD dwRet
, dwLength
;
4588 DPRINT("RChangeServiceConfig2A() called\n");
4589 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4591 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4593 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4595 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4596 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4598 //lpServiceDescriptonA = Info.psd;
4600 ///if (lpServiceDescriptonA &&
4601 ///lpServiceDescriptonA->lpDescription)
4603 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4605 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4607 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4608 if (!lpServiceDescriptonW
)
4610 return ERROR_NOT_ENOUGH_MEMORY
;
4613 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4615 MultiByteToWideChar(CP_ACP
,
4619 lpServiceDescriptonW
->lpDescription
,
4622 ptr
= lpServiceDescriptonW
;
4623 InfoW
.psd
= lpServiceDescriptonW
;
4626 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4628 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4629 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4630 DWORD dwRebootLen
= 0;
4631 DWORD dwCommandLen
= 0;
4633 lpServiceFailureActionsA
= Info
.psfa
;
4635 if (lpServiceFailureActionsA
)
4637 if (lpServiceFailureActionsA
->lpRebootMsg
)
4639 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4641 if (lpServiceFailureActionsA
->lpCommand
)
4643 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4645 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4647 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4650 if (!lpServiceFailureActionsW
)
4652 return ERROR_NOT_ENOUGH_MEMORY
;
4655 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4656 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4657 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4659 if (lpServiceFailureActionsA
->lpRebootMsg
)
4661 MultiByteToWideChar(CP_ACP
,
4663 lpServiceFailureActionsA
->lpRebootMsg
,
4665 lpServiceFailureActionsW
->lpRebootMsg
,
4669 if (lpServiceFailureActionsA
->lpCommand
)
4671 MultiByteToWideChar(CP_ACP
,
4673 lpServiceFailureActionsA
->lpCommand
,
4675 lpServiceFailureActionsW
->lpCommand
,
4679 ptr
= lpServiceFailureActionsW
;
4683 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4685 HeapFree(GetProcessHeap(), 0, ptr
);
4692 DWORD
RChangeServiceConfig2W(
4693 SC_RPC_HANDLE hService
,
4694 SC_RPC_CONFIG_INFOW Info
)
4696 DWORD dwError
= ERROR_SUCCESS
;
4697 PSERVICE_HANDLE hSvc
;
4698 PSERVICE lpService
= NULL
;
4699 HKEY hServiceKey
= NULL
;
4701 DPRINT("RChangeServiceConfig2W() called\n");
4702 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4705 return ERROR_SHUTDOWN_IN_PROGRESS
;
4707 hSvc
= ScmGetServiceFromHandle(hService
);
4710 DPRINT1("Invalid service handle!\n");
4711 return ERROR_INVALID_HANDLE
;
4714 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4715 SERVICE_CHANGE_CONFIG
))
4717 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4718 return ERROR_ACCESS_DENIED
;
4721 lpService
= hSvc
->ServiceEntry
;
4722 if (lpService
== NULL
)
4724 DPRINT("lpService == NULL!\n");
4725 return ERROR_INVALID_HANDLE
;
4728 /* Lock the service database exclusively */
4729 ScmLockDatabaseExclusive();
4731 if (lpService
->bDeleted
)
4733 DPRINT("The service has already been marked for delete!\n");
4734 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4738 /* Open the service key */
4739 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4742 if (dwError
!= ERROR_SUCCESS
)
4745 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4747 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4749 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4750 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4752 if (lpServiceDescription
!= NULL
&&
4753 lpServiceDescription
->lpDescription
!= NULL
)
4755 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4756 dwError
= RegSetValueExW(hServiceKey
,
4760 (LPBYTE
)lpServiceDescription
->lpDescription
,
4761 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4762 if (dwError
!= ERROR_SUCCESS
)
4766 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4769 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4774 /* Unlock the service database */
4775 ScmUnlockDatabase();
4777 if (hServiceKey
!= NULL
)
4778 RegCloseKey(hServiceKey
);
4780 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4787 DWORD
RQueryServiceConfig2A(
4788 SC_RPC_HANDLE hService
,
4792 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4794 DWORD dwError
= ERROR_SUCCESS
;
4795 PSERVICE_HANDLE hSvc
;
4796 PSERVICE lpService
= NULL
;
4797 HKEY hServiceKey
= NULL
;
4798 LPWSTR lpDescriptionW
= NULL
;
4799 LPSTR lpDescription
= NULL
;
4801 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4802 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4805 return ERROR_INVALID_ADDRESS
;
4808 return ERROR_SHUTDOWN_IN_PROGRESS
;
4810 hSvc
= ScmGetServiceFromHandle(hService
);
4813 DPRINT1("Invalid service handle!\n");
4814 return ERROR_INVALID_HANDLE
;
4817 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4818 SERVICE_QUERY_CONFIG
))
4820 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4821 return ERROR_ACCESS_DENIED
;
4824 lpService
= hSvc
->ServiceEntry
;
4825 if (lpService
== NULL
)
4827 DPRINT("lpService == NULL!\n");
4828 return ERROR_INVALID_HANDLE
;
4831 /* Lock the service database shared */
4832 ScmLockDatabaseShared();
4834 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4837 if (dwError
!= ERROR_SUCCESS
)
4840 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4842 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4845 dwError
= ScmReadString(hServiceKey
,
4848 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4851 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4852 if (dwError
== ERROR_SUCCESS
)
4853 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4855 if (cbBufSize
< *pcbBytesNeeded
)
4857 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4861 if (dwError
== ERROR_SUCCESS
)
4863 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4865 WideCharToMultiByte(CP_ACP
,
4870 wcslen(lpDescriptionW
),
4873 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4877 lpServiceDescription
->lpDescription
= NULL
;
4878 dwError
= ERROR_SUCCESS
;
4882 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4885 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4890 /* Unlock the service database */
4891 ScmUnlockDatabase();
4893 if (lpDescription
!= NULL
)
4894 HeapFree(GetProcessHeap(), 0, lpDescription
);
4896 if (hServiceKey
!= NULL
)
4897 RegCloseKey(hServiceKey
);
4899 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4906 DWORD
RQueryServiceConfig2W(
4907 SC_RPC_HANDLE hService
,
4911 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4913 DWORD dwError
= ERROR_SUCCESS
;
4914 PSERVICE_HANDLE hSvc
;
4915 PSERVICE lpService
= NULL
;
4916 HKEY hServiceKey
= NULL
;
4917 DWORD dwRequiredSize
;
4918 LPWSTR lpDescription
= NULL
;
4919 LPWSTR lpFailureCommand
= NULL
;
4920 LPWSTR lpRebootMessage
= NULL
;
4922 DPRINT("RQueryServiceConfig2W() called\n");
4925 return ERROR_INVALID_ADDRESS
;
4928 return ERROR_SHUTDOWN_IN_PROGRESS
;
4930 hSvc
= ScmGetServiceFromHandle(hService
);
4933 DPRINT1("Invalid service handle!\n");
4934 return ERROR_INVALID_HANDLE
;
4937 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4938 SERVICE_QUERY_CONFIG
))
4940 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4941 return ERROR_ACCESS_DENIED
;
4944 lpService
= hSvc
->ServiceEntry
;
4945 if (lpService
== NULL
)
4947 DPRINT("lpService == NULL!\n");
4948 return ERROR_INVALID_HANDLE
;
4951 /* Lock the service database shared */
4952 ScmLockDatabaseShared();
4954 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4957 if (dwError
!= ERROR_SUCCESS
)
4960 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4962 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4965 dwError
= ScmReadString(hServiceKey
,
4968 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4971 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4972 if (dwError
== ERROR_SUCCESS
)
4973 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4975 if (cbBufSize
< *pcbBytesNeeded
)
4977 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4981 if (dwError
== ERROR_SUCCESS
)
4983 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4984 wcscpy(lpStr
, lpDescription
);
4985 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4989 lpServiceDescription
->lpDescription
= NULL
;
4990 dwError
= ERROR_SUCCESS
;
4993 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4996 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
5000 dwError
= ScmReadString(hServiceKey
,
5004 dwError
= ScmReadString(hServiceKey
,
5008 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5010 if (lpFailureCommand
)
5011 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
5013 if (lpRebootMessage
)
5014 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
5016 if (cbBufSize
< dwRequiredSize
)
5018 *pcbBytesNeeded
= dwRequiredSize
;
5019 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5023 lpFailureActions
->cActions
= 0;
5024 lpFailureActions
->dwResetPeriod
= 0;
5025 lpFailureActions
->lpCommand
= NULL
;
5026 lpFailureActions
->lpRebootMsg
= NULL
;
5027 lpFailureActions
->lpsaActions
= NULL
;
5029 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
5030 if (lpRebootMessage
)
5032 wcscpy(lpStr
, lpRebootMessage
);
5033 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
5034 lpStr
+= wcslen(lpRebootMessage
) + 1;
5037 if (lpFailureCommand
)
5039 wcscpy(lpStr
, lpFailureCommand
);
5040 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
5041 lpStr
+= wcslen(lpRebootMessage
) + 1;
5043 dwError
= STATUS_SUCCESS
;
5048 /* Unlock the service database */
5049 ScmUnlockDatabase();
5051 if (lpDescription
!= NULL
)
5052 HeapFree(GetProcessHeap(), 0, lpDescription
);
5054 if (lpRebootMessage
!= NULL
)
5055 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5057 if (lpFailureCommand
!= NULL
)
5058 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5060 if (hServiceKey
!= NULL
)
5061 RegCloseKey(hServiceKey
);
5063 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5070 DWORD
RQueryServiceStatusEx(
5071 SC_RPC_HANDLE hService
,
5072 SC_STATUS_TYPE InfoLevel
,
5075 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5077 LPSERVICE_STATUS_PROCESS lpStatus
;
5078 PSERVICE_HANDLE hSvc
;
5081 DPRINT("RQueryServiceStatusEx() called\n");
5084 return ERROR_SHUTDOWN_IN_PROGRESS
;
5086 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
5087 return ERROR_INVALID_LEVEL
;
5089 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
5091 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
5092 return ERROR_INSUFFICIENT_BUFFER
;
5094 hSvc
= ScmGetServiceFromHandle(hService
);
5097 DPRINT1("Invalid service handle!\n");
5098 return ERROR_INVALID_HANDLE
;
5101 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5102 SERVICE_QUERY_STATUS
))
5104 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5105 return ERROR_ACCESS_DENIED
;
5108 lpService
= hSvc
->ServiceEntry
;
5109 if (lpService
== NULL
)
5111 DPRINT("lpService == NULL!\n");
5112 return ERROR_INVALID_HANDLE
;
5115 /* Lock the service database shared */
5116 ScmLockDatabaseShared();
5118 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
5120 /* Return service status information */
5121 RtlCopyMemory(lpStatus
,
5123 sizeof(SERVICE_STATUS
));
5125 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
5126 lpStatus
->dwServiceFlags
= 0; /* FIXME */
5128 /* Unlock the service database */
5129 ScmUnlockDatabase();
5131 return ERROR_SUCCESS
;
5136 DWORD
REnumServicesStatusExA(
5137 SC_RPC_HANDLE hSCManager
,
5138 SC_ENUM_TYPE InfoLevel
,
5139 DWORD dwServiceType
,
5140 DWORD dwServiceState
,
5143 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5144 LPBOUNDED_DWORD_256K lpServicesReturned
,
5145 LPBOUNDED_DWORD_256K lpResumeIndex
,
5146 LPCSTR pszGroupName
)
5148 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
5149 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
5150 LPWSTR lpStringPtrW
;
5152 LPWSTR pszGroupNameW
= NULL
;
5154 DWORD dwServiceCount
;
5156 DPRINT("REnumServicesStatusExA() called\n");
5160 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
5163 DPRINT("Failed to allocate buffer!\n");
5164 return ERROR_NOT_ENOUGH_MEMORY
;
5167 MultiByteToWideChar(CP_ACP
,
5172 strlen(pszGroupName
) + 1);
5175 if ((cbBufSize
> 0) && (lpBuffer
))
5177 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
5180 DPRINT("Failed to allocate buffer!\n");
5181 return ERROR_NOT_ENOUGH_MEMORY
;
5185 dwError
= REnumServicesStatusExW(hSCManager
,
5189 (LPBYTE
)lpStatusPtrW
,
5196 /* if no services were returned then we are Done */
5197 if (*lpServicesReturned
== 0)
5200 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5201 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5202 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5203 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5204 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5206 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5208 /* Copy the service name */
5209 WideCharToMultiByte(CP_ACP
,
5214 wcslen(lpStringPtrW
),
5218 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5219 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5220 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5222 /* Copy the display name */
5223 WideCharToMultiByte(CP_ACP
,
5228 wcslen(lpStringPtrW
),
5232 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5233 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5234 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5236 /* Copy the status information */
5237 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5238 &lpStatusPtrW
->ServiceStatusProcess
,
5239 sizeof(SERVICE_STATUS
));
5241 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5242 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5248 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5251 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5253 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5260 DWORD
REnumServicesStatusExW(
5261 SC_RPC_HANDLE hSCManager
,
5262 SC_ENUM_TYPE InfoLevel
,
5263 DWORD dwServiceType
,
5264 DWORD dwServiceState
,
5267 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5268 LPBOUNDED_DWORD_256K lpServicesReturned
,
5269 LPBOUNDED_DWORD_256K lpResumeIndex
,
5270 LPCWSTR pszGroupName
)
5272 PMANAGER_HANDLE hManager
;
5274 DWORD dwError
= ERROR_SUCCESS
;
5275 PLIST_ENTRY ServiceEntry
;
5276 PSERVICE CurrentService
;
5278 DWORD dwRequiredSize
;
5279 DWORD dwServiceCount
;
5281 DWORD dwLastResumeCount
= 0;
5282 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5285 DPRINT("REnumServicesStatusExW() called\n");
5288 return ERROR_SHUTDOWN_IN_PROGRESS
;
5290 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5291 return ERROR_INVALID_LEVEL
;
5293 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5294 if (hManager
== NULL
)
5296 DPRINT1("Invalid service manager handle!\n");
5297 return ERROR_INVALID_HANDLE
;
5300 *pcbBytesNeeded
= 0;
5301 *lpServicesReturned
= 0;
5303 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
5305 DPRINT("Not a valid Service Type!\n");
5306 return ERROR_INVALID_PARAMETER
;
5309 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
5311 DPRINT("Not a valid Service State!\n");
5312 return ERROR_INVALID_PARAMETER
;
5315 /* Check access rights */
5316 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5317 SC_MANAGER_ENUMERATE_SERVICE
))
5319 DPRINT("Insufficient access rights! 0x%lx\n",
5320 hManager
->Handle
.DesiredAccess
);
5321 return ERROR_ACCESS_DENIED
;
5325 dwLastResumeCount
= *lpResumeIndex
;
5327 /* Lock the service database shared */
5328 ScmLockDatabaseShared();
5330 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5331 if (lpService
== NULL
)
5333 dwError
= ERROR_SUCCESS
;
5340 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5341 ServiceEntry
!= &ServiceListHead
;
5342 ServiceEntry
= ServiceEntry
->Flink
)
5344 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5348 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5351 dwState
= SERVICE_ACTIVE
;
5352 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5353 dwState
= SERVICE_INACTIVE
;
5355 if ((dwState
& dwServiceState
) == 0)
5360 if (*pszGroupName
== 0)
5362 if (CurrentService
->lpGroup
!= NULL
)
5367 if ((CurrentService
->lpGroup
== NULL
) ||
5368 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5373 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5374 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5375 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5377 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5379 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5380 dwRequiredSize
+= dwSize
;
5382 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5386 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5392 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5393 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5396 ServiceEntry
!= &ServiceListHead
;
5397 ServiceEntry
= ServiceEntry
->Flink
)
5399 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5403 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5406 dwState
= SERVICE_ACTIVE
;
5407 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5408 dwState
= SERVICE_INACTIVE
;
5410 if ((dwState
& dwServiceState
) == 0)
5415 if (*pszGroupName
== 0)
5417 if (CurrentService
->lpGroup
!= NULL
)
5422 if ((CurrentService
->lpGroup
== NULL
) ||
5423 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5428 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5429 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5430 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5432 dwError
= ERROR_MORE_DATA
;
5435 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5438 *lpResumeIndex
= dwLastResumeCount
;
5440 *lpServicesReturned
= dwServiceCount
;
5441 *pcbBytesNeeded
= dwRequiredSize
;
5443 /* If there was no services that matched */
5444 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5446 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5450 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5451 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5452 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5455 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5456 ServiceEntry
!= &ServiceListHead
;
5457 ServiceEntry
= ServiceEntry
->Flink
)
5459 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5463 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5466 dwState
= SERVICE_ACTIVE
;
5467 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5468 dwState
= SERVICE_INACTIVE
;
5470 if ((dwState
& dwServiceState
) == 0)
5475 if (*pszGroupName
== 0)
5477 if (CurrentService
->lpGroup
!= NULL
)
5482 if ((CurrentService
->lpGroup
== NULL
) ||
5483 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5488 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5489 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5490 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5492 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5494 /* Copy the service name */
5496 CurrentService
->lpServiceName
);
5497 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5498 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5500 /* Copy the display name */
5502 CurrentService
->lpDisplayName
);
5503 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5504 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5506 /* Copy the status information */
5507 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5508 &CurrentService
->Status
,
5509 sizeof(SERVICE_STATUS
));
5510 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5511 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5512 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5515 dwRequiredSize
+= dwSize
;
5525 *pcbBytesNeeded
= 0;
5531 /* Unlock the service database */
5532 ScmUnlockDatabase();
5534 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5541 DWORD
RSendTSMessage(
5542 handle_t BindingHandle
) /* FIXME */
5545 return ERROR_CALL_NOT_IMPLEMENTED
;
5550 DWORD
RCreateServiceWOW64A(
5551 handle_t BindingHandle
,
5552 LPSTR lpServiceName
,
5553 LPSTR lpDisplayName
,
5554 DWORD dwDesiredAccess
,
5555 DWORD dwServiceType
,
5557 DWORD dwErrorControl
,
5558 LPSTR lpBinaryPathName
,
5559 LPSTR lpLoadOrderGroup
,
5561 LPBYTE lpDependencies
,
5563 LPSTR lpServiceStartName
,
5566 LPSC_RPC_HANDLE lpServiceHandle
)
5569 return ERROR_CALL_NOT_IMPLEMENTED
;
5574 DWORD
RCreateServiceWOW64W(
5575 handle_t BindingHandle
,
5576 LPWSTR lpServiceName
,
5577 LPWSTR lpDisplayName
,
5578 DWORD dwDesiredAccess
,
5579 DWORD dwServiceType
,
5581 DWORD dwErrorControl
,
5582 LPWSTR lpBinaryPathName
,
5583 LPWSTR lpLoadOrderGroup
,
5585 LPBYTE lpDependencies
,
5587 LPWSTR lpServiceStartName
,
5590 LPSC_RPC_HANDLE lpServiceHandle
)
5593 return ERROR_CALL_NOT_IMPLEMENTED
;
5598 DWORD
RQueryServiceTagInfo(
5599 handle_t BindingHandle
) /* FIXME */
5602 return ERROR_CALL_NOT_IMPLEMENTED
;
5607 DWORD
RNotifyServiceStatusChange(
5608 SC_RPC_HANDLE hService
,
5609 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5610 GUID
*pClientProcessGuid
,
5611 GUID
*pSCMProcessGuid
,
5612 PBOOL pfCreateRemoteQueue
,
5613 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5616 return ERROR_CALL_NOT_IMPLEMENTED
;
5621 DWORD
RGetNotifyResults(
5622 SC_NOTIFY_RPC_HANDLE hNotify
,
5623 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5626 return ERROR_CALL_NOT_IMPLEMENTED
;
5631 DWORD
RCloseNotifyHandle(
5632 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5636 return ERROR_CALL_NOT_IMPLEMENTED
;
5641 DWORD
RControlServiceExA(
5642 SC_RPC_HANDLE hService
,
5647 return ERROR_CALL_NOT_IMPLEMENTED
;
5652 DWORD
RControlServiceExW(
5653 SC_RPC_HANDLE hService
,
5658 return ERROR_CALL_NOT_IMPLEMENTED
;
5663 DWORD
RSendPnPMessage(
5664 handle_t BindingHandle
) /* FIXME */
5667 return ERROR_CALL_NOT_IMPLEMENTED
;
5672 DWORD
RValidatePnPService(
5673 handle_t BindingHandle
) /* FIXME */
5676 return ERROR_CALL_NOT_IMPLEMENTED
;
5681 DWORD
ROpenServiceStatusHandle(
5682 handle_t BindingHandle
) /* FIXME */
5685 return ERROR_CALL_NOT_IMPLEMENTED
;
5691 handle_t BindingHandle
) /* FIXME */
5694 return ERROR_CALL_NOT_IMPLEMENTED
;
5698 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5700 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5704 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5706 HeapFree(GetProcessHeap(), 0, ptr
);
5710 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5715 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5720 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)