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 nTagOffset
= pdwGroupTags
[i
] - dwTagUsedBase
;
337 if (nTagOffset
>= 0 && nTagOffset
< TAG_ARRAY_SIZE
)
338 TagUsed
[nTagOffset
] = 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 nTagOffset
= CurrentService
->dwTag
- dwTagUsedBase
;
350 if (nTagOffset
>= 0 && nTagOffset
< TAG_ARRAY_SIZE
)
351 TagUsed
[nTagOffset
] = 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
;
368 } while (!dwFreeTag
);
372 HeapFree(GetProcessHeap(), 0, pdwGroupTags
);
379 lpService
->dwTag
= dwFreeTag
;
380 DPRINT("Assigning new tag %lu to service %S in group %S\n",
381 lpService
->dwTag
, lpService
->lpServiceName
, lpService
->lpGroup
->szGroupName
);
382 dwError
= ERROR_SUCCESS
;
386 DPRINT1("Failed to assign new tag to service %S, error=%lu\n",
387 lpService
->lpServiceName
, dwError
);
394 /* Create a path suitable for the bootloader out of the full path */
396 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
398 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
401 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
402 OBJECT_ATTRIBUTES ObjectAttributes
;
404 HANDLE SymbolicLinkHandle
;
406 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
409 return ERROR_INVALID_PARAMETER
;
411 *RelativeName
= NULL
;
413 ServiceNameLen
= wcslen(CanonName
);
415 /* First check, if it's already good */
416 if (ServiceNameLen
> 12 &&
417 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
419 *RelativeName
= HeapAlloc(GetProcessHeap(),
421 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
422 if (*RelativeName
== NULL
)
424 DPRINT("Error allocating memory for boot driver name!\n");
425 return ERROR_NOT_ENOUGH_MEMORY
;
429 wcscpy(*RelativeName
, CanonName
);
431 DPRINT("Bootdriver name %S\n", *RelativeName
);
432 return ERROR_SUCCESS
;
435 /* If it has %SystemRoot% prefix, substitute it to \System*/
436 if (ServiceNameLen
> 13 &&
437 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
439 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
440 *RelativeName
= HeapAlloc(GetProcessHeap(),
442 ServiceNameLen
* sizeof(WCHAR
));
444 if (*RelativeName
== NULL
)
446 DPRINT("Error allocating memory for boot driver name!\n");
447 return ERROR_NOT_ENOUGH_MEMORY
;
451 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
452 wcscat(*RelativeName
, CanonName
+ 13);
454 DPRINT("Bootdriver name %S\n", *RelativeName
);
455 return ERROR_SUCCESS
;
458 /* Get buffer size needed for expanding env strings */
459 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
463 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
464 return ERROR_INVALID_ENVIRONMENT
;
467 /* Allocate memory, since the size is known now */
468 Expanded
= HeapAlloc(GetProcessHeap(),
470 (BufferSize
+ 1) * sizeof(WCHAR
));
473 DPRINT("Error allocating memory for boot driver name!\n");
474 return ERROR_NOT_ENOUGH_MEMORY
;
478 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
481 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
482 HeapFree(GetProcessHeap(), 0, Expanded
);
483 return ERROR_NOT_ENOUGH_MEMORY
;
486 /* Convert to NT-style path */
487 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
489 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
490 return ERROR_INVALID_ENVIRONMENT
;
493 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
495 /* No need to keep the dos-path anymore */
496 HeapFree(GetProcessHeap(), 0, Expanded
);
498 /* Copy it to the allocated place */
499 Expanded
= HeapAlloc(GetProcessHeap(),
501 NtPathName
.Length
+ sizeof(UNICODE_NULL
));
504 DPRINT("Error allocating memory for boot driver name!\n");
505 return ERROR_NOT_ENOUGH_MEMORY
;
508 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
509 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
510 Expanded
[ExpandedLen
] = UNICODE_NULL
;
512 if (ServiceNameLen
> ExpandedLen
&&
513 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
515 /* Only \SystemRoot\ is missing */
516 *RelativeName
= HeapAlloc(GetProcessHeap(),
518 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
519 if (*RelativeName
== NULL
)
521 DPRINT("Error allocating memory for boot driver name!\n");
522 HeapFree(GetProcessHeap(), 0, Expanded
);
523 return ERROR_NOT_ENOUGH_MEMORY
;
526 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
527 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
529 RtlFreeUnicodeString(&NtPathName
);
530 return ERROR_SUCCESS
;
533 /* The most complex case starts here */
534 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
535 InitializeObjectAttributes(&ObjectAttributes
,
537 OBJ_CASE_INSENSITIVE
,
541 /* Open this symlink */
542 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
544 if (NT_SUCCESS(Status
))
546 LinkTarget
.Length
= 0;
547 LinkTarget
.MaximumLength
= 0;
549 DPRINT("Opened symbolic link object\n");
551 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
552 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
554 /* Check if required buffer size is sane */
555 if (BufferSize
> 0xFFFD)
557 DPRINT("Too large buffer required\n");
559 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
560 HeapFree(GetProcessHeap(), 0, Expanded
);
561 return ERROR_NOT_ENOUGH_MEMORY
;
564 /* Alloc the string */
565 LinkTarget
.Length
= (USHORT
)BufferSize
;
566 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(UNICODE_NULL
);
567 LinkTarget
.Buffer
= HeapAlloc(GetProcessHeap(),
569 LinkTarget
.MaximumLength
);
570 if (!LinkTarget
.Buffer
)
572 DPRINT("Unable to alloc buffer\n");
573 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
574 HeapFree(GetProcessHeap(), 0, Expanded
);
575 return ERROR_NOT_ENOUGH_MEMORY
;
578 /* Do a real query now */
579 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
580 if (NT_SUCCESS(Status
))
582 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
584 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
585 if ((ServiceNameLen
> ExpandedLen
) &&
586 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
588 *RelativeName
= HeapAlloc(GetProcessHeap(),
590 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
592 if (*RelativeName
== NULL
)
594 DPRINT("Unable to alloc buffer\n");
595 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
596 HeapFree(GetProcessHeap(), 0, Expanded
);
597 RtlFreeUnicodeString(&NtPathName
);
598 return ERROR_NOT_ENOUGH_MEMORY
;
601 /* Copy it over, substituting the first part
603 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
604 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
607 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
608 HeapFree(GetProcessHeap(), 0, Expanded
);
609 RtlFreeUnicodeString(&NtPathName
);
612 return ERROR_SUCCESS
;
616 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
617 HeapFree(GetProcessHeap(), 0, Expanded
);
618 RtlFreeUnicodeString(&NtPathName
);
619 return ERROR_INVALID_PARAMETER
;
624 DPRINT("Error, Status = %08X\n", Status
);
625 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
626 HeapFree(GetProcessHeap(), 0, Expanded
);
627 RtlFreeUnicodeString(&NtPathName
);
628 return ERROR_INVALID_PARAMETER
;
633 DPRINT("Error, Status = %08X\n", Status
);
634 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
635 HeapFree(GetProcessHeap(), 0, Expanded
);
636 RtlFreeUnicodeString(&NtPathName
);
637 return ERROR_INVALID_PARAMETER
;
643 DPRINT("Error, Status = %08X\n", Status
);
644 HeapFree(GetProcessHeap(), 0, Expanded
);
645 return ERROR_INVALID_PARAMETER
;
651 ScmCanonDriverImagePath(DWORD dwStartType
,
652 const wchar_t *lpServiceName
,
653 wchar_t **lpCanonName
)
655 DWORD ServiceNameLen
, Result
;
656 UNICODE_STRING NtServiceName
;
658 const WCHAR
*SourceName
= lpServiceName
;
660 /* Calculate the length of the service's name */
661 ServiceNameLen
= wcslen(lpServiceName
);
663 /* 12 is wcslen(L"\\SystemRoot\\") */
664 if (ServiceNameLen
> 12 &&
665 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
667 /* SystemRoot prefix is already included */
668 *lpCanonName
= HeapAlloc(GetProcessHeap(),
670 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
672 if (*lpCanonName
== NULL
)
674 DPRINT("Error allocating memory for canonized service name!\n");
675 return ERROR_NOT_ENOUGH_MEMORY
;
678 /* If it's a boot-time driver, it must be systemroot relative */
679 if (dwStartType
== SERVICE_BOOT_START
)
683 wcscpy(*lpCanonName
, SourceName
);
685 DPRINT("Canonicalized name %S\n", *lpCanonName
);
689 /* Check if it has %SystemRoot% (len=13) */
690 if (ServiceNameLen
> 13 &&
691 !_wcsnicmp(L
"%SystemRoot%\\", lpServiceName
, 13))
693 /* Substitute %SystemRoot% with \\SystemRoot\\ */
694 *lpCanonName
= HeapAlloc(GetProcessHeap(),
696 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
698 if (*lpCanonName
== NULL
)
700 DPRINT("Error allocating memory for canonized service name!\n");
701 return ERROR_NOT_ENOUGH_MEMORY
;
704 /* If it's a boot-time driver, it must be systemroot relative */
705 if (dwStartType
== SERVICE_BOOT_START
)
706 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
708 wcscat(*lpCanonName
, lpServiceName
+ 13);
710 DPRINT("Canonicalized name %S\n", *lpCanonName
);
714 /* Check if it's a relative path name */
715 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
717 *lpCanonName
= HeapAlloc(GetProcessHeap(),
719 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
721 if (*lpCanonName
== NULL
)
723 DPRINT("Error allocating memory for canonized service name!\n");
724 return ERROR_NOT_ENOUGH_MEMORY
;
727 /* Just copy it over without changing */
728 wcscpy(*lpCanonName
, lpServiceName
);
733 /* It seems to be a DOS path, convert it */
734 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
736 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
737 return ERROR_INVALID_PARAMETER
;
740 *lpCanonName
= HeapAlloc(GetProcessHeap(),
742 NtServiceName
.Length
+ sizeof(WCHAR
));
744 if (*lpCanonName
== NULL
)
746 DPRINT("Error allocating memory for canonized service name!\n");
747 RtlFreeUnicodeString(&NtServiceName
);
748 return ERROR_NOT_ENOUGH_MEMORY
;
751 /* Copy the string */
752 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
754 /* The unicode string is not needed anymore */
755 RtlFreeUnicodeString(&NtServiceName
);
757 if (dwStartType
!= SERVICE_BOOT_START
)
759 DPRINT("Canonicalized name %S\n", *lpCanonName
);
763 /* The service is boot-started, so must be relative */
764 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
767 /* There is a problem, free name and return */
768 HeapFree(GetProcessHeap(), 0, *lpCanonName
);
769 DPRINT("Error converting named!\n");
773 ASSERT(RelativeName
);
775 /* Copy that string */
776 wcscpy(*lpCanonName
, RelativeName
+ 12);
778 /* Free the allocated buffer */
779 HeapFree(GetProcessHeap(), 0, RelativeName
);
781 DPRINT("Canonicalized name %S\n", *lpCanonName
);
788 /* Internal recursive function */
789 /* Need to search for every dependency on every service */
791 Int_EnumDependentServicesW(HKEY hServicesKey
,
793 DWORD dwServiceState
,
794 PSERVICE
*lpServices
,
795 LPDWORD pcbBytesNeeded
,
796 LPDWORD lpServicesReturned
)
798 DWORD dwError
= ERROR_SUCCESS
;
799 WCHAR szNameBuf
[MAX_PATH
];
800 WCHAR szValueBuf
[MAX_PATH
];
801 WCHAR
*lpszNameBuf
= szNameBuf
;
802 WCHAR
*lpszValueBuf
= szValueBuf
;
806 PSERVICE lpCurrentService
;
807 HKEY hServiceEnumKey
;
808 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
809 DWORD dwDependServiceStrPtr
= 0;
810 DWORD dwRequiredSize
= 0;
812 /* Get the number of service keys */
813 dwError
= RegQueryInfoKeyW(hServicesKey
,
825 if (dwError
!= ERROR_SUCCESS
)
827 DPRINT("ERROR! Unable to get number of services keys.\n");
831 /* Iterate the service keys to see if another service depends on the this service */
832 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
835 dwError
= RegEnumKeyExW(hServicesKey
,
843 if (dwError
!= ERROR_SUCCESS
)
846 /* Open the Service key */
847 dwError
= RegOpenKeyExW(hServicesKey
,
852 if (dwError
!= ERROR_SUCCESS
)
857 /* Check for the DependOnService Value */
858 dwError
= RegQueryValueExW(hServiceEnumKey
,
862 (LPBYTE
)lpszValueBuf
,
865 /* FIXME: Handle load order. */
867 /* If the service found has a DependOnService value */
868 if (dwError
== ERROR_SUCCESS
)
870 dwDependServiceStrPtr
= 0;
872 /* Can be more than one Dependencies in the DependOnService string */
873 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
875 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
877 /* Get the current enumed service pointer */
878 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
880 /* Check for valid Service */
881 if (!lpCurrentService
)
883 /* This should never happen! */
884 DPRINT("This should not happen at this point, report to Developer\n");
885 return ERROR_NOT_FOUND
;
888 /* Determine state the service is in */
889 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
890 dwCurrentServiceState
= SERVICE_INACTIVE
;
892 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
893 if ((dwCurrentServiceState
== dwServiceState
) ||
894 (dwServiceState
== SERVICE_STATE_ALL
))
896 /* Calculate the required size */
897 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
898 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
899 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
901 /* Add the size for service name and display name pointers */
902 dwRequiredSize
+= (2 * sizeof(PVOID
));
904 /* increase the BytesNeeded size */
905 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
907 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
910 /* Recursive call to check for its dependencies */
911 Int_EnumDependentServicesW(hServicesKey
,
918 /* If the lpServices is valid set the service pointer */
920 lpServices
[*lpServicesReturned
] = lpCurrentService
;
922 *lpServicesReturned
= *lpServicesReturned
+ 1;
926 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
929 else if (*pcbBytesNeeded
)
931 dwError
= ERROR_SUCCESS
;
934 RegCloseKey(hServiceEnumKey
);
942 DWORD
RCloseServiceHandle(
943 LPSC_RPC_HANDLE hSCObject
)
945 PMANAGER_HANDLE hManager
;
946 PSERVICE_HANDLE hService
;
950 DWORD pcbBytesNeeded
= 0;
951 DWORD dwServicesReturned
= 0;
953 DPRINT("RCloseServiceHandle() called\n");
955 DPRINT("hSCObject = %p\n", *hSCObject
);
958 return ERROR_INVALID_HANDLE
;
960 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
961 hService
= ScmGetServiceFromHandle(*hSCObject
);
963 if (hManager
!= NULL
)
965 DPRINT("Found manager handle\n");
967 /* FIXME: add handle cleanup code */
969 HeapFree(GetProcessHeap(), 0, hManager
);
974 DPRINT("RCloseServiceHandle() done\n");
975 return ERROR_SUCCESS
;
977 else if (hService
!= NULL
)
979 DPRINT("Found service handle\n");
981 /* Lock the service database exlusively */
982 ScmLockDatabaseExclusive();
984 /* Get the pointer to the service record */
985 lpService
= hService
->ServiceEntry
;
987 /* FIXME: add handle cleanup code */
989 /* Free the handle */
990 HeapFree(GetProcessHeap(), 0, hService
);
993 ASSERT(lpService
->dwRefCount
> 0);
995 lpService
->dwRefCount
--;
996 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
997 lpService
->dwRefCount
);
999 if (lpService
->dwRefCount
== 0)
1001 /* If this service has been marked for deletion */
1002 if (lpService
->bDeleted
)
1004 /* Open the Services Reg key */
1005 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1006 L
"System\\CurrentControlSet\\Services",
1008 KEY_SET_VALUE
| KEY_READ
,
1010 if (dwError
!= ERROR_SUCCESS
)
1012 DPRINT("Failed to open services key\n");
1013 ScmUnlockDatabase();
1017 /* Call the internal function with NULL, just to get bytes we need */
1018 Int_EnumDependentServicesW(hServicesKey
,
1023 &dwServicesReturned
);
1025 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */
1028 DPRINT("Deletion failed due to running dependencies.\n");
1029 RegCloseKey(hServicesKey
);
1030 ScmUnlockDatabase();
1031 return ERROR_SUCCESS
;
1034 /* There are no references and no runnning dependencies,
1035 it is now safe to delete the service */
1037 /* Delete the Service Key */
1038 dwError
= RegDeleteKeyW(hServicesKey
,
1039 lpService
->lpServiceName
);
1041 RegCloseKey(hServicesKey
);
1043 if (dwError
!= ERROR_SUCCESS
)
1045 DPRINT("Failed to Delete the Service Registry key\n");
1046 ScmUnlockDatabase();
1050 /* Delete the Service */
1051 ScmDeleteServiceRecord(lpService
);
1055 ScmUnlockDatabase();
1059 DPRINT("RCloseServiceHandle() done\n");
1060 return ERROR_SUCCESS
;
1063 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
1065 return ERROR_INVALID_HANDLE
;
1070 DWORD
RControlService(
1071 SC_RPC_HANDLE hService
,
1073 LPSERVICE_STATUS lpServiceStatus
)
1075 PSERVICE_HANDLE hSvc
;
1077 ACCESS_MASK DesiredAccess
;
1078 DWORD dwError
= ERROR_SUCCESS
;
1079 DWORD pcbBytesNeeded
= 0;
1080 DWORD dwServicesReturned
= 0;
1081 DWORD dwControlsAccepted
;
1082 DWORD dwCurrentState
;
1083 HKEY hServicesKey
= NULL
;
1085 DPRINT("RControlService() called\n");
1088 return ERROR_SHUTDOWN_IN_PROGRESS
;
1090 /* Check the service handle */
1091 hSvc
= ScmGetServiceFromHandle(hService
);
1094 DPRINT1("Invalid service handle!\n");
1095 return ERROR_INVALID_HANDLE
;
1098 /* Check the service entry point */
1099 lpService
= hSvc
->ServiceEntry
;
1100 if (lpService
== NULL
)
1102 DPRINT1("lpService == NULL!\n");
1103 return ERROR_INVALID_HANDLE
;
1106 /* Check access rights */
1109 case SERVICE_CONTROL_STOP
:
1110 DesiredAccess
= SERVICE_STOP
;
1113 case SERVICE_CONTROL_PAUSE
:
1114 case SERVICE_CONTROL_CONTINUE
:
1115 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
1118 case SERVICE_CONTROL_INTERROGATE
:
1119 DesiredAccess
= SERVICE_INTERROGATE
;
1123 if (dwControl
>= 128 && dwControl
<= 255)
1124 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
1126 return ERROR_INVALID_PARAMETER
;
1130 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1132 return ERROR_ACCESS_DENIED
;
1134 /* Return the current service status information */
1135 RtlCopyMemory(lpServiceStatus
,
1137 sizeof(SERVICE_STATUS
));
1139 if (dwControl
== SERVICE_CONTROL_STOP
)
1141 /* Check if the service has dependencies running as windows
1142 doesn't stop a service that does */
1144 /* Open the Services Reg key */
1145 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1146 L
"System\\CurrentControlSet\\Services",
1150 if (dwError
!= ERROR_SUCCESS
)
1152 DPRINT("Failed to open services key\n");
1156 /* Call the internal function with NULL, just to get bytes we need */
1157 Int_EnumDependentServicesW(hServicesKey
,
1162 &dwServicesReturned
);
1164 RegCloseKey(hServicesKey
);
1166 /* If pcbBytesNeeded is not zero then there are services running that
1167 are dependent on this service */
1168 if (pcbBytesNeeded
!= 0)
1170 DPRINT("Service has running dependencies. Failed to stop service.\n");
1171 return ERROR_DEPENDENT_SERVICES_RUNNING
;
1175 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1177 /* Send control code to the driver */
1178 dwError
= ScmControlDriver(lpService
,
1184 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
1185 dwCurrentState
= lpService
->Status
.dwCurrentState
;
1187 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1188 if (lpService
->lpImage
== NULL
|| dwCurrentState
== SERVICE_STOPPED
)
1189 return ERROR_SERVICE_NOT_ACTIVE
;
1191 /* Check the current state before sending a control request */
1192 switch (dwCurrentState
)
1194 case SERVICE_STOP_PENDING
:
1195 case SERVICE_STOPPED
:
1196 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1198 case SERVICE_START_PENDING
:
1201 case SERVICE_CONTROL_STOP
:
1204 case SERVICE_CONTROL_INTERROGATE
:
1205 RtlCopyMemory(lpServiceStatus
,
1207 sizeof(SERVICE_STATUS
));
1208 return ERROR_SUCCESS
;
1211 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1216 /* Check if the control code is acceptable to the service */
1219 case SERVICE_CONTROL_STOP
:
1220 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
1221 return ERROR_INVALID_SERVICE_CONTROL
;
1224 case SERVICE_CONTROL_PAUSE
:
1225 case SERVICE_CONTROL_CONTINUE
:
1226 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
1227 return ERROR_INVALID_SERVICE_CONTROL
;
1231 /* Send control code to the service */
1232 dwError
= ScmControlService(lpService
,
1235 /* Return service status information */
1236 RtlCopyMemory(lpServiceStatus
,
1238 sizeof(SERVICE_STATUS
));
1246 DWORD
RDeleteService(
1247 SC_RPC_HANDLE hService
)
1249 PSERVICE_HANDLE hSvc
;
1253 DPRINT("RDeleteService() called\n");
1256 return ERROR_SHUTDOWN_IN_PROGRESS
;
1258 hSvc
= ScmGetServiceFromHandle(hService
);
1261 DPRINT1("Invalid service handle!\n");
1262 return ERROR_INVALID_HANDLE
;
1265 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1267 return ERROR_ACCESS_DENIED
;
1269 lpService
= hSvc
->ServiceEntry
;
1270 if (lpService
== NULL
)
1272 DPRINT("lpService == NULL!\n");
1273 return ERROR_INVALID_HANDLE
;
1276 /* Lock the service database exclusively */
1277 ScmLockDatabaseExclusive();
1279 if (lpService
->bDeleted
)
1281 DPRINT("The service has already been marked for delete!\n");
1282 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1286 /* Mark service for delete */
1287 lpService
->bDeleted
= TRUE
;
1289 dwError
= ScmMarkServiceForDelete(lpService
);
1292 /* Unlock the service database */
1293 ScmUnlockDatabase();
1295 DPRINT("RDeleteService() done\n");
1302 DWORD
RLockServiceDatabase(
1303 SC_RPC_HANDLE hSCManager
,
1304 LPSC_RPC_LOCK lpLock
)
1306 PMANAGER_HANDLE hMgr
;
1308 DPRINT("RLockServiceDatabase() called\n");
1312 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
1315 DPRINT1("Invalid service manager handle!\n");
1316 return ERROR_INVALID_HANDLE
;
1319 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
1321 return ERROR_ACCESS_DENIED
;
1323 // return ScmLockDatabase(0, hMgr->0xC, hLock);
1325 /* FIXME: Lock the database */
1326 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
1328 return ERROR_SUCCESS
;
1333 DWORD
RQueryServiceObjectSecurity(
1334 SC_RPC_HANDLE hService
,
1335 SECURITY_INFORMATION dwSecurityInformation
,
1336 LPBYTE lpSecurityDescriptor
,
1338 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1340 PSERVICE_HANDLE hSvc
;
1342 ULONG DesiredAccess
= 0;
1344 DWORD dwBytesNeeded
;
1348 SECURITY_DESCRIPTOR ObjectDescriptor
;
1350 DPRINT("RQueryServiceObjectSecurity() called\n");
1352 hSvc
= ScmGetServiceFromHandle(hService
);
1355 DPRINT1("Invalid service handle!\n");
1356 return ERROR_INVALID_HANDLE
;
1359 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1360 GROUP_SECURITY_INFORMATION
|
1361 OWNER_SECURITY_INFORMATION
))
1362 DesiredAccess
|= READ_CONTROL
;
1364 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1365 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1367 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1370 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1371 return ERROR_ACCESS_DENIED
;
1374 lpService
= hSvc
->ServiceEntry
;
1375 if (lpService
== NULL
)
1377 DPRINT("lpService == NULL!\n");
1378 return ERROR_INVALID_HANDLE
;
1381 /* Lock the service database */
1382 ScmLockDatabaseShared();
1386 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
1388 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
1389 dwSecurityInformation
,
1390 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1394 /* Unlock the service database */
1395 ScmUnlockDatabase();
1397 if (NT_SUCCESS(Status
))
1399 *pcbBytesNeeded
= dwBytesNeeded
;
1400 dwError
= STATUS_SUCCESS
;
1402 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1404 *pcbBytesNeeded
= dwBytesNeeded
;
1405 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1407 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1409 dwError
= ERROR_GEN_FAILURE
;
1413 dwError
= RtlNtStatusToDosError(Status
);
1421 DWORD
RSetServiceObjectSecurity(
1422 SC_RPC_HANDLE hService
,
1423 DWORD dwSecurityInformation
,
1424 LPBYTE lpSecurityDescriptor
,
1425 DWORD dwSecuityDescriptorSize
)
1427 PSERVICE_HANDLE hSvc
;
1429 ULONG DesiredAccess
= 0;
1430 /* HANDLE hToken = NULL; */
1432 /* NTSTATUS Status; */
1435 DPRINT("RSetServiceObjectSecurity() called\n");
1437 hSvc
= ScmGetServiceFromHandle(hService
);
1440 DPRINT1("Invalid service handle!\n");
1441 return ERROR_INVALID_HANDLE
;
1444 if (dwSecurityInformation
== 0 ||
1445 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1446 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1447 return ERROR_INVALID_PARAMETER
;
1449 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1450 return ERROR_INVALID_PARAMETER
;
1452 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1453 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1455 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1456 DesiredAccess
|= WRITE_DAC
;
1458 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1459 DesiredAccess
|= WRITE_OWNER
;
1461 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1462 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1463 return ERROR_INVALID_PARAMETER
;
1465 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1466 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1467 return ERROR_INVALID_PARAMETER
;
1469 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1472 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1473 return ERROR_ACCESS_DENIED
;
1476 lpService
= hSvc
->ServiceEntry
;
1477 if (lpService
== NULL
)
1479 DPRINT("lpService == NULL!\n");
1480 return ERROR_INVALID_HANDLE
;
1483 if (lpService
->bDeleted
)
1484 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1487 RpcImpersonateClient(NULL
);
1489 Status
= NtOpenThreadToken(NtCurrentThread(),
1493 if (!NT_SUCCESS(Status
))
1494 return RtlNtStatusToDosError(Status
);
1499 /* Lock the service database exclusive */
1500 ScmLockDatabaseExclusive();
1503 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1504 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1505 &lpService
->lpSecurityDescriptor
,
1508 if (!NT_SUCCESS(Status
))
1510 dwError
= RtlNtStatusToDosError(Status
);
1515 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1516 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1518 if (dwError
!= ERROR_SUCCESS
)
1522 dwError
= ERROR_SUCCESS
;
1523 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1524 // lpService->lpSecurityDescriptor);
1526 RegFlushKey(hServiceKey
);
1527 RegCloseKey(hServiceKey
);
1536 /* Unlock service database */
1537 ScmUnlockDatabase();
1539 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1546 DWORD
RQueryServiceStatus(
1547 SC_RPC_HANDLE hService
,
1548 LPSERVICE_STATUS lpServiceStatus
)
1550 PSERVICE_HANDLE hSvc
;
1553 DPRINT("RQueryServiceStatus() called\n");
1556 return ERROR_SHUTDOWN_IN_PROGRESS
;
1558 hSvc
= ScmGetServiceFromHandle(hService
);
1561 DPRINT1("Invalid service handle!\n");
1562 return ERROR_INVALID_HANDLE
;
1565 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1566 SERVICE_QUERY_STATUS
))
1568 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1569 return ERROR_ACCESS_DENIED
;
1572 lpService
= hSvc
->ServiceEntry
;
1573 if (lpService
== NULL
)
1575 DPRINT("lpService == NULL!\n");
1576 return ERROR_INVALID_HANDLE
;
1579 /* Lock the service database shared */
1580 ScmLockDatabaseShared();
1582 /* Return service status information */
1583 RtlCopyMemory(lpServiceStatus
,
1585 sizeof(SERVICE_STATUS
));
1587 /* Unlock the service database */
1588 ScmUnlockDatabase();
1590 return ERROR_SUCCESS
;
1595 ScmIsValidServiceState(DWORD dwCurrentState
)
1597 switch (dwCurrentState
)
1599 case SERVICE_STOPPED
:
1600 case SERVICE_START_PENDING
:
1601 case SERVICE_STOP_PENDING
:
1602 case SERVICE_RUNNING
:
1603 case SERVICE_CONTINUE_PENDING
:
1604 case SERVICE_PAUSE_PENDING
:
1605 case SERVICE_PAUSED
:
1615 DWORD
RSetServiceStatus(
1616 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1617 LPSERVICE_STATUS lpServiceStatus
)
1620 DWORD dwPreviousState
;
1621 LPCWSTR lpErrorStrings
[2];
1622 WCHAR szErrorBuffer
[32];
1624 DPRINT("RSetServiceStatus() called\n");
1625 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1626 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1627 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1628 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1629 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1630 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1631 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1632 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1634 if (hServiceStatus
== 0)
1636 DPRINT("hServiceStatus == NULL!\n");
1637 return ERROR_INVALID_HANDLE
;
1640 lpService
= (PSERVICE
)hServiceStatus
;
1641 if (lpService
== NULL
)
1643 DPRINT("lpService == NULL!\n");
1644 return ERROR_INVALID_HANDLE
;
1647 /* Check current state */
1648 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1650 DPRINT("Invalid service state!\n");
1651 return ERROR_INVALID_DATA
;
1654 /* Check service type */
1655 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1656 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1658 DPRINT("Invalid service type!\n");
1659 return ERROR_INVALID_DATA
;
1662 /* Check accepted controls */
1663 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1665 DPRINT("Invalid controls accepted!\n");
1666 return ERROR_INVALID_DATA
;
1669 /* Lock the service database exclusively */
1670 ScmLockDatabaseExclusive();
1672 /* Save the current service state */
1673 dwPreviousState
= lpService
->Status
.dwCurrentState
;
1675 RtlCopyMemory(&lpService
->Status
,
1677 sizeof(SERVICE_STATUS
));
1679 /* Unlock the service database */
1680 ScmUnlockDatabase();
1682 /* Log a failed service stop */
1683 if ((lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
) &&
1684 (dwPreviousState
!= SERVICE_STOPPED
))
1686 if (lpServiceStatus
->dwWin32ExitCode
!= ERROR_SUCCESS
)
1688 swprintf(szErrorBuffer
, L
"%lu", lpServiceStatus
->dwWin32ExitCode
);
1689 lpErrorStrings
[0] = lpService
->lpDisplayName
;
1690 lpErrorStrings
[1] = szErrorBuffer
;
1692 ScmLogError(EVENT_SERVICE_EXIT_FAILED
,
1698 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1699 DPRINT("RSetServiceStatus() done\n");
1701 return ERROR_SUCCESS
;
1706 DWORD
RUnlockServiceDatabase(
1710 return ERROR_SUCCESS
;
1715 DWORD
RNotifyBootConfigStatus(
1716 SVCCTL_HANDLEW lpMachineName
,
1717 DWORD BootAcceptable
)
1719 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1720 return ERROR_SUCCESS
;
1723 // return ERROR_CALL_NOT_IMPLEMENTED;
1728 DWORD
RI_ScSetServiceBitsW(
1729 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1730 DWORD dwServiceBits
,
1732 int bUpdateImmediately
,
1736 return ERROR_CALL_NOT_IMPLEMENTED
;
1741 DWORD
RChangeServiceConfigW(
1742 SC_RPC_HANDLE hService
,
1743 DWORD dwServiceType
,
1745 DWORD dwErrorControl
,
1746 LPWSTR lpBinaryPathName
,
1747 LPWSTR lpLoadOrderGroup
,
1749 LPBYTE lpDependencies
,
1751 LPWSTR lpServiceStartName
,
1754 LPWSTR lpDisplayName
)
1756 DWORD dwError
= ERROR_SUCCESS
;
1757 PSERVICE_HANDLE hSvc
;
1758 PSERVICE lpService
= NULL
;
1759 HKEY hServiceKey
= NULL
;
1760 LPWSTR lpDisplayNameW
= NULL
;
1761 LPWSTR lpImagePathW
= NULL
;
1763 DPRINT("RChangeServiceConfigW() called\n");
1764 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1765 DPRINT("dwStartType = %lu\n", dwStartType
);
1766 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1767 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1768 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1769 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1772 return ERROR_SHUTDOWN_IN_PROGRESS
;
1774 hSvc
= ScmGetServiceFromHandle(hService
);
1777 DPRINT1("Invalid service handle!\n");
1778 return ERROR_INVALID_HANDLE
;
1781 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1782 SERVICE_CHANGE_CONFIG
))
1784 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1785 return ERROR_ACCESS_DENIED
;
1788 lpService
= hSvc
->ServiceEntry
;
1789 if (lpService
== NULL
)
1791 DPRINT("lpService == NULL!\n");
1792 return ERROR_INVALID_HANDLE
;
1795 /* Lock the service database exclusively */
1796 ScmLockDatabaseExclusive();
1798 if (lpService
->bDeleted
)
1800 DPRINT("The service has already been marked for delete!\n");
1801 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1805 /* Open the service key */
1806 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1809 if (dwError
!= ERROR_SUCCESS
)
1812 /* Write service data to the registry */
1813 /* Set the display name */
1814 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1816 RegSetValueExW(hServiceKey
,
1820 (LPBYTE
)lpDisplayName
,
1821 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1823 /* Update the display name */
1824 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
1826 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1827 if (lpDisplayNameW
== NULL
)
1829 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1833 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1834 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1836 lpService
->lpDisplayName
= lpDisplayNameW
;
1839 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1841 /* Set the service type */
1842 dwError
= RegSetValueExW(hServiceKey
,
1846 (LPBYTE
)&dwServiceType
,
1848 if (dwError
!= ERROR_SUCCESS
)
1851 lpService
->Status
.dwServiceType
= dwServiceType
;
1854 if (dwStartType
!= SERVICE_NO_CHANGE
)
1856 /* Set the start value */
1857 dwError
= RegSetValueExW(hServiceKey
,
1861 (LPBYTE
)&dwStartType
,
1863 if (dwError
!= ERROR_SUCCESS
)
1866 lpService
->dwStartType
= dwStartType
;
1869 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1871 /* Set the error control value */
1872 dwError
= RegSetValueExW(hServiceKey
,
1876 (LPBYTE
)&dwErrorControl
,
1878 if (dwError
!= ERROR_SUCCESS
)
1881 lpService
->dwErrorControl
= dwErrorControl
;
1884 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1886 /* Set the image path */
1887 lpImagePathW
= lpBinaryPathName
;
1889 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1891 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
1895 if (dwError
!= ERROR_SUCCESS
)
1899 dwError
= RegSetValueExW(hServiceKey
,
1903 (LPBYTE
)lpImagePathW
,
1904 (wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
));
1906 if (lpImagePathW
!= lpBinaryPathName
)
1907 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
1909 if (dwError
!= ERROR_SUCCESS
)
1913 /* Set the group name */
1914 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1916 dwError
= RegSetValueExW(hServiceKey
,
1920 (LPBYTE
)lpLoadOrderGroup
,
1921 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1922 if (dwError
!= ERROR_SUCCESS
)
1925 dwError
= ScmSetServiceGroup(lpService
,
1927 if (dwError
!= ERROR_SUCCESS
)
1931 if (lpdwTagId
!= NULL
)
1933 dwError
= ScmAssignNewTag(lpService
);
1934 if (dwError
!= ERROR_SUCCESS
)
1937 dwError
= RegSetValueExW(hServiceKey
,
1941 (LPBYTE
)&lpService
->dwTag
,
1943 if (dwError
!= ERROR_SUCCESS
)
1946 *lpdwTagId
= lpService
->dwTag
;
1949 /* Write dependencies */
1950 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1952 dwError
= ScmWriteDependencies(hServiceKey
,
1953 (LPWSTR
)lpDependencies
,
1955 if (dwError
!= ERROR_SUCCESS
)
1959 if (lpPassword
!= NULL
)
1961 /* FIXME: Write password */
1965 if (hServiceKey
!= NULL
)
1966 RegCloseKey(hServiceKey
);
1968 /* Unlock the service database */
1969 ScmUnlockDatabase();
1971 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1978 DWORD
RCreateServiceW(
1979 SC_RPC_HANDLE hSCManager
,
1980 LPCWSTR lpServiceName
,
1981 LPCWSTR lpDisplayName
,
1982 DWORD dwDesiredAccess
,
1983 DWORD dwServiceType
,
1985 DWORD dwErrorControl
,
1986 LPCWSTR lpBinaryPathName
,
1987 LPCWSTR lpLoadOrderGroup
,
1989 LPBYTE lpDependencies
,
1991 LPCWSTR lpServiceStartName
,
1994 LPSC_RPC_HANDLE lpServiceHandle
)
1996 PMANAGER_HANDLE hManager
;
1997 DWORD dwError
= ERROR_SUCCESS
;
1998 PSERVICE lpService
= NULL
;
1999 SC_HANDLE hServiceHandle
= NULL
;
2000 LPWSTR lpImagePath
= NULL
;
2001 HKEY hServiceKey
= NULL
;
2002 LPWSTR lpObjectName
;
2004 DPRINT("RCreateServiceW() called\n");
2005 DPRINT("lpServiceName = %S\n", lpServiceName
);
2006 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
2007 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
2008 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2009 DPRINT("dwStartType = %lu\n", dwStartType
);
2010 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2011 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
2012 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
2013 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
2016 return ERROR_SHUTDOWN_IN_PROGRESS
;
2018 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2019 if (hManager
== NULL
)
2021 DPRINT1("Invalid service manager handle!\n");
2022 return ERROR_INVALID_HANDLE
;
2025 /* Check access rights */
2026 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2027 SC_MANAGER_CREATE_SERVICE
))
2029 DPRINT("Insufficient access rights! 0x%lx\n",
2030 hManager
->Handle
.DesiredAccess
);
2031 return ERROR_ACCESS_DENIED
;
2034 if (wcslen(lpServiceName
) == 0)
2036 return ERROR_INVALID_NAME
;
2039 if (wcslen(lpBinaryPathName
) == 0)
2041 return ERROR_INVALID_PARAMETER
;
2044 /* Check for invalid service type value */
2045 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2046 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2047 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2048 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2049 return ERROR_INVALID_PARAMETER
;
2051 /* Check for invalid start type value */
2052 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2053 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2054 (dwStartType
!= SERVICE_AUTO_START
) &&
2055 (dwStartType
!= SERVICE_DEMAND_START
) &&
2056 (dwStartType
!= SERVICE_DISABLED
))
2057 return ERROR_INVALID_PARAMETER
;
2059 /* Only drivers can be boot start or system start services */
2060 if ((dwStartType
== SERVICE_BOOT_START
) ||
2061 (dwStartType
== SERVICE_SYSTEM_START
))
2063 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2064 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2065 return ERROR_INVALID_PARAMETER
;
2068 /* Check for invalid error control value */
2069 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2070 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2071 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2072 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2073 return ERROR_INVALID_PARAMETER
;
2075 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2076 (lpServiceStartName
))
2078 return ERROR_INVALID_PARAMETER
;
2081 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2083 return ERROR_INVALID_PARAMETER
;
2086 /* Lock the service database exclusively */
2087 ScmLockDatabaseExclusive();
2089 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2092 /* Unlock the service database */
2093 ScmUnlockDatabase();
2095 /* Check if it is marked for deletion */
2096 if (lpService
->bDeleted
)
2097 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2099 /* Return Error exist */
2100 return ERROR_SERVICE_EXISTS
;
2103 if (lpDisplayName
!= NULL
&&
2104 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2106 /* Unlock the service database */
2107 ScmUnlockDatabase();
2109 return ERROR_DUPLICATE_SERVICE_NAME
;
2112 if (dwServiceType
& SERVICE_DRIVER
)
2114 dwError
= ScmCanonDriverImagePath(dwStartType
,
2117 if (dwError
!= ERROR_SUCCESS
)
2122 if (dwStartType
== SERVICE_BOOT_START
||
2123 dwStartType
== SERVICE_SYSTEM_START
)
2125 /* Unlock the service database */
2126 ScmUnlockDatabase();
2128 return ERROR_INVALID_PARAMETER
;
2132 /* Allocate a new service entry */
2133 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2135 if (dwError
!= ERROR_SUCCESS
)
2138 /* Fill the new service entry */
2139 lpService
->Status
.dwServiceType
= dwServiceType
;
2140 lpService
->dwStartType
= dwStartType
;
2141 lpService
->dwErrorControl
= dwErrorControl
;
2143 /* Fill the display name */
2144 if (lpDisplayName
!= NULL
&&
2145 *lpDisplayName
!= 0 &&
2146 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2148 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(), 0,
2149 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2150 if (lpService
->lpDisplayName
== NULL
)
2152 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2155 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2158 /* Assign the service to a group */
2159 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2161 dwError
= ScmSetServiceGroup(lpService
,
2163 if (dwError
!= ERROR_SUCCESS
)
2167 /* Assign a new tag */
2168 if (lpdwTagId
!= NULL
)
2170 dwError
= ScmAssignNewTag(lpService
);
2171 if (dwError
!= ERROR_SUCCESS
)
2175 /* Write service data to the registry */
2176 /* Create the service key */
2177 dwError
= ScmCreateServiceKey(lpServiceName
,
2180 if (dwError
!= ERROR_SUCCESS
)
2183 /* Set the display name */
2184 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2186 RegSetValueExW(hServiceKey
,
2190 (LPBYTE
)lpDisplayName
,
2191 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2194 /* Set the service type */
2195 dwError
= RegSetValueExW(hServiceKey
,
2199 (LPBYTE
)&dwServiceType
,
2201 if (dwError
!= ERROR_SUCCESS
)
2204 /* Set the start value */
2205 dwError
= RegSetValueExW(hServiceKey
,
2209 (LPBYTE
)&dwStartType
,
2211 if (dwError
!= ERROR_SUCCESS
)
2214 /* Set the error control value */
2215 dwError
= RegSetValueExW(hServiceKey
,
2219 (LPBYTE
)&dwErrorControl
,
2221 if (dwError
!= ERROR_SUCCESS
)
2224 /* Set the image path */
2225 if (dwServiceType
& SERVICE_WIN32
)
2227 dwError
= RegSetValueExW(hServiceKey
,
2231 (LPBYTE
)lpBinaryPathName
,
2232 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2233 if (dwError
!= ERROR_SUCCESS
)
2236 else if (dwServiceType
& SERVICE_DRIVER
)
2238 dwError
= RegSetValueExW(hServiceKey
,
2242 (LPBYTE
)lpImagePath
,
2243 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2244 if (dwError
!= ERROR_SUCCESS
)
2248 /* Set the group name */
2249 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2251 dwError
= RegSetValueExW(hServiceKey
,
2255 (LPBYTE
)lpLoadOrderGroup
,
2256 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2257 if (dwError
!= ERROR_SUCCESS
)
2261 if (lpdwTagId
!= NULL
)
2263 dwError
= RegSetValueExW(hServiceKey
,
2267 (LPBYTE
)&lpService
->dwTag
,
2269 if (dwError
!= ERROR_SUCCESS
)
2273 /* Write dependencies */
2274 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2276 dwError
= ScmWriteDependencies(hServiceKey
,
2277 (LPCWSTR
)lpDependencies
,
2279 if (dwError
!= ERROR_SUCCESS
)
2283 /* Write service start name */
2284 if (dwServiceType
& SERVICE_WIN32
)
2286 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2287 dwError
= RegSetValueExW(hServiceKey
,
2291 (LPBYTE
)lpObjectName
,
2292 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2293 if (dwError
!= ERROR_SUCCESS
)
2297 if (lpPassword
!= NULL
)
2299 /* FIXME: Write password */
2302 dwError
= ScmCreateServiceHandle(lpService
,
2304 if (dwError
!= ERROR_SUCCESS
)
2307 dwError
= ScmCheckAccess(hServiceHandle
,
2309 if (dwError
!= ERROR_SUCCESS
)
2312 lpService
->dwRefCount
= 1;
2313 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2316 /* Unlock the service database */
2317 ScmUnlockDatabase();
2319 if (hServiceKey
!= NULL
)
2320 RegCloseKey(hServiceKey
);
2322 if (dwError
== ERROR_SUCCESS
)
2324 DPRINT("hService %p\n", hServiceHandle
);
2325 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2327 if (lpdwTagId
!= NULL
)
2328 *lpdwTagId
= lpService
->dwTag
;
2332 if (lpService
!= NULL
&&
2333 lpService
->lpServiceName
!= NULL
)
2335 /* Release the display name buffer */
2336 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2341 /* Remove the service handle */
2342 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2345 if (lpService
!= NULL
)
2347 /* FIXME: remove the service entry */
2351 if (lpImagePath
!= NULL
)
2352 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2354 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2361 DWORD
REnumDependentServicesW(
2362 SC_RPC_HANDLE hService
,
2363 DWORD dwServiceState
,
2366 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2367 LPBOUNDED_DWORD_256K lpServicesReturned
)
2369 DWORD dwError
= ERROR_SUCCESS
;
2370 DWORD dwServicesReturned
= 0;
2371 DWORD dwServiceCount
;
2372 HKEY hServicesKey
= NULL
;
2373 PSERVICE_HANDLE hSvc
;
2374 PSERVICE lpService
= NULL
;
2375 PSERVICE
*lpServicesArray
= NULL
;
2376 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2379 *pcbBytesNeeded
= 0;
2380 *lpServicesReturned
= 0;
2382 DPRINT("REnumDependentServicesW() called\n");
2384 hSvc
= ScmGetServiceFromHandle(hService
);
2387 DPRINT1("Invalid service handle!\n");
2388 return ERROR_INVALID_HANDLE
;
2391 lpService
= hSvc
->ServiceEntry
;
2393 /* Check access rights */
2394 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2395 SC_MANAGER_ENUMERATE_SERVICE
))
2397 DPRINT("Insufficient access rights! 0x%lx\n",
2398 hSvc
->Handle
.DesiredAccess
);
2399 return ERROR_ACCESS_DENIED
;
2402 /* Open the Services Reg key */
2403 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2404 L
"System\\CurrentControlSet\\Services",
2408 if (dwError
!= ERROR_SUCCESS
)
2411 /* First determine the bytes needed and get the number of dependent services */
2412 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2417 &dwServicesReturned
);
2418 if (dwError
!= ERROR_SUCCESS
)
2421 /* If buffer size is less than the bytes needed or pointer is null */
2422 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2424 dwError
= ERROR_MORE_DATA
;
2428 /* Allocate memory for array of service pointers */
2429 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2431 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2432 if (!lpServicesArray
)
2434 DPRINT1("Could not allocate a buffer!!\n");
2435 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2439 dwServicesReturned
= 0;
2440 *pcbBytesNeeded
= 0;
2442 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2447 &dwServicesReturned
);
2448 if (dwError
!= ERROR_SUCCESS
)
2453 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2454 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2456 /* Copy EnumDepenedentService to Buffer */
2457 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2459 lpService
= lpServicesArray
[dwServiceCount
];
2461 /* Copy status info */
2462 memcpy(&lpServicesPtr
->ServiceStatus
,
2464 sizeof(SERVICE_STATUS
));
2466 /* Copy display name */
2467 wcscpy(lpStr
, lpService
->lpDisplayName
);
2468 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2469 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2471 /* Copy service name */
2472 wcscpy(lpStr
, lpService
->lpServiceName
);
2473 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2474 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2479 *lpServicesReturned
= dwServicesReturned
;
2482 if (lpServicesArray
!= NULL
)
2483 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2485 RegCloseKey(hServicesKey
);
2487 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2494 DWORD
REnumServicesStatusW(
2495 SC_RPC_HANDLE hSCManager
,
2496 DWORD dwServiceType
,
2497 DWORD dwServiceState
,
2500 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2501 LPBOUNDED_DWORD_256K lpServicesReturned
,
2502 LPBOUNDED_DWORD_256K lpResumeHandle
)
2504 /* Enumerate all the services, not regarding of their group */
2505 return REnumServiceGroupW(hSCManager
,
2518 DWORD
ROpenSCManagerW(
2519 LPWSTR lpMachineName
,
2520 LPWSTR lpDatabaseName
,
2521 DWORD dwDesiredAccess
,
2522 LPSC_RPC_HANDLE lpScHandle
)
2527 DPRINT("ROpenSCManagerW() called\n");
2528 DPRINT("lpMachineName = %p\n", lpMachineName
);
2529 DPRINT("lpMachineName: %S\n", lpMachineName
);
2530 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2531 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2532 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2535 return ERROR_SHUTDOWN_IN_PROGRESS
;
2538 return ERROR_INVALID_PARAMETER
;
2540 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2542 if (dwError
!= ERROR_SUCCESS
)
2544 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2548 /* Check the desired access */
2549 dwError
= ScmCheckAccess(hHandle
,
2550 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2551 if (dwError
!= ERROR_SUCCESS
)
2553 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2554 HeapFree(GetProcessHeap(), 0, hHandle
);
2558 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2559 DPRINT("*hScm = %p\n", *lpScHandle
);
2561 DPRINT("ROpenSCManagerW() done\n");
2563 return ERROR_SUCCESS
;
2568 DWORD
ROpenServiceW(
2569 SC_RPC_HANDLE hSCManager
,
2570 LPWSTR lpServiceName
,
2571 DWORD dwDesiredAccess
,
2572 LPSC_RPC_HANDLE lpServiceHandle
)
2575 PMANAGER_HANDLE hManager
;
2577 DWORD dwError
= ERROR_SUCCESS
;
2579 DPRINT("ROpenServiceW() called\n");
2580 DPRINT("hSCManager = %p\n", hSCManager
);
2581 DPRINT("lpServiceName = %p\n", lpServiceName
);
2582 DPRINT("lpServiceName: %S\n", lpServiceName
);
2583 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2586 return ERROR_SHUTDOWN_IN_PROGRESS
;
2588 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2589 if (hManager
== NULL
)
2591 DPRINT1("Invalid service manager handle!\n");
2592 return ERROR_INVALID_HANDLE
;
2595 if (!lpServiceHandle
)
2596 return ERROR_INVALID_PARAMETER
;
2599 return ERROR_INVALID_ADDRESS
;
2601 /* Lock the service database exclusive */
2602 ScmLockDatabaseExclusive();
2604 /* Get service database entry */
2605 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2606 if (lpService
== NULL
)
2608 DPRINT("Could not find a service!\n");
2609 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2613 /* Create a service handle */
2614 dwError
= ScmCreateServiceHandle(lpService
,
2616 if (dwError
!= ERROR_SUCCESS
)
2618 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2622 /* Check the desired access */
2623 dwError
= ScmCheckAccess(hHandle
,
2625 if (dwError
!= ERROR_SUCCESS
)
2627 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2628 HeapFree(GetProcessHeap(), 0, hHandle
);
2632 lpService
->dwRefCount
++;
2633 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2635 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2636 DPRINT("*hService = %p\n", *lpServiceHandle
);
2639 /* Unlock the service database */
2640 ScmUnlockDatabase();
2642 DPRINT("ROpenServiceW() done\n");
2649 DWORD
RQueryServiceConfigW(
2650 SC_RPC_HANDLE hService
,
2651 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2653 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2655 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2656 DWORD dwError
= ERROR_SUCCESS
;
2657 PSERVICE_HANDLE hSvc
;
2658 PSERVICE lpService
= NULL
;
2659 HKEY hServiceKey
= NULL
;
2660 LPWSTR lpImagePath
= NULL
;
2661 LPWSTR lpServiceStartName
= NULL
;
2662 LPWSTR lpDependencies
= NULL
;
2663 DWORD dwDependenciesLength
= 0;
2664 DWORD dwRequiredSize
;
2665 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2666 WCHAR lpEmptyString
[] = {0,0};
2669 DPRINT("RQueryServiceConfigW() called\n");
2672 return ERROR_SHUTDOWN_IN_PROGRESS
;
2674 hSvc
= ScmGetServiceFromHandle(hService
);
2677 DPRINT1("Invalid service handle!\n");
2678 return ERROR_INVALID_HANDLE
;
2681 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2682 SERVICE_QUERY_CONFIG
))
2684 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2685 return ERROR_ACCESS_DENIED
;
2688 lpService
= hSvc
->ServiceEntry
;
2689 if (lpService
== NULL
)
2691 DPRINT("lpService == NULL!\n");
2692 return ERROR_INVALID_HANDLE
;
2695 /* Lock the service database shared */
2696 ScmLockDatabaseShared();
2698 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2701 if (dwError
!= ERROR_SUCCESS
)
2704 /* Read the image path */
2705 dwError
= ScmReadString(hServiceKey
,
2708 if (dwError
!= ERROR_SUCCESS
)
2711 /* Read the service start name */
2712 ScmReadString(hServiceKey
,
2714 &lpServiceStartName
);
2716 /* Read the dependencies */
2717 ScmReadDependencies(hServiceKey
,
2719 &dwDependenciesLength
);
2721 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2723 if (lpImagePath
!= NULL
)
2724 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2726 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2728 if (lpService
->lpGroup
!= NULL
)
2729 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2731 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2733 if (lpDependencies
!= NULL
)
2734 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2736 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2738 if (lpServiceStartName
!= NULL
)
2739 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2741 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2743 if (lpService
->lpDisplayName
!= NULL
)
2744 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2746 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2748 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2750 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2754 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2755 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2756 lpConfig
->dwStartType
= lpService
->dwStartType
;
2757 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2758 lpConfig
->dwTagId
= lpService
->dwTag
;
2760 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2762 /* Append the image path */
2763 if (lpImagePath
!= NULL
)
2765 wcscpy(lpStr
, lpImagePath
);
2769 wcscpy(lpStr
, lpEmptyString
);
2772 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2773 lpStr
+= (wcslen(lpStr
) + 1);
2775 /* Append the group name */
2776 if (lpService
->lpGroup
!= NULL
)
2778 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2782 wcscpy(lpStr
, lpEmptyString
);
2785 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2786 lpStr
+= (wcslen(lpStr
) + 1);
2788 /* Append Dependencies */
2789 if (lpDependencies
!= NULL
)
2793 dwDependenciesLength
* sizeof(WCHAR
));
2797 wcscpy(lpStr
, lpEmptyString
);
2800 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2801 if (lpDependencies
!= NULL
)
2802 lpStr
+= dwDependenciesLength
;
2804 lpStr
+= (wcslen(lpStr
) + 1);
2806 /* Append the service start name */
2807 if (lpServiceStartName
!= NULL
)
2809 wcscpy(lpStr
, lpServiceStartName
);
2813 wcscpy(lpStr
, lpEmptyString
);
2816 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2817 lpStr
+= (wcslen(lpStr
) + 1);
2819 /* Append the display name */
2820 if (lpService
->lpDisplayName
!= NULL
)
2822 wcscpy(lpStr
, lpService
->lpDisplayName
);
2826 wcscpy(lpStr
, lpEmptyString
);
2829 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2832 if (pcbBytesNeeded
!= NULL
)
2833 *pcbBytesNeeded
= dwRequiredSize
;
2836 /* Unlock the service database */
2837 ScmUnlockDatabase();
2839 if (lpImagePath
!= NULL
)
2840 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2842 if (lpServiceStartName
!= NULL
)
2843 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2845 if (lpDependencies
!= NULL
)
2846 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2848 if (hServiceKey
!= NULL
)
2849 RegCloseKey(hServiceKey
);
2851 DPRINT("RQueryServiceConfigW() done\n");
2858 DWORD
RQueryServiceLockStatusW(
2859 SC_RPC_HANDLE hSCManager
,
2860 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2862 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2865 return ERROR_CALL_NOT_IMPLEMENTED
;
2870 DWORD
RStartServiceW(
2871 SC_RPC_HANDLE hService
,
2873 LPSTRING_PTRSW argv
)
2875 DWORD dwError
= ERROR_SUCCESS
;
2876 PSERVICE_HANDLE hSvc
;
2877 PSERVICE lpService
= NULL
;
2880 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
2881 DPRINT(" argc: %lu\n", argc
);
2884 for (i
= 0; i
< argc
; i
++)
2886 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
]);
2891 return ERROR_SHUTDOWN_IN_PROGRESS
;
2893 hSvc
= ScmGetServiceFromHandle(hService
);
2896 DPRINT1("Invalid service handle!\n");
2897 return ERROR_INVALID_HANDLE
;
2900 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2903 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2904 return ERROR_ACCESS_DENIED
;
2907 lpService
= hSvc
->ServiceEntry
;
2908 if (lpService
== NULL
)
2910 DPRINT("lpService == NULL!\n");
2911 return ERROR_INVALID_HANDLE
;
2914 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2915 return ERROR_SERVICE_DISABLED
;
2917 if (lpService
->bDeleted
)
2918 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2920 /* Start the service */
2921 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2928 DWORD
RGetServiceDisplayNameW(
2929 SC_RPC_HANDLE hSCManager
,
2930 LPCWSTR lpServiceName
,
2931 LPWSTR lpDisplayName
,
2934 // PMANAGER_HANDLE hManager;
2939 DPRINT("RGetServiceDisplayNameW() called\n");
2940 DPRINT("hSCManager = %p\n", hSCManager
);
2941 DPRINT("lpServiceName: %S\n", lpServiceName
);
2942 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2943 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2945 // hManager = (PMANAGER_HANDLE)hSCManager;
2946 // if (hManager->Handle.Tag != MANAGER_TAG)
2948 // DPRINT("Invalid manager handle!\n");
2949 // return ERROR_INVALID_HANDLE;
2952 /* Get service database entry */
2953 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2954 if (lpService
== NULL
)
2956 DPRINT("Could not find a service!\n");
2958 /* If the service could not be found and lpcchBuffer is less than 2, windows
2959 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2960 if (*lpcchBuffer
< 2)
2963 if (lpDisplayName
!= NULL
)
2965 *lpDisplayName
= '\0';
2969 return ERROR_SERVICE_DOES_NOT_EXIST
;
2972 if (!lpService
->lpDisplayName
)
2974 dwLength
= wcslen(lpService
->lpServiceName
);
2976 if (lpDisplayName
!= NULL
&&
2977 *lpcchBuffer
> dwLength
)
2979 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2984 dwLength
= wcslen(lpService
->lpDisplayName
);
2986 if (lpDisplayName
!= NULL
&&
2987 *lpcchBuffer
> dwLength
)
2989 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2993 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2995 *lpcchBuffer
= dwLength
;
3002 DWORD
RGetServiceKeyNameW(
3003 SC_RPC_HANDLE hSCManager
,
3004 LPCWSTR lpDisplayName
,
3005 LPWSTR lpServiceName
,
3008 // PMANAGER_HANDLE hManager;
3013 DPRINT("RGetServiceKeyNameW() called\n");
3014 DPRINT("hSCManager = %p\n", hSCManager
);
3015 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3016 DPRINT("lpServiceName: %p\n", lpServiceName
);
3017 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3019 // hManager = (PMANAGER_HANDLE)hSCManager;
3020 // if (hManager->Handle.Tag != MANAGER_TAG)
3022 // DPRINT("Invalid manager handle!\n");
3023 // return ERROR_INVALID_HANDLE;
3026 /* Get service database entry */
3027 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3028 if (lpService
== NULL
)
3030 DPRINT("Could not find a service!\n");
3032 /* If the service could not be found and lpcchBuffer is less than 2, windows
3033 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3034 if (*lpcchBuffer
< 2)
3037 if (lpServiceName
!= NULL
)
3039 *lpServiceName
= '\0';
3043 return ERROR_SERVICE_DOES_NOT_EXIST
;
3046 dwLength
= wcslen(lpService
->lpServiceName
);
3048 if (lpServiceName
!= NULL
&&
3049 *lpcchBuffer
> dwLength
)
3051 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3052 *lpcchBuffer
= dwLength
;
3053 return ERROR_SUCCESS
;
3056 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3058 *lpcchBuffer
= dwLength
;
3065 DWORD
RI_ScSetServiceBitsA(
3066 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3067 DWORD dwServiceBits
,
3069 int bUpdateImmediately
,
3073 return ERROR_CALL_NOT_IMPLEMENTED
;
3078 DWORD
RChangeServiceConfigA(
3079 SC_RPC_HANDLE hService
,
3080 DWORD dwServiceType
,
3082 DWORD dwErrorControl
,
3083 LPSTR lpBinaryPathName
,
3084 LPSTR lpLoadOrderGroup
,
3086 LPSTR lpDependencies
,
3088 LPSTR lpServiceStartName
,
3091 LPSTR lpDisplayName
)
3093 DWORD dwError
= ERROR_SUCCESS
;
3094 PSERVICE_HANDLE hSvc
;
3095 PSERVICE lpService
= NULL
;
3096 HKEY hServiceKey
= NULL
;
3097 LPWSTR lpDisplayNameW
= NULL
;
3098 LPWSTR lpBinaryPathNameW
= NULL
;
3099 LPWSTR lpCanonicalImagePathW
= NULL
;
3100 LPWSTR lpLoadOrderGroupW
= NULL
;
3101 LPWSTR lpDependenciesW
= NULL
;
3102 // LPWSTR lpPasswordW = NULL;
3104 DPRINT("RChangeServiceConfigA() called\n");
3105 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3106 DPRINT("dwStartType = %lu\n", dwStartType
);
3107 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3108 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3109 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3110 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3113 return ERROR_SHUTDOWN_IN_PROGRESS
;
3115 hSvc
= ScmGetServiceFromHandle(hService
);
3118 DPRINT1("Invalid service handle!\n");
3119 return ERROR_INVALID_HANDLE
;
3122 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3123 SERVICE_CHANGE_CONFIG
))
3125 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3126 return ERROR_ACCESS_DENIED
;
3129 lpService
= hSvc
->ServiceEntry
;
3130 if (lpService
== NULL
)
3132 DPRINT("lpService == NULL!\n");
3133 return ERROR_INVALID_HANDLE
;
3136 /* Lock the service database exclusively */
3137 ScmLockDatabaseExclusive();
3139 if (lpService
->bDeleted
)
3141 DPRINT("The service has already been marked for delete!\n");
3142 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3146 /* Open the service key */
3147 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3150 if (dwError
!= ERROR_SUCCESS
)
3153 /* Write service data to the registry */
3155 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3157 /* Set the display name */
3158 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3160 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3161 if (lpDisplayNameW
== NULL
)
3163 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3167 MultiByteToWideChar(CP_ACP
,
3172 strlen(lpDisplayName
) + 1);
3174 RegSetValueExW(hServiceKey
,
3178 (LPBYTE
)lpDisplayNameW
,
3179 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3181 /* Update lpService->lpDisplayName */
3182 if (lpService
->lpDisplayName
)
3183 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3185 lpService
->lpDisplayName
= lpDisplayNameW
;
3188 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3190 /* Set the service type */
3191 dwError
= RegSetValueExW(hServiceKey
,
3195 (LPBYTE
)&dwServiceType
,
3197 if (dwError
!= ERROR_SUCCESS
)
3200 lpService
->Status
.dwServiceType
= dwServiceType
;
3203 if (dwStartType
!= SERVICE_NO_CHANGE
)
3205 /* Set the start value */
3206 dwError
= RegSetValueExW(hServiceKey
,
3210 (LPBYTE
)&dwStartType
,
3212 if (dwError
!= ERROR_SUCCESS
)
3215 lpService
->dwStartType
= dwStartType
;
3218 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3220 /* Set the error control value */
3221 dwError
= RegSetValueExW(hServiceKey
,
3225 (LPBYTE
)&dwErrorControl
,
3227 if (dwError
!= ERROR_SUCCESS
)
3230 lpService
->dwErrorControl
= dwErrorControl
;
3233 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3235 /* Set the image path */
3236 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(),
3238 (strlen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
3239 if (lpBinaryPathNameW
== NULL
)
3241 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3245 MultiByteToWideChar(CP_ACP
,
3250 strlen(lpBinaryPathName
) + 1);
3252 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
3254 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
3256 &lpCanonicalImagePathW
);
3258 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3260 if (dwError
!= ERROR_SUCCESS
)
3263 lpBinaryPathNameW
= lpCanonicalImagePathW
;
3266 dwError
= RegSetValueExW(hServiceKey
,
3270 (LPBYTE
)lpBinaryPathNameW
,
3271 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3273 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3275 if (dwError
!= ERROR_SUCCESS
)
3279 /* Set the group name */
3280 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3282 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3284 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3285 if (lpLoadOrderGroupW
== NULL
)
3287 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3291 MultiByteToWideChar(CP_ACP
,
3296 strlen(lpLoadOrderGroup
) + 1);
3298 dwError
= RegSetValueExW(hServiceKey
,
3302 (LPBYTE
)lpLoadOrderGroupW
,
3303 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3304 if (dwError
!= ERROR_SUCCESS
)
3306 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3310 dwError
= ScmSetServiceGroup(lpService
,
3313 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3315 if (dwError
!= ERROR_SUCCESS
)
3319 if (lpdwTagId
!= NULL
)
3321 dwError
= ScmAssignNewTag(lpService
);
3322 if (dwError
!= ERROR_SUCCESS
)
3325 dwError
= RegSetValueExW(hServiceKey
,
3329 (LPBYTE
)&lpService
->dwTag
,
3331 if (dwError
!= ERROR_SUCCESS
)
3334 *lpdwTagId
= lpService
->dwTag
;
3337 /* Write dependencies */
3338 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3340 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3342 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3343 if (lpDependenciesW
== NULL
)
3345 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3349 MultiByteToWideChar(CP_ACP
,
3354 strlen(lpDependencies
) + 1);
3356 dwError
= ScmWriteDependencies(hServiceKey
,
3357 (LPWSTR
)lpDependenciesW
,
3360 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3363 if (lpPassword
!= NULL
)
3365 /* FIXME: Write password */
3369 /* Unlock the service database */
3370 ScmUnlockDatabase();
3372 if (hServiceKey
!= NULL
)
3373 RegCloseKey(hServiceKey
);
3375 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3382 DWORD
RCreateServiceA(
3383 SC_RPC_HANDLE hSCManager
,
3384 LPSTR lpServiceName
,
3385 LPSTR lpDisplayName
,
3386 DWORD dwDesiredAccess
,
3387 DWORD dwServiceType
,
3389 DWORD dwErrorControl
,
3390 LPSTR lpBinaryPathName
,
3391 LPSTR lpLoadOrderGroup
,
3393 LPBYTE lpDependencies
,
3395 LPSTR lpServiceStartName
,
3398 LPSC_RPC_HANDLE lpServiceHandle
)
3400 DWORD dwError
= ERROR_SUCCESS
;
3401 LPWSTR lpServiceNameW
= NULL
;
3402 LPWSTR lpDisplayNameW
= NULL
;
3403 LPWSTR lpBinaryPathNameW
= NULL
;
3404 LPWSTR lpLoadOrderGroupW
= NULL
;
3405 LPWSTR lpDependenciesW
= NULL
;
3406 LPWSTR lpServiceStartNameW
= NULL
;
3407 DWORD dwDependenciesLength
= 0;
3414 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3415 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3416 if (!lpServiceNameW
)
3418 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3421 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3426 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3427 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3428 if (!lpDisplayNameW
)
3430 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3433 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3436 if (lpBinaryPathName
)
3438 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3439 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3440 if (!lpBinaryPathNameW
)
3442 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3445 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3448 if (lpLoadOrderGroup
)
3450 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3451 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3452 if (!lpLoadOrderGroupW
)
3454 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3457 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3462 lpStr
= (LPCSTR
)lpDependencies
;
3465 dwLength
= strlen(lpStr
) + 1;
3466 dwDependenciesLength
+= dwLength
;
3467 lpStr
= lpStr
+ dwLength
;
3469 dwDependenciesLength
++;
3471 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3472 if (!lpDependenciesW
)
3474 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3477 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3480 if (lpServiceStartName
)
3482 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3483 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3484 if (!lpServiceStartNameW
)
3486 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3489 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3492 dwError
= RCreateServiceW(hSCManager
,
3502 (LPBYTE
)lpDependenciesW
,
3503 dwDependenciesLength
,
3504 lpServiceStartNameW
,
3510 if (lpServiceNameW
!=NULL
)
3511 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3513 if (lpDisplayNameW
!= NULL
)
3514 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3516 if (lpBinaryPathNameW
!= NULL
)
3517 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3519 if (lpLoadOrderGroupW
!= NULL
)
3520 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3522 if (lpDependenciesW
!= NULL
)
3523 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3525 if (lpServiceStartNameW
!= NULL
)
3526 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3533 DWORD
REnumDependentServicesA(
3534 SC_RPC_HANDLE hService
,
3535 DWORD dwServiceState
,
3538 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3539 LPBOUNDED_DWORD_256K lpServicesReturned
)
3541 DWORD dwError
= ERROR_SUCCESS
;
3542 DWORD dwServicesReturned
= 0;
3543 DWORD dwServiceCount
;
3544 HKEY hServicesKey
= NULL
;
3545 PSERVICE_HANDLE hSvc
;
3546 PSERVICE lpService
= NULL
;
3547 PSERVICE
*lpServicesArray
= NULL
;
3548 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3551 *pcbBytesNeeded
= 0;
3552 *lpServicesReturned
= 0;
3554 DPRINT("REnumDependentServicesA() called\n");
3556 hSvc
= ScmGetServiceFromHandle(hService
);
3559 DPRINT1("Invalid service handle!\n");
3560 return ERROR_INVALID_HANDLE
;
3563 lpService
= hSvc
->ServiceEntry
;
3565 /* Check access rights */
3566 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3567 SC_MANAGER_ENUMERATE_SERVICE
))
3569 DPRINT("Insufficient access rights! 0x%lx\n",
3570 hSvc
->Handle
.DesiredAccess
);
3571 return ERROR_ACCESS_DENIED
;
3574 /* Open the Services Reg key */
3575 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3576 L
"System\\CurrentControlSet\\Services",
3581 if (dwError
!= ERROR_SUCCESS
)
3584 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3585 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3586 are the same for both. Verified in WINXP. */
3588 /* First determine the bytes needed and get the number of dependent services*/
3589 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3594 &dwServicesReturned
);
3595 if (dwError
!= ERROR_SUCCESS
)
3598 /* If buffer size is less than the bytes needed or pointer is null*/
3599 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3601 dwError
= ERROR_MORE_DATA
;
3605 /* Allocate memory for array of service pointers */
3606 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3608 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3609 if (!lpServicesArray
)
3611 DPRINT("Could not allocate a buffer!!\n");
3612 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3616 dwServicesReturned
= 0;
3617 *pcbBytesNeeded
= 0;
3619 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3624 &dwServicesReturned
);
3625 if (dwError
!= ERROR_SUCCESS
)
3630 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3631 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3633 /* Copy EnumDepenedentService to Buffer */
3634 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3636 lpService
= lpServicesArray
[dwServiceCount
];
3638 /* Copy the status info */
3639 memcpy(&lpServicesPtr
->ServiceStatus
,
3641 sizeof(SERVICE_STATUS
));
3643 /* Copy display name */
3644 WideCharToMultiByte(CP_ACP
,
3646 lpService
->lpDisplayName
,
3649 wcslen(lpService
->lpDisplayName
),
3652 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3653 lpStr
+= strlen(lpStr
) + 1;
3655 /* Copy service name */
3656 WideCharToMultiByte(CP_ACP
,
3658 lpService
->lpServiceName
,
3661 wcslen(lpService
->lpServiceName
),
3664 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3665 lpStr
+= strlen(lpStr
) + 1;
3670 *lpServicesReturned
= dwServicesReturned
;
3673 if (lpServicesArray
)
3674 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3676 RegCloseKey(hServicesKey
);
3678 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3685 DWORD
REnumServicesStatusA(
3686 SC_RPC_HANDLE hSCManager
,
3687 DWORD dwServiceType
,
3688 DWORD dwServiceState
,
3691 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3692 LPBOUNDED_DWORD_256K lpServicesReturned
,
3693 LPBOUNDED_DWORD_256K lpResumeHandle
)
3695 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3696 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3697 LPWSTR lpStringPtrW
;
3700 DWORD dwServiceCount
;
3702 DPRINT("REnumServicesStatusA() called\n");
3704 if ((dwBufSize
> 0) && (lpBuffer
))
3706 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3709 DPRINT("Failed to allocate buffer!\n");
3710 return ERROR_NOT_ENOUGH_MEMORY
;
3714 dwError
= REnumServicesStatusW(hSCManager
,
3717 (LPBYTE
)lpStatusPtrW
,
3723 /* if no services were returned then we are Done */
3724 if (*lpServicesReturned
== 0)
3727 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3728 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3729 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3730 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3731 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3733 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3735 /* Copy the service name */
3736 WideCharToMultiByte(CP_ACP
,
3741 wcslen(lpStringPtrW
),
3745 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3746 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3747 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3749 /* Copy the display name */
3750 WideCharToMultiByte(CP_ACP
,
3755 wcslen(lpStringPtrW
),
3759 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3760 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3761 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3763 /* Copy the status information */
3764 memcpy(&lpStatusPtrA
->ServiceStatus
,
3765 &lpStatusPtrW
->ServiceStatus
,
3766 sizeof(SERVICE_STATUS
));
3773 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3775 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3782 DWORD
ROpenSCManagerA(
3783 LPSTR lpMachineName
,
3784 LPSTR lpDatabaseName
,
3785 DWORD dwDesiredAccess
,
3786 LPSC_RPC_HANDLE lpScHandle
)
3788 UNICODE_STRING MachineName
;
3789 UNICODE_STRING DatabaseName
;
3792 DPRINT("ROpenSCManagerA() called\n");
3795 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3799 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3802 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3803 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3808 RtlFreeUnicodeString(&MachineName
);
3811 RtlFreeUnicodeString(&DatabaseName
);
3818 DWORD
ROpenServiceA(
3819 SC_RPC_HANDLE hSCManager
,
3820 LPSTR lpServiceName
,
3821 DWORD dwDesiredAccess
,
3822 LPSC_RPC_HANDLE lpServiceHandle
)
3824 UNICODE_STRING ServiceName
;
3827 DPRINT("ROpenServiceA() called\n");
3830 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3833 dwError
= ROpenServiceW(hSCManager
,
3834 lpServiceName
? ServiceName
.Buffer
: NULL
,
3839 RtlFreeUnicodeString(&ServiceName
);
3846 DWORD
RQueryServiceConfigA(
3847 SC_RPC_HANDLE hService
,
3848 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3850 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3852 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3853 DWORD dwError
= ERROR_SUCCESS
;
3854 PSERVICE_HANDLE hSvc
;
3855 PSERVICE lpService
= NULL
;
3856 HKEY hServiceKey
= NULL
;
3857 LPWSTR lpImagePath
= NULL
;
3858 LPWSTR lpServiceStartName
= NULL
;
3859 LPWSTR lpDependencies
= NULL
;
3860 DWORD dwDependenciesLength
= 0;
3861 DWORD dwRequiredSize
;
3862 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3863 CHAR lpEmptyString
[]={0,0};
3866 DPRINT("RQueryServiceConfigA() called\n");
3869 return ERROR_SHUTDOWN_IN_PROGRESS
;
3871 hSvc
= ScmGetServiceFromHandle(hService
);
3874 DPRINT1("Invalid service handle!\n");
3875 return ERROR_INVALID_HANDLE
;
3878 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3879 SERVICE_QUERY_CONFIG
))
3881 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3882 return ERROR_ACCESS_DENIED
;
3885 lpService
= hSvc
->ServiceEntry
;
3886 if (lpService
== NULL
)
3888 DPRINT("lpService == NULL!\n");
3889 return ERROR_INVALID_HANDLE
;
3892 /* Lock the service database shared */
3893 ScmLockDatabaseShared();
3895 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3898 if (dwError
!= ERROR_SUCCESS
)
3901 /* Read the image path */
3902 dwError
= ScmReadString(hServiceKey
,
3905 if (dwError
!= ERROR_SUCCESS
)
3908 /* Read the service start name */
3909 ScmReadString(hServiceKey
,
3911 &lpServiceStartName
);
3913 /* Read the dependencies */
3914 ScmReadDependencies(hServiceKey
,
3916 &dwDependenciesLength
);
3918 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGA
);
3920 if (lpImagePath
!= NULL
)
3921 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3923 dwRequiredSize
+= 2;
3925 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3926 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3928 dwRequiredSize
+= 2;
3930 /* Add Dependencies length */
3931 if (lpDependencies
!= NULL
)
3932 dwRequiredSize
+= dwDependenciesLength
;
3934 dwRequiredSize
+= 2;
3936 if (lpServiceStartName
!= NULL
)
3937 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3939 dwRequiredSize
+= 2;
3941 if (lpService
->lpDisplayName
!= NULL
)
3942 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3944 dwRequiredSize
+= 2;
3946 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3948 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3952 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3953 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3954 lpConfig
->dwStartType
= lpService
->dwStartType
;
3955 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3956 lpConfig
->dwTagId
= lpService
->dwTag
;
3958 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3960 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3961 Verified in WINXP */
3965 WideCharToMultiByte(CP_ACP
,
3970 wcslen(lpImagePath
) + 1,
3976 strcpy(lpStr
, lpEmptyString
);
3979 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3980 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3982 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3984 WideCharToMultiByte(CP_ACP
,
3986 lpService
->lpGroup
->lpGroupName
,
3989 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3995 strcpy(lpStr
, lpEmptyString
);
3998 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3999 lpStr
+= (strlen(lpStr
) + 1);
4001 /* Append Dependencies */
4004 WideCharToMultiByte(CP_ACP
,
4007 dwDependenciesLength
,
4009 dwDependenciesLength
,
4015 strcpy(lpStr
, lpEmptyString
);
4018 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4020 lpStr
+= dwDependenciesLength
;
4022 lpStr
+= (strlen(lpStr
) + 1);
4024 if (lpServiceStartName
)
4026 WideCharToMultiByte(CP_ACP
,
4031 wcslen(lpServiceStartName
) + 1,
4037 strcpy(lpStr
, lpEmptyString
);
4040 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4041 lpStr
+= (strlen(lpStr
) + 1);
4043 if (lpService
->lpDisplayName
)
4045 WideCharToMultiByte(CP_ACP
,
4047 lpService
->lpDisplayName
,
4050 wcslen(lpService
->lpDisplayName
) + 1,
4056 strcpy(lpStr
, lpEmptyString
);
4059 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4062 if (pcbBytesNeeded
!= NULL
)
4063 *pcbBytesNeeded
= dwRequiredSize
;
4066 /* Unlock the service database */
4067 ScmUnlockDatabase();
4069 if (lpImagePath
!= NULL
)
4070 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4072 if (lpServiceStartName
!= NULL
)
4073 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4075 if (lpDependencies
!= NULL
)
4076 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4078 if (hServiceKey
!= NULL
)
4079 RegCloseKey(hServiceKey
);
4081 DPRINT("RQueryServiceConfigA() done\n");
4088 DWORD
RQueryServiceLockStatusA(
4089 SC_RPC_HANDLE hSCManager
,
4090 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4092 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4095 return ERROR_CALL_NOT_IMPLEMENTED
;
4100 DWORD
RStartServiceA(
4101 SC_RPC_HANDLE hService
,
4103 LPSTRING_PTRSA argv
)
4105 DWORD dwError
= ERROR_SUCCESS
;
4106 PSERVICE_HANDLE hSvc
;
4107 PSERVICE lpService
= NULL
;
4108 LPWSTR
*lpVector
= NULL
;
4112 DPRINT("RStartServiceA() called\n");
4115 return ERROR_SHUTDOWN_IN_PROGRESS
;
4117 hSvc
= ScmGetServiceFromHandle(hService
);
4120 DPRINT1("Invalid service handle!\n");
4121 return ERROR_INVALID_HANDLE
;
4124 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4127 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4128 return ERROR_ACCESS_DENIED
;
4131 lpService
= hSvc
->ServiceEntry
;
4132 if (lpService
== NULL
)
4134 DPRINT("lpService == NULL!\n");
4135 return ERROR_INVALID_HANDLE
;
4138 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4139 return ERROR_SERVICE_DISABLED
;
4141 if (lpService
->bDeleted
)
4142 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4144 /* Build a Unicode argument vector */
4147 lpVector
= HeapAlloc(GetProcessHeap(),
4149 argc
* sizeof(LPWSTR
));
4150 if (lpVector
== NULL
)
4151 return ERROR_NOT_ENOUGH_MEMORY
;
4153 for (i
= 0; i
< argc
; i
++)
4155 dwLength
= MultiByteToWideChar(CP_ACP
,
4162 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4164 dwLength
* sizeof(WCHAR
));
4165 if (lpVector
[i
] == NULL
)
4167 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4171 MultiByteToWideChar(CP_ACP
,
4180 /* Start the service */
4181 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4184 /* Free the Unicode argument vector */
4185 if (lpVector
!= NULL
)
4187 for (i
= 0; i
< argc
; i
++)
4189 if (lpVector
[i
] != NULL
)
4190 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4192 HeapFree(GetProcessHeap(), 0, lpVector
);
4200 DWORD
RGetServiceDisplayNameA(
4201 SC_RPC_HANDLE hSCManager
,
4202 LPCSTR lpServiceName
,
4203 LPSTR lpDisplayName
,
4204 LPBOUNDED_DWORD_4K lpcchBuffer
)
4206 // PMANAGER_HANDLE hManager;
4207 PSERVICE lpService
= NULL
;
4210 LPWSTR lpServiceNameW
;
4212 DPRINT("RGetServiceDisplayNameA() called\n");
4213 DPRINT("hSCManager = %p\n", hSCManager
);
4214 DPRINT("lpServiceName: %s\n", lpServiceName
);
4215 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4216 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4218 // hManager = (PMANAGER_HANDLE)hSCManager;
4219 // if (hManager->Handle.Tag != MANAGER_TAG)
4221 // DPRINT("Invalid manager handle!\n");
4222 // return ERROR_INVALID_HANDLE;
4225 if (lpServiceName
!= NULL
)
4227 dwLength
= strlen(lpServiceName
) + 1;
4228 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4230 dwLength
* sizeof(WCHAR
));
4231 if (!lpServiceNameW
)
4232 return ERROR_NOT_ENOUGH_MEMORY
;
4234 MultiByteToWideChar(CP_ACP
,
4241 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4243 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4246 if (lpService
== NULL
)
4248 DPRINT("Could not find a service!\n");
4250 /* If the service could not be found and lpcchBuffer is 0, windows
4251 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4252 if (*lpcchBuffer
== 0)
4255 if (lpDisplayName
!= NULL
)
4257 *lpDisplayName
= '\0';
4260 return ERROR_SERVICE_DOES_NOT_EXIST
;
4263 if (!lpService
->lpDisplayName
)
4265 dwLength
= wcslen(lpService
->lpServiceName
);
4266 if (lpDisplayName
!= NULL
&&
4267 *lpcchBuffer
> dwLength
)
4269 WideCharToMultiByte(CP_ACP
,
4271 lpService
->lpServiceName
,
4272 wcslen(lpService
->lpServiceName
),
4277 return ERROR_SUCCESS
;
4282 dwLength
= wcslen(lpService
->lpDisplayName
);
4283 if (lpDisplayName
!= NULL
&&
4284 *lpcchBuffer
> dwLength
)
4286 WideCharToMultiByte(CP_ACP
,
4288 lpService
->lpDisplayName
,
4289 wcslen(lpService
->lpDisplayName
),
4294 return ERROR_SUCCESS
;
4298 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4300 *lpcchBuffer
= dwLength
* 2;
4307 DWORD
RGetServiceKeyNameA(
4308 SC_RPC_HANDLE hSCManager
,
4309 LPCSTR lpDisplayName
,
4310 LPSTR lpServiceName
,
4311 LPBOUNDED_DWORD_4K lpcchBuffer
)
4316 LPWSTR lpDisplayNameW
;
4318 DPRINT("RGetServiceKeyNameA() called\n");
4319 DPRINT("hSCManager = %p\n", hSCManager
);
4320 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4321 DPRINT("lpServiceName: %p\n", lpServiceName
);
4322 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4324 dwLength
= strlen(lpDisplayName
) + 1;
4325 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4327 dwLength
* sizeof(WCHAR
));
4328 if (!lpDisplayNameW
)
4329 return ERROR_NOT_ENOUGH_MEMORY
;
4331 MultiByteToWideChar(CP_ACP
,
4338 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4340 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4342 if (lpService
== NULL
)
4344 DPRINT("Could not find the service!\n");
4346 /* If the service could not be found and lpcchBuffer is 0,
4347 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4348 if (*lpcchBuffer
== 0)
4351 if (lpServiceName
!= NULL
)
4353 *lpServiceName
= '\0';
4357 return ERROR_SERVICE_DOES_NOT_EXIST
;
4360 dwLength
= wcslen(lpService
->lpServiceName
);
4361 if (lpServiceName
!= NULL
&&
4362 *lpcchBuffer
> dwLength
)
4364 WideCharToMultiByte(CP_ACP
,
4366 lpService
->lpServiceName
,
4367 wcslen(lpService
->lpServiceName
),
4372 return ERROR_SUCCESS
;
4375 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4377 *lpcchBuffer
= dwLength
* 2;
4384 DWORD
RI_ScGetCurrentGroupStateW(
4385 SC_RPC_HANDLE hSCManager
,
4386 LPWSTR lpLoadOrderGroup
,
4390 return ERROR_CALL_NOT_IMPLEMENTED
;
4395 DWORD
REnumServiceGroupW(
4396 SC_RPC_HANDLE hSCManager
,
4397 DWORD dwServiceType
,
4398 DWORD dwServiceState
,
4401 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4402 LPBOUNDED_DWORD_256K lpServicesReturned
,
4403 LPBOUNDED_DWORD_256K lpResumeIndex
,
4404 LPCWSTR pszGroupName
)
4406 PMANAGER_HANDLE hManager
;
4408 DWORD dwError
= ERROR_SUCCESS
;
4409 PLIST_ENTRY ServiceEntry
;
4410 PSERVICE CurrentService
;
4412 DWORD dwRequiredSize
;
4413 DWORD dwServiceCount
;
4415 DWORD dwLastResumeCount
= 0;
4416 LPENUM_SERVICE_STATUSW lpStatusPtr
;
4419 DPRINT("REnumServiceGroupW() called\n");
4422 return ERROR_SHUTDOWN_IN_PROGRESS
;
4424 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
4425 if (hManager
== NULL
)
4427 DPRINT1("Invalid service manager handle!\n");
4428 return ERROR_INVALID_HANDLE
;
4431 *pcbBytesNeeded
= 0;
4432 *lpServicesReturned
= 0;
4434 if ((dwServiceType
== 0) ||
4435 ((dwServiceType
& ~(SERVICE_DRIVER
| SERVICE_WIN32
)) != 0))
4437 DPRINT("Not a valid Service Type!\n");
4438 return ERROR_INVALID_PARAMETER
;
4441 if ((dwServiceState
!= SERVICE_ACTIVE
) &&
4442 (dwServiceState
!= SERVICE_INACTIVE
) &&
4443 (dwServiceState
!= SERVICE_STATE_ALL
))
4445 DPRINT("Not a valid Service State!\n");
4446 return ERROR_INVALID_PARAMETER
;
4449 /* Check access rights */
4450 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4451 SC_MANAGER_ENUMERATE_SERVICE
))
4453 DPRINT("Insufficient access rights! 0x%lx\n",
4454 hManager
->Handle
.DesiredAccess
);
4455 return ERROR_ACCESS_DENIED
;
4459 dwLastResumeCount
= *lpResumeIndex
;
4461 /* Lock the service database shared */
4462 ScmLockDatabaseShared();
4464 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4465 if (lpService
== NULL
)
4467 dwError
= ERROR_SUCCESS
;
4474 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4475 ServiceEntry
!= &ServiceListHead
;
4476 ServiceEntry
= ServiceEntry
->Flink
)
4478 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4482 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4485 dwState
= SERVICE_ACTIVE
;
4486 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4487 dwState
= SERVICE_INACTIVE
;
4489 if ((dwState
& dwServiceState
) == 0)
4494 if (*pszGroupName
== 0)
4496 if (CurrentService
->lpGroup
!= NULL
)
4501 if ((CurrentService
->lpGroup
== NULL
) ||
4502 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4507 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
4508 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4509 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4511 if (dwRequiredSize
+ dwSize
> cbBufSize
)
4513 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4517 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4518 dwRequiredSize
+= dwSize
;
4520 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4523 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4524 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4527 ServiceEntry
!= &ServiceListHead
;
4528 ServiceEntry
= ServiceEntry
->Flink
)
4530 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4534 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4537 dwState
= SERVICE_ACTIVE
;
4538 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4539 dwState
= SERVICE_INACTIVE
;
4541 if ((dwState
& dwServiceState
) == 0)
4546 if (*pszGroupName
== 0)
4548 if (CurrentService
->lpGroup
!= NULL
)
4553 if ((CurrentService
->lpGroup
== NULL
) ||
4554 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4559 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
4560 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4561 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4563 dwError
= ERROR_MORE_DATA
;
4566 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4569 *lpResumeIndex
= dwLastResumeCount
;
4571 *lpServicesReturned
= dwServiceCount
;
4572 *pcbBytesNeeded
= dwRequiredSize
;
4574 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
4575 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4576 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
4579 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4580 ServiceEntry
!= &ServiceListHead
;
4581 ServiceEntry
= ServiceEntry
->Flink
)
4583 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4587 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4590 dwState
= SERVICE_ACTIVE
;
4591 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4592 dwState
= SERVICE_INACTIVE
;
4594 if ((dwState
& dwServiceState
) == 0)
4599 if (*pszGroupName
== 0)
4601 if (CurrentService
->lpGroup
!= NULL
)
4606 if ((CurrentService
->lpGroup
== NULL
) ||
4607 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4612 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
4613 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4614 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4616 if (dwRequiredSize
+ dwSize
> cbBufSize
)
4619 /* Copy the service name */
4620 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
4621 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4622 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4624 /* Copy the display name */
4625 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
4626 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4627 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4629 /* Copy the status information */
4630 memcpy(&lpStatusPtr
->ServiceStatus
,
4631 &CurrentService
->Status
,
4632 sizeof(SERVICE_STATUS
));
4635 dwRequiredSize
+= dwSize
;
4638 if (dwError
== ERROR_SUCCESS
)
4640 *pcbBytesNeeded
= 0;
4641 if (lpResumeIndex
) *lpResumeIndex
= 0;
4645 /* Unlock the service database */
4646 ScmUnlockDatabase();
4648 DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError
);
4655 // WARNING: This function is untested
4658 DWORD
RChangeServiceConfig2A(
4659 SC_RPC_HANDLE hService
,
4660 SC_RPC_CONFIG_INFOA Info
)
4662 SC_RPC_CONFIG_INFOW InfoW
;
4663 DWORD dwRet
, dwLength
;
4666 DPRINT("RChangeServiceConfig2A() called\n");
4667 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4669 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4671 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4673 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4674 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4676 //lpServiceDescriptonA = Info.psd;
4678 ///if (lpServiceDescriptonA &&
4679 ///lpServiceDescriptonA->lpDescription)
4681 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4683 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4685 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4686 if (!lpServiceDescriptonW
)
4688 return ERROR_NOT_ENOUGH_MEMORY
;
4691 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4693 MultiByteToWideChar(CP_ACP
,
4697 lpServiceDescriptonW
->lpDescription
,
4700 ptr
= lpServiceDescriptonW
;
4701 InfoW
.psd
= lpServiceDescriptonW
;
4704 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4706 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4707 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4708 DWORD dwRebootLen
= 0;
4709 DWORD dwCommandLen
= 0;
4711 lpServiceFailureActionsA
= Info
.psfa
;
4713 if (lpServiceFailureActionsA
)
4715 if (lpServiceFailureActionsA
->lpRebootMsg
)
4717 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4719 if (lpServiceFailureActionsA
->lpCommand
)
4721 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4723 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4725 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4728 if (!lpServiceFailureActionsW
)
4730 return ERROR_NOT_ENOUGH_MEMORY
;
4733 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4734 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4735 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4737 if (lpServiceFailureActionsA
->lpRebootMsg
)
4739 MultiByteToWideChar(CP_ACP
,
4741 lpServiceFailureActionsA
->lpRebootMsg
,
4743 lpServiceFailureActionsW
->lpRebootMsg
,
4747 if (lpServiceFailureActionsA
->lpCommand
)
4749 MultiByteToWideChar(CP_ACP
,
4751 lpServiceFailureActionsA
->lpCommand
,
4753 lpServiceFailureActionsW
->lpCommand
,
4757 ptr
= lpServiceFailureActionsW
;
4761 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4763 HeapFree(GetProcessHeap(), 0, ptr
);
4770 DWORD
RChangeServiceConfig2W(
4771 SC_RPC_HANDLE hService
,
4772 SC_RPC_CONFIG_INFOW Info
)
4774 DWORD dwError
= ERROR_SUCCESS
;
4775 PSERVICE_HANDLE hSvc
;
4776 PSERVICE lpService
= NULL
;
4777 HKEY hServiceKey
= NULL
;
4779 DPRINT("RChangeServiceConfig2W() called\n");
4780 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4783 return ERROR_SHUTDOWN_IN_PROGRESS
;
4785 hSvc
= ScmGetServiceFromHandle(hService
);
4788 DPRINT1("Invalid service handle!\n");
4789 return ERROR_INVALID_HANDLE
;
4792 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4793 SERVICE_CHANGE_CONFIG
))
4795 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4796 return ERROR_ACCESS_DENIED
;
4799 lpService
= hSvc
->ServiceEntry
;
4800 if (lpService
== NULL
)
4802 DPRINT("lpService == NULL!\n");
4803 return ERROR_INVALID_HANDLE
;
4806 /* Lock the service database exclusively */
4807 ScmLockDatabaseExclusive();
4809 if (lpService
->bDeleted
)
4811 DPRINT("The service has already been marked for delete!\n");
4812 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4816 /* Open the service key */
4817 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4820 if (dwError
!= ERROR_SUCCESS
)
4823 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4825 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4827 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4829 if (lpServiceDescription
!= NULL
&&
4830 lpServiceDescription
->lpDescription
!= NULL
)
4832 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4833 dwError
= RegSetValueExW(hServiceKey
,
4837 (LPBYTE
)lpServiceDescription
->lpDescription
,
4838 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4839 if (dwError
!= ERROR_SUCCESS
)
4843 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4846 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4851 /* Unlock the service database */
4852 ScmUnlockDatabase();
4854 if (hServiceKey
!= NULL
)
4855 RegCloseKey(hServiceKey
);
4857 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4864 DWORD
RQueryServiceConfig2A(
4865 SC_RPC_HANDLE hService
,
4869 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4871 DWORD dwError
= ERROR_SUCCESS
;
4872 PSERVICE_HANDLE hSvc
;
4873 PSERVICE lpService
= NULL
;
4874 HKEY hServiceKey
= NULL
;
4875 DWORD dwRequiredSize
= 0;
4877 LPWSTR lpDescriptionW
= NULL
;
4878 LPWSTR lpRebootMessageW
= NULL
;
4879 LPWSTR lpFailureCommandW
= NULL
;
4881 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4882 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4885 return ERROR_INVALID_ADDRESS
;
4888 return ERROR_SHUTDOWN_IN_PROGRESS
;
4890 hSvc
= ScmGetServiceFromHandle(hService
);
4893 DPRINT1("Invalid service handle!\n");
4894 return ERROR_INVALID_HANDLE
;
4897 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4898 SERVICE_QUERY_CONFIG
))
4900 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4901 return ERROR_ACCESS_DENIED
;
4904 lpService
= hSvc
->ServiceEntry
;
4905 if (lpService
== NULL
)
4907 DPRINT("lpService == NULL!\n");
4908 return ERROR_INVALID_HANDLE
;
4911 /* Lock the service database shared */
4912 ScmLockDatabaseShared();
4914 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4917 if (dwError
!= ERROR_SUCCESS
)
4920 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4922 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4925 dwError
= ScmReadString(hServiceKey
,
4928 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4931 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4932 if (dwError
== ERROR_SUCCESS
)
4933 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4935 if (cbBufSize
< *pcbBytesNeeded
)
4937 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4941 if (dwError
== ERROR_SUCCESS
)
4943 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4945 WideCharToMultiByte(CP_ACP
,
4950 wcslen(lpDescriptionW
),
4953 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4957 lpServiceDescription
->lpDescription
= NULL
;
4958 dwError
= ERROR_SUCCESS
;
4961 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4963 LPSERVICE_FAILURE_ACTIONSA lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSA
)lpBuffer
;
4966 /* Query value length */
4968 dwError
= RegQueryValueExW(hServiceKey
,
4974 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_MORE_DATA
)
4977 if (dwType
!= REG_BINARY
)
4979 dwError
= ERROR_UNSUPPORTED_TYPE
;
4983 dwRequiredSize
= max(sizeof(SERVICE_FAILURE_ACTIONSA
), dwRequiredSize
);
4985 dwError
= ScmReadString(hServiceKey
,
4987 &lpFailureCommandW
);
4989 dwError
= ScmReadString(hServiceKey
,
4993 if (lpRebootMessageW
)
4994 dwRequiredSize
+= (wcslen(lpRebootMessageW
) + 1) * sizeof(WCHAR
);
4996 if (lpFailureCommandW
)
4997 dwRequiredSize
+= (wcslen(lpFailureCommandW
) + 1) * sizeof(WCHAR
);
4999 if (cbBufSize
< dwRequiredSize
)
5001 *pcbBytesNeeded
= dwRequiredSize
;
5002 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5006 /* Now we can fill the buffer */
5007 dwError
= RegQueryValueExW(hServiceKey
,
5011 (LPBYTE
)lpFailureActions
,
5013 if (dwError
!= ERROR_SUCCESS
)
5016 if ((dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSA
)) ||
5017 (dwRequiredSize
> cbBufSize
))
5019 dwError
= ERROR_BUFFER_OVERFLOW
;
5023 if (dwError
== ERROR_SUCCESS
)
5025 lpFailureActions
->cActions
= min(lpFailureActions
->cActions
, (dwRequiredSize
- FIELD_OFFSET(SERVICE_FAILURE_ACTIONSA
, lpsaActions
)) / sizeof(SC_ACTION
));
5026 lpFailureActions
->lpsaActions
= (lpFailureActions
->cActions
> 0) ? (LPSC_ACTION
)(lpFailureActions
+ 1) : NULL
;
5027 lpStr
= (LPSTR
)((ULONG_PTR
)(lpFailureActions
+ 1) + lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5031 lpFailureActions
->dwResetPeriod
= 0;
5032 lpFailureActions
->cActions
= 0;
5033 lpFailureActions
->lpsaActions
= NULL
;
5034 lpStr
= (LPSTR
)(lpFailureActions
+ 1);
5037 lpFailureActions
->lpRebootMsg
= NULL
;
5038 lpFailureActions
->lpCommand
= NULL
;
5040 if (lpRebootMessageW
)
5042 WideCharToMultiByte(CP_ACP
,
5047 wcslen(lpRebootMessageW
),
5050 lpFailureActions
->lpRebootMsg
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5051 lpStr
+= strlen(lpStr
) + 1;
5054 if (lpFailureCommandW
)
5056 WideCharToMultiByte(CP_ACP
,
5061 wcslen(lpFailureCommandW
),
5064 lpFailureActions
->lpCommand
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5065 /* lpStr += strlen(lpStr) + 1; */
5068 dwError
= ERROR_SUCCESS
;
5072 /* Unlock the service database */
5073 ScmUnlockDatabase();
5075 if (lpDescriptionW
!= NULL
)
5076 HeapFree(GetProcessHeap(), 0, lpDescriptionW
);
5078 if (lpRebootMessageW
!= NULL
)
5079 HeapFree(GetProcessHeap(), 0, lpRebootMessageW
);
5081 if (lpFailureCommandW
!= NULL
)
5082 HeapFree(GetProcessHeap(), 0, lpFailureCommandW
);
5084 if (hServiceKey
!= NULL
)
5085 RegCloseKey(hServiceKey
);
5087 DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError
);
5094 DWORD
RQueryServiceConfig2W(
5095 SC_RPC_HANDLE hService
,
5099 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5101 DWORD dwError
= ERROR_SUCCESS
;
5102 PSERVICE_HANDLE hSvc
;
5103 PSERVICE lpService
= NULL
;
5104 HKEY hServiceKey
= NULL
;
5105 DWORD dwRequiredSize
= 0;
5107 LPWSTR lpDescription
= NULL
;
5108 LPWSTR lpRebootMessage
= NULL
;
5109 LPWSTR lpFailureCommand
= NULL
;
5111 DPRINT("RQueryServiceConfig2W() called\n");
5114 return ERROR_INVALID_ADDRESS
;
5117 return ERROR_SHUTDOWN_IN_PROGRESS
;
5119 hSvc
= ScmGetServiceFromHandle(hService
);
5122 DPRINT1("Invalid service handle!\n");
5123 return ERROR_INVALID_HANDLE
;
5126 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5127 SERVICE_QUERY_CONFIG
))
5129 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5130 return ERROR_ACCESS_DENIED
;
5133 lpService
= hSvc
->ServiceEntry
;
5134 if (lpService
== NULL
)
5136 DPRINT("lpService == NULL!\n");
5137 return ERROR_INVALID_HANDLE
;
5140 /* Lock the service database shared */
5141 ScmLockDatabaseShared();
5143 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
5146 if (dwError
!= ERROR_SUCCESS
)
5149 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5151 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
5154 dwError
= ScmReadString(hServiceKey
,
5157 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5160 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
5161 if (dwError
== ERROR_SUCCESS
)
5162 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
5164 if (cbBufSize
< *pcbBytesNeeded
)
5166 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5170 if (dwError
== ERROR_SUCCESS
)
5172 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
5173 wcscpy(lpStr
, lpDescription
);
5174 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
5178 lpServiceDescription
->lpDescription
= NULL
;
5179 dwError
= ERROR_SUCCESS
;
5182 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5184 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
5187 /* Query value length */
5189 dwError
= RegQueryValueExW(hServiceKey
,
5195 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_MORE_DATA
)
5198 if (dwType
!= REG_BINARY
)
5200 dwError
= ERROR_UNSUPPORTED_TYPE
;
5204 dwRequiredSize
= max(sizeof(SERVICE_FAILURE_ACTIONSW
), dwRequiredSize
);
5206 dwError
= ScmReadString(hServiceKey
,
5210 dwError
= ScmReadString(hServiceKey
,
5214 if (lpRebootMessage
)
5215 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
5217 if (lpFailureCommand
)
5218 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
5220 if (cbBufSize
< dwRequiredSize
)
5222 *pcbBytesNeeded
= dwRequiredSize
;
5223 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5227 /* Now we can fill the buffer */
5228 dwError
= RegQueryValueExW(hServiceKey
,
5232 (LPBYTE
)lpFailureActions
,
5234 if (dwError
!= ERROR_SUCCESS
)
5237 if ((dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSW
)) ||
5238 (dwRequiredSize
> cbBufSize
))
5240 dwError
= ERROR_BUFFER_OVERFLOW
;
5244 if (dwError
== ERROR_SUCCESS
)
5246 lpFailureActions
->cActions
= min(lpFailureActions
->cActions
, (dwRequiredSize
- FIELD_OFFSET(SERVICE_FAILURE_ACTIONSW
, lpsaActions
)) / sizeof(SC_ACTION
));
5247 lpFailureActions
->lpsaActions
= (lpFailureActions
->cActions
> 0 ? (LPSC_ACTION
)(lpFailureActions
+ 1) : NULL
);
5248 lpStr
= (LPWSTR
)((ULONG_PTR
)(lpFailureActions
+ 1) + lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5252 lpFailureActions
->dwResetPeriod
= 0;
5253 lpFailureActions
->cActions
= 0;
5254 lpFailureActions
->lpsaActions
= NULL
;
5255 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
5258 lpFailureActions
->lpRebootMsg
= NULL
;
5259 lpFailureActions
->lpCommand
= NULL
;
5261 if (lpRebootMessage
)
5263 wcscpy(lpStr
, lpRebootMessage
);
5264 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5265 lpStr
+= wcslen(lpStr
) + 1;
5268 if (lpFailureCommand
)
5270 wcscpy(lpStr
, lpFailureCommand
);
5271 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5272 /* lpStr += wcslen(lpStr) + 1; */
5275 dwError
= ERROR_SUCCESS
;
5279 /* Unlock the service database */
5280 ScmUnlockDatabase();
5282 if (lpDescription
!= NULL
)
5283 HeapFree(GetProcessHeap(), 0, lpDescription
);
5285 if (lpRebootMessage
!= NULL
)
5286 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5288 if (lpFailureCommand
!= NULL
)
5289 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5291 if (hServiceKey
!= NULL
)
5292 RegCloseKey(hServiceKey
);
5294 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5301 DWORD
RQueryServiceStatusEx(
5302 SC_RPC_HANDLE hService
,
5303 SC_STATUS_TYPE InfoLevel
,
5306 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5308 LPSERVICE_STATUS_PROCESS lpStatus
;
5309 PSERVICE_HANDLE hSvc
;
5312 DPRINT("RQueryServiceStatusEx() called\n");
5315 return ERROR_SHUTDOWN_IN_PROGRESS
;
5317 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
5318 return ERROR_INVALID_LEVEL
;
5320 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
5322 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
5323 return ERROR_INSUFFICIENT_BUFFER
;
5325 hSvc
= ScmGetServiceFromHandle(hService
);
5328 DPRINT1("Invalid service handle!\n");
5329 return ERROR_INVALID_HANDLE
;
5332 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5333 SERVICE_QUERY_STATUS
))
5335 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5336 return ERROR_ACCESS_DENIED
;
5339 lpService
= hSvc
->ServiceEntry
;
5340 if (lpService
== NULL
)
5342 DPRINT("lpService == NULL!\n");
5343 return ERROR_INVALID_HANDLE
;
5346 /* Lock the service database shared */
5347 ScmLockDatabaseShared();
5349 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
5351 /* Return service status information */
5352 RtlCopyMemory(lpStatus
,
5354 sizeof(SERVICE_STATUS
));
5356 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
5357 lpStatus
->dwServiceFlags
= 0; /* FIXME */
5359 /* Unlock the service database */
5360 ScmUnlockDatabase();
5362 return ERROR_SUCCESS
;
5367 DWORD
REnumServicesStatusExA(
5368 SC_RPC_HANDLE hSCManager
,
5369 SC_ENUM_TYPE InfoLevel
,
5370 DWORD dwServiceType
,
5371 DWORD dwServiceState
,
5374 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5375 LPBOUNDED_DWORD_256K lpServicesReturned
,
5376 LPBOUNDED_DWORD_256K lpResumeIndex
,
5377 LPCSTR pszGroupName
)
5379 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
5380 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
5381 LPWSTR lpStringPtrW
;
5383 LPWSTR pszGroupNameW
= NULL
;
5385 DWORD dwServiceCount
;
5387 DPRINT("REnumServicesStatusExA() called\n");
5391 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
5394 DPRINT("Failed to allocate buffer!\n");
5395 return ERROR_NOT_ENOUGH_MEMORY
;
5398 MultiByteToWideChar(CP_ACP
,
5403 strlen(pszGroupName
) + 1);
5406 if ((cbBufSize
> 0) && (lpBuffer
))
5408 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
5411 DPRINT("Failed to allocate buffer!\n");
5412 return ERROR_NOT_ENOUGH_MEMORY
;
5416 dwError
= REnumServicesStatusExW(hSCManager
,
5420 (LPBYTE
)lpStatusPtrW
,
5427 /* if no services were returned then we are Done */
5428 if (*lpServicesReturned
== 0)
5431 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5432 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5433 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5434 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5435 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5437 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5439 /* Copy the service name */
5440 WideCharToMultiByte(CP_ACP
,
5445 wcslen(lpStringPtrW
),
5449 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5450 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5451 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5453 /* Copy the display name */
5454 WideCharToMultiByte(CP_ACP
,
5459 wcslen(lpStringPtrW
),
5463 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5464 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5465 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5467 /* Copy the status information */
5468 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5469 &lpStatusPtrW
->ServiceStatusProcess
,
5470 sizeof(SERVICE_STATUS
));
5472 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5473 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5479 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5482 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5484 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5491 DWORD
REnumServicesStatusExW(
5492 SC_RPC_HANDLE hSCManager
,
5493 SC_ENUM_TYPE InfoLevel
,
5494 DWORD dwServiceType
,
5495 DWORD dwServiceState
,
5498 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5499 LPBOUNDED_DWORD_256K lpServicesReturned
,
5500 LPBOUNDED_DWORD_256K lpResumeIndex
,
5501 LPCWSTR pszGroupName
)
5503 PMANAGER_HANDLE hManager
;
5505 DWORD dwError
= ERROR_SUCCESS
;
5506 PLIST_ENTRY ServiceEntry
;
5507 PSERVICE CurrentService
;
5509 DWORD dwRequiredSize
;
5510 DWORD dwServiceCount
;
5512 DWORD dwLastResumeCount
= 0;
5513 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5516 DPRINT("REnumServicesStatusExW() called\n");
5519 return ERROR_SHUTDOWN_IN_PROGRESS
;
5521 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5522 return ERROR_INVALID_LEVEL
;
5524 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5525 if (hManager
== NULL
)
5527 DPRINT1("Invalid service manager handle!\n");
5528 return ERROR_INVALID_HANDLE
;
5531 *pcbBytesNeeded
= 0;
5532 *lpServicesReturned
= 0;
5534 if ((dwServiceType
== 0) ||
5535 ((dwServiceType
& ~(SERVICE_DRIVER
| SERVICE_WIN32
)) != 0))
5537 DPRINT("Not a valid Service Type!\n");
5538 return ERROR_INVALID_PARAMETER
;
5541 if ((dwServiceState
!= SERVICE_ACTIVE
) &&
5542 (dwServiceState
!= SERVICE_INACTIVE
) &&
5543 (dwServiceState
!= SERVICE_STATE_ALL
))
5545 DPRINT("Not a valid Service State!\n");
5546 return ERROR_INVALID_PARAMETER
;
5549 /* Check access rights */
5550 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5551 SC_MANAGER_ENUMERATE_SERVICE
))
5553 DPRINT("Insufficient access rights! 0x%lx\n",
5554 hManager
->Handle
.DesiredAccess
);
5555 return ERROR_ACCESS_DENIED
;
5559 dwLastResumeCount
= *lpResumeIndex
;
5561 /* Lock the service database shared */
5562 ScmLockDatabaseShared();
5564 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5565 if (lpService
== NULL
)
5567 dwError
= ERROR_SUCCESS
;
5574 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5575 ServiceEntry
!= &ServiceListHead
;
5576 ServiceEntry
= ServiceEntry
->Flink
)
5578 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5582 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5585 dwState
= SERVICE_ACTIVE
;
5586 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5587 dwState
= SERVICE_INACTIVE
;
5589 if ((dwState
& dwServiceState
) == 0)
5594 if (*pszGroupName
== 0)
5596 if (CurrentService
->lpGroup
!= NULL
)
5601 if ((CurrentService
->lpGroup
== NULL
) ||
5602 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
5607 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5608 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5609 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5611 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5613 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5614 dwRequiredSize
+= dwSize
;
5616 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5620 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5626 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5627 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5630 ServiceEntry
!= &ServiceListHead
;
5631 ServiceEntry
= ServiceEntry
->Flink
)
5633 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5637 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5640 dwState
= SERVICE_ACTIVE
;
5641 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5642 dwState
= SERVICE_INACTIVE
;
5644 if ((dwState
& dwServiceState
) == 0)
5649 if (*pszGroupName
== 0)
5651 if (CurrentService
->lpGroup
!= NULL
)
5656 if ((CurrentService
->lpGroup
== NULL
) ||
5657 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
5662 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5663 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5664 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5666 dwError
= ERROR_MORE_DATA
;
5669 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5672 *lpResumeIndex
= dwLastResumeCount
;
5674 *lpServicesReturned
= dwServiceCount
;
5675 *pcbBytesNeeded
= dwRequiredSize
;
5677 /* If there was no services that matched */
5678 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5680 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5684 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5685 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5686 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5689 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5690 ServiceEntry
!= &ServiceListHead
;
5691 ServiceEntry
= ServiceEntry
->Flink
)
5693 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5697 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5700 dwState
= SERVICE_ACTIVE
;
5701 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5702 dwState
= SERVICE_INACTIVE
;
5704 if ((dwState
& dwServiceState
) == 0)
5709 if (*pszGroupName
== 0)
5711 if (CurrentService
->lpGroup
!= NULL
)
5716 if ((CurrentService
->lpGroup
== NULL
) ||
5717 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
5722 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5723 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5724 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5726 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5728 /* Copy the service name */
5730 CurrentService
->lpServiceName
);
5731 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5732 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5734 /* Copy the display name */
5736 CurrentService
->lpDisplayName
);
5737 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5738 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5740 /* Copy the status information */
5741 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5742 &CurrentService
->Status
,
5743 sizeof(SERVICE_STATUS
));
5744 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5745 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5746 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5749 dwRequiredSize
+= dwSize
;
5759 *pcbBytesNeeded
= 0;
5765 /* Unlock the service database */
5766 ScmUnlockDatabase();
5768 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5775 DWORD
RSendTSMessage(
5776 handle_t BindingHandle
) /* FIXME */
5779 return ERROR_CALL_NOT_IMPLEMENTED
;
5784 DWORD
RCreateServiceWOW64A(
5785 handle_t BindingHandle
,
5786 LPSTR lpServiceName
,
5787 LPSTR lpDisplayName
,
5788 DWORD dwDesiredAccess
,
5789 DWORD dwServiceType
,
5791 DWORD dwErrorControl
,
5792 LPSTR lpBinaryPathName
,
5793 LPSTR lpLoadOrderGroup
,
5795 LPBYTE lpDependencies
,
5797 LPSTR lpServiceStartName
,
5800 LPSC_RPC_HANDLE lpServiceHandle
)
5803 return ERROR_CALL_NOT_IMPLEMENTED
;
5808 DWORD
RCreateServiceWOW64W(
5809 handle_t BindingHandle
,
5810 LPWSTR lpServiceName
,
5811 LPWSTR lpDisplayName
,
5812 DWORD dwDesiredAccess
,
5813 DWORD dwServiceType
,
5815 DWORD dwErrorControl
,
5816 LPWSTR lpBinaryPathName
,
5817 LPWSTR lpLoadOrderGroup
,
5819 LPBYTE lpDependencies
,
5821 LPWSTR lpServiceStartName
,
5824 LPSC_RPC_HANDLE lpServiceHandle
)
5827 return ERROR_CALL_NOT_IMPLEMENTED
;
5832 DWORD
RQueryServiceTagInfo(
5833 handle_t BindingHandle
) /* FIXME */
5836 return ERROR_CALL_NOT_IMPLEMENTED
;
5841 DWORD
RNotifyServiceStatusChange(
5842 SC_RPC_HANDLE hService
,
5843 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5844 GUID
*pClientProcessGuid
,
5845 GUID
*pSCMProcessGuid
,
5846 PBOOL pfCreateRemoteQueue
,
5847 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5850 return ERROR_CALL_NOT_IMPLEMENTED
;
5855 DWORD
RGetNotifyResults(
5856 SC_NOTIFY_RPC_HANDLE hNotify
,
5857 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5860 return ERROR_CALL_NOT_IMPLEMENTED
;
5865 DWORD
RCloseNotifyHandle(
5866 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5870 return ERROR_CALL_NOT_IMPLEMENTED
;
5875 DWORD
RControlServiceExA(
5876 SC_RPC_HANDLE hService
,
5881 return ERROR_CALL_NOT_IMPLEMENTED
;
5886 DWORD
RControlServiceExW(
5887 SC_RPC_HANDLE hService
,
5892 return ERROR_CALL_NOT_IMPLEMENTED
;
5897 DWORD
RSendPnPMessage(
5898 handle_t BindingHandle
) /* FIXME */
5901 return ERROR_CALL_NOT_IMPLEMENTED
;
5906 DWORD
RValidatePnPService(
5907 handle_t BindingHandle
) /* FIXME */
5910 return ERROR_CALL_NOT_IMPLEMENTED
;
5915 DWORD
ROpenServiceStatusHandle(
5916 handle_t BindingHandle
) /* FIXME */
5919 return ERROR_CALL_NOT_IMPLEMENTED
;
5925 handle_t BindingHandle
) /* FIXME */
5928 return ERROR_CALL_NOT_IMPLEMENTED
;
5932 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5934 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5938 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5940 HeapFree(GetProcessHeap(), 0, ptr
);
5944 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5946 /* Close the handle */
5947 RCloseServiceHandle(&hSCObject
);
5951 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5953 /* Unlock the database */
5954 RUnlockServiceDatabase(&Lock
);
5958 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)