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(), HEAP_ZERO_MEMORY
, 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 SIZE_T ServiceNameLen
, ExpandedLen
;
402 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
403 OBJECT_ATTRIBUTES ObjectAttributes
;
405 HANDLE SymbolicLinkHandle
;
407 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
410 return ERROR_INVALID_PARAMETER
;
412 *RelativeName
= NULL
;
414 ServiceNameLen
= wcslen(CanonName
);
416 /* First check, if it's already good */
417 if (ServiceNameLen
> 12 &&
418 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
420 *RelativeName
= HeapAlloc(GetProcessHeap(),
422 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
423 if (*RelativeName
== NULL
)
425 DPRINT("Error allocating memory for boot driver name!\n");
426 return ERROR_NOT_ENOUGH_MEMORY
;
430 wcscpy(*RelativeName
, CanonName
);
432 DPRINT("Bootdriver name %S\n", *RelativeName
);
433 return ERROR_SUCCESS
;
436 /* If it has %SystemRoot% prefix, substitute it to \System*/
437 if (ServiceNameLen
> 13 &&
438 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
440 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
441 *RelativeName
= HeapAlloc(GetProcessHeap(),
443 ServiceNameLen
* sizeof(WCHAR
));
445 if (*RelativeName
== NULL
)
447 DPRINT("Error allocating memory for boot driver name!\n");
448 return ERROR_NOT_ENOUGH_MEMORY
;
452 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
453 wcscat(*RelativeName
, CanonName
+ 13);
455 DPRINT("Bootdriver name %S\n", *RelativeName
);
456 return ERROR_SUCCESS
;
459 /* Get buffer size needed for expanding env strings */
460 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
464 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
465 return ERROR_INVALID_ENVIRONMENT
;
468 /* Allocate memory, since the size is known now */
469 Expanded
= HeapAlloc(GetProcessHeap(),
471 (BufferSize
+ 1) * sizeof(WCHAR
));
474 DPRINT("Error allocating memory for boot driver name!\n");
475 return ERROR_NOT_ENOUGH_MEMORY
;
479 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
482 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
483 HeapFree(GetProcessHeap(), 0, Expanded
);
484 return ERROR_NOT_ENOUGH_MEMORY
;
487 /* Convert to NT-style path */
488 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
490 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
491 return ERROR_INVALID_ENVIRONMENT
;
494 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
496 /* No need to keep the dos-path anymore */
497 HeapFree(GetProcessHeap(), 0, Expanded
);
499 /* Copy it to the allocated place */
500 Expanded
= HeapAlloc(GetProcessHeap(),
502 NtPathName
.Length
+ sizeof(UNICODE_NULL
));
505 DPRINT("Error allocating memory for boot driver name!\n");
506 return ERROR_NOT_ENOUGH_MEMORY
;
509 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
510 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
511 Expanded
[ExpandedLen
] = UNICODE_NULL
;
513 if (ServiceNameLen
> ExpandedLen
&&
514 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
516 /* Only \SystemRoot\ is missing */
517 *RelativeName
= HeapAlloc(GetProcessHeap(),
519 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
520 if (*RelativeName
== NULL
)
522 DPRINT("Error allocating memory for boot driver name!\n");
523 HeapFree(GetProcessHeap(), 0, Expanded
);
524 return ERROR_NOT_ENOUGH_MEMORY
;
527 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
528 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
530 RtlFreeUnicodeString(&NtPathName
);
531 return ERROR_SUCCESS
;
534 /* The most complex case starts here */
535 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
536 InitializeObjectAttributes(&ObjectAttributes
,
538 OBJ_CASE_INSENSITIVE
,
542 /* Open this symlink */
543 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
545 if (NT_SUCCESS(Status
))
547 LinkTarget
.Length
= 0;
548 LinkTarget
.MaximumLength
= 0;
550 DPRINT("Opened symbolic link object\n");
552 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
553 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
555 /* Check if required buffer size is sane */
556 if (BufferSize
> 0xFFFD)
558 DPRINT("Too large buffer required\n");
560 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
561 HeapFree(GetProcessHeap(), 0, Expanded
);
562 return ERROR_NOT_ENOUGH_MEMORY
;
565 /* Alloc the string */
566 LinkTarget
.Length
= (USHORT
)BufferSize
;
567 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(UNICODE_NULL
);
568 LinkTarget
.Buffer
= HeapAlloc(GetProcessHeap(),
570 LinkTarget
.MaximumLength
);
571 if (!LinkTarget
.Buffer
)
573 DPRINT("Unable to alloc buffer\n");
574 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
575 HeapFree(GetProcessHeap(), 0, Expanded
);
576 return ERROR_NOT_ENOUGH_MEMORY
;
579 /* Do a real query now */
580 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
581 if (NT_SUCCESS(Status
))
583 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
585 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
586 if ((ServiceNameLen
> ExpandedLen
) &&
587 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
589 *RelativeName
= HeapAlloc(GetProcessHeap(),
591 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
593 if (*RelativeName
== NULL
)
595 DPRINT("Unable to alloc buffer\n");
596 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
597 HeapFree(GetProcessHeap(), 0, Expanded
);
598 RtlFreeUnicodeString(&NtPathName
);
599 return ERROR_NOT_ENOUGH_MEMORY
;
602 /* Copy it over, substituting the first part
604 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
605 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
608 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
609 HeapFree(GetProcessHeap(), 0, Expanded
);
610 RtlFreeUnicodeString(&NtPathName
);
613 return ERROR_SUCCESS
;
617 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
618 HeapFree(GetProcessHeap(), 0, Expanded
);
619 RtlFreeUnicodeString(&NtPathName
);
620 return ERROR_INVALID_PARAMETER
;
625 DPRINT("Error, Status = %08X\n", Status
);
626 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
627 HeapFree(GetProcessHeap(), 0, Expanded
);
628 RtlFreeUnicodeString(&NtPathName
);
629 return ERROR_INVALID_PARAMETER
;
634 DPRINT("Error, Status = %08X\n", Status
);
635 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
636 HeapFree(GetProcessHeap(), 0, Expanded
);
637 RtlFreeUnicodeString(&NtPathName
);
638 return ERROR_INVALID_PARAMETER
;
644 DPRINT("Error, Status = %08X\n", Status
);
645 HeapFree(GetProcessHeap(), 0, Expanded
);
646 return ERROR_INVALID_PARAMETER
;
652 ScmCanonDriverImagePath(DWORD dwStartType
,
653 const wchar_t *lpServiceName
,
654 wchar_t **lpCanonName
)
657 SIZE_T ServiceNameLen
;
658 UNICODE_STRING NtServiceName
;
660 const WCHAR
*SourceName
= lpServiceName
;
662 /* Calculate the length of the service's name */
663 ServiceNameLen
= wcslen(lpServiceName
);
665 /* 12 is wcslen(L"\\SystemRoot\\") */
666 if (ServiceNameLen
> 12 &&
667 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
669 /* SystemRoot prefix is already included */
670 *lpCanonName
= HeapAlloc(GetProcessHeap(),
672 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
674 if (*lpCanonName
== NULL
)
676 DPRINT("Error allocating memory for canonized service name!\n");
677 return ERROR_NOT_ENOUGH_MEMORY
;
680 /* If it's a boot-time driver, it must be systemroot relative */
681 if (dwStartType
== SERVICE_BOOT_START
)
685 wcscpy(*lpCanonName
, SourceName
);
687 DPRINT("Canonicalized name %S\n", *lpCanonName
);
691 /* Check if it has %SystemRoot% (len=13) */
692 if (ServiceNameLen
> 13 &&
693 !_wcsnicmp(L
"%SystemRoot%\\", lpServiceName
, 13))
695 /* Substitute %SystemRoot% with \\SystemRoot\\ */
696 *lpCanonName
= HeapAlloc(GetProcessHeap(),
698 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
700 if (*lpCanonName
== NULL
)
702 DPRINT("Error allocating memory for canonized service name!\n");
703 return ERROR_NOT_ENOUGH_MEMORY
;
706 /* If it's a boot-time driver, it must be systemroot relative */
707 if (dwStartType
== SERVICE_BOOT_START
)
708 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
710 wcscat(*lpCanonName
, lpServiceName
+ 13);
712 DPRINT("Canonicalized name %S\n", *lpCanonName
);
716 /* Check if it's a relative path name */
717 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
719 *lpCanonName
= HeapAlloc(GetProcessHeap(),
721 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
723 if (*lpCanonName
== NULL
)
725 DPRINT("Error allocating memory for canonized service name!\n");
726 return ERROR_NOT_ENOUGH_MEMORY
;
729 /* Just copy it over without changing */
730 wcscpy(*lpCanonName
, lpServiceName
);
735 /* It seems to be a DOS path, convert it */
736 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
738 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
739 return ERROR_INVALID_PARAMETER
;
742 *lpCanonName
= HeapAlloc(GetProcessHeap(),
744 NtServiceName
.Length
+ sizeof(WCHAR
));
746 if (*lpCanonName
== NULL
)
748 DPRINT("Error allocating memory for canonized service name!\n");
749 RtlFreeUnicodeString(&NtServiceName
);
750 return ERROR_NOT_ENOUGH_MEMORY
;
753 /* Copy the string */
754 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
756 /* The unicode string is not needed anymore */
757 RtlFreeUnicodeString(&NtServiceName
);
759 if (dwStartType
!= SERVICE_BOOT_START
)
761 DPRINT("Canonicalized name %S\n", *lpCanonName
);
765 /* The service is boot-started, so must be relative */
766 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
769 /* There is a problem, free name and return */
770 HeapFree(GetProcessHeap(), 0, *lpCanonName
);
771 DPRINT("Error converting named!\n");
775 ASSERT(RelativeName
);
777 /* Copy that string */
778 wcscpy(*lpCanonName
, RelativeName
+ 12);
780 /* Free the allocated buffer */
781 HeapFree(GetProcessHeap(), 0, RelativeName
);
783 DPRINT("Canonicalized name %S\n", *lpCanonName
);
790 /* Internal recursive function */
791 /* Need to search for every dependency on every service */
793 Int_EnumDependentServicesW(HKEY hServicesKey
,
795 DWORD dwServiceState
,
796 PSERVICE
*lpServices
,
797 LPDWORD pcbBytesNeeded
,
798 LPDWORD lpServicesReturned
)
800 DWORD dwError
= ERROR_SUCCESS
;
801 WCHAR szNameBuf
[MAX_PATH
];
802 WCHAR szValueBuf
[MAX_PATH
];
803 WCHAR
*lpszNameBuf
= szNameBuf
;
804 WCHAR
*lpszValueBuf
= szValueBuf
;
808 PSERVICE lpCurrentService
;
809 HKEY hServiceEnumKey
;
810 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
811 DWORD dwDependServiceStrPtr
= 0;
812 DWORD dwRequiredSize
= 0;
814 /* Get the number of service keys */
815 dwError
= RegQueryInfoKeyW(hServicesKey
,
827 if (dwError
!= ERROR_SUCCESS
)
829 DPRINT("ERROR! Unable to get number of services keys.\n");
833 /* Iterate the service keys to see if another service depends on the this service */
834 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
837 dwError
= RegEnumKeyExW(hServicesKey
,
845 if (dwError
!= ERROR_SUCCESS
)
848 /* Open the Service key */
849 dwError
= RegOpenKeyExW(hServicesKey
,
854 if (dwError
!= ERROR_SUCCESS
)
859 /* Check for the DependOnService Value */
860 dwError
= RegQueryValueExW(hServiceEnumKey
,
864 (LPBYTE
)lpszValueBuf
,
867 /* FIXME: Handle load order. */
869 /* If the service found has a DependOnService value */
870 if (dwError
== ERROR_SUCCESS
)
872 dwDependServiceStrPtr
= 0;
874 /* Can be more than one Dependencies in the DependOnService string */
875 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
877 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
879 /* Get the current enumed service pointer */
880 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
882 /* Check for valid Service */
883 if (!lpCurrentService
)
885 /* This should never happen! */
886 DPRINT("This should not happen at this point, report to Developer\n");
887 return ERROR_NOT_FOUND
;
890 /* Determine state the service is in */
891 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
892 dwCurrentServiceState
= SERVICE_INACTIVE
;
894 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
895 if ((dwCurrentServiceState
== dwServiceState
) ||
896 (dwServiceState
== SERVICE_STATE_ALL
))
898 /* Calculate the required size */
899 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
900 dwRequiredSize
+= (DWORD
)((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
901 dwRequiredSize
+= (DWORD
)((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
903 /* Add the size for service name and display name pointers */
904 dwRequiredSize
+= (2 * sizeof(PVOID
));
906 /* increase the BytesNeeded size */
907 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
909 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
912 /* Recursive call to check for its dependencies */
913 Int_EnumDependentServicesW(hServicesKey
,
920 /* If the lpServices is valid set the service pointer */
922 lpServices
[*lpServicesReturned
] = lpCurrentService
;
924 *lpServicesReturned
= *lpServicesReturned
+ 1;
928 dwDependServiceStrPtr
+= (DWORD
)(wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
931 else if (*pcbBytesNeeded
)
933 dwError
= ERROR_SUCCESS
;
936 RegCloseKey(hServiceEnumKey
);
944 DWORD
RCloseServiceHandle(
945 LPSC_RPC_HANDLE hSCObject
)
947 PMANAGER_HANDLE hManager
;
948 PSERVICE_HANDLE hService
;
952 DWORD pcbBytesNeeded
= 0;
953 DWORD dwServicesReturned
= 0;
955 DPRINT("RCloseServiceHandle() called\n");
957 DPRINT("hSCObject = %p\n", *hSCObject
);
960 return ERROR_INVALID_HANDLE
;
962 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
963 hService
= ScmGetServiceFromHandle(*hSCObject
);
965 if (hManager
!= NULL
)
967 DPRINT("Found manager handle\n");
969 /* FIXME: add handle cleanup code */
971 HeapFree(GetProcessHeap(), 0, hManager
);
976 DPRINT("RCloseServiceHandle() done\n");
977 return ERROR_SUCCESS
;
979 else if (hService
!= NULL
)
981 DPRINT("Found service handle\n");
983 /* Lock the service database exlusively */
984 ScmLockDatabaseExclusive();
986 /* Get the pointer to the service record */
987 lpService
= hService
->ServiceEntry
;
989 /* FIXME: add handle cleanup code */
991 /* Free the handle */
992 HeapFree(GetProcessHeap(), 0, hService
);
995 ASSERT(lpService
->dwRefCount
> 0);
997 lpService
->dwRefCount
--;
998 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
999 lpService
->dwRefCount
);
1001 if (lpService
->dwRefCount
== 0)
1003 /* If this service has been marked for deletion */
1004 if (lpService
->bDeleted
)
1006 /* Open the Services Reg key */
1007 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1008 L
"System\\CurrentControlSet\\Services",
1010 KEY_SET_VALUE
| KEY_READ
,
1012 if (dwError
!= ERROR_SUCCESS
)
1014 DPRINT("Failed to open services key\n");
1015 ScmUnlockDatabase();
1019 /* Call the internal function with NULL, just to get bytes we need */
1020 Int_EnumDependentServicesW(hServicesKey
,
1025 &dwServicesReturned
);
1027 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */
1030 DPRINT("Deletion failed due to running dependencies.\n");
1031 RegCloseKey(hServicesKey
);
1032 ScmUnlockDatabase();
1033 return ERROR_SUCCESS
;
1036 /* There are no references and no runnning dependencies,
1037 it is now safe to delete the service */
1039 /* Delete the Service Key */
1040 dwError
= RegDeleteKeyW(hServicesKey
,
1041 lpService
->lpServiceName
);
1043 RegCloseKey(hServicesKey
);
1045 if (dwError
!= ERROR_SUCCESS
)
1047 DPRINT("Failed to Delete the Service Registry key\n");
1048 ScmUnlockDatabase();
1052 /* Delete the Service */
1053 ScmDeleteServiceRecord(lpService
);
1057 ScmUnlockDatabase();
1061 DPRINT("RCloseServiceHandle() done\n");
1062 return ERROR_SUCCESS
;
1065 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
1067 return ERROR_INVALID_HANDLE
;
1072 DWORD
RControlService(
1073 SC_RPC_HANDLE hService
,
1075 LPSERVICE_STATUS lpServiceStatus
)
1077 PSERVICE_HANDLE hSvc
;
1079 ACCESS_MASK DesiredAccess
;
1080 DWORD dwError
= ERROR_SUCCESS
;
1081 DWORD pcbBytesNeeded
= 0;
1082 DWORD dwServicesReturned
= 0;
1083 DWORD dwControlsAccepted
;
1084 DWORD dwCurrentState
;
1085 HKEY hServicesKey
= NULL
;
1087 DPRINT("RControlService() called\n");
1090 return ERROR_SHUTDOWN_IN_PROGRESS
;
1092 /* Check the service handle */
1093 hSvc
= ScmGetServiceFromHandle(hService
);
1096 DPRINT1("Invalid service handle!\n");
1097 return ERROR_INVALID_HANDLE
;
1100 /* Check the service entry point */
1101 lpService
= hSvc
->ServiceEntry
;
1102 if (lpService
== NULL
)
1104 DPRINT1("lpService == NULL!\n");
1105 return ERROR_INVALID_HANDLE
;
1108 /* Check access rights */
1111 case SERVICE_CONTROL_STOP
:
1112 DesiredAccess
= SERVICE_STOP
;
1115 case SERVICE_CONTROL_PAUSE
:
1116 case SERVICE_CONTROL_CONTINUE
:
1117 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
1120 case SERVICE_CONTROL_INTERROGATE
:
1121 DesiredAccess
= SERVICE_INTERROGATE
;
1125 if (dwControl
>= 128 && dwControl
<= 255)
1126 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
1128 return ERROR_INVALID_PARAMETER
;
1132 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1134 return ERROR_ACCESS_DENIED
;
1136 /* Return the current service status information */
1137 RtlCopyMemory(lpServiceStatus
,
1139 sizeof(SERVICE_STATUS
));
1141 if (dwControl
== SERVICE_CONTROL_STOP
)
1143 /* Check if the service has dependencies running as windows
1144 doesn't stop a service that does */
1146 /* Open the Services Reg key */
1147 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1148 L
"System\\CurrentControlSet\\Services",
1152 if (dwError
!= ERROR_SUCCESS
)
1154 DPRINT("Failed to open services key\n");
1158 /* Call the internal function with NULL, just to get bytes we need */
1159 Int_EnumDependentServicesW(hServicesKey
,
1164 &dwServicesReturned
);
1166 RegCloseKey(hServicesKey
);
1168 /* If pcbBytesNeeded is not zero then there are services running that
1169 are dependent on this service */
1170 if (pcbBytesNeeded
!= 0)
1172 DPRINT("Service has running dependencies. Failed to stop service.\n");
1173 return ERROR_DEPENDENT_SERVICES_RUNNING
;
1177 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1179 /* Send control code to the driver */
1180 dwError
= ScmControlDriver(lpService
,
1186 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
1187 dwCurrentState
= lpService
->Status
.dwCurrentState
;
1189 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1190 if (lpService
->lpImage
== NULL
|| dwCurrentState
== SERVICE_STOPPED
)
1191 return ERROR_SERVICE_NOT_ACTIVE
;
1193 /* Check the current state before sending a control request */
1194 switch (dwCurrentState
)
1196 case SERVICE_STOP_PENDING
:
1197 case SERVICE_STOPPED
:
1198 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1200 case SERVICE_START_PENDING
:
1203 case SERVICE_CONTROL_STOP
:
1206 case SERVICE_CONTROL_INTERROGATE
:
1207 RtlCopyMemory(lpServiceStatus
,
1209 sizeof(SERVICE_STATUS
));
1210 return ERROR_SUCCESS
;
1213 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1218 /* Check if the control code is acceptable to the service */
1221 case SERVICE_CONTROL_STOP
:
1222 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
1223 return ERROR_INVALID_SERVICE_CONTROL
;
1226 case SERVICE_CONTROL_PAUSE
:
1227 case SERVICE_CONTROL_CONTINUE
:
1228 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
1229 return ERROR_INVALID_SERVICE_CONTROL
;
1233 /* Send control code to the service */
1234 dwError
= ScmControlService(lpService
,
1237 /* Return service status information */
1238 RtlCopyMemory(lpServiceStatus
,
1240 sizeof(SERVICE_STATUS
));
1248 DWORD
RDeleteService(
1249 SC_RPC_HANDLE hService
)
1251 PSERVICE_HANDLE hSvc
;
1255 DPRINT("RDeleteService() called\n");
1258 return ERROR_SHUTDOWN_IN_PROGRESS
;
1260 hSvc
= ScmGetServiceFromHandle(hService
);
1263 DPRINT1("Invalid service handle!\n");
1264 return ERROR_INVALID_HANDLE
;
1267 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1269 return ERROR_ACCESS_DENIED
;
1271 lpService
= hSvc
->ServiceEntry
;
1272 if (lpService
== NULL
)
1274 DPRINT("lpService == NULL!\n");
1275 return ERROR_INVALID_HANDLE
;
1278 /* Lock the service database exclusively */
1279 ScmLockDatabaseExclusive();
1281 if (lpService
->bDeleted
)
1283 DPRINT("The service has already been marked for delete!\n");
1284 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1288 /* Mark service for delete */
1289 lpService
->bDeleted
= TRUE
;
1291 dwError
= ScmMarkServiceForDelete(lpService
);
1294 /* Unlock the service database */
1295 ScmUnlockDatabase();
1297 DPRINT("RDeleteService() done\n");
1304 DWORD
RLockServiceDatabase(
1305 SC_RPC_HANDLE hSCManager
,
1306 LPSC_RPC_LOCK lpLock
)
1308 PMANAGER_HANDLE hMgr
;
1310 DPRINT("RLockServiceDatabase() called\n");
1314 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
1317 DPRINT1("Invalid service manager handle!\n");
1318 return ERROR_INVALID_HANDLE
;
1321 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
1323 return ERROR_ACCESS_DENIED
;
1325 return ScmAcquireServiceStartLock(FALSE
, lpLock
);
1330 DWORD
RQueryServiceObjectSecurity(
1331 SC_RPC_HANDLE hService
,
1332 SECURITY_INFORMATION dwSecurityInformation
,
1333 LPBYTE lpSecurityDescriptor
,
1335 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1337 PSERVICE_HANDLE hSvc
;
1339 ULONG DesiredAccess
= 0;
1341 DWORD dwBytesNeeded
;
1345 SECURITY_DESCRIPTOR ObjectDescriptor
;
1347 DPRINT("RQueryServiceObjectSecurity() called\n");
1349 hSvc
= ScmGetServiceFromHandle(hService
);
1352 DPRINT1("Invalid service handle!\n");
1353 return ERROR_INVALID_HANDLE
;
1356 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1357 GROUP_SECURITY_INFORMATION
|
1358 OWNER_SECURITY_INFORMATION
))
1359 DesiredAccess
|= READ_CONTROL
;
1361 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1362 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1364 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1367 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1368 return ERROR_ACCESS_DENIED
;
1371 lpService
= hSvc
->ServiceEntry
;
1372 if (lpService
== NULL
)
1374 DPRINT("lpService == NULL!\n");
1375 return ERROR_INVALID_HANDLE
;
1378 /* Lock the service database */
1379 ScmLockDatabaseShared();
1383 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
1385 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
1386 dwSecurityInformation
,
1387 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1391 /* Unlock the service database */
1392 ScmUnlockDatabase();
1394 if (NT_SUCCESS(Status
))
1396 *pcbBytesNeeded
= dwBytesNeeded
;
1397 dwError
= STATUS_SUCCESS
;
1399 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1401 *pcbBytesNeeded
= dwBytesNeeded
;
1402 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1404 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1406 dwError
= ERROR_GEN_FAILURE
;
1410 dwError
= RtlNtStatusToDosError(Status
);
1418 DWORD
RSetServiceObjectSecurity(
1419 SC_RPC_HANDLE hService
,
1420 DWORD dwSecurityInformation
,
1421 LPBYTE lpSecurityDescriptor
,
1422 DWORD dwSecuityDescriptorSize
)
1424 PSERVICE_HANDLE hSvc
;
1426 ULONG DesiredAccess
= 0;
1427 /* HANDLE hToken = NULL; */
1429 /* NTSTATUS Status; */
1432 DPRINT("RSetServiceObjectSecurity() called\n");
1434 hSvc
= ScmGetServiceFromHandle(hService
);
1437 DPRINT1("Invalid service handle!\n");
1438 return ERROR_INVALID_HANDLE
;
1441 if (dwSecurityInformation
== 0 ||
1442 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1443 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1444 return ERROR_INVALID_PARAMETER
;
1446 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1447 return ERROR_INVALID_PARAMETER
;
1449 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1450 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1452 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1453 DesiredAccess
|= WRITE_DAC
;
1455 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1456 DesiredAccess
|= WRITE_OWNER
;
1458 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1459 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1460 return ERROR_INVALID_PARAMETER
;
1462 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1463 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1464 return ERROR_INVALID_PARAMETER
;
1466 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1469 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1470 return ERROR_ACCESS_DENIED
;
1473 lpService
= hSvc
->ServiceEntry
;
1474 if (lpService
== NULL
)
1476 DPRINT("lpService == NULL!\n");
1477 return ERROR_INVALID_HANDLE
;
1480 if (lpService
->bDeleted
)
1481 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1484 RpcImpersonateClient(NULL
);
1486 Status
= NtOpenThreadToken(NtCurrentThread(),
1490 if (!NT_SUCCESS(Status
))
1491 return RtlNtStatusToDosError(Status
);
1496 /* Lock the service database exclusive */
1497 ScmLockDatabaseExclusive();
1500 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1501 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1502 &lpService
->lpSecurityDescriptor
,
1505 if (!NT_SUCCESS(Status
))
1507 dwError
= RtlNtStatusToDosError(Status
);
1512 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1513 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1515 if (dwError
!= ERROR_SUCCESS
)
1519 dwError
= ERROR_SUCCESS
;
1520 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1521 // lpService->lpSecurityDescriptor);
1523 RegFlushKey(hServiceKey
);
1524 RegCloseKey(hServiceKey
);
1533 /* Unlock service database */
1534 ScmUnlockDatabase();
1536 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1543 DWORD
RQueryServiceStatus(
1544 SC_RPC_HANDLE hService
,
1545 LPSERVICE_STATUS lpServiceStatus
)
1547 PSERVICE_HANDLE hSvc
;
1550 DPRINT("RQueryServiceStatus() called\n");
1553 return ERROR_SHUTDOWN_IN_PROGRESS
;
1555 hSvc
= ScmGetServiceFromHandle(hService
);
1558 DPRINT1("Invalid service handle!\n");
1559 return ERROR_INVALID_HANDLE
;
1562 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1563 SERVICE_QUERY_STATUS
))
1565 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1566 return ERROR_ACCESS_DENIED
;
1569 lpService
= hSvc
->ServiceEntry
;
1570 if (lpService
== NULL
)
1572 DPRINT("lpService == NULL!\n");
1573 return ERROR_INVALID_HANDLE
;
1576 /* Lock the service database shared */
1577 ScmLockDatabaseShared();
1579 /* Return service status information */
1580 RtlCopyMemory(lpServiceStatus
,
1582 sizeof(SERVICE_STATUS
));
1584 /* Unlock the service database */
1585 ScmUnlockDatabase();
1587 return ERROR_SUCCESS
;
1592 ScmIsValidServiceState(DWORD dwCurrentState
)
1594 switch (dwCurrentState
)
1596 case SERVICE_STOPPED
:
1597 case SERVICE_START_PENDING
:
1598 case SERVICE_STOP_PENDING
:
1599 case SERVICE_RUNNING
:
1600 case SERVICE_CONTINUE_PENDING
:
1601 case SERVICE_PAUSE_PENDING
:
1602 case SERVICE_PAUSED
:
1612 DWORD
RSetServiceStatus(
1613 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1614 LPSERVICE_STATUS lpServiceStatus
)
1617 DWORD dwPreviousState
;
1618 LPCWSTR lpErrorStrings
[2];
1619 WCHAR szErrorBuffer
[32];
1621 DPRINT("RSetServiceStatus() called\n");
1622 DPRINT("hServiceStatus = %lu\n", hServiceStatus
);
1623 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1624 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1625 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1626 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1627 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1628 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1629 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1631 if (hServiceStatus
== 0)
1633 DPRINT("hServiceStatus == NULL!\n");
1634 return ERROR_INVALID_HANDLE
;
1637 lpService
= (PSERVICE
)hServiceStatus
;
1639 /* Check current state */
1640 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1642 DPRINT("Invalid service state!\n");
1643 return ERROR_INVALID_DATA
;
1646 /* Check service type */
1647 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1648 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1650 DPRINT("Invalid service type!\n");
1651 return ERROR_INVALID_DATA
;
1654 /* Check accepted controls */
1655 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1657 DPRINT("Invalid controls accepted!\n");
1658 return ERROR_INVALID_DATA
;
1661 /* Lock the service database exclusively */
1662 ScmLockDatabaseExclusive();
1664 /* Save the current service state */
1665 dwPreviousState
= lpService
->Status
.dwCurrentState
;
1667 RtlCopyMemory(&lpService
->Status
,
1669 sizeof(SERVICE_STATUS
));
1671 /* Unlock the service database */
1672 ScmUnlockDatabase();
1674 /* Log a failed service stop */
1675 if ((lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
) &&
1676 (dwPreviousState
!= SERVICE_STOPPED
))
1678 if (lpServiceStatus
->dwWin32ExitCode
!= ERROR_SUCCESS
)
1680 swprintf(szErrorBuffer
, L
"%lu", lpServiceStatus
->dwWin32ExitCode
);
1681 lpErrorStrings
[0] = lpService
->lpDisplayName
;
1682 lpErrorStrings
[1] = szErrorBuffer
;
1684 ScmLogError(EVENT_SERVICE_EXIT_FAILED
,
1690 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1691 DPRINT("RSetServiceStatus() done\n");
1693 return ERROR_SUCCESS
;
1698 DWORD
RUnlockServiceDatabase(
1701 DPRINT("RUnlockServiceDatabase(%p)\n", Lock
);
1702 return ScmReleaseServiceStartLock(Lock
);
1707 DWORD
RNotifyBootConfigStatus(
1708 SVCCTL_HANDLEW lpMachineName
,
1709 DWORD BootAcceptable
)
1711 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1712 return ERROR_SUCCESS
;
1715 // return ERROR_CALL_NOT_IMPLEMENTED;
1720 DWORD
RI_ScSetServiceBitsW(
1721 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1722 DWORD dwServiceBits
,
1724 int bUpdateImmediately
,
1728 return ERROR_CALL_NOT_IMPLEMENTED
;
1733 DWORD
RChangeServiceConfigW(
1734 SC_RPC_HANDLE hService
,
1735 DWORD dwServiceType
,
1737 DWORD dwErrorControl
,
1738 LPWSTR lpBinaryPathName
,
1739 LPWSTR lpLoadOrderGroup
,
1741 LPBYTE lpDependencies
,
1743 LPWSTR lpServiceStartName
,
1746 LPWSTR lpDisplayName
)
1748 DWORD dwError
= ERROR_SUCCESS
;
1749 PSERVICE_HANDLE hSvc
;
1750 PSERVICE lpService
= NULL
;
1751 HKEY hServiceKey
= NULL
;
1752 LPWSTR lpDisplayNameW
= NULL
;
1753 LPWSTR lpImagePathW
= NULL
;
1755 DPRINT("RChangeServiceConfigW() called\n");
1756 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1757 DPRINT("dwStartType = %lu\n", dwStartType
);
1758 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1759 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1760 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1761 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1764 return ERROR_SHUTDOWN_IN_PROGRESS
;
1766 hSvc
= ScmGetServiceFromHandle(hService
);
1769 DPRINT1("Invalid service handle!\n");
1770 return ERROR_INVALID_HANDLE
;
1773 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1774 SERVICE_CHANGE_CONFIG
))
1776 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1777 return ERROR_ACCESS_DENIED
;
1780 lpService
= hSvc
->ServiceEntry
;
1781 if (lpService
== NULL
)
1783 DPRINT("lpService == NULL!\n");
1784 return ERROR_INVALID_HANDLE
;
1787 /* Lock the service database exclusively */
1788 ScmLockDatabaseExclusive();
1790 if (lpService
->bDeleted
)
1792 DPRINT("The service has already been marked for delete!\n");
1793 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1797 /* Open the service key */
1798 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1801 if (dwError
!= ERROR_SUCCESS
)
1804 /* Write service data to the registry */
1805 /* Set the display name */
1806 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1808 RegSetValueExW(hServiceKey
,
1812 (LPBYTE
)lpDisplayName
,
1813 (DWORD
)((wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
)));
1815 /* Update the display name */
1816 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
1818 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1819 if (lpDisplayNameW
== NULL
)
1821 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1825 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1826 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1828 lpService
->lpDisplayName
= lpDisplayNameW
;
1831 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1833 /* Set the service type */
1834 dwError
= RegSetValueExW(hServiceKey
,
1838 (LPBYTE
)&dwServiceType
,
1840 if (dwError
!= ERROR_SUCCESS
)
1843 lpService
->Status
.dwServiceType
= dwServiceType
;
1846 if (dwStartType
!= SERVICE_NO_CHANGE
)
1848 /* Set the start value */
1849 dwError
= RegSetValueExW(hServiceKey
,
1853 (LPBYTE
)&dwStartType
,
1855 if (dwError
!= ERROR_SUCCESS
)
1858 lpService
->dwStartType
= dwStartType
;
1861 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1863 /* Set the error control value */
1864 dwError
= RegSetValueExW(hServiceKey
,
1868 (LPBYTE
)&dwErrorControl
,
1870 if (dwError
!= ERROR_SUCCESS
)
1873 lpService
->dwErrorControl
= dwErrorControl
;
1876 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1878 /* Set the image path */
1879 lpImagePathW
= lpBinaryPathName
;
1881 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1883 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
1887 if (dwError
!= ERROR_SUCCESS
)
1891 dwError
= RegSetValueExW(hServiceKey
,
1895 (LPBYTE
)lpImagePathW
,
1896 (DWORD
)((wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
)));
1898 if (lpImagePathW
!= lpBinaryPathName
)
1899 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
1901 if (dwError
!= ERROR_SUCCESS
)
1905 /* Set the group name */
1906 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1908 dwError
= RegSetValueExW(hServiceKey
,
1912 (LPBYTE
)lpLoadOrderGroup
,
1913 (DWORD
)((wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
)));
1914 if (dwError
!= ERROR_SUCCESS
)
1917 dwError
= ScmSetServiceGroup(lpService
,
1919 if (dwError
!= ERROR_SUCCESS
)
1923 if (lpdwTagId
!= NULL
)
1925 dwError
= ScmAssignNewTag(lpService
);
1926 if (dwError
!= ERROR_SUCCESS
)
1929 dwError
= RegSetValueExW(hServiceKey
,
1933 (LPBYTE
)&lpService
->dwTag
,
1935 if (dwError
!= ERROR_SUCCESS
)
1938 *lpdwTagId
= lpService
->dwTag
;
1941 /* Write dependencies */
1942 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1944 dwError
= ScmWriteDependencies(hServiceKey
,
1945 (LPWSTR
)lpDependencies
,
1947 if (dwError
!= ERROR_SUCCESS
)
1951 if (lpPassword
!= NULL
)
1953 /* FIXME: Decrypt and write password */
1957 if (hServiceKey
!= NULL
)
1958 RegCloseKey(hServiceKey
);
1960 /* Unlock the service database */
1961 ScmUnlockDatabase();
1963 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1970 DWORD
RCreateServiceW(
1971 SC_RPC_HANDLE hSCManager
,
1972 LPCWSTR lpServiceName
,
1973 LPCWSTR lpDisplayName
,
1974 DWORD dwDesiredAccess
,
1975 DWORD dwServiceType
,
1977 DWORD dwErrorControl
,
1978 LPCWSTR lpBinaryPathName
,
1979 LPCWSTR lpLoadOrderGroup
,
1981 LPBYTE lpDependencies
,
1983 LPCWSTR lpServiceStartName
,
1986 LPSC_RPC_HANDLE lpServiceHandle
)
1988 PMANAGER_HANDLE hManager
;
1989 DWORD dwError
= ERROR_SUCCESS
;
1990 PSERVICE lpService
= NULL
;
1991 SC_HANDLE hServiceHandle
= NULL
;
1992 LPWSTR lpImagePath
= NULL
;
1993 HKEY hServiceKey
= NULL
;
1994 LPWSTR lpObjectName
;
1996 DPRINT("RCreateServiceW() called\n");
1997 DPRINT("lpServiceName = %S\n", lpServiceName
);
1998 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1999 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
2000 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2001 DPRINT("dwStartType = %lu\n", dwStartType
);
2002 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2003 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
2004 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
2005 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
2008 return ERROR_SHUTDOWN_IN_PROGRESS
;
2010 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2011 if (hManager
== NULL
)
2013 DPRINT1("Invalid service manager handle!\n");
2014 return ERROR_INVALID_HANDLE
;
2017 /* Check access rights */
2018 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2019 SC_MANAGER_CREATE_SERVICE
))
2021 DPRINT("Insufficient access rights! 0x%lx\n",
2022 hManager
->Handle
.DesiredAccess
);
2023 return ERROR_ACCESS_DENIED
;
2026 if (wcslen(lpServiceName
) == 0)
2028 return ERROR_INVALID_NAME
;
2031 if (wcslen(lpBinaryPathName
) == 0)
2033 return ERROR_INVALID_PARAMETER
;
2036 /* Check for invalid service type value */
2037 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2038 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2039 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2040 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2041 return ERROR_INVALID_PARAMETER
;
2043 /* Check for invalid start type value */
2044 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2045 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2046 (dwStartType
!= SERVICE_AUTO_START
) &&
2047 (dwStartType
!= SERVICE_DEMAND_START
) &&
2048 (dwStartType
!= SERVICE_DISABLED
))
2049 return ERROR_INVALID_PARAMETER
;
2051 /* Only drivers can be boot start or system start services */
2052 if ((dwStartType
== SERVICE_BOOT_START
) ||
2053 (dwStartType
== SERVICE_SYSTEM_START
))
2055 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2056 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2057 return ERROR_INVALID_PARAMETER
;
2060 /* Check for invalid error control value */
2061 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2062 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2063 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2064 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2065 return ERROR_INVALID_PARAMETER
;
2067 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2068 (lpServiceStartName
))
2070 return ERROR_INVALID_PARAMETER
;
2073 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2075 return ERROR_INVALID_PARAMETER
;
2078 /* Lock the service database exclusively */
2079 ScmLockDatabaseExclusive();
2081 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2084 /* Unlock the service database */
2085 ScmUnlockDatabase();
2087 /* Check if it is marked for deletion */
2088 if (lpService
->bDeleted
)
2089 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2091 /* Return Error exist */
2092 return ERROR_SERVICE_EXISTS
;
2095 if (lpDisplayName
!= NULL
&&
2096 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2098 /* Unlock the service database */
2099 ScmUnlockDatabase();
2101 return ERROR_DUPLICATE_SERVICE_NAME
;
2104 if (dwServiceType
& SERVICE_DRIVER
)
2106 dwError
= ScmCanonDriverImagePath(dwStartType
,
2109 if (dwError
!= ERROR_SUCCESS
)
2114 if (dwStartType
== SERVICE_BOOT_START
||
2115 dwStartType
== SERVICE_SYSTEM_START
)
2117 /* Unlock the service database */
2118 ScmUnlockDatabase();
2120 return ERROR_INVALID_PARAMETER
;
2124 /* Allocate a new service entry */
2125 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2127 if (dwError
!= ERROR_SUCCESS
)
2130 /* Fill the new service entry */
2131 lpService
->Status
.dwServiceType
= dwServiceType
;
2132 lpService
->dwStartType
= dwStartType
;
2133 lpService
->dwErrorControl
= dwErrorControl
;
2135 /* Fill the display name */
2136 if (lpDisplayName
!= NULL
&&
2137 *lpDisplayName
!= 0 &&
2138 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2140 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(),
2142 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2143 if (lpService
->lpDisplayName
== NULL
)
2145 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2148 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2151 /* Assign the service to a group */
2152 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2154 dwError
= ScmSetServiceGroup(lpService
,
2156 if (dwError
!= ERROR_SUCCESS
)
2160 /* Assign a new tag */
2161 if (lpdwTagId
!= NULL
)
2163 dwError
= ScmAssignNewTag(lpService
);
2164 if (dwError
!= ERROR_SUCCESS
)
2168 /* Write service data to the registry */
2169 /* Create the service key */
2170 dwError
= ScmCreateServiceKey(lpServiceName
,
2173 if (dwError
!= ERROR_SUCCESS
)
2176 /* Set the display name */
2177 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2179 RegSetValueExW(hServiceKey
,
2183 (LPBYTE
)lpDisplayName
,
2184 (DWORD
)((wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
)));
2187 /* Set the service type */
2188 dwError
= RegSetValueExW(hServiceKey
,
2192 (LPBYTE
)&dwServiceType
,
2194 if (dwError
!= ERROR_SUCCESS
)
2197 /* Set the start value */
2198 dwError
= RegSetValueExW(hServiceKey
,
2202 (LPBYTE
)&dwStartType
,
2204 if (dwError
!= ERROR_SUCCESS
)
2207 /* Set the error control value */
2208 dwError
= RegSetValueExW(hServiceKey
,
2212 (LPBYTE
)&dwErrorControl
,
2214 if (dwError
!= ERROR_SUCCESS
)
2217 /* Set the image path */
2218 if (dwServiceType
& SERVICE_WIN32
)
2220 dwError
= RegSetValueExW(hServiceKey
,
2224 (LPBYTE
)lpBinaryPathName
,
2225 (DWORD
)((wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
)));
2226 if (dwError
!= ERROR_SUCCESS
)
2229 else if (dwServiceType
& SERVICE_DRIVER
)
2231 dwError
= RegSetValueExW(hServiceKey
,
2235 (LPBYTE
)lpImagePath
,
2236 (DWORD
)((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
)));
2237 if (dwError
!= ERROR_SUCCESS
)
2241 /* Set the group name */
2242 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2244 dwError
= RegSetValueExW(hServiceKey
,
2248 (LPBYTE
)lpLoadOrderGroup
,
2249 (DWORD
)((wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
)));
2250 if (dwError
!= ERROR_SUCCESS
)
2254 if (lpdwTagId
!= NULL
)
2256 dwError
= RegSetValueExW(hServiceKey
,
2260 (LPBYTE
)&lpService
->dwTag
,
2262 if (dwError
!= ERROR_SUCCESS
)
2266 /* Write dependencies */
2267 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2269 dwError
= ScmWriteDependencies(hServiceKey
,
2270 (LPCWSTR
)lpDependencies
,
2272 if (dwError
!= ERROR_SUCCESS
)
2276 /* Write service start name */
2277 if (dwServiceType
& SERVICE_WIN32
)
2279 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2280 dwError
= RegSetValueExW(hServiceKey
,
2284 (LPBYTE
)lpObjectName
,
2285 (DWORD
)((wcslen(lpObjectName
) + 1) * sizeof(WCHAR
)));
2286 if (dwError
!= ERROR_SUCCESS
)
2290 if (lpPassword
!= NULL
)
2292 /* FIXME: Decrypt and write password */
2295 dwError
= ScmCreateServiceHandle(lpService
,
2297 if (dwError
!= ERROR_SUCCESS
)
2300 dwError
= ScmCheckAccess(hServiceHandle
,
2302 if (dwError
!= ERROR_SUCCESS
)
2305 lpService
->dwRefCount
= 1;
2306 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2309 /* Unlock the service database */
2310 ScmUnlockDatabase();
2312 if (hServiceKey
!= NULL
)
2313 RegCloseKey(hServiceKey
);
2315 if (dwError
== ERROR_SUCCESS
)
2317 DPRINT("hService %p\n", hServiceHandle
);
2318 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2320 if (lpdwTagId
!= NULL
)
2321 *lpdwTagId
= lpService
->dwTag
;
2325 if (lpService
!= NULL
&&
2326 lpService
->lpServiceName
!= NULL
)
2328 /* Release the display name buffer */
2329 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2334 /* Remove the service handle */
2335 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2338 if (lpService
!= NULL
)
2340 /* FIXME: remove the service entry */
2344 if (lpImagePath
!= NULL
)
2345 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2347 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2354 DWORD
REnumDependentServicesW(
2355 SC_RPC_HANDLE hService
,
2356 DWORD dwServiceState
,
2359 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2360 LPBOUNDED_DWORD_256K lpServicesReturned
)
2362 DWORD dwError
= ERROR_SUCCESS
;
2363 DWORD dwServicesReturned
= 0;
2364 DWORD dwServiceCount
;
2365 HKEY hServicesKey
= NULL
;
2366 PSERVICE_HANDLE hSvc
;
2367 PSERVICE lpService
= NULL
;
2368 PSERVICE
*lpServicesArray
= NULL
;
2369 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2372 *pcbBytesNeeded
= 0;
2373 *lpServicesReturned
= 0;
2375 DPRINT("REnumDependentServicesW() called\n");
2377 hSvc
= ScmGetServiceFromHandle(hService
);
2380 DPRINT1("Invalid service handle!\n");
2381 return ERROR_INVALID_HANDLE
;
2384 lpService
= hSvc
->ServiceEntry
;
2386 /* Check access rights */
2387 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2388 SC_MANAGER_ENUMERATE_SERVICE
))
2390 DPRINT("Insufficient access rights! 0x%lx\n",
2391 hSvc
->Handle
.DesiredAccess
);
2392 return ERROR_ACCESS_DENIED
;
2395 /* Open the Services Reg key */
2396 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2397 L
"System\\CurrentControlSet\\Services",
2401 if (dwError
!= ERROR_SUCCESS
)
2404 /* First determine the bytes needed and get the number of dependent services */
2405 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2410 &dwServicesReturned
);
2411 if (dwError
!= ERROR_SUCCESS
)
2414 /* If buffer size is less than the bytes needed or pointer is null */
2415 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2417 dwError
= ERROR_MORE_DATA
;
2421 /* Allocate memory for array of service pointers */
2422 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2424 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2425 if (!lpServicesArray
)
2427 DPRINT1("Could not allocate a buffer!!\n");
2428 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2432 dwServicesReturned
= 0;
2433 *pcbBytesNeeded
= 0;
2435 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2440 &dwServicesReturned
);
2441 if (dwError
!= ERROR_SUCCESS
)
2446 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
)lpServices
;
2447 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2449 /* Copy EnumDepenedentService to Buffer */
2450 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2452 lpService
= lpServicesArray
[dwServiceCount
];
2454 /* Copy status info */
2455 memcpy(&lpServicesPtr
->ServiceStatus
,
2457 sizeof(SERVICE_STATUS
));
2459 /* Copy display name */
2460 wcscpy(lpStr
, lpService
->lpDisplayName
);
2461 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2462 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2464 /* Copy service name */
2465 wcscpy(lpStr
, lpService
->lpServiceName
);
2466 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2467 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2472 *lpServicesReturned
= dwServicesReturned
;
2475 if (lpServicesArray
!= NULL
)
2476 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2478 RegCloseKey(hServicesKey
);
2480 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2487 DWORD
REnumServicesStatusW(
2488 SC_RPC_HANDLE hSCManager
,
2489 DWORD dwServiceType
,
2490 DWORD dwServiceState
,
2493 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2494 LPBOUNDED_DWORD_256K lpServicesReturned
,
2495 LPBOUNDED_DWORD_256K lpResumeHandle
)
2497 /* Enumerate all the services, not regarding of their group */
2498 return REnumServiceGroupW(hSCManager
,
2511 DWORD
ROpenSCManagerW(
2512 LPWSTR lpMachineName
,
2513 LPWSTR lpDatabaseName
,
2514 DWORD dwDesiredAccess
,
2515 LPSC_RPC_HANDLE lpScHandle
)
2520 DPRINT("ROpenSCManagerW() called\n");
2521 DPRINT("lpMachineName = %p\n", lpMachineName
);
2522 DPRINT("lpMachineName: %S\n", lpMachineName
);
2523 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2524 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2525 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2528 return ERROR_SHUTDOWN_IN_PROGRESS
;
2531 return ERROR_INVALID_PARAMETER
;
2533 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2535 if (dwError
!= ERROR_SUCCESS
)
2537 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2541 /* Check the desired access */
2542 dwError
= ScmCheckAccess(hHandle
,
2543 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2544 if (dwError
!= ERROR_SUCCESS
)
2546 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2547 HeapFree(GetProcessHeap(), 0, hHandle
);
2551 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2552 DPRINT("*hScm = %p\n", *lpScHandle
);
2554 DPRINT("ROpenSCManagerW() done\n");
2556 return ERROR_SUCCESS
;
2561 DWORD
ROpenServiceW(
2562 SC_RPC_HANDLE hSCManager
,
2563 LPWSTR lpServiceName
,
2564 DWORD dwDesiredAccess
,
2565 LPSC_RPC_HANDLE lpServiceHandle
)
2568 PMANAGER_HANDLE hManager
;
2570 DWORD dwError
= ERROR_SUCCESS
;
2572 DPRINT("ROpenServiceW() called\n");
2573 DPRINT("hSCManager = %p\n", hSCManager
);
2574 DPRINT("lpServiceName = %p\n", lpServiceName
);
2575 DPRINT("lpServiceName: %S\n", lpServiceName
);
2576 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2579 return ERROR_SHUTDOWN_IN_PROGRESS
;
2581 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2582 if (hManager
== NULL
)
2584 DPRINT1("Invalid service manager handle!\n");
2585 return ERROR_INVALID_HANDLE
;
2588 if (!lpServiceHandle
)
2589 return ERROR_INVALID_PARAMETER
;
2592 return ERROR_INVALID_ADDRESS
;
2594 /* Lock the service database exclusive */
2595 ScmLockDatabaseExclusive();
2597 /* Get service database entry */
2598 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2599 if (lpService
== NULL
)
2601 DPRINT("Could not find a service!\n");
2602 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2606 /* Create a service handle */
2607 dwError
= ScmCreateServiceHandle(lpService
,
2609 if (dwError
!= ERROR_SUCCESS
)
2611 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2615 /* Check the desired access */
2616 dwError
= ScmCheckAccess(hHandle
,
2618 if (dwError
!= ERROR_SUCCESS
)
2620 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2621 HeapFree(GetProcessHeap(), 0, hHandle
);
2625 lpService
->dwRefCount
++;
2626 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2628 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2629 DPRINT("*hService = %p\n", *lpServiceHandle
);
2632 /* Unlock the service database */
2633 ScmUnlockDatabase();
2635 DPRINT("ROpenServiceW() done\n");
2642 DWORD
RQueryServiceConfigW(
2643 SC_RPC_HANDLE hService
,
2644 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2646 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2648 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2649 DWORD dwError
= ERROR_SUCCESS
;
2650 PSERVICE_HANDLE hSvc
;
2651 PSERVICE lpService
= NULL
;
2652 HKEY hServiceKey
= NULL
;
2653 LPWSTR lpImagePath
= NULL
;
2654 LPWSTR lpServiceStartName
= NULL
;
2655 LPWSTR lpDependencies
= NULL
;
2656 DWORD dwDependenciesLength
= 0;
2657 DWORD dwRequiredSize
;
2658 WCHAR lpEmptyString
[] = {0,0};
2661 DPRINT("RQueryServiceConfigW() called\n");
2664 return ERROR_SHUTDOWN_IN_PROGRESS
;
2666 hSvc
= ScmGetServiceFromHandle(hService
);
2669 DPRINT1("Invalid service handle!\n");
2670 return ERROR_INVALID_HANDLE
;
2673 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2674 SERVICE_QUERY_CONFIG
))
2676 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2677 return ERROR_ACCESS_DENIED
;
2680 lpService
= hSvc
->ServiceEntry
;
2681 if (lpService
== NULL
)
2683 DPRINT("lpService == NULL!\n");
2684 return ERROR_INVALID_HANDLE
;
2687 /* Lock the service database shared */
2688 ScmLockDatabaseShared();
2690 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2693 if (dwError
!= ERROR_SUCCESS
)
2696 /* Read the image path */
2697 dwError
= ScmReadString(hServiceKey
,
2700 if (dwError
!= ERROR_SUCCESS
)
2703 /* Read the service start name */
2704 ScmReadString(hServiceKey
,
2706 &lpServiceStartName
);
2708 /* Read the dependencies */
2709 ScmReadDependencies(hServiceKey
,
2711 &dwDependenciesLength
);
2713 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2715 if (lpImagePath
!= NULL
)
2716 dwRequiredSize
+= (DWORD
)((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2718 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2720 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
2721 dwRequiredSize
+= (DWORD
)((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2723 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2725 if (lpDependencies
!= NULL
)
2726 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2728 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2730 if (lpServiceStartName
!= NULL
)
2731 dwRequiredSize
+= (DWORD
)((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2733 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2735 if (lpService
->lpDisplayName
!= NULL
)
2736 dwRequiredSize
+= (DWORD
)((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2738 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2740 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2742 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2746 lpServiceConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2747 lpServiceConfig
->dwStartType
= lpService
->dwStartType
;
2748 lpServiceConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2749 lpServiceConfig
->dwTagId
= lpService
->dwTag
;
2751 lpStr
= (LPWSTR
)(lpServiceConfig
+ 1);
2753 /* Append the image path */
2754 if (lpImagePath
!= NULL
)
2756 wcscpy(lpStr
, lpImagePath
);
2760 wcscpy(lpStr
, lpEmptyString
);
2763 lpServiceConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2764 lpStr
+= (wcslen(lpStr
) + 1);
2766 /* Append the group name */
2767 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
2769 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2773 wcscpy(lpStr
, lpEmptyString
);
2776 lpServiceConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2777 lpStr
+= (wcslen(lpStr
) + 1);
2779 /* Append Dependencies */
2780 if (lpDependencies
!= NULL
)
2784 dwDependenciesLength
* sizeof(WCHAR
));
2788 wcscpy(lpStr
, lpEmptyString
);
2791 lpServiceConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2792 if (lpDependencies
!= NULL
)
2793 lpStr
+= dwDependenciesLength
;
2795 lpStr
+= (wcslen(lpStr
) + 1);
2797 /* Append the service start name */
2798 if (lpServiceStartName
!= NULL
)
2800 wcscpy(lpStr
, lpServiceStartName
);
2804 wcscpy(lpStr
, lpEmptyString
);
2807 lpServiceConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2808 lpStr
+= (wcslen(lpStr
) + 1);
2810 /* Append the display name */
2811 if (lpService
->lpDisplayName
!= NULL
)
2813 wcscpy(lpStr
, lpService
->lpDisplayName
);
2817 wcscpy(lpStr
, lpEmptyString
);
2820 lpServiceConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
2823 if (pcbBytesNeeded
!= NULL
)
2824 *pcbBytesNeeded
= dwRequiredSize
;
2827 /* Unlock the service database */
2828 ScmUnlockDatabase();
2830 if (lpImagePath
!= NULL
)
2831 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2833 if (lpServiceStartName
!= NULL
)
2834 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2836 if (lpDependencies
!= NULL
)
2837 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2839 if (hServiceKey
!= NULL
)
2840 RegCloseKey(hServiceKey
);
2842 DPRINT("RQueryServiceConfigW() done\n");
2849 DWORD
RQueryServiceLockStatusW(
2850 SC_RPC_HANDLE hSCManager
,
2851 LPBYTE lpBuf
, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
2853 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2855 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
= (LPQUERY_SERVICE_LOCK_STATUSW
)lpBuf
;
2856 PMANAGER_HANDLE hMgr
;
2857 DWORD dwRequiredSize
;
2859 if (!lpLockStatus
|| !pcbBytesNeeded
)
2860 return ERROR_INVALID_PARAMETER
;
2862 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
2865 DPRINT1("Invalid service manager handle!\n");
2866 return ERROR_INVALID_HANDLE
;
2869 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
2870 SC_MANAGER_QUERY_LOCK_STATUS
))
2872 DPRINT("Insufficient access rights! 0x%lx\n", hMgr
->Handle
.DesiredAccess
);
2873 return ERROR_ACCESS_DENIED
;
2876 /* FIXME: we need to compute instead the real length of the owner name */
2877 dwRequiredSize
= sizeof(QUERY_SERVICE_LOCK_STATUSW
) + sizeof(WCHAR
);
2878 *pcbBytesNeeded
= dwRequiredSize
;
2880 if (cbBufSize
< dwRequiredSize
)
2881 return ERROR_INSUFFICIENT_BUFFER
;
2883 ScmQueryServiceLockStatusW(lpLockStatus
);
2885 return ERROR_SUCCESS
;
2890 DWORD
RStartServiceW(
2891 SC_RPC_HANDLE hService
,
2893 LPSTRING_PTRSW argv
)
2895 DWORD dwError
= ERROR_SUCCESS
;
2896 PSERVICE_HANDLE hSvc
;
2897 PSERVICE lpService
= NULL
;
2902 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
2903 DPRINT(" argc: %lu\n", argc
);
2906 for (i
= 0; i
< argc
; i
++)
2908 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
].StringPtr
);
2914 return ERROR_SHUTDOWN_IN_PROGRESS
;
2916 hSvc
= ScmGetServiceFromHandle(hService
);
2919 DPRINT1("Invalid service handle!\n");
2920 return ERROR_INVALID_HANDLE
;
2923 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2926 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2927 return ERROR_ACCESS_DENIED
;
2930 lpService
= hSvc
->ServiceEntry
;
2931 if (lpService
== NULL
)
2933 DPRINT("lpService == NULL!\n");
2934 return ERROR_INVALID_HANDLE
;
2937 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2938 return ERROR_SERVICE_DISABLED
;
2940 if (lpService
->bDeleted
)
2941 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2943 /* Start the service */
2944 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2951 DWORD
RGetServiceDisplayNameW(
2952 SC_RPC_HANDLE hSCManager
,
2953 LPCWSTR lpServiceName
,
2954 LPWSTR lpDisplayName
,
2957 // PMANAGER_HANDLE hManager;
2962 DPRINT("RGetServiceDisplayNameW() called\n");
2963 DPRINT("hSCManager = %p\n", hSCManager
);
2964 DPRINT("lpServiceName: %S\n", lpServiceName
);
2965 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2966 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2968 // hManager = (PMANAGER_HANDLE)hSCManager;
2969 // if (hManager->Handle.Tag != MANAGER_TAG)
2971 // DPRINT("Invalid manager handle!\n");
2972 // return ERROR_INVALID_HANDLE;
2975 /* Get service database entry */
2976 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2977 if (lpService
== NULL
)
2979 DPRINT("Could not find a service!\n");
2981 /* If the service could not be found and lpcchBuffer is less than 2, windows
2982 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2983 if (*lpcchBuffer
< 2)
2986 if (lpDisplayName
!= NULL
)
2992 return ERROR_SERVICE_DOES_NOT_EXIST
;
2995 if (!lpService
->lpDisplayName
)
2997 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
2999 if (lpDisplayName
!= NULL
&&
3000 *lpcchBuffer
> dwLength
)
3002 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3007 dwLength
= (DWORD
)wcslen(lpService
->lpDisplayName
);
3009 if (lpDisplayName
!= NULL
&&
3010 *lpcchBuffer
> dwLength
)
3012 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3016 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3018 *lpcchBuffer
= dwLength
;
3025 DWORD
RGetServiceKeyNameW(
3026 SC_RPC_HANDLE hSCManager
,
3027 LPCWSTR lpDisplayName
,
3028 LPWSTR lpServiceName
,
3031 // PMANAGER_HANDLE hManager;
3036 DPRINT("RGetServiceKeyNameW() called\n");
3037 DPRINT("hSCManager = %p\n", hSCManager
);
3038 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3039 DPRINT("lpServiceName: %p\n", lpServiceName
);
3040 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3042 // hManager = (PMANAGER_HANDLE)hSCManager;
3043 // if (hManager->Handle.Tag != MANAGER_TAG)
3045 // DPRINT("Invalid manager handle!\n");
3046 // return ERROR_INVALID_HANDLE;
3049 /* Get service database entry */
3050 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3051 if (lpService
== NULL
)
3053 DPRINT("Could not find a service!\n");
3055 /* If the service could not be found and lpcchBuffer is less than 2, windows
3056 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3057 if (*lpcchBuffer
< 2)
3060 if (lpServiceName
!= NULL
)
3066 return ERROR_SERVICE_DOES_NOT_EXIST
;
3069 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
3071 if (lpServiceName
!= NULL
&&
3072 *lpcchBuffer
> dwLength
)
3074 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3075 *lpcchBuffer
= dwLength
;
3076 return ERROR_SUCCESS
;
3079 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3081 *lpcchBuffer
= dwLength
;
3088 DWORD
RI_ScSetServiceBitsA(
3089 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3090 DWORD dwServiceBits
,
3092 int bUpdateImmediately
,
3096 return ERROR_CALL_NOT_IMPLEMENTED
;
3101 DWORD
RChangeServiceConfigA(
3102 SC_RPC_HANDLE hService
,
3103 DWORD dwServiceType
,
3105 DWORD dwErrorControl
,
3106 LPSTR lpBinaryPathName
,
3107 LPSTR lpLoadOrderGroup
,
3109 LPBYTE lpDependencies
,
3111 LPSTR lpServiceStartName
,
3114 LPSTR lpDisplayName
)
3116 DWORD dwError
= ERROR_SUCCESS
;
3117 PSERVICE_HANDLE hSvc
;
3118 PSERVICE lpService
= NULL
;
3119 HKEY hServiceKey
= NULL
;
3120 LPWSTR lpDisplayNameW
= NULL
;
3121 LPWSTR lpBinaryPathNameW
= NULL
;
3122 LPWSTR lpCanonicalImagePathW
= NULL
;
3123 LPWSTR lpLoadOrderGroupW
= NULL
;
3124 LPWSTR lpDependenciesW
= NULL
;
3126 DPRINT("RChangeServiceConfigA() called\n");
3127 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3128 DPRINT("dwStartType = %lu\n", dwStartType
);
3129 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3130 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3131 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3132 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3135 return ERROR_SHUTDOWN_IN_PROGRESS
;
3137 hSvc
= ScmGetServiceFromHandle(hService
);
3140 DPRINT1("Invalid service handle!\n");
3141 return ERROR_INVALID_HANDLE
;
3144 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3145 SERVICE_CHANGE_CONFIG
))
3147 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3148 return ERROR_ACCESS_DENIED
;
3151 lpService
= hSvc
->ServiceEntry
;
3152 if (lpService
== NULL
)
3154 DPRINT("lpService == NULL!\n");
3155 return ERROR_INVALID_HANDLE
;
3158 /* Lock the service database exclusively */
3159 ScmLockDatabaseExclusive();
3161 if (lpService
->bDeleted
)
3163 DPRINT("The service has already been marked for delete!\n");
3164 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3168 /* Open the service key */
3169 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3172 if (dwError
!= ERROR_SUCCESS
)
3175 /* Write service data to the registry */
3177 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3179 /* Set the display name */
3180 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3182 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3183 if (lpDisplayNameW
== NULL
)
3185 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3189 MultiByteToWideChar(CP_ACP
,
3194 (int)(strlen(lpDisplayName
) + 1));
3196 RegSetValueExW(hServiceKey
,
3200 (LPBYTE
)lpDisplayNameW
,
3201 (DWORD
)((wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
)));
3203 /* Update lpService->lpDisplayName */
3204 if (lpService
->lpDisplayName
)
3205 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3207 lpService
->lpDisplayName
= lpDisplayNameW
;
3210 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3212 /* Set the service type */
3213 dwError
= RegSetValueExW(hServiceKey
,
3217 (LPBYTE
)&dwServiceType
,
3219 if (dwError
!= ERROR_SUCCESS
)
3222 lpService
->Status
.dwServiceType
= dwServiceType
;
3225 if (dwStartType
!= SERVICE_NO_CHANGE
)
3227 /* Set the start value */
3228 dwError
= RegSetValueExW(hServiceKey
,
3232 (LPBYTE
)&dwStartType
,
3234 if (dwError
!= ERROR_SUCCESS
)
3237 lpService
->dwStartType
= dwStartType
;
3240 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3242 /* Set the error control value */
3243 dwError
= RegSetValueExW(hServiceKey
,
3247 (LPBYTE
)&dwErrorControl
,
3249 if (dwError
!= ERROR_SUCCESS
)
3252 lpService
->dwErrorControl
= dwErrorControl
;
3255 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3257 /* Set the image path */
3258 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(),
3260 (strlen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
3261 if (lpBinaryPathNameW
== NULL
)
3263 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3267 MultiByteToWideChar(CP_ACP
,
3272 (int)(strlen(lpBinaryPathName
) + 1));
3274 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
3276 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
3278 &lpCanonicalImagePathW
);
3280 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3282 if (dwError
!= ERROR_SUCCESS
)
3285 lpBinaryPathNameW
= lpCanonicalImagePathW
;
3288 dwError
= RegSetValueExW(hServiceKey
,
3292 (LPBYTE
)lpBinaryPathNameW
,
3293 (DWORD
)((wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
)));
3295 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3297 if (dwError
!= ERROR_SUCCESS
)
3301 /* Set the group name */
3302 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3304 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3306 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3307 if (lpLoadOrderGroupW
== NULL
)
3309 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3313 MultiByteToWideChar(CP_ACP
,
3318 (int)(strlen(lpLoadOrderGroup
) + 1));
3320 dwError
= RegSetValueExW(hServiceKey
,
3324 (LPBYTE
)lpLoadOrderGroupW
,
3325 (DWORD
)((wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
)));
3326 if (dwError
!= ERROR_SUCCESS
)
3328 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3332 dwError
= ScmSetServiceGroup(lpService
,
3335 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3337 if (dwError
!= ERROR_SUCCESS
)
3341 if (lpdwTagId
!= NULL
)
3343 dwError
= ScmAssignNewTag(lpService
);
3344 if (dwError
!= ERROR_SUCCESS
)
3347 dwError
= RegSetValueExW(hServiceKey
,
3351 (LPBYTE
)&lpService
->dwTag
,
3353 if (dwError
!= ERROR_SUCCESS
)
3356 *lpdwTagId
= lpService
->dwTag
;
3359 /* Write dependencies */
3360 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3362 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3364 (strlen((LPSTR
)lpDependencies
) + 1) * sizeof(WCHAR
));
3365 if (lpDependenciesW
== NULL
)
3367 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3371 MultiByteToWideChar(CP_ACP
,
3373 (LPSTR
)lpDependencies
,
3376 (int)(strlen((LPSTR
)lpDependencies
) + 1));
3378 dwError
= ScmWriteDependencies(hServiceKey
,
3379 (LPWSTR
)lpDependenciesW
,
3382 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3385 if (lpPassword
!= NULL
)
3387 /* FIXME: Decrypt and write password */
3391 /* Unlock the service database */
3392 ScmUnlockDatabase();
3394 if (hServiceKey
!= NULL
)
3395 RegCloseKey(hServiceKey
);
3397 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3404 DWORD
RCreateServiceA(
3405 SC_RPC_HANDLE hSCManager
,
3406 LPSTR lpServiceName
,
3407 LPSTR lpDisplayName
,
3408 DWORD dwDesiredAccess
,
3409 DWORD dwServiceType
,
3411 DWORD dwErrorControl
,
3412 LPSTR lpBinaryPathName
,
3413 LPSTR lpLoadOrderGroup
,
3415 LPBYTE lpDependencies
,
3417 LPSTR lpServiceStartName
,
3420 LPSC_RPC_HANDLE lpServiceHandle
)
3422 DWORD dwError
= ERROR_SUCCESS
;
3423 LPWSTR lpServiceNameW
= NULL
;
3424 LPWSTR lpDisplayNameW
= NULL
;
3425 LPWSTR lpBinaryPathNameW
= NULL
;
3426 LPWSTR lpLoadOrderGroupW
= NULL
;
3427 LPWSTR lpDependenciesW
= NULL
;
3428 LPWSTR lpServiceStartNameW
= NULL
;
3429 DWORD dwDependenciesLength
= 0;
3436 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3437 lpServiceNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3438 if (!lpServiceNameW
)
3440 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3443 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3448 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3449 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3450 if (!lpDisplayNameW
)
3452 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3455 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3458 if (lpBinaryPathName
)
3460 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3461 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3462 if (!lpBinaryPathNameW
)
3464 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3467 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3470 if (lpLoadOrderGroup
)
3472 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3473 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3474 if (!lpLoadOrderGroupW
)
3476 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3479 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3484 lpStr
= (LPCSTR
)lpDependencies
;
3487 cchLength
= strlen(lpStr
) + 1;
3488 dwDependenciesLength
+= (DWORD
)cchLength
;
3489 lpStr
= lpStr
+ cchLength
;
3491 dwDependenciesLength
++;
3493 lpDependenciesW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDependenciesLength
* sizeof(WCHAR
));
3494 if (!lpDependenciesW
)
3496 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3499 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3502 if (lpServiceStartName
)
3504 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3505 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
3506 if (!lpServiceStartNameW
)
3508 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3511 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3514 dwError
= RCreateServiceW(hSCManager
,
3524 (LPBYTE
)lpDependenciesW
,
3525 dwDependenciesLength
,
3526 lpServiceStartNameW
,
3532 if (lpServiceNameW
!=NULL
)
3533 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3535 if (lpDisplayNameW
!= NULL
)
3536 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3538 if (lpBinaryPathNameW
!= NULL
)
3539 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3541 if (lpLoadOrderGroupW
!= NULL
)
3542 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3544 if (lpDependenciesW
!= NULL
)
3545 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3547 if (lpServiceStartNameW
!= NULL
)
3548 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3555 DWORD
REnumDependentServicesA(
3556 SC_RPC_HANDLE hService
,
3557 DWORD dwServiceState
,
3560 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3561 LPBOUNDED_DWORD_256K lpServicesReturned
)
3563 DWORD dwError
= ERROR_SUCCESS
;
3564 DWORD dwServicesReturned
= 0;
3565 DWORD dwServiceCount
;
3566 HKEY hServicesKey
= NULL
;
3567 PSERVICE_HANDLE hSvc
;
3568 PSERVICE lpService
= NULL
;
3569 PSERVICE
*lpServicesArray
= NULL
;
3570 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3573 *pcbBytesNeeded
= 0;
3574 *lpServicesReturned
= 0;
3576 DPRINT("REnumDependentServicesA() called\n");
3578 hSvc
= ScmGetServiceFromHandle(hService
);
3581 DPRINT1("Invalid service handle!\n");
3582 return ERROR_INVALID_HANDLE
;
3585 lpService
= hSvc
->ServiceEntry
;
3587 /* Check access rights */
3588 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3589 SC_MANAGER_ENUMERATE_SERVICE
))
3591 DPRINT("Insufficient access rights! 0x%lx\n",
3592 hSvc
->Handle
.DesiredAccess
);
3593 return ERROR_ACCESS_DENIED
;
3596 /* Open the Services Reg key */
3597 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3598 L
"System\\CurrentControlSet\\Services",
3603 if (dwError
!= ERROR_SUCCESS
)
3606 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3607 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3608 are the same for both. Verified in WINXP. */
3610 /* First determine the bytes needed and get the number of dependent services*/
3611 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3616 &dwServicesReturned
);
3617 if (dwError
!= ERROR_SUCCESS
)
3620 /* If buffer size is less than the bytes needed or pointer is null*/
3621 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3623 dwError
= ERROR_MORE_DATA
;
3627 /* Allocate memory for array of service pointers */
3628 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3630 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3631 if (!lpServicesArray
)
3633 DPRINT("Could not allocate a buffer!!\n");
3634 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3638 dwServicesReturned
= 0;
3639 *pcbBytesNeeded
= 0;
3641 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3646 &dwServicesReturned
);
3647 if (dwError
!= ERROR_SUCCESS
)
3652 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3653 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3655 /* Copy EnumDepenedentService to Buffer */
3656 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3658 lpService
= lpServicesArray
[dwServiceCount
];
3660 /* Copy the status info */
3661 memcpy(&lpServicesPtr
->ServiceStatus
,
3663 sizeof(SERVICE_STATUS
));
3665 /* Copy display name */
3666 WideCharToMultiByte(CP_ACP
,
3668 lpService
->lpDisplayName
,
3671 (int)wcslen(lpService
->lpDisplayName
),
3674 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3675 lpStr
+= strlen(lpStr
) + 1;
3677 /* Copy service name */
3678 WideCharToMultiByte(CP_ACP
,
3680 lpService
->lpServiceName
,
3683 (int)wcslen(lpService
->lpServiceName
),
3686 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3687 lpStr
+= strlen(lpStr
) + 1;
3692 *lpServicesReturned
= dwServicesReturned
;
3695 if (lpServicesArray
)
3696 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3698 RegCloseKey(hServicesKey
);
3700 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3707 DWORD
REnumServicesStatusA(
3708 SC_RPC_HANDLE hSCManager
,
3709 DWORD dwServiceType
,
3710 DWORD dwServiceState
,
3713 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3714 LPBOUNDED_DWORD_256K lpServicesReturned
,
3715 LPBOUNDED_DWORD_256K lpResumeHandle
)
3717 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3718 LPENUM_SERVICE_STATUSW lpStatusPtrIncrW
;
3719 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3720 LPWSTR lpStringPtrW
;
3723 DWORD dwServiceCount
;
3725 DPRINT("REnumServicesStatusA() called\n");
3727 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
3729 return ERROR_INVALID_ADDRESS
;
3732 if ((dwBufSize
> 0) && (lpBuffer
))
3734 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3737 DPRINT("Failed to allocate buffer!\n");
3738 return ERROR_NOT_ENOUGH_MEMORY
;
3742 dwError
= REnumServicesStatusW(hSCManager
,
3745 (LPBYTE
)lpStatusPtrW
,
3751 /* if no services were returned then we are Done */
3752 if (*lpServicesReturned
== 0)
3755 lpStatusPtrIncrW
= lpStatusPtrW
;
3756 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3757 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3758 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3759 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3760 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3762 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3764 /* Copy the service name */
3765 WideCharToMultiByte(CP_ACP
,
3770 (int)wcslen(lpStringPtrW
),
3774 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3775 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3776 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3778 /* Copy the display name */
3779 WideCharToMultiByte(CP_ACP
,
3784 (int)wcslen(lpStringPtrW
),
3788 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3789 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3790 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3792 /* Copy the status information */
3793 memcpy(&lpStatusPtrA
->ServiceStatus
,
3794 &lpStatusPtrIncrW
->ServiceStatus
,
3795 sizeof(SERVICE_STATUS
));
3803 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3805 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3812 DWORD
ROpenSCManagerA(
3813 LPSTR lpMachineName
,
3814 LPSTR lpDatabaseName
,
3815 DWORD dwDesiredAccess
,
3816 LPSC_RPC_HANDLE lpScHandle
)
3818 UNICODE_STRING MachineName
;
3819 UNICODE_STRING DatabaseName
;
3822 DPRINT("ROpenSCManagerA() called\n");
3825 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3829 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3832 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3833 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3838 RtlFreeUnicodeString(&MachineName
);
3841 RtlFreeUnicodeString(&DatabaseName
);
3848 DWORD
ROpenServiceA(
3849 SC_RPC_HANDLE hSCManager
,
3850 LPSTR lpServiceName
,
3851 DWORD dwDesiredAccess
,
3852 LPSC_RPC_HANDLE lpServiceHandle
)
3854 UNICODE_STRING ServiceName
;
3857 DPRINT("ROpenServiceA() called\n");
3860 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3863 dwError
= ROpenServiceW(hSCManager
,
3864 lpServiceName
? ServiceName
.Buffer
: NULL
,
3869 RtlFreeUnicodeString(&ServiceName
);
3876 DWORD
RQueryServiceConfigA(
3877 SC_RPC_HANDLE hService
,
3878 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3880 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3882 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3883 DWORD dwError
= ERROR_SUCCESS
;
3884 PSERVICE_HANDLE hSvc
;
3885 PSERVICE lpService
= NULL
;
3886 HKEY hServiceKey
= NULL
;
3887 LPWSTR lpImagePath
= NULL
;
3888 LPWSTR lpServiceStartName
= NULL
;
3889 LPWSTR lpDependencies
= NULL
;
3890 DWORD dwDependenciesLength
= 0;
3891 DWORD dwRequiredSize
;
3892 CHAR lpEmptyString
[]={0,0};
3895 DPRINT("RQueryServiceConfigA() called\n");
3898 return ERROR_SHUTDOWN_IN_PROGRESS
;
3900 hSvc
= ScmGetServiceFromHandle(hService
);
3903 DPRINT1("Invalid service handle!\n");
3904 return ERROR_INVALID_HANDLE
;
3907 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3908 SERVICE_QUERY_CONFIG
))
3910 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3911 return ERROR_ACCESS_DENIED
;
3914 lpService
= hSvc
->ServiceEntry
;
3915 if (lpService
== NULL
)
3917 DPRINT("lpService == NULL!\n");
3918 return ERROR_INVALID_HANDLE
;
3921 /* Lock the service database shared */
3922 ScmLockDatabaseShared();
3924 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3927 if (dwError
!= ERROR_SUCCESS
)
3930 /* Read the image path */
3931 dwError
= ScmReadString(hServiceKey
,
3934 if (dwError
!= ERROR_SUCCESS
)
3937 /* Read the service start name */
3938 ScmReadString(hServiceKey
,
3940 &lpServiceStartName
);
3942 /* Read the dependencies */
3943 ScmReadDependencies(hServiceKey
,
3945 &dwDependenciesLength
);
3947 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGA
);
3949 if (lpImagePath
!= NULL
)
3950 dwRequiredSize
+= (DWORD
)(wcslen(lpImagePath
) + 1);
3952 dwRequiredSize
+= 2;
3954 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3955 dwRequiredSize
+= (DWORD
)(wcslen(lpService
->lpGroup
->lpGroupName
) + 1);
3957 dwRequiredSize
+= 2;
3959 /* Add Dependencies length */
3960 if (lpDependencies
!= NULL
)
3961 dwRequiredSize
+= dwDependenciesLength
;
3963 dwRequiredSize
+= 2;
3965 if (lpServiceStartName
!= NULL
)
3966 dwRequiredSize
+= (DWORD
)(wcslen(lpServiceStartName
) + 1);
3968 dwRequiredSize
+= 2;
3970 if (lpService
->lpDisplayName
!= NULL
)
3971 dwRequiredSize
+= (DWORD
)(wcslen(lpService
->lpDisplayName
) + 1);
3973 dwRequiredSize
+= 2;
3975 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3977 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3981 lpServiceConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3982 lpServiceConfig
->dwStartType
= lpService
->dwStartType
;
3983 lpServiceConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3984 lpServiceConfig
->dwTagId
= lpService
->dwTag
;
3986 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3988 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3989 Verified in WINXP */
3993 WideCharToMultiByte(CP_ACP
,
3998 (int)(wcslen(lpImagePath
) + 1),
4004 strcpy(lpStr
, lpEmptyString
);
4007 lpServiceConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4008 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4010 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4012 WideCharToMultiByte(CP_ACP
,
4014 lpService
->lpGroup
->lpGroupName
,
4017 (int)(wcslen(lpService
->lpGroup
->lpGroupName
) + 1),
4023 strcpy(lpStr
, lpEmptyString
);
4026 lpServiceConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4027 lpStr
+= (strlen(lpStr
) + 1);
4029 /* Append Dependencies */
4032 WideCharToMultiByte(CP_ACP
,
4035 dwDependenciesLength
,
4037 dwDependenciesLength
,
4043 strcpy(lpStr
, lpEmptyString
);
4046 lpServiceConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4048 lpStr
+= dwDependenciesLength
;
4050 lpStr
+= (strlen(lpStr
) + 1);
4052 if (lpServiceStartName
)
4054 WideCharToMultiByte(CP_ACP
,
4059 (int)(wcslen(lpServiceStartName
) + 1),
4065 strcpy(lpStr
, lpEmptyString
);
4068 lpServiceConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4069 lpStr
+= (strlen(lpStr
) + 1);
4071 if (lpService
->lpDisplayName
)
4073 WideCharToMultiByte(CP_ACP
,
4075 lpService
->lpDisplayName
,
4078 (int)(wcslen(lpService
->lpDisplayName
) + 1),
4084 strcpy(lpStr
, lpEmptyString
);
4087 lpServiceConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceConfig
);
4090 if (pcbBytesNeeded
!= NULL
)
4091 *pcbBytesNeeded
= dwRequiredSize
;
4094 /* Unlock the service database */
4095 ScmUnlockDatabase();
4097 if (lpImagePath
!= NULL
)
4098 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4100 if (lpServiceStartName
!= NULL
)
4101 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4103 if (lpDependencies
!= NULL
)
4104 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4106 if (hServiceKey
!= NULL
)
4107 RegCloseKey(hServiceKey
);
4109 DPRINT("RQueryServiceConfigA() done\n");
4116 DWORD
RQueryServiceLockStatusA(
4117 SC_RPC_HANDLE hSCManager
,
4118 LPBYTE lpBuf
, // LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
4120 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4122 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
= (LPQUERY_SERVICE_LOCK_STATUSA
)lpBuf
;
4123 PMANAGER_HANDLE hMgr
;
4124 DWORD dwRequiredSize
;
4126 if (!lpLockStatus
|| !pcbBytesNeeded
)
4127 return ERROR_INVALID_PARAMETER
;
4129 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
4132 DPRINT1("Invalid service manager handle!\n");
4133 return ERROR_INVALID_HANDLE
;
4136 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
4137 SC_MANAGER_QUERY_LOCK_STATUS
))
4139 DPRINT("Insufficient access rights! 0x%lx\n", hMgr
->Handle
.DesiredAccess
);
4140 return ERROR_ACCESS_DENIED
;
4143 /* FIXME: we need to compute instead the real length of the owner name */
4144 dwRequiredSize
= sizeof(QUERY_SERVICE_LOCK_STATUSA
) + sizeof(CHAR
);
4145 *pcbBytesNeeded
= dwRequiredSize
;
4147 if (cbBufSize
< dwRequiredSize
)
4148 return ERROR_INSUFFICIENT_BUFFER
;
4150 ScmQueryServiceLockStatusA(lpLockStatus
);
4152 return ERROR_SUCCESS
;
4157 DWORD
RStartServiceA(
4158 SC_RPC_HANDLE hService
,
4160 LPSTRING_PTRSA argv
)
4162 DWORD dwError
= ERROR_SUCCESS
;
4163 PSERVICE_HANDLE hSvc
;
4164 PSERVICE lpService
= NULL
;
4165 LPWSTR
*lpVector
= NULL
;
4169 DPRINT("RStartServiceA() called\n");
4172 return ERROR_SHUTDOWN_IN_PROGRESS
;
4174 hSvc
= ScmGetServiceFromHandle(hService
);
4177 DPRINT1("Invalid service handle!\n");
4178 return ERROR_INVALID_HANDLE
;
4181 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4184 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4185 return ERROR_ACCESS_DENIED
;
4188 lpService
= hSvc
->ServiceEntry
;
4189 if (lpService
== NULL
)
4191 DPRINT("lpService == NULL!\n");
4192 return ERROR_INVALID_HANDLE
;
4195 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4196 return ERROR_SERVICE_DISABLED
;
4198 if (lpService
->bDeleted
)
4199 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4201 /* Build a Unicode argument vector */
4204 lpVector
= HeapAlloc(GetProcessHeap(),
4206 argc
* sizeof(LPWSTR
));
4207 if (lpVector
== NULL
)
4208 return ERROR_NOT_ENOUGH_MEMORY
;
4210 for (i
= 0; i
< argc
; i
++)
4212 dwLength
= MultiByteToWideChar(CP_ACP
,
4219 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4221 dwLength
* sizeof(WCHAR
));
4222 if (lpVector
[i
] == NULL
)
4224 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4228 MultiByteToWideChar(CP_ACP
,
4237 /* Start the service */
4238 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4241 /* Free the Unicode argument vector */
4242 if (lpVector
!= NULL
)
4244 for (i
= 0; i
< argc
; i
++)
4246 if (lpVector
[i
] != NULL
)
4247 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4249 HeapFree(GetProcessHeap(), 0, lpVector
);
4257 DWORD
RGetServiceDisplayNameA(
4258 SC_RPC_HANDLE hSCManager
,
4259 LPCSTR lpServiceName
,
4260 LPSTR lpDisplayName
,
4261 LPBOUNDED_DWORD_4K lpcchBuffer
)
4263 // PMANAGER_HANDLE hManager;
4264 PSERVICE lpService
= NULL
;
4267 LPWSTR lpServiceNameW
;
4269 DPRINT("RGetServiceDisplayNameA() called\n");
4270 DPRINT("hSCManager = %p\n", hSCManager
);
4271 DPRINT("lpServiceName: %s\n", lpServiceName
);
4272 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4273 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4275 // hManager = (PMANAGER_HANDLE)hSCManager;
4276 // if (hManager->Handle.Tag != MANAGER_TAG)
4278 // DPRINT("Invalid manager handle!\n");
4279 // return ERROR_INVALID_HANDLE;
4282 if (lpServiceName
!= NULL
)
4284 dwLength
= (DWORD
)(strlen(lpServiceName
) + 1);
4285 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4287 dwLength
* sizeof(WCHAR
));
4288 if (!lpServiceNameW
)
4289 return ERROR_NOT_ENOUGH_MEMORY
;
4291 MultiByteToWideChar(CP_ACP
,
4298 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4300 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4303 if (lpService
== NULL
)
4305 DPRINT("Could not find a service!\n");
4307 /* If the service could not be found and lpcchBuffer is 0, windows
4308 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4309 if (*lpcchBuffer
== 0)
4312 if (lpDisplayName
!= NULL
)
4317 return ERROR_SERVICE_DOES_NOT_EXIST
;
4320 if (!lpService
->lpDisplayName
)
4322 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
4323 if (lpDisplayName
!= NULL
&&
4324 *lpcchBuffer
> dwLength
)
4326 WideCharToMultiByte(CP_ACP
,
4328 lpService
->lpServiceName
,
4329 (int)wcslen(lpService
->lpServiceName
),
4334 return ERROR_SUCCESS
;
4339 dwLength
= (DWORD
)wcslen(lpService
->lpDisplayName
);
4340 if (lpDisplayName
!= NULL
&&
4341 *lpcchBuffer
> dwLength
)
4343 WideCharToMultiByte(CP_ACP
,
4345 lpService
->lpDisplayName
,
4346 (int)wcslen(lpService
->lpDisplayName
),
4351 return ERROR_SUCCESS
;
4355 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4357 *lpcchBuffer
= dwLength
* 2;
4364 DWORD
RGetServiceKeyNameA(
4365 SC_RPC_HANDLE hSCManager
,
4366 LPCSTR lpDisplayName
,
4367 LPSTR lpServiceName
,
4368 LPBOUNDED_DWORD_4K lpcchBuffer
)
4373 LPWSTR lpDisplayNameW
;
4375 DPRINT("RGetServiceKeyNameA() called\n");
4376 DPRINT("hSCManager = %p\n", hSCManager
);
4377 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4378 DPRINT("lpServiceName: %p\n", lpServiceName
);
4379 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4381 dwLength
= (DWORD
)(strlen(lpDisplayName
) + 1);
4382 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4384 dwLength
* sizeof(WCHAR
));
4385 if (!lpDisplayNameW
)
4386 return ERROR_NOT_ENOUGH_MEMORY
;
4388 MultiByteToWideChar(CP_ACP
,
4395 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4397 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4399 if (lpService
== NULL
)
4401 DPRINT("Could not find the service!\n");
4403 /* If the service could not be found and lpcchBuffer is 0,
4404 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4405 if (*lpcchBuffer
== 0)
4408 if (lpServiceName
!= NULL
)
4414 return ERROR_SERVICE_DOES_NOT_EXIST
;
4417 dwLength
= (DWORD
)wcslen(lpService
->lpServiceName
);
4418 if (lpServiceName
!= NULL
&&
4419 *lpcchBuffer
> dwLength
)
4421 WideCharToMultiByte(CP_ACP
,
4423 lpService
->lpServiceName
,
4424 (int)wcslen(lpService
->lpServiceName
),
4429 return ERROR_SUCCESS
;
4432 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4434 *lpcchBuffer
= dwLength
* 2;
4441 DWORD
RI_ScGetCurrentGroupStateW(
4442 SC_RPC_HANDLE hSCManager
,
4443 LPWSTR lpLoadOrderGroup
,
4447 return ERROR_CALL_NOT_IMPLEMENTED
;
4452 DWORD
REnumServiceGroupW(
4453 SC_RPC_HANDLE hSCManager
,
4454 DWORD dwServiceType
,
4455 DWORD dwServiceState
,
4458 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4459 LPBOUNDED_DWORD_256K lpServicesReturned
,
4460 LPBOUNDED_DWORD_256K lpResumeIndex
,
4461 LPCWSTR pszGroupName
)
4463 PMANAGER_HANDLE hManager
;
4465 DWORD dwError
= ERROR_SUCCESS
;
4466 PLIST_ENTRY ServiceEntry
;
4467 PSERVICE CurrentService
;
4469 DWORD dwRequiredSize
;
4470 DWORD dwServiceCount
;
4472 DWORD dwLastResumeCount
= 0;
4473 LPENUM_SERVICE_STATUSW lpStatusPtr
;
4476 DPRINT("REnumServiceGroupW() called\n");
4479 return ERROR_SHUTDOWN_IN_PROGRESS
;
4481 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
4482 if (hManager
== NULL
)
4484 DPRINT1("Invalid service manager handle!\n");
4485 return ERROR_INVALID_HANDLE
;
4488 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
4490 return ERROR_INVALID_ADDRESS
;
4493 *pcbBytesNeeded
= 0;
4494 *lpServicesReturned
= 0;
4496 if ((dwServiceType
== 0) ||
4497 ((dwServiceType
& ~SERVICE_TYPE_ALL
) != 0))
4499 DPRINT("Not a valid Service Type!\n");
4500 return ERROR_INVALID_PARAMETER
;
4503 if ((dwServiceState
== 0) ||
4504 ((dwServiceState
& ~SERVICE_STATE_ALL
) != 0))
4506 DPRINT("Not a valid Service State!\n");
4507 return ERROR_INVALID_PARAMETER
;
4510 /* Check access rights */
4511 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4512 SC_MANAGER_ENUMERATE_SERVICE
))
4514 DPRINT("Insufficient access rights! 0x%lx\n",
4515 hManager
->Handle
.DesiredAccess
);
4516 return ERROR_ACCESS_DENIED
;
4520 dwLastResumeCount
= *lpResumeIndex
;
4522 /* Lock the service database shared */
4523 ScmLockDatabaseShared();
4525 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4526 if (lpService
== NULL
)
4528 dwError
= ERROR_SUCCESS
;
4535 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4536 ServiceEntry
!= &ServiceListHead
;
4537 ServiceEntry
= ServiceEntry
->Flink
)
4539 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4543 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4546 dwState
= SERVICE_ACTIVE
;
4547 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4548 dwState
= SERVICE_INACTIVE
;
4550 if ((dwState
& dwServiceState
) == 0)
4555 if (*pszGroupName
== 0)
4557 if (CurrentService
->lpGroup
!= NULL
)
4562 if ((CurrentService
->lpGroup
== NULL
) ||
4563 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4568 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
4569 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4570 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4572 if (dwRequiredSize
+ dwSize
> cbBufSize
)
4574 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4578 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4579 dwRequiredSize
+= dwSize
;
4581 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4584 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4585 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4588 ServiceEntry
!= &ServiceListHead
;
4589 ServiceEntry
= ServiceEntry
->Flink
)
4591 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4595 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4598 dwState
= SERVICE_ACTIVE
;
4599 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4600 dwState
= SERVICE_INACTIVE
;
4602 if ((dwState
& dwServiceState
) == 0)
4607 if (*pszGroupName
== 0)
4609 if (CurrentService
->lpGroup
!= NULL
)
4614 if ((CurrentService
->lpGroup
== NULL
) ||
4615 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4620 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
4621 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4622 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4624 dwError
= ERROR_MORE_DATA
;
4627 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4630 *lpResumeIndex
= dwLastResumeCount
;
4632 *lpServicesReturned
= dwServiceCount
;
4633 *pcbBytesNeeded
= dwRequiredSize
;
4635 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
4636 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4637 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
4640 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4641 ServiceEntry
!= &ServiceListHead
;
4642 ServiceEntry
= ServiceEntry
->Flink
)
4644 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4648 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4651 dwState
= SERVICE_ACTIVE
;
4652 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4653 dwState
= SERVICE_INACTIVE
;
4655 if ((dwState
& dwServiceState
) == 0)
4660 if (*pszGroupName
== 0)
4662 if (CurrentService
->lpGroup
!= NULL
)
4667 if ((CurrentService
->lpGroup
== NULL
) ||
4668 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
4673 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
4674 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4675 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4677 if (dwRequiredSize
+ dwSize
> cbBufSize
)
4680 /* Copy the service name */
4681 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
4682 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4683 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4685 /* Copy the display name */
4686 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
4687 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4688 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4690 /* Copy the status information */
4691 memcpy(&lpStatusPtr
->ServiceStatus
,
4692 &CurrentService
->Status
,
4693 sizeof(SERVICE_STATUS
));
4696 dwRequiredSize
+= dwSize
;
4699 if (dwError
== ERROR_SUCCESS
)
4701 *pcbBytesNeeded
= 0;
4702 if (lpResumeIndex
) *lpResumeIndex
= 0;
4706 /* Unlock the service database */
4707 ScmUnlockDatabase();
4709 DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError
);
4716 // WARNING: This function is untested
4719 DWORD
RChangeServiceConfig2A(
4720 SC_RPC_HANDLE hService
,
4721 SC_RPC_CONFIG_INFOA Info
)
4723 SC_RPC_CONFIG_INFOW InfoW
;
4724 DWORD dwRet
, dwLength
;
4727 DPRINT("RChangeServiceConfig2A() called\n");
4728 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4730 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4732 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4734 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4735 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4737 //lpServiceDescriptonA = Info.psd;
4739 ///if (lpServiceDescriptonA &&
4740 ///lpServiceDescriptonA->lpDescription)
4742 dwLength
= (DWORD
)((strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
));
4744 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4746 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4747 if (!lpServiceDescriptonW
)
4749 return ERROR_NOT_ENOUGH_MEMORY
;
4752 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4754 MultiByteToWideChar(CP_ACP
,
4758 lpServiceDescriptonW
->lpDescription
,
4761 ptr
= lpServiceDescriptonW
;
4762 InfoW
.psd
= lpServiceDescriptonW
;
4765 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4767 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4768 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4769 DWORD dwRebootLen
= 0;
4770 DWORD dwCommandLen
= 0;
4772 lpServiceFailureActionsA
= Info
.psfa
;
4774 if (lpServiceFailureActionsA
)
4776 if (lpServiceFailureActionsA
->lpRebootMsg
)
4778 dwRebootLen
= (DWORD
)((strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
));
4780 if (lpServiceFailureActionsA
->lpCommand
)
4782 dwCommandLen
= (DWORD
)((strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
));
4784 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4786 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4789 if (!lpServiceFailureActionsW
)
4791 return ERROR_NOT_ENOUGH_MEMORY
;
4794 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4795 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4796 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4798 if (lpServiceFailureActionsA
->lpRebootMsg
)
4800 MultiByteToWideChar(CP_ACP
,
4802 lpServiceFailureActionsA
->lpRebootMsg
,
4804 lpServiceFailureActionsW
->lpRebootMsg
,
4808 if (lpServiceFailureActionsA
->lpCommand
)
4810 MultiByteToWideChar(CP_ACP
,
4812 lpServiceFailureActionsA
->lpCommand
,
4814 lpServiceFailureActionsW
->lpCommand
,
4818 ptr
= lpServiceFailureActionsW
;
4822 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4824 HeapFree(GetProcessHeap(), 0, ptr
);
4831 ScmSetFailureActions(PSERVICE_HANDLE hSvc
,
4834 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
)
4836 LPSERVICE_FAILURE_ACTIONSW lpReadBuffer
= NULL
;
4837 LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer
= NULL
;
4838 BOOL bIsActionRebootSet
= FALSE
;
4839 DWORD dwDesiredAccess
= SERVICE_CHANGE_CONFIG
;
4840 DWORD dwRequiredSize
= 0;
4845 /* There is nothing to be done if we have no failure actions */
4846 if (lpFailureActions
== NULL
)
4847 return ERROR_SUCCESS
;
4850 * 1- Check whether or not we can set
4851 * failure actions for this service.
4854 /* Failure actions can only be set for Win32 services, not for drivers */
4855 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
4856 return ERROR_CANNOT_DETECT_DRIVER_FAILURE
;
4859 * If the service controller handles the SC_ACTION_RESTART action,
4860 * hService must have the SERVICE_START access right.
4862 * If you specify SC_ACTION_REBOOT, the caller must have the
4863 * SE_SHUTDOWN_NAME privilege.
4865 if (lpFailureActions
->cActions
> 0 &&
4866 lpFailureActions
->lpsaActions
!= NULL
)
4868 for (i
= 0; i
< lpFailureActions
->cActions
; ++i
)
4870 if (lpFailureActions
->lpsaActions
[i
].Type
== SC_ACTION_RESTART
)
4871 dwDesiredAccess
|= SERVICE_START
;
4872 else if (lpFailureActions
->lpsaActions
[i
].Type
== SC_ACTION_REBOOT
)
4873 bIsActionRebootSet
= TRUE
;
4877 /* Re-check the access rights */
4878 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4881 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4882 return ERROR_ACCESS_DENIED
;
4885 /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */
4886 if (bIsActionRebootSet
)
4891 * 2- Retrieve the original value of FailureActions.
4894 /* Query value length */
4895 dwError
= RegQueryValueExW(hServiceKey
,
4901 if (dwError
!= ERROR_SUCCESS
&&
4902 dwError
!= ERROR_MORE_DATA
&&
4903 dwError
!= ERROR_FILE_NOT_FOUND
)
4906 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSW
), dwRequiredSize
)
4907 : sizeof(SERVICE_FAILURE_ACTIONSW
);
4909 /* Initialize the read buffer */
4910 lpReadBuffer
= HeapAlloc(GetProcessHeap(),
4913 if (lpReadBuffer
== NULL
)
4914 return ERROR_NOT_ENOUGH_MEMORY
;
4916 /* Now we can fill the read buffer */
4917 if (dwError
!= ERROR_FILE_NOT_FOUND
&&
4918 dwType
== REG_BINARY
)
4920 dwError
= RegQueryValueExW(hServiceKey
,
4924 (LPBYTE
)lpReadBuffer
,
4926 if (dwError
!= ERROR_SUCCESS
&&
4927 dwError
!= ERROR_FILE_NOT_FOUND
)
4930 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSW
))
4931 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4936 * The value of the error doesn't really matter, the only
4937 * important thing is that it must be != ERROR_SUCCESS.
4939 dwError
= ERROR_INVALID_DATA
;
4942 if (dwError
== ERROR_SUCCESS
)
4944 lpReadBuffer
->cActions
= min(lpReadBuffer
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSW
)) / sizeof(SC_ACTION
));
4945 lpReadBuffer
->lpsaActions
= (lpReadBuffer
->cActions
> 0 ? (LPSC_ACTION
)(lpReadBuffer
+ 1) : NULL
);
4949 lpReadBuffer
->dwResetPeriod
= 0;
4950 lpReadBuffer
->cActions
= 0;
4951 lpReadBuffer
->lpsaActions
= NULL
;
4954 lpReadBuffer
->lpRebootMsg
= NULL
;
4955 lpReadBuffer
->lpCommand
= NULL
;
4958 * 3- Initialize the new value to set.
4961 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4963 if (lpFailureActions
->lpsaActions
== NULL
)
4966 * lpFailureActions->cActions is ignored.
4967 * Therefore we use the original values
4968 * of cActions and lpsaActions.
4970 dwRequiredSize
+= lpReadBuffer
->cActions
* sizeof(SC_ACTION
);
4975 * The reset period and array of failure actions
4976 * are deleted if lpFailureActions->cActions == 0 .
4978 dwRequiredSize
+= lpFailureActions
->cActions
* sizeof(SC_ACTION
);
4981 lpWriteBuffer
= HeapAlloc(GetProcessHeap(),
4984 if (lpWriteBuffer
== NULL
)
4986 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4990 /* Clean the pointers as they have no meaning when the structure is stored in the registry */
4991 lpWriteBuffer
->lpRebootMsg
= NULL
;
4992 lpWriteBuffer
->lpCommand
= NULL
;
4993 lpWriteBuffer
->lpsaActions
= NULL
;
4995 /* Set the members */
4996 if (lpFailureActions
->lpsaActions
== NULL
)
4999 * lpFailureActions->dwResetPeriod and lpFailureActions->cActions are ignored.
5000 * Therefore we use the original values of dwResetPeriod, cActions and lpsaActions.
5002 lpWriteBuffer
->dwResetPeriod
= lpReadBuffer
->dwResetPeriod
;
5003 lpWriteBuffer
->cActions
= lpReadBuffer
->cActions
;
5005 if (lpReadBuffer
->lpsaActions
!= NULL
)
5007 memmove(lpWriteBuffer
+ 1,
5008 lpReadBuffer
->lpsaActions
,
5009 lpReadBuffer
->cActions
* sizeof(SC_ACTION
));
5014 if (lpFailureActions
->cActions
> 0)
5016 lpWriteBuffer
->dwResetPeriod
= lpFailureActions
->dwResetPeriod
;
5017 lpWriteBuffer
->cActions
= lpFailureActions
->cActions
;
5019 memmove(lpWriteBuffer
+ 1,
5020 lpFailureActions
->lpsaActions
,
5021 lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5025 /* The reset period and array of failure actions are deleted */
5026 lpWriteBuffer
->dwResetPeriod
= 0;
5027 lpWriteBuffer
->cActions
= 0;
5031 /* Save the new failure actions into the registry */
5032 dwError
= RegSetValueExW(hServiceKey
,
5036 (LPBYTE
)lpWriteBuffer
,
5039 /* We modify the strings only in case of success.*/
5040 if (dwError
== ERROR_SUCCESS
)
5042 /* Modify the Reboot Message value, if specified */
5043 if (lpFailureActions
->lpRebootMsg
!= NULL
)
5045 /* If the Reboot Message is "" then we delete it */
5046 if (*lpFailureActions
->lpRebootMsg
== 0)
5048 DPRINT("Delete Reboot Message value\n");
5049 RegDeleteValueW(hServiceKey
, L
"RebootMessage");
5053 DPRINT("Setting Reboot Message value %S\n", lpFailureActions
->lpRebootMsg
);
5054 RegSetValueExW(hServiceKey
,
5058 (LPBYTE
)lpFailureActions
->lpRebootMsg
,
5059 (DWORD
)((wcslen(lpFailureActions
->lpRebootMsg
) + 1) * sizeof(WCHAR
)));
5063 /* Modify the Failure Command value, if specified */
5064 if (lpFailureActions
->lpCommand
!= NULL
)
5066 /* If the FailureCommand string is an empty string, delete the value */
5067 if (*lpFailureActions
->lpCommand
== 0)
5069 DPRINT("Delete Failure Command value\n");
5070 RegDeleteValueW(hServiceKey
, L
"FailureCommand");
5074 DPRINT("Setting Failure Command value %S\n", lpFailureActions
->lpCommand
);
5075 RegSetValueExW(hServiceKey
,
5079 (LPBYTE
)lpFailureActions
->lpCommand
,
5080 (DWORD
)((wcslen(lpFailureActions
->lpCommand
) + 1) * sizeof(WCHAR
)));
5086 if (lpWriteBuffer
!= NULL
)
5087 HeapFree(GetProcessHeap(), 0, lpWriteBuffer
);
5089 if (lpReadBuffer
!= NULL
)
5090 HeapFree(GetProcessHeap(), 0, lpReadBuffer
);
5097 DWORD
RChangeServiceConfig2W(
5098 SC_RPC_HANDLE hService
,
5099 SC_RPC_CONFIG_INFOW Info
)
5101 DWORD dwError
= ERROR_SUCCESS
;
5102 PSERVICE_HANDLE hSvc
;
5103 PSERVICE lpService
= NULL
;
5104 HKEY hServiceKey
= NULL
;
5106 DPRINT("RChangeServiceConfig2W() called\n");
5107 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
5110 return ERROR_SHUTDOWN_IN_PROGRESS
;
5112 hSvc
= ScmGetServiceFromHandle(hService
);
5115 DPRINT1("Invalid service handle!\n");
5116 return ERROR_INVALID_HANDLE
;
5119 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5120 SERVICE_CHANGE_CONFIG
))
5122 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5123 return ERROR_ACCESS_DENIED
;
5126 lpService
= hSvc
->ServiceEntry
;
5127 if (lpService
== NULL
)
5129 DPRINT("lpService == NULL!\n");
5130 return ERROR_INVALID_HANDLE
;
5133 /* Lock the service database exclusively */
5134 ScmLockDatabaseExclusive();
5136 if (lpService
->bDeleted
)
5138 DPRINT("The service has already been marked for delete!\n");
5139 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
5143 /* Open the service key */
5144 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
5145 KEY_READ
| KEY_SET_VALUE
,
5147 if (dwError
!= ERROR_SUCCESS
)
5150 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5152 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
5154 /* Modify the service description, if specified */
5155 if (lpServiceDescription
!= NULL
&&
5156 lpServiceDescription
->lpDescription
!= NULL
)
5158 /* If the description is "" then we delete it */
5159 if (*lpServiceDescription
->lpDescription
== 0)
5161 DPRINT("Delete service description\n");
5162 dwError
= RegDeleteValueW(hServiceKey
, L
"Description");
5164 if (dwError
== ERROR_FILE_NOT_FOUND
)
5165 dwError
= ERROR_SUCCESS
;
5169 DPRINT("Setting service description value %S\n", lpServiceDescription
->lpDescription
);
5170 dwError
= RegSetValueExW(hServiceKey
,
5174 (LPBYTE
)lpServiceDescription
->lpDescription
,
5175 (DWORD
)((wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
)));
5180 dwError
= ERROR_SUCCESS
;
5183 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5185 dwError
= ScmSetFailureActions(hSvc
,
5188 (LPSERVICE_FAILURE_ACTIONSW
)Info
.psfa
);
5192 if (hServiceKey
!= NULL
)
5193 RegCloseKey(hServiceKey
);
5195 /* Unlock the service database */
5196 ScmUnlockDatabase();
5198 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
5205 DWORD
RQueryServiceConfig2A(
5206 SC_RPC_HANDLE hService
,
5210 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5212 DWORD dwError
= ERROR_SUCCESS
;
5213 PSERVICE_HANDLE hSvc
;
5214 PSERVICE lpService
= NULL
;
5215 HKEY hServiceKey
= NULL
;
5216 DWORD dwRequiredSize
= 0;
5218 LPWSTR lpDescriptionW
= NULL
;
5219 LPWSTR lpRebootMessageW
= NULL
;
5220 LPWSTR lpFailureCommandW
= NULL
;
5222 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
5223 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
5226 return ERROR_INVALID_ADDRESS
;
5229 return ERROR_SHUTDOWN_IN_PROGRESS
;
5231 hSvc
= ScmGetServiceFromHandle(hService
);
5234 DPRINT1("Invalid service handle!\n");
5235 return ERROR_INVALID_HANDLE
;
5238 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5239 SERVICE_QUERY_CONFIG
))
5241 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5242 return ERROR_ACCESS_DENIED
;
5245 lpService
= hSvc
->ServiceEntry
;
5246 if (lpService
== NULL
)
5248 DPRINT("lpService == NULL!\n");
5249 return ERROR_INVALID_HANDLE
;
5252 /* Lock the service database shared */
5253 ScmLockDatabaseShared();
5255 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
5258 if (dwError
!= ERROR_SUCCESS
)
5261 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5263 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
5266 dwError
= ScmReadString(hServiceKey
,
5269 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5272 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
5273 if (dwError
== ERROR_SUCCESS
)
5274 *pcbBytesNeeded
+= (DWORD
)((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
5276 if (cbBufSize
< *pcbBytesNeeded
)
5278 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5282 if (dwError
== ERROR_SUCCESS
)
5284 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
5286 WideCharToMultiByte(CP_ACP
,
5291 (int)wcslen(lpDescriptionW
),
5294 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
5298 lpServiceDescription
->lpDescription
= NULL
;
5299 dwError
= ERROR_SUCCESS
;
5302 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5304 LPSERVICE_FAILURE_ACTIONSA lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSA
)lpBuffer
;
5307 /* Query value length */
5308 dwError
= RegQueryValueExW(hServiceKey
,
5314 if (dwError
!= ERROR_SUCCESS
&&
5315 dwError
!= ERROR_MORE_DATA
&&
5316 dwError
!= ERROR_FILE_NOT_FOUND
)
5319 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSA
), dwRequiredSize
)
5320 : sizeof(SERVICE_FAILURE_ACTIONSA
);
5322 /* Get the strings */
5323 ScmReadString(hServiceKey
,
5325 &lpFailureCommandW
);
5327 ScmReadString(hServiceKey
,
5331 if (lpRebootMessageW
)
5332 dwRequiredSize
+= (DWORD
)((wcslen(lpRebootMessageW
) + 1) * sizeof(WCHAR
));
5334 if (lpFailureCommandW
)
5335 dwRequiredSize
+= (DWORD
)((wcslen(lpFailureCommandW
) + 1) * sizeof(WCHAR
));
5337 if (cbBufSize
< dwRequiredSize
)
5339 *pcbBytesNeeded
= dwRequiredSize
;
5340 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5344 /* Now we can fill the buffer */
5345 if (dwError
!= ERROR_FILE_NOT_FOUND
&& dwType
== REG_BINARY
)
5347 dwError
= RegQueryValueExW(hServiceKey
,
5351 (LPBYTE
)lpFailureActions
,
5353 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5356 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSA
))
5357 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSA
);
5362 * The value of the error doesn't really matter, the only
5363 * important thing is that it must be != ERROR_SUCCESS .
5365 dwError
= ERROR_INVALID_DATA
;
5368 if (dwError
== ERROR_SUCCESS
)
5370 lpFailureActions
->cActions
= min(lpFailureActions
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSA
)) / sizeof(SC_ACTION
));
5372 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5373 lpFailureActions
->lpsaActions
= (lpFailureActions
->cActions
> 0 ? (LPSC_ACTION
)(ULONG_PTR
)sizeof(SERVICE_FAILURE_ACTIONSA
) : NULL
);
5375 lpStr
= (LPSTR
)((ULONG_PTR
)(lpFailureActions
+ 1) + lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5379 lpFailureActions
->dwResetPeriod
= 0;
5380 lpFailureActions
->cActions
= 0;
5381 lpFailureActions
->lpsaActions
= NULL
;
5382 lpStr
= (LPSTR
)(lpFailureActions
+ 1);
5385 lpFailureActions
->lpRebootMsg
= NULL
;
5386 lpFailureActions
->lpCommand
= NULL
;
5388 if (lpRebootMessageW
)
5390 WideCharToMultiByte(CP_ACP
,
5395 (int)wcslen(lpRebootMessageW
),
5398 lpFailureActions
->lpRebootMsg
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5399 lpStr
+= strlen(lpStr
) + 1;
5402 if (lpFailureCommandW
)
5404 WideCharToMultiByte(CP_ACP
,
5409 (int)wcslen(lpFailureCommandW
),
5412 lpFailureActions
->lpCommand
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5413 /* lpStr += strlen(lpStr) + 1; */
5416 dwError
= ERROR_SUCCESS
;
5420 /* Unlock the service database */
5421 ScmUnlockDatabase();
5423 if (lpDescriptionW
!= NULL
)
5424 HeapFree(GetProcessHeap(), 0, lpDescriptionW
);
5426 if (lpRebootMessageW
!= NULL
)
5427 HeapFree(GetProcessHeap(), 0, lpRebootMessageW
);
5429 if (lpFailureCommandW
!= NULL
)
5430 HeapFree(GetProcessHeap(), 0, lpFailureCommandW
);
5432 if (hServiceKey
!= NULL
)
5433 RegCloseKey(hServiceKey
);
5435 DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError
);
5442 DWORD
RQueryServiceConfig2W(
5443 SC_RPC_HANDLE hService
,
5447 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5449 DWORD dwError
= ERROR_SUCCESS
;
5450 PSERVICE_HANDLE hSvc
;
5451 PSERVICE lpService
= NULL
;
5452 HKEY hServiceKey
= NULL
;
5453 DWORD dwRequiredSize
= 0;
5455 LPWSTR lpDescription
= NULL
;
5456 LPWSTR lpRebootMessage
= NULL
;
5457 LPWSTR lpFailureCommand
= NULL
;
5459 DPRINT("RQueryServiceConfig2W() called\n");
5462 return ERROR_INVALID_ADDRESS
;
5465 return ERROR_SHUTDOWN_IN_PROGRESS
;
5467 hSvc
= ScmGetServiceFromHandle(hService
);
5470 DPRINT1("Invalid service handle!\n");
5471 return ERROR_INVALID_HANDLE
;
5474 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5475 SERVICE_QUERY_CONFIG
))
5477 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5478 return ERROR_ACCESS_DENIED
;
5481 lpService
= hSvc
->ServiceEntry
;
5482 if (lpService
== NULL
)
5484 DPRINT("lpService == NULL!\n");
5485 return ERROR_INVALID_HANDLE
;
5488 /* Lock the service database shared */
5489 ScmLockDatabaseShared();
5491 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
5494 if (dwError
!= ERROR_SUCCESS
)
5497 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
5499 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
5502 dwError
= ScmReadString(hServiceKey
,
5505 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5508 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
5509 if (dwError
== ERROR_SUCCESS
)
5510 *pcbBytesNeeded
+= (DWORD
)((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
5512 if (cbBufSize
< *pcbBytesNeeded
)
5514 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5518 if (dwError
== ERROR_SUCCESS
)
5520 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
5521 wcscpy(lpStr
, lpDescription
);
5522 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
5526 lpServiceDescription
->lpDescription
= NULL
;
5527 dwError
= ERROR_SUCCESS
;
5530 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5532 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
5533 LPWSTR lpStr
= NULL
;
5535 /* Query value length */
5536 dwError
= RegQueryValueExW(hServiceKey
,
5542 if (dwError
!= ERROR_SUCCESS
&&
5543 dwError
!= ERROR_MORE_DATA
&&
5544 dwError
!= ERROR_FILE_NOT_FOUND
)
5547 dwRequiredSize
= (dwType
== REG_BINARY
) ? max(sizeof(SERVICE_FAILURE_ACTIONSW
), dwRequiredSize
)
5548 : sizeof(SERVICE_FAILURE_ACTIONSW
);
5550 /* Get the strings */
5551 ScmReadString(hServiceKey
,
5555 ScmReadString(hServiceKey
,
5559 if (lpRebootMessage
)
5560 dwRequiredSize
+= (DWORD
)((wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
));
5562 if (lpFailureCommand
)
5563 dwRequiredSize
+= (DWORD
)((wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
));
5565 if (cbBufSize
< dwRequiredSize
)
5567 *pcbBytesNeeded
= dwRequiredSize
;
5568 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5572 /* Now we can fill the buffer */
5573 if (dwError
!= ERROR_FILE_NOT_FOUND
&& dwType
== REG_BINARY
)
5575 dwError
= RegQueryValueExW(hServiceKey
,
5579 (LPBYTE
)lpFailureActions
,
5581 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
5584 if (dwRequiredSize
< sizeof(SERVICE_FAILURE_ACTIONSW
))
5585 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5590 * The value of the error doesn't really matter, the only
5591 * important thing is that it must be != ERROR_SUCCESS .
5593 dwError
= ERROR_INVALID_DATA
;
5596 if (dwError
== ERROR_SUCCESS
)
5598 lpFailureActions
->cActions
= min(lpFailureActions
->cActions
, (dwRequiredSize
- sizeof(SERVICE_FAILURE_ACTIONSW
)) / sizeof(SC_ACTION
));
5600 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5601 lpFailureActions
->lpsaActions
= (lpFailureActions
->cActions
> 0 ? (LPSC_ACTION
)(ULONG_PTR
)sizeof(SERVICE_FAILURE_ACTIONSW
) : NULL
);
5603 lpStr
= (LPWSTR
)((ULONG_PTR
)(lpFailureActions
+ 1) + lpFailureActions
->cActions
* sizeof(SC_ACTION
));
5607 lpFailureActions
->dwResetPeriod
= 0;
5608 lpFailureActions
->cActions
= 0;
5609 lpFailureActions
->lpsaActions
= NULL
;
5610 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
5613 lpFailureActions
->lpRebootMsg
= NULL
;
5614 lpFailureActions
->lpCommand
= NULL
;
5616 if (lpRebootMessage
)
5618 wcscpy(lpStr
, lpRebootMessage
);
5619 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5620 lpStr
+= wcslen(lpStr
) + 1;
5623 if (lpFailureCommand
)
5625 wcscpy(lpStr
, lpFailureCommand
);
5626 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureActions
);
5627 /* lpStr += wcslen(lpStr) + 1; */
5630 dwError
= ERROR_SUCCESS
;
5634 /* Unlock the service database */
5635 ScmUnlockDatabase();
5637 if (lpDescription
!= NULL
)
5638 HeapFree(GetProcessHeap(), 0, lpDescription
);
5640 if (lpRebootMessage
!= NULL
)
5641 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5643 if (lpFailureCommand
!= NULL
)
5644 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5646 if (hServiceKey
!= NULL
)
5647 RegCloseKey(hServiceKey
);
5649 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5656 DWORD
RQueryServiceStatusEx(
5657 SC_RPC_HANDLE hService
,
5658 SC_STATUS_TYPE InfoLevel
,
5661 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5663 LPSERVICE_STATUS_PROCESS lpStatus
;
5664 PSERVICE_HANDLE hSvc
;
5667 DPRINT("RQueryServiceStatusEx() called\n");
5670 return ERROR_SHUTDOWN_IN_PROGRESS
;
5672 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
5673 return ERROR_INVALID_LEVEL
;
5675 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
5677 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
5678 return ERROR_INSUFFICIENT_BUFFER
;
5680 hSvc
= ScmGetServiceFromHandle(hService
);
5683 DPRINT1("Invalid service handle!\n");
5684 return ERROR_INVALID_HANDLE
;
5687 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5688 SERVICE_QUERY_STATUS
))
5690 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5691 return ERROR_ACCESS_DENIED
;
5694 lpService
= hSvc
->ServiceEntry
;
5695 if (lpService
== NULL
)
5697 DPRINT("lpService == NULL!\n");
5698 return ERROR_INVALID_HANDLE
;
5701 /* Lock the service database shared */
5702 ScmLockDatabaseShared();
5704 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
5706 /* Return service status information */
5707 RtlCopyMemory(lpStatus
,
5709 sizeof(SERVICE_STATUS
));
5711 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
5712 lpStatus
->dwServiceFlags
= 0; /* FIXME */
5714 /* Unlock the service database */
5715 ScmUnlockDatabase();
5717 return ERROR_SUCCESS
;
5722 DWORD
REnumServicesStatusExA(
5723 SC_RPC_HANDLE hSCManager
,
5724 SC_ENUM_TYPE InfoLevel
,
5725 DWORD dwServiceType
,
5726 DWORD dwServiceState
,
5729 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5730 LPBOUNDED_DWORD_256K lpServicesReturned
,
5731 LPBOUNDED_DWORD_256K lpResumeIndex
,
5732 LPCSTR pszGroupName
)
5734 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
5735 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW
;
5736 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
5737 LPWSTR lpStringPtrW
;
5739 LPWSTR pszGroupNameW
= NULL
;
5741 DWORD dwServiceCount
;
5743 DPRINT("REnumServicesStatusExA() called\n");
5745 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
5747 return ERROR_INVALID_ADDRESS
;
5752 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
5755 DPRINT("Failed to allocate buffer!\n");
5756 return ERROR_NOT_ENOUGH_MEMORY
;
5759 MultiByteToWideChar(CP_ACP
,
5764 (int)(strlen(pszGroupName
) + 1));
5767 if ((cbBufSize
> 0) && (lpBuffer
))
5769 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
5772 DPRINT("Failed to allocate buffer!\n");
5773 return ERROR_NOT_ENOUGH_MEMORY
;
5777 dwError
= REnumServicesStatusExW(hSCManager
,
5781 (LPBYTE
)lpStatusPtrW
,
5788 /* if no services were returned then we are Done */
5789 if (*lpServicesReturned
== 0)
5792 lpStatusPtrIncrW
= lpStatusPtrW
;
5793 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5794 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5795 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5796 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5797 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5799 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5801 /* Copy the service name */
5802 WideCharToMultiByte(CP_ACP
,
5807 (int)wcslen(lpStringPtrW
),
5811 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5812 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5813 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5815 /* Copy the display name */
5816 WideCharToMultiByte(CP_ACP
,
5821 (int)wcslen(lpStringPtrW
),
5825 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5826 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5827 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5829 /* Copy the status information */
5830 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5831 &lpStatusPtrIncrW
->ServiceStatusProcess
,
5832 sizeof(SERVICE_STATUS
));
5834 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrIncrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5835 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5843 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5846 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5848 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5855 DWORD
REnumServicesStatusExW(
5856 SC_RPC_HANDLE hSCManager
,
5857 SC_ENUM_TYPE InfoLevel
,
5858 DWORD dwServiceType
,
5859 DWORD dwServiceState
,
5862 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5863 LPBOUNDED_DWORD_256K lpServicesReturned
,
5864 LPBOUNDED_DWORD_256K lpResumeIndex
,
5865 LPCWSTR pszGroupName
)
5867 PMANAGER_HANDLE hManager
;
5869 DWORD dwError
= ERROR_SUCCESS
;
5870 PLIST_ENTRY ServiceEntry
;
5871 PSERVICE CurrentService
;
5873 DWORD dwRequiredSize
;
5874 DWORD dwServiceCount
;
5876 DWORD dwLastResumeCount
= 0;
5877 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5880 DPRINT("REnumServicesStatusExW() called\n");
5883 return ERROR_SHUTDOWN_IN_PROGRESS
;
5885 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5886 return ERROR_INVALID_LEVEL
;
5888 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5889 if (hManager
== NULL
)
5891 DPRINT1("Invalid service manager handle!\n");
5892 return ERROR_INVALID_HANDLE
;
5895 if (pcbBytesNeeded
== NULL
|| lpServicesReturned
== NULL
)
5897 return ERROR_INVALID_ADDRESS
;
5900 *pcbBytesNeeded
= 0;
5901 *lpServicesReturned
= 0;
5903 if ((dwServiceType
== 0) ||
5904 ((dwServiceType
& ~SERVICE_TYPE_ALL
) != 0))
5906 DPRINT("Not a valid Service Type!\n");
5907 return ERROR_INVALID_PARAMETER
;
5910 if ((dwServiceState
== 0) ||
5911 ((dwServiceState
& ~SERVICE_STATE_ALL
) != 0))
5913 DPRINT("Not a valid Service State!\n");
5914 return ERROR_INVALID_PARAMETER
;
5917 /* Check access rights */
5918 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5919 SC_MANAGER_ENUMERATE_SERVICE
))
5921 DPRINT("Insufficient access rights! 0x%lx\n",
5922 hManager
->Handle
.DesiredAccess
);
5923 return ERROR_ACCESS_DENIED
;
5927 dwLastResumeCount
= *lpResumeIndex
;
5929 /* Lock the service database shared */
5930 ScmLockDatabaseShared();
5932 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5933 if (lpService
== NULL
)
5935 dwError
= ERROR_SUCCESS
;
5942 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5943 ServiceEntry
!= &ServiceListHead
;
5944 ServiceEntry
= ServiceEntry
->Flink
)
5946 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5950 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5953 dwState
= SERVICE_ACTIVE
;
5954 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5955 dwState
= SERVICE_INACTIVE
;
5957 if ((dwState
& dwServiceState
) == 0)
5962 if (*pszGroupName
== 0)
5964 if (CurrentService
->lpGroup
!= NULL
)
5969 if ((CurrentService
->lpGroup
== NULL
) ||
5970 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
5975 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5976 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5977 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5979 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5981 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5982 dwRequiredSize
+= dwSize
;
5984 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5988 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5994 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5995 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5998 ServiceEntry
!= &ServiceListHead
;
5999 ServiceEntry
= ServiceEntry
->Flink
)
6001 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
6005 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
6008 dwState
= SERVICE_ACTIVE
;
6009 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
6010 dwState
= SERVICE_INACTIVE
;
6012 if ((dwState
& dwServiceState
) == 0)
6017 if (*pszGroupName
== 0)
6019 if (CurrentService
->lpGroup
!= NULL
)
6024 if ((CurrentService
->lpGroup
== NULL
) ||
6025 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
6030 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
6031 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
6032 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
6034 dwError
= ERROR_MORE_DATA
;
6037 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
6040 *lpResumeIndex
= dwLastResumeCount
;
6042 *lpServicesReturned
= dwServiceCount
;
6043 *pcbBytesNeeded
= dwRequiredSize
;
6045 /* If there was no services that matched */
6046 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
6048 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
6052 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
6053 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
6054 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
6057 for (ServiceEntry
= &lpService
->ServiceListEntry
;
6058 ServiceEntry
!= &ServiceListHead
;
6059 ServiceEntry
= ServiceEntry
->Flink
)
6061 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
6065 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
6068 dwState
= SERVICE_ACTIVE
;
6069 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
6070 dwState
= SERVICE_INACTIVE
;
6072 if ((dwState
& dwServiceState
) == 0)
6077 if (*pszGroupName
== 0)
6079 if (CurrentService
->lpGroup
!= NULL
)
6084 if ((CurrentService
->lpGroup
== NULL
) ||
6085 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
) != 0)
6090 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
6091 (DWORD
)((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
6092 (DWORD
)((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
6094 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
6096 /* Copy the service name */
6098 CurrentService
->lpServiceName
);
6099 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
6100 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
6102 /* Copy the display name */
6104 CurrentService
->lpDisplayName
);
6105 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
6106 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
6108 /* Copy the status information */
6109 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
6110 &CurrentService
->Status
,
6111 sizeof(SERVICE_STATUS
));
6112 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
6113 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
6114 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
6117 dwRequiredSize
+= dwSize
;
6127 *pcbBytesNeeded
= 0;
6133 /* Unlock the service database */
6134 ScmUnlockDatabase();
6136 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
6143 DWORD
RSendTSMessage(
6144 handle_t BindingHandle
) /* FIXME */
6147 return ERROR_CALL_NOT_IMPLEMENTED
;
6152 DWORD
RCreateServiceWOW64A(
6153 handle_t BindingHandle
,
6154 LPSTR lpServiceName
,
6155 LPSTR lpDisplayName
,
6156 DWORD dwDesiredAccess
,
6157 DWORD dwServiceType
,
6159 DWORD dwErrorControl
,
6160 LPSTR lpBinaryPathName
,
6161 LPSTR lpLoadOrderGroup
,
6163 LPBYTE lpDependencies
,
6165 LPSTR lpServiceStartName
,
6168 LPSC_RPC_HANDLE lpServiceHandle
)
6171 return ERROR_CALL_NOT_IMPLEMENTED
;
6176 DWORD
RCreateServiceWOW64W(
6177 handle_t BindingHandle
,
6178 LPWSTR lpServiceName
,
6179 LPWSTR lpDisplayName
,
6180 DWORD dwDesiredAccess
,
6181 DWORD dwServiceType
,
6183 DWORD dwErrorControl
,
6184 LPWSTR lpBinaryPathName
,
6185 LPWSTR lpLoadOrderGroup
,
6187 LPBYTE lpDependencies
,
6189 LPWSTR lpServiceStartName
,
6192 LPSC_RPC_HANDLE lpServiceHandle
)
6195 return ERROR_CALL_NOT_IMPLEMENTED
;
6200 DWORD
RQueryServiceTagInfo(
6201 handle_t BindingHandle
) /* FIXME */
6204 return ERROR_CALL_NOT_IMPLEMENTED
;
6209 DWORD
RNotifyServiceStatusChange(
6210 SC_RPC_HANDLE hService
,
6211 SC_RPC_NOTIFY_PARAMS NotifyParams
,
6212 GUID
*pClientProcessGuid
,
6213 GUID
*pSCMProcessGuid
,
6214 PBOOL pfCreateRemoteQueue
,
6215 LPSC_NOTIFY_RPC_HANDLE phNotify
)
6218 return ERROR_CALL_NOT_IMPLEMENTED
;
6223 DWORD
RGetNotifyResults(
6224 SC_NOTIFY_RPC_HANDLE hNotify
,
6225 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
6228 return ERROR_CALL_NOT_IMPLEMENTED
;
6233 DWORD
RCloseNotifyHandle(
6234 LPSC_NOTIFY_RPC_HANDLE phNotify
,
6238 return ERROR_CALL_NOT_IMPLEMENTED
;
6243 DWORD
RControlServiceExA(
6244 SC_RPC_HANDLE hService
,
6249 return ERROR_CALL_NOT_IMPLEMENTED
;
6254 DWORD
RControlServiceExW(
6255 SC_RPC_HANDLE hService
,
6260 return ERROR_CALL_NOT_IMPLEMENTED
;
6265 DWORD
RSendPnPMessage(
6266 handle_t BindingHandle
) /* FIXME */
6269 return ERROR_CALL_NOT_IMPLEMENTED
;
6274 DWORD
RValidatePnPService(
6275 handle_t BindingHandle
) /* FIXME */
6278 return ERROR_CALL_NOT_IMPLEMENTED
;
6283 DWORD
ROpenServiceStatusHandle(
6284 handle_t BindingHandle
) /* FIXME */
6287 return ERROR_CALL_NOT_IMPLEMENTED
;
6293 handle_t BindingHandle
) /* FIXME */
6296 return ERROR_CALL_NOT_IMPLEMENTED
;
6300 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
6302 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
6306 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
6308 HeapFree(GetProcessHeap(), 0, ptr
);
6312 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
6314 /* Close the handle */
6315 RCloseServiceHandle(&hSCObject
);
6319 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
6321 /* Unlock the database */
6322 RUnlockServiceDatabase(&Lock
);
6326 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)