2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/rpcserver.c
5 * PURPOSE: RPC server interface for the advapi32 calls
6 * COPYRIGHT: Copyright 2005-2006 Eric Kohl
7 * Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
8 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
11 /* INCLUDES ****************************************************************/
18 /* GLOBALS *****************************************************************/
20 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
21 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
23 typedef struct _SCMGR_HANDLE
30 typedef struct _MANAGER_HANDLE
33 WCHAR DatabaseName
[1];
34 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
37 typedef struct _SERVICE_HANDLE
40 PSERVICE ServiceEntry
;
41 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
44 #define SC_MANAGER_READ \
45 (STANDARD_RIGHTS_READ | \
46 SC_MANAGER_QUERY_LOCK_STATUS | \
47 SC_MANAGER_ENUMERATE_SERVICE)
49 #define SC_MANAGER_WRITE \
50 (STANDARD_RIGHTS_WRITE | \
51 SC_MANAGER_MODIFY_BOOT_CONFIG | \
52 SC_MANAGER_CREATE_SERVICE)
54 #define SC_MANAGER_EXECUTE \
55 (STANDARD_RIGHTS_EXECUTE | \
57 SC_MANAGER_ENUMERATE_SERVICE | \
58 SC_MANAGER_CONNECT | \
59 SC_MANAGER_CREATE_SERVICE)
62 #define SERVICE_READ \
63 (STANDARD_RIGHTS_READ | \
64 SERVICE_INTERROGATE | \
65 SERVICE_ENUMERATE_DEPENDENTS | \
66 SERVICE_QUERY_STATUS | \
69 #define SERVICE_WRITE \
70 (STANDARD_RIGHTS_WRITE | \
71 SERVICE_CHANGE_CONFIG)
73 #define SERVICE_EXECUTE \
74 (STANDARD_RIGHTS_EXECUTE | \
75 SERVICE_USER_DEFINED_CONTROL | \
76 SERVICE_PAUSE_CONTINUE | \
80 #define TAG_ARRAY_SIZE 32
82 /* VARIABLES ***************************************************************/
84 static GENERIC_MAPPING
85 ScmManagerMapping
= {SC_MANAGER_READ
,
88 SC_MANAGER_ALL_ACCESS
};
90 static GENERIC_MAPPING
91 ScmServiceMapping
= {SERVICE_READ
,
97 /* FUNCTIONS ***************************************************************/
100 ScmStartRpcServer(VOID
)
104 DPRINT("ScmStartRpcServer() called\n");
106 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
110 if (Status
!= RPC_S_OK
)
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
116 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
125 Status
= RpcServerListen(1, 20, TRUE
);
126 if (Status
!= RPC_S_OK
)
128 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
132 DPRINT("ScmStartRpcServer() done\n");
137 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
142 if (lpDatabaseName
== NULL
)
143 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
145 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
147 DPRINT("Database %S, does not exist\n", lpDatabaseName
);
148 return ERROR_DATABASE_DOES_NOT_EXIST
;
150 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
152 DPRINT("Invalid Database name %S.\n", lpDatabaseName
);
153 return ERROR_INVALID_NAME
;
156 Ptr
= HeapAlloc(GetProcessHeap(),
158 FIELD_OFFSET(MANAGER_HANDLE
, DatabaseName
[wcslen(lpDatabaseName
) + 1]));
160 return ERROR_NOT_ENOUGH_MEMORY
;
162 Ptr
->Handle
.Tag
= MANAGER_TAG
;
164 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
166 *Handle
= (SC_HANDLE
)Ptr
;
168 return ERROR_SUCCESS
;
173 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
178 Ptr
= HeapAlloc(GetProcessHeap(),
180 sizeof(SERVICE_HANDLE
));
182 return ERROR_NOT_ENOUGH_MEMORY
;
184 Ptr
->Handle
.Tag
= SERVICE_TAG
;
186 Ptr
->ServiceEntry
= lpServiceEntry
;
188 *Handle
= (SC_HANDLE
)Ptr
;
190 return ERROR_SUCCESS
;
194 static PMANAGER_HANDLE
195 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
197 PMANAGER_HANDLE pManager
= NULL
;
201 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
202 pManager
= (PMANAGER_HANDLE
)Handle
;
204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
206 DPRINT1("Exception: Invalid Service Manager handle!\n");
214 static PSERVICE_HANDLE
215 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
217 PSERVICE_HANDLE pService
= NULL
;
221 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
222 pService
= (PSERVICE_HANDLE
)Handle
;
224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
226 DPRINT1("Exception: Invalid Service handle!\n");
235 ScmCheckAccess(SC_HANDLE Handle
,
236 DWORD dwDesiredAccess
)
238 PMANAGER_HANDLE hMgr
;
240 hMgr
= (PMANAGER_HANDLE
)Handle
;
241 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
243 RtlMapGenericMask(&dwDesiredAccess
,
246 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
248 return ERROR_SUCCESS
;
250 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
252 RtlMapGenericMask(&dwDesiredAccess
,
255 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
257 return ERROR_SUCCESS
;
260 return ERROR_INVALID_HANDLE
;
265 ScmAssignNewTag(PSERVICE lpService
)
269 DWORD dwGroupTagCount
= 0;
270 PDWORD pdwGroupTags
= NULL
;
272 DWORD dwTagUsedBase
= 1;
273 BOOLEAN TagUsed
[TAG_ARRAY_SIZE
];
277 PLIST_ENTRY ServiceEntry
;
278 PSERVICE CurrentService
;
280 ASSERT(lpService
!= NULL
);
281 ASSERT(lpService
->lpGroup
!= NULL
);
283 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
284 L
"System\\CurrentControlSet\\Control\\GroupOrderList",
289 if (dwError
!= ERROR_SUCCESS
)
292 /* query value length */
294 dwError
= RegQueryValueExW(hKey
,
295 lpService
->lpGroup
->szGroupName
,
301 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_MORE_DATA
)
304 pdwGroupTags
= HeapAlloc(GetProcessHeap(), 0, cbDataSize
);
307 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
311 dwError
= RegQueryValueExW(hKey
,
312 lpService
->lpGroup
->szGroupName
,
315 (LPBYTE
)pdwGroupTags
,
318 if (dwError
!= ERROR_SUCCESS
)
321 if (cbDataSize
< sizeof(pdwGroupTags
[0]))
324 dwGroupTagCount
= min(pdwGroupTags
[0], cbDataSize
/ sizeof(pdwGroupTags
[0]) - 1);
329 /* mark all tags as unused */
330 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
333 /* mark tags in GroupOrderList as used */
334 for (i
= 1; i
<= dwGroupTagCount
; i
++)
336 nTagOffset
= pdwGroupTags
[i
] - dwTagUsedBase
;
337 if (nTagOffset
>= 0 && nTagOffset
< TAG_ARRAY_SIZE
)
338 TagUsed
[nTagOffset
] = TRUE
;
341 /* mark tags in service list as used */
342 ServiceEntry
= lpService
->ServiceListEntry
.Flink
;
343 while (ServiceEntry
!= &lpService
->ServiceListEntry
)
345 ASSERT(ServiceEntry
!= NULL
);
346 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
347 if (CurrentService
->lpGroup
== lpService
->lpGroup
)
349 nTagOffset
= CurrentService
->dwTag
- dwTagUsedBase
;
350 if (nTagOffset
>= 0 && nTagOffset
< TAG_ARRAY_SIZE
)
351 TagUsed
[nTagOffset
] = TRUE
;
354 ServiceEntry
= ServiceEntry
->Flink
;
357 /* find unused tag, if any */
358 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
362 dwFreeTag
= dwTagUsedBase
+ i
;
367 dwTagUsedBase
+= TAG_ARRAY_SIZE
;
368 } while (!dwFreeTag
);
372 HeapFree(GetProcessHeap(), 0, pdwGroupTags
);
379 lpService
->dwTag
= dwFreeTag
;
380 DPRINT("Assigning new tag %lu to service %S in group %S\n",
381 lpService
->dwTag
, lpService
->lpServiceName
, lpService
->lpGroup
->szGroupName
);
382 dwError
= ERROR_SUCCESS
;
386 DPRINT1("Failed to assign new tag to service %S, error=%lu\n",
387 lpService
->lpServiceName
, dwError
);
394 /* Create a path suitable for the bootloader out of the full path */
396 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
398 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
401 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
402 OBJECT_ATTRIBUTES ObjectAttributes
;
404 HANDLE SymbolicLinkHandle
;
406 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
408 ServiceNameLen
= wcslen(CanonName
);
410 /* First check, if it's already good */
411 if (ServiceNameLen
> 12 &&
412 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
414 *RelativeName
= HeapAlloc(GetProcessHeap(),
416 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
417 if (*RelativeName
== NULL
)
419 DPRINT("Error allocating memory for boot driver name!\n");
420 return ERROR_NOT_ENOUGH_MEMORY
;
424 wcscpy(*RelativeName
, CanonName
);
426 DPRINT("Bootdriver name %S\n", *RelativeName
);
427 return ERROR_SUCCESS
;
430 /* If it has %SystemRoot% prefix, substitute it to \System*/
431 if (ServiceNameLen
> 13 &&
432 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
434 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
435 *RelativeName
= HeapAlloc(GetProcessHeap(),
437 ServiceNameLen
* sizeof(WCHAR
));
439 if (*RelativeName
== NULL
)
441 DPRINT("Error allocating memory for boot driver name!\n");
442 return ERROR_NOT_ENOUGH_MEMORY
;
446 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
447 wcscat(*RelativeName
, CanonName
+ 13);
449 DPRINT("Bootdriver name %S\n", *RelativeName
);
450 return ERROR_SUCCESS
;
453 /* Get buffer size needed for expanding env strings */
454 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
458 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
459 return ERROR_INVALID_ENVIRONMENT
;
462 /* Allocate memory, since the size is known now */
463 Expanded
= HeapAlloc(GetProcessHeap(),
465 (BufferSize
+ 1) * sizeof(WCHAR
));
468 DPRINT("Error allocating memory for boot driver name!\n");
469 return ERROR_NOT_ENOUGH_MEMORY
;
473 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
476 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
477 HeapFree(GetProcessHeap(), 0, Expanded
);
478 return ERROR_NOT_ENOUGH_MEMORY
;
481 /* Convert to NY-style path */
482 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
484 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
485 return ERROR_INVALID_ENVIRONMENT
;
488 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
490 /* No need to keep the dos-path anymore */
491 HeapFree(GetProcessHeap(), 0, Expanded
);
493 /* Copy it to the allocated place */
494 Expanded
= HeapAlloc(GetProcessHeap(),
496 NtPathName
.Length
+ sizeof(UNICODE_NULL
));
499 DPRINT("Error allocating memory for boot driver name!\n");
500 return ERROR_NOT_ENOUGH_MEMORY
;
503 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
504 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
505 Expanded
[ExpandedLen
] = UNICODE_NULL
;
507 if (ServiceNameLen
> ExpandedLen
&&
508 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
510 /* Only \SystemRoot\ is missing */
511 *RelativeName
= HeapAlloc(GetProcessHeap(),
513 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
514 if (*RelativeName
== NULL
)
516 DPRINT("Error allocating memory for boot driver name!\n");
517 HeapFree(GetProcessHeap(), 0, Expanded
);
518 return ERROR_NOT_ENOUGH_MEMORY
;
521 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
522 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
524 RtlFreeUnicodeString(&NtPathName
);
525 return ERROR_SUCCESS
;
528 /* The most complex case starts here */
529 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
530 InitializeObjectAttributes(&ObjectAttributes
,
532 OBJ_CASE_INSENSITIVE
,
536 /* Open this symlink */
537 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
539 if (NT_SUCCESS(Status
))
541 LinkTarget
.Length
= 0;
542 LinkTarget
.MaximumLength
= 0;
544 DPRINT("Opened symbolic link object\n");
546 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
547 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
549 /* Check if required buffer size is sane */
550 if (BufferSize
> 0xFFFD)
552 DPRINT("Too large buffer required\n");
555 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
556 HeapFree(GetProcessHeap(), 0, Expanded
);
557 return ERROR_NOT_ENOUGH_MEMORY
;
560 /* Alloc the string */
561 LinkTarget
.Length
= (USHORT
)BufferSize
;
562 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(UNICODE_NULL
);
563 LinkTarget
.Buffer
= HeapAlloc(GetProcessHeap(),
565 LinkTarget
.MaximumLength
);
566 if (!LinkTarget
.Buffer
)
568 DPRINT("Unable to alloc buffer\n");
569 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
570 HeapFree(GetProcessHeap(), 0, Expanded
);
571 return ERROR_NOT_ENOUGH_MEMORY
;
574 /* Do a real query now */
575 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
576 if (NT_SUCCESS(Status
))
578 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
580 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
581 if ((ServiceNameLen
> ExpandedLen
) &&
582 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
584 *RelativeName
= HeapAlloc(GetProcessHeap(),
586 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
588 if (*RelativeName
== NULL
)
590 DPRINT("Unable to alloc buffer\n");
591 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
592 HeapFree(GetProcessHeap(), 0, Expanded
);
593 RtlFreeUnicodeString(&NtPathName
);
594 return ERROR_NOT_ENOUGH_MEMORY
;
597 /* Copy it over, substituting the first part
599 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
600 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
603 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
604 HeapFree(GetProcessHeap(), 0, Expanded
);
605 RtlFreeUnicodeString(&NtPathName
);
608 return ERROR_SUCCESS
;
612 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
613 HeapFree(GetProcessHeap(), 0, Expanded
);
614 RtlFreeUnicodeString(&NtPathName
);
615 return ERROR_INVALID_PARAMETER
;
620 DPRINT("Error, Status = %08X\n", Status
);
621 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
622 HeapFree(GetProcessHeap(), 0, Expanded
);
623 RtlFreeUnicodeString(&NtPathName
);
624 return ERROR_INVALID_PARAMETER
;
629 DPRINT("Error, Status = %08X\n", Status
);
630 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
631 HeapFree(GetProcessHeap(), 0, Expanded
);
632 RtlFreeUnicodeString(&NtPathName
);
633 return ERROR_INVALID_PARAMETER
;
638 DPRINT("Error, Status = %08X\n", Status
);
639 HeapFree(GetProcessHeap(), 0, Expanded
);
640 return ERROR_INVALID_PARAMETER
;
644 *RelativeName
= NULL
;
645 return ERROR_INVALID_PARAMETER
;
650 ScmCanonDriverImagePath(DWORD dwStartType
,
651 const wchar_t *lpServiceName
,
652 wchar_t **lpCanonName
)
654 DWORD ServiceNameLen
, Result
;
655 UNICODE_STRING NtServiceName
;
657 const WCHAR
*SourceName
= lpServiceName
;
659 /* Calculate the length of the service's name */
660 ServiceNameLen
= wcslen(lpServiceName
);
662 /* 12 is wcslen(L"\\SystemRoot\\") */
663 if (ServiceNameLen
> 12 &&
664 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
666 /* SystemRoot prefix is already included */
667 *lpCanonName
= HeapAlloc(GetProcessHeap(),
669 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
671 if (*lpCanonName
== NULL
)
673 DPRINT("Error allocating memory for canonized service name!\n");
674 return ERROR_NOT_ENOUGH_MEMORY
;
677 /* If it's a boot-time driver, it must be systemroot relative */
678 if (dwStartType
== SERVICE_BOOT_START
)
682 wcscpy(*lpCanonName
, SourceName
);
684 DPRINT("Canonicalized name %S\n", *lpCanonName
);
688 /* Check if it has %SystemRoot% (len=13) */
689 if (ServiceNameLen
> 13 &&
690 !_wcsnicmp(L
"%SystemRoot%\\", lpServiceName
, 13))
692 /* Substitute %SystemRoot% with \\SystemRoot\\ */
693 *lpCanonName
= HeapAlloc(GetProcessHeap(),
695 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
697 if (*lpCanonName
== NULL
)
699 DPRINT("Error allocating memory for canonized service name!\n");
700 return ERROR_NOT_ENOUGH_MEMORY
;
703 /* If it's a boot-time driver, it must be systemroot relative */
704 if (dwStartType
== SERVICE_BOOT_START
)
705 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
707 wcscat(*lpCanonName
, lpServiceName
+ 13);
709 DPRINT("Canonicalized name %S\n", *lpCanonName
);
713 /* Check if it's a relative path name */
714 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
716 *lpCanonName
= HeapAlloc(GetProcessHeap(),
718 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
720 if (*lpCanonName
== NULL
)
722 DPRINT("Error allocating memory for canonized service name!\n");
723 return ERROR_NOT_ENOUGH_MEMORY
;
726 /* Just copy it over without changing */
727 wcscpy(*lpCanonName
, lpServiceName
);
732 /* It seems to be a DOS path, convert it */
733 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
735 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
736 return ERROR_INVALID_PARAMETER
;
739 *lpCanonName
= HeapAlloc(GetProcessHeap(),
741 NtServiceName
.Length
+ sizeof(WCHAR
));
743 if (*lpCanonName
== NULL
)
745 DPRINT("Error allocating memory for canonized service name!\n");
746 RtlFreeUnicodeString(&NtServiceName
);
747 return ERROR_NOT_ENOUGH_MEMORY
;
750 /* Copy the string */
751 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
753 /* The unicode string is not needed anymore */
754 RtlFreeUnicodeString(&NtServiceName
);
756 if (dwStartType
!= SERVICE_BOOT_START
)
758 DPRINT("Canonicalized name %S\n", *lpCanonName
);
762 /* The service is boot-started, so must be relative */
763 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
766 /* There is a problem, free name and return */
767 HeapFree(GetProcessHeap(), 0, *lpCanonName
);
768 DPRINT("Error converting named!\n");
772 ASSERT(RelativeName
);
774 /* Copy that string */
775 wcscpy(*lpCanonName
, RelativeName
+ 12);
777 /* Free the allocated buffer */
778 HeapFree(GetProcessHeap(), 0, RelativeName
);
780 DPRINT("Canonicalized name %S\n", *lpCanonName
);
787 /* Internal recursive function */
788 /* Need to search for every dependency on every service */
790 Int_EnumDependentServicesW(HKEY hServicesKey
,
792 DWORD dwServiceState
,
793 PSERVICE
*lpServices
,
794 LPDWORD pcbBytesNeeded
,
795 LPDWORD lpServicesReturned
)
797 DWORD dwError
= ERROR_SUCCESS
;
798 WCHAR szNameBuf
[MAX_PATH
];
799 WCHAR szValueBuf
[MAX_PATH
];
800 WCHAR
*lpszNameBuf
= szNameBuf
;
801 WCHAR
*lpszValueBuf
= szValueBuf
;
805 PSERVICE lpCurrentService
;
806 HKEY hServiceEnumKey
;
807 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
808 DWORD dwDependServiceStrPtr
= 0;
809 DWORD dwRequiredSize
= 0;
811 /* Get the number of service keys */
812 dwError
= RegQueryInfoKeyW(hServicesKey
,
824 if (dwError
!= ERROR_SUCCESS
)
826 DPRINT("ERROR! Unable to get number of services keys.\n");
830 /* Iterate the service keys to see if another service depends on the this service */
831 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
834 dwError
= RegEnumKeyExW(hServicesKey
,
842 if (dwError
!= ERROR_SUCCESS
)
845 /* Open the Service key */
846 dwError
= RegOpenKeyExW(hServicesKey
,
851 if (dwError
!= ERROR_SUCCESS
)
856 /* Check for the DependOnService Value */
857 dwError
= RegQueryValueExW(hServiceEnumKey
,
861 (LPBYTE
)lpszValueBuf
,
864 /* FIXME: Handle load order. */
866 /* If the service found has a DependOnService value */
867 if (dwError
== ERROR_SUCCESS
)
869 dwDependServiceStrPtr
= 0;
871 /* Can be more than one Dependencies in the DependOnService string */
872 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
874 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
876 /* Get the current enumed service pointer */
877 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
879 /* Check for valid Service */
880 if (!lpCurrentService
)
882 /* This should never happen! */
883 DPRINT("This should not happen at this point, report to Developer\n");
884 return ERROR_NOT_FOUND
;
887 /* Determine state the service is in */
888 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
889 dwCurrentServiceState
= SERVICE_INACTIVE
;
891 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
892 if ((dwCurrentServiceState
== dwServiceState
) ||
893 (dwServiceState
== SERVICE_STATE_ALL
))
895 /* Calculate the required size */
896 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
897 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
898 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
900 /* Add the size for service name and display name pointers */
901 dwRequiredSize
+= (2 * sizeof(PVOID
));
903 /* increase the BytesNeeded size */
904 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
906 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
909 /* Recursive call to check for its dependencies */
910 Int_EnumDependentServicesW(hServicesKey
,
917 /* If the lpServices is valid set the service pointer */
919 lpServices
[*lpServicesReturned
] = lpCurrentService
;
921 *lpServicesReturned
= *lpServicesReturned
+ 1;
925 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
928 else if (*pcbBytesNeeded
)
930 dwError
= ERROR_SUCCESS
;
933 RegCloseKey(hServiceEnumKey
);
941 DWORD
RCloseServiceHandle(
942 LPSC_RPC_HANDLE hSCObject
)
944 PMANAGER_HANDLE hManager
;
945 PSERVICE_HANDLE hService
;
949 DWORD pcbBytesNeeded
= 0;
950 DWORD dwServicesReturned
= 0;
952 DPRINT("RCloseServiceHandle() called\n");
954 DPRINT("hSCObject = %p\n", *hSCObject
);
957 return ERROR_INVALID_HANDLE
;
959 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
960 hService
= ScmGetServiceFromHandle(*hSCObject
);
962 if (hManager
!= NULL
)
964 DPRINT("Found manager handle\n");
966 /* FIXME: add handle cleanup code */
968 HeapFree(GetProcessHeap(), 0, hManager
);
973 DPRINT("RCloseServiceHandle() done\n");
974 return ERROR_SUCCESS
;
976 else if (hService
!= NULL
)
978 DPRINT("Found service handle\n");
980 /* Lock the service database exlusively */
981 ScmLockDatabaseExclusive();
983 /* Get the pointer to the service record */
984 lpService
= hService
->ServiceEntry
;
986 /* FIXME: add handle cleanup code */
988 /* Free the handle */
989 HeapFree(GetProcessHeap(), 0, hService
);
992 ASSERT(lpService
->dwRefCount
> 0);
994 lpService
->dwRefCount
--;
995 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
996 lpService
->dwRefCount
);
998 if (lpService
->dwRefCount
== 0)
1000 /* If this service has been marked for deletion */
1001 if (lpService
->bDeleted
)
1003 /* Open the Services Reg key */
1004 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1005 L
"System\\CurrentControlSet\\Services",
1007 KEY_SET_VALUE
| KEY_READ
,
1009 if (dwError
!= ERROR_SUCCESS
)
1011 DPRINT("Failed to open services key\n");
1012 ScmUnlockDatabase();
1016 /* Call the internal function with NULL, just to get bytes we need */
1017 Int_EnumDependentServicesW(hServicesKey
,
1022 &dwServicesReturned
);
1024 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */
1027 DPRINT("Deletion failed due to running dependencies.\n");
1028 RegCloseKey(hServicesKey
);
1029 ScmUnlockDatabase();
1030 return ERROR_SUCCESS
;
1033 /* There are no references and no runnning dependencies,
1034 it is now safe to delete the service */
1036 /* Delete the Service Key */
1037 dwError
= RegDeleteKeyW(hServicesKey
,
1038 lpService
->lpServiceName
);
1040 RegCloseKey(hServicesKey
);
1042 if (dwError
!= ERROR_SUCCESS
)
1044 DPRINT("Failed to Delete the Service Registry key\n");
1045 ScmUnlockDatabase();
1049 /* Delete the Service */
1050 ScmDeleteServiceRecord(lpService
);
1054 ScmUnlockDatabase();
1058 DPRINT("RCloseServiceHandle() done\n");
1059 return ERROR_SUCCESS
;
1062 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
1064 return ERROR_INVALID_HANDLE
;
1069 DWORD
RControlService(
1070 SC_RPC_HANDLE hService
,
1072 LPSERVICE_STATUS lpServiceStatus
)
1074 PSERVICE_HANDLE hSvc
;
1076 ACCESS_MASK DesiredAccess
;
1077 DWORD dwError
= ERROR_SUCCESS
;
1078 DWORD pcbBytesNeeded
= 0;
1079 DWORD dwServicesReturned
= 0;
1080 DWORD dwControlsAccepted
;
1081 DWORD dwCurrentState
;
1082 HKEY hServicesKey
= NULL
;
1084 DPRINT("RControlService() called\n");
1087 return ERROR_SHUTDOWN_IN_PROGRESS
;
1089 /* Check the service handle */
1090 hSvc
= ScmGetServiceFromHandle(hService
);
1093 DPRINT1("Invalid service handle!\n");
1094 return ERROR_INVALID_HANDLE
;
1097 /* Check the service entry point */
1098 lpService
= hSvc
->ServiceEntry
;
1099 if (lpService
== NULL
)
1101 DPRINT1("lpService == NULL!\n");
1102 return ERROR_INVALID_HANDLE
;
1105 /* Check access rights */
1108 case SERVICE_CONTROL_STOP
:
1109 DesiredAccess
= SERVICE_STOP
;
1112 case SERVICE_CONTROL_PAUSE
:
1113 case SERVICE_CONTROL_CONTINUE
:
1114 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
1117 case SERVICE_INTERROGATE
:
1118 DesiredAccess
= SERVICE_INTERROGATE
;
1122 if (dwControl
>= 128 && dwControl
<= 255)
1123 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
1125 return ERROR_INVALID_PARAMETER
;
1129 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1131 return ERROR_ACCESS_DENIED
;
1133 /* Return the current service status information */
1134 RtlCopyMemory(lpServiceStatus
,
1136 sizeof(SERVICE_STATUS
));
1138 if (dwControl
== SERVICE_CONTROL_STOP
)
1140 /* Check if the service has dependencies running as windows
1141 doesn't stop a service that does */
1143 /* Open the Services Reg key */
1144 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1145 L
"System\\CurrentControlSet\\Services",
1149 if (dwError
!= ERROR_SUCCESS
)
1151 DPRINT("Failed to open services key\n");
1155 /* Call the internal function with NULL, just to get bytes we need */
1156 Int_EnumDependentServicesW(hServicesKey
,
1161 &dwServicesReturned
);
1163 RegCloseKey(hServicesKey
);
1165 /* If pcbBytesNeeded is not zero then there are services running that
1166 are dependent on this service */
1167 if (pcbBytesNeeded
!= 0)
1169 DPRINT("Service has running dependencies. Failed to stop service.\n");
1170 return ERROR_DEPENDENT_SERVICES_RUNNING
;
1174 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1176 /* Send control code to the driver */
1177 dwError
= ScmControlDriver(lpService
,
1183 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
1184 dwCurrentState
= lpService
->Status
.dwCurrentState
;
1186 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1187 if (lpService
->lpImage
== NULL
|| dwCurrentState
== SERVICE_STOPPED
)
1188 return ERROR_SERVICE_NOT_ACTIVE
;
1190 /* Check the current state before sending a control request */
1191 switch (dwCurrentState
)
1193 case SERVICE_STOP_PENDING
:
1194 case SERVICE_STOPPED
:
1195 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1197 case SERVICE_START_PENDING
:
1200 case SERVICE_CONTROL_STOP
:
1203 case SERVICE_CONTROL_INTERROGATE
:
1204 RtlCopyMemory(lpServiceStatus
,
1206 sizeof(SERVICE_STATUS
));
1207 return ERROR_SUCCESS
;
1210 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
1215 /* Check if the control code is acceptable to the service */
1218 case SERVICE_CONTROL_STOP
:
1219 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
1220 return ERROR_INVALID_SERVICE_CONTROL
;
1223 case SERVICE_CONTROL_PAUSE
:
1224 case SERVICE_CONTROL_CONTINUE
:
1225 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
1226 return ERROR_INVALID_SERVICE_CONTROL
;
1230 /* Send control code to the service */
1231 dwError
= ScmControlService(lpService
,
1234 /* Return service status information */
1235 RtlCopyMemory(lpServiceStatus
,
1237 sizeof(SERVICE_STATUS
));
1240 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
1241 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
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 ScmLockDatabase(0, hMgr->0xC, hLock);
1327 /* FIXME: Lock the database */
1328 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
1330 return ERROR_SUCCESS
;
1335 DWORD
RQueryServiceObjectSecurity(
1336 SC_RPC_HANDLE hService
,
1337 SECURITY_INFORMATION dwSecurityInformation
,
1338 LPBYTE lpSecurityDescriptor
,
1340 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1342 PSERVICE_HANDLE hSvc
;
1344 ULONG DesiredAccess
= 0;
1346 DWORD dwBytesNeeded
;
1350 SECURITY_DESCRIPTOR ObjectDescriptor
;
1352 DPRINT("RQueryServiceObjectSecurity() called\n");
1354 hSvc
= ScmGetServiceFromHandle(hService
);
1357 DPRINT1("Invalid service handle!\n");
1358 return ERROR_INVALID_HANDLE
;
1361 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1362 GROUP_SECURITY_INFORMATION
|
1363 OWNER_SECURITY_INFORMATION
))
1364 DesiredAccess
|= READ_CONTROL
;
1366 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1367 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1369 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1372 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1373 return ERROR_ACCESS_DENIED
;
1376 lpService
= hSvc
->ServiceEntry
;
1377 if (lpService
== NULL
)
1379 DPRINT("lpService == NULL!\n");
1380 return ERROR_INVALID_HANDLE
;
1383 /* Lock the service database */
1384 ScmLockDatabaseShared();
1388 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
1390 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
1391 dwSecurityInformation
,
1392 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1396 /* Unlock the service database */
1397 ScmUnlockDatabase();
1399 if (NT_SUCCESS(Status
))
1401 *pcbBytesNeeded
= dwBytesNeeded
;
1402 dwError
= STATUS_SUCCESS
;
1404 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1406 *pcbBytesNeeded
= dwBytesNeeded
;
1407 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1409 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1411 dwError
= ERROR_GEN_FAILURE
;
1415 dwError
= RtlNtStatusToDosError(Status
);
1423 DWORD
RSetServiceObjectSecurity(
1424 SC_RPC_HANDLE hService
,
1425 DWORD dwSecurityInformation
,
1426 LPBYTE lpSecurityDescriptor
,
1427 DWORD dwSecuityDescriptorSize
)
1429 PSERVICE_HANDLE hSvc
;
1431 ULONG DesiredAccess
= 0;
1432 /* HANDLE hToken = NULL; */
1434 /* NTSTATUS Status; */
1437 DPRINT("RSetServiceObjectSecurity() called\n");
1439 hSvc
= ScmGetServiceFromHandle(hService
);
1442 DPRINT1("Invalid service handle!\n");
1443 return ERROR_INVALID_HANDLE
;
1446 if (dwSecurityInformation
== 0 ||
1447 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1448 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1449 return ERROR_INVALID_PARAMETER
;
1451 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1452 return ERROR_INVALID_PARAMETER
;
1454 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1455 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1457 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1458 DesiredAccess
|= WRITE_DAC
;
1460 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1461 DesiredAccess
|= WRITE_OWNER
;
1463 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1464 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1465 return ERROR_INVALID_PARAMETER
;
1467 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1468 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1469 return ERROR_INVALID_PARAMETER
;
1471 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1474 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1475 return ERROR_ACCESS_DENIED
;
1478 lpService
= hSvc
->ServiceEntry
;
1479 if (lpService
== NULL
)
1481 DPRINT("lpService == NULL!\n");
1482 return ERROR_INVALID_HANDLE
;
1485 if (lpService
->bDeleted
)
1486 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1489 RpcImpersonateClient(NULL
);
1491 Status
= NtOpenThreadToken(NtCurrentThread(),
1495 if (!NT_SUCCESS(Status
))
1496 return RtlNtStatusToDosError(Status
);
1501 /* Lock the service database exclusive */
1502 ScmLockDatabaseExclusive();
1505 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1506 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1507 &lpService
->lpSecurityDescriptor
,
1510 if (!NT_SUCCESS(Status
))
1512 dwError
= RtlNtStatusToDosError(Status
);
1517 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1518 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1520 if (dwError
!= ERROR_SUCCESS
)
1524 dwError
= ERROR_SUCCESS
;
1525 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1526 // lpService->lpSecurityDescriptor);
1528 RegFlushKey(hServiceKey
);
1529 RegCloseKey(hServiceKey
);
1538 /* Unlock service database */
1539 ScmUnlockDatabase();
1541 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1548 DWORD
RQueryServiceStatus(
1549 SC_RPC_HANDLE hService
,
1550 LPSERVICE_STATUS lpServiceStatus
)
1552 PSERVICE_HANDLE hSvc
;
1555 DPRINT("RQueryServiceStatus() called\n");
1558 return ERROR_SHUTDOWN_IN_PROGRESS
;
1560 hSvc
= ScmGetServiceFromHandle(hService
);
1563 DPRINT1("Invalid service handle!\n");
1564 return ERROR_INVALID_HANDLE
;
1567 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1568 SERVICE_QUERY_STATUS
))
1570 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1571 return ERROR_ACCESS_DENIED
;
1574 lpService
= hSvc
->ServiceEntry
;
1575 if (lpService
== NULL
)
1577 DPRINT("lpService == NULL!\n");
1578 return ERROR_INVALID_HANDLE
;
1581 /* Lock the service database shared */
1582 ScmLockDatabaseShared();
1584 /* Return service status information */
1585 RtlCopyMemory(lpServiceStatus
,
1587 sizeof(SERVICE_STATUS
));
1589 /* Unlock the service database */
1590 ScmUnlockDatabase();
1592 return ERROR_SUCCESS
;
1597 ScmIsValidServiceState(DWORD dwCurrentState
)
1599 switch (dwCurrentState
)
1601 case SERVICE_STOPPED
:
1602 case SERVICE_START_PENDING
:
1603 case SERVICE_STOP_PENDING
:
1604 case SERVICE_RUNNING
:
1605 case SERVICE_CONTINUE_PENDING
:
1606 case SERVICE_PAUSE_PENDING
:
1607 case SERVICE_PAUSED
:
1617 DWORD
RSetServiceStatus(
1618 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1619 LPSERVICE_STATUS lpServiceStatus
)
1623 DPRINT("RSetServiceStatus() called\n");
1624 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1625 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1626 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1627 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1628 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1629 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1630 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1631 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1633 if (hServiceStatus
== 0)
1635 DPRINT("hServiceStatus == NULL!\n");
1636 return ERROR_INVALID_HANDLE
;
1639 lpService
= (PSERVICE
)hServiceStatus
;
1640 if (lpService
== NULL
)
1642 DPRINT("lpService == NULL!\n");
1643 return ERROR_INVALID_HANDLE
;
1646 /* Check current state */
1647 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1649 DPRINT("Invalid service state!\n");
1650 return ERROR_INVALID_DATA
;
1653 /* Check service type */
1654 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1655 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1657 DPRINT("Invalid service type!\n");
1658 return ERROR_INVALID_DATA
;
1661 /* Check accepted controls */
1662 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1664 DPRINT("Invalid controls accepted!\n");
1665 return ERROR_INVALID_DATA
;
1668 /* Lock the service database exclusively */
1669 ScmLockDatabaseExclusive();
1671 RtlCopyMemory(&lpService
->Status
,
1673 sizeof(SERVICE_STATUS
));
1675 /* Unlock the service database */
1676 ScmUnlockDatabase();
1678 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1679 DPRINT("RSetServiceStatus() done\n");
1681 return ERROR_SUCCESS
;
1686 DWORD
RUnlockServiceDatabase(
1690 return ERROR_SUCCESS
;
1695 DWORD
RNotifyBootConfigStatus(
1696 SVCCTL_HANDLEW lpMachineName
,
1697 DWORD BootAcceptable
)
1699 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1700 return ERROR_SUCCESS
;
1703 // return ERROR_CALL_NOT_IMPLEMENTED;
1708 DWORD
RI_ScSetServiceBitsW(
1709 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1710 DWORD dwServiceBits
,
1712 int bUpdateImmediately
,
1716 return ERROR_CALL_NOT_IMPLEMENTED
;
1721 DWORD
RChangeServiceConfigW(
1722 SC_RPC_HANDLE hService
,
1723 DWORD dwServiceType
,
1725 DWORD dwErrorControl
,
1726 LPWSTR lpBinaryPathName
,
1727 LPWSTR lpLoadOrderGroup
,
1729 LPBYTE lpDependencies
,
1731 LPWSTR lpServiceStartName
,
1734 LPWSTR lpDisplayName
)
1736 DWORD dwError
= ERROR_SUCCESS
;
1737 PSERVICE_HANDLE hSvc
;
1738 PSERVICE lpService
= NULL
;
1739 HKEY hServiceKey
= NULL
;
1740 LPWSTR lpDisplayNameW
= NULL
;
1741 LPWSTR lpImagePathW
= NULL
;
1743 DPRINT("RChangeServiceConfigW() called\n");
1744 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1745 DPRINT("dwStartType = %lu\n", dwStartType
);
1746 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1747 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1748 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1749 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1752 return ERROR_SHUTDOWN_IN_PROGRESS
;
1754 hSvc
= ScmGetServiceFromHandle(hService
);
1757 DPRINT1("Invalid service handle!\n");
1758 return ERROR_INVALID_HANDLE
;
1761 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1762 SERVICE_CHANGE_CONFIG
))
1764 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1765 return ERROR_ACCESS_DENIED
;
1768 lpService
= hSvc
->ServiceEntry
;
1769 if (lpService
== NULL
)
1771 DPRINT("lpService == NULL!\n");
1772 return ERROR_INVALID_HANDLE
;
1775 /* Lock the service database exclusively */
1776 ScmLockDatabaseExclusive();
1778 if (lpService
->bDeleted
)
1780 DPRINT("The service has already been marked for delete!\n");
1781 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1785 /* Open the service key */
1786 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1789 if (dwError
!= ERROR_SUCCESS
)
1792 /* Write service data to the registry */
1793 /* Set the display name */
1794 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1796 RegSetValueExW(hServiceKey
,
1800 (LPBYTE
)lpDisplayName
,
1801 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1803 /* Update the display name */
1804 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
1806 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1807 if (lpDisplayNameW
== NULL
)
1809 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1813 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1814 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1816 lpService
->lpDisplayName
= lpDisplayNameW
;
1819 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1821 /* Set the service type */
1822 dwError
= RegSetValueExW(hServiceKey
,
1826 (LPBYTE
)&dwServiceType
,
1828 if (dwError
!= ERROR_SUCCESS
)
1831 lpService
->Status
.dwServiceType
= dwServiceType
;
1834 if (dwStartType
!= SERVICE_NO_CHANGE
)
1836 /* Set the start value */
1837 dwError
= RegSetValueExW(hServiceKey
,
1841 (LPBYTE
)&dwStartType
,
1843 if (dwError
!= ERROR_SUCCESS
)
1846 lpService
->dwStartType
= dwStartType
;
1849 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1851 /* Set the error control value */
1852 dwError
= RegSetValueExW(hServiceKey
,
1856 (LPBYTE
)&dwErrorControl
,
1858 if (dwError
!= ERROR_SUCCESS
)
1861 lpService
->dwErrorControl
= dwErrorControl
;
1864 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1866 /* Set the image path */
1867 lpImagePathW
= lpBinaryPathName
;
1869 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1871 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
1875 if (dwError
!= ERROR_SUCCESS
)
1879 dwError
= RegSetValueExW(hServiceKey
,
1883 (LPBYTE
)lpImagePathW
,
1884 (wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
));
1886 if (lpImagePathW
!= lpBinaryPathName
)
1887 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
1889 if (dwError
!= ERROR_SUCCESS
)
1893 /* Set the group name */
1894 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1896 dwError
= RegSetValueExW(hServiceKey
,
1900 (LPBYTE
)lpLoadOrderGroup
,
1901 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1902 if (dwError
!= ERROR_SUCCESS
)
1905 dwError
= ScmSetServiceGroup(lpService
,
1907 if (dwError
!= ERROR_SUCCESS
)
1911 if (lpdwTagId
!= NULL
)
1913 dwError
= ScmAssignNewTag(lpService
);
1914 if (dwError
!= ERROR_SUCCESS
)
1917 dwError
= RegSetValueExW(hServiceKey
,
1921 (LPBYTE
)&lpService
->dwTag
,
1923 if (dwError
!= ERROR_SUCCESS
)
1926 *lpdwTagId
= lpService
->dwTag
;
1929 /* Write dependencies */
1930 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1932 dwError
= ScmWriteDependencies(hServiceKey
,
1933 (LPWSTR
)lpDependencies
,
1935 if (dwError
!= ERROR_SUCCESS
)
1939 if (lpPassword
!= NULL
)
1941 /* FIXME: Write password */
1945 if (hServiceKey
!= NULL
)
1946 RegCloseKey(hServiceKey
);
1948 /* Unlock the service database */
1949 ScmUnlockDatabase();
1951 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1958 DWORD
RCreateServiceW(
1959 SC_RPC_HANDLE hSCManager
,
1960 LPCWSTR lpServiceName
,
1961 LPCWSTR lpDisplayName
,
1962 DWORD dwDesiredAccess
,
1963 DWORD dwServiceType
,
1965 DWORD dwErrorControl
,
1966 LPCWSTR lpBinaryPathName
,
1967 LPCWSTR lpLoadOrderGroup
,
1969 LPBYTE lpDependencies
,
1971 LPCWSTR lpServiceStartName
,
1974 LPSC_RPC_HANDLE lpServiceHandle
)
1976 PMANAGER_HANDLE hManager
;
1977 DWORD dwError
= ERROR_SUCCESS
;
1978 PSERVICE lpService
= NULL
;
1979 SC_HANDLE hServiceHandle
= NULL
;
1980 LPWSTR lpImagePath
= NULL
;
1981 HKEY hServiceKey
= NULL
;
1982 LPWSTR lpObjectName
;
1984 DPRINT("RCreateServiceW() called\n");
1985 DPRINT("lpServiceName = %S\n", lpServiceName
);
1986 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1987 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1988 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1989 DPRINT("dwStartType = %lu\n", dwStartType
);
1990 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1991 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1992 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1993 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
1996 return ERROR_SHUTDOWN_IN_PROGRESS
;
1998 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1999 if (hManager
== NULL
)
2001 DPRINT1("Invalid service manager handle!\n");
2002 return ERROR_INVALID_HANDLE
;
2005 /* Check access rights */
2006 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2007 SC_MANAGER_CREATE_SERVICE
))
2009 DPRINT("Insufficient access rights! 0x%lx\n",
2010 hManager
->Handle
.DesiredAccess
);
2011 return ERROR_ACCESS_DENIED
;
2014 if (wcslen(lpServiceName
) == 0)
2016 return ERROR_INVALID_NAME
;
2019 if (wcslen(lpBinaryPathName
) == 0)
2021 return ERROR_INVALID_PARAMETER
;
2024 /* Check for invalid service type value */
2025 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2026 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2027 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2028 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2029 return ERROR_INVALID_PARAMETER
;
2031 /* Check for invalid start type value */
2032 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2033 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2034 (dwStartType
!= SERVICE_AUTO_START
) &&
2035 (dwStartType
!= SERVICE_DEMAND_START
) &&
2036 (dwStartType
!= SERVICE_DISABLED
))
2037 return ERROR_INVALID_PARAMETER
;
2039 /* Only drivers can be boot start or system start services */
2040 if ((dwStartType
== SERVICE_BOOT_START
) ||
2041 (dwStartType
== SERVICE_SYSTEM_START
))
2043 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2044 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2045 return ERROR_INVALID_PARAMETER
;
2048 /* Check for invalid error control value */
2049 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2050 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2051 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2052 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2053 return ERROR_INVALID_PARAMETER
;
2055 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2056 (lpServiceStartName
))
2058 return ERROR_INVALID_PARAMETER
;
2061 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2063 return ERROR_INVALID_PARAMETER
;
2066 /* Lock the service database exclusively */
2067 ScmLockDatabaseExclusive();
2069 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2072 /* Unlock the service database */
2073 ScmUnlockDatabase();
2075 /* Check if it is marked for deletion */
2076 if (lpService
->bDeleted
)
2077 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2079 /* Return Error exist */
2080 return ERROR_SERVICE_EXISTS
;
2083 if (lpDisplayName
!= NULL
&&
2084 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2086 /* Unlock the service database */
2087 ScmUnlockDatabase();
2089 return ERROR_DUPLICATE_SERVICE_NAME
;
2092 if (dwServiceType
& SERVICE_DRIVER
)
2094 dwError
= ScmCanonDriverImagePath(dwStartType
,
2097 if (dwError
!= ERROR_SUCCESS
)
2102 if (dwStartType
== SERVICE_BOOT_START
||
2103 dwStartType
== SERVICE_SYSTEM_START
)
2105 /* Unlock the service database */
2106 ScmUnlockDatabase();
2108 return ERROR_INVALID_PARAMETER
;
2112 /* Allocate a new service entry */
2113 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2115 if (dwError
!= ERROR_SUCCESS
)
2118 /* Fill the new service entry */
2119 lpService
->Status
.dwServiceType
= dwServiceType
;
2120 lpService
->dwStartType
= dwStartType
;
2121 lpService
->dwErrorControl
= dwErrorControl
;
2123 /* Fill the display name */
2124 if (lpDisplayName
!= NULL
&&
2125 *lpDisplayName
!= 0 &&
2126 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2128 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(), 0,
2129 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2130 if (lpService
->lpDisplayName
== NULL
)
2132 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2135 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2138 /* Assign the service to a group */
2139 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2141 dwError
= ScmSetServiceGroup(lpService
,
2143 if (dwError
!= ERROR_SUCCESS
)
2147 /* Assign a new tag */
2148 if (lpdwTagId
!= NULL
)
2150 dwError
= ScmAssignNewTag(lpService
);
2151 if (dwError
!= ERROR_SUCCESS
)
2155 /* Write service data to the registry */
2156 /* Create the service key */
2157 dwError
= ScmCreateServiceKey(lpServiceName
,
2160 if (dwError
!= ERROR_SUCCESS
)
2163 /* Set the display name */
2164 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2166 RegSetValueExW(hServiceKey
,
2170 (LPBYTE
)lpDisplayName
,
2171 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2174 /* Set the service type */
2175 dwError
= RegSetValueExW(hServiceKey
,
2179 (LPBYTE
)&dwServiceType
,
2181 if (dwError
!= ERROR_SUCCESS
)
2184 /* Set the start value */
2185 dwError
= RegSetValueExW(hServiceKey
,
2189 (LPBYTE
)&dwStartType
,
2191 if (dwError
!= ERROR_SUCCESS
)
2194 /* Set the error control value */
2195 dwError
= RegSetValueExW(hServiceKey
,
2199 (LPBYTE
)&dwErrorControl
,
2201 if (dwError
!= ERROR_SUCCESS
)
2204 /* Set the image path */
2205 if (dwServiceType
& SERVICE_WIN32
)
2207 dwError
= RegSetValueExW(hServiceKey
,
2211 (LPBYTE
)lpBinaryPathName
,
2212 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2213 if (dwError
!= ERROR_SUCCESS
)
2216 else if (dwServiceType
& SERVICE_DRIVER
)
2218 dwError
= RegSetValueExW(hServiceKey
,
2222 (LPBYTE
)lpImagePath
,
2223 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2224 if (dwError
!= ERROR_SUCCESS
)
2228 /* Set the group name */
2229 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2231 dwError
= RegSetValueExW(hServiceKey
,
2235 (LPBYTE
)lpLoadOrderGroup
,
2236 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2237 if (dwError
!= ERROR_SUCCESS
)
2241 if (lpdwTagId
!= NULL
)
2243 dwError
= RegSetValueExW(hServiceKey
,
2247 (LPBYTE
)&lpService
->dwTag
,
2249 if (dwError
!= ERROR_SUCCESS
)
2253 /* Write dependencies */
2254 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2256 dwError
= ScmWriteDependencies(hServiceKey
,
2257 (LPCWSTR
)lpDependencies
,
2259 if (dwError
!= ERROR_SUCCESS
)
2263 /* Write service start name */
2264 if (dwServiceType
& SERVICE_WIN32
)
2266 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2267 dwError
= RegSetValueExW(hServiceKey
,
2271 (LPBYTE
)lpObjectName
,
2272 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2273 if (dwError
!= ERROR_SUCCESS
)
2277 if (lpPassword
!= NULL
)
2279 /* FIXME: Write password */
2282 dwError
= ScmCreateServiceHandle(lpService
,
2284 if (dwError
!= ERROR_SUCCESS
)
2287 dwError
= ScmCheckAccess(hServiceHandle
,
2289 if (dwError
!= ERROR_SUCCESS
)
2292 lpService
->dwRefCount
= 1;
2293 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2296 /* Unlock the service database */
2297 ScmUnlockDatabase();
2299 if (hServiceKey
!= NULL
)
2300 RegCloseKey(hServiceKey
);
2302 if (dwError
== ERROR_SUCCESS
)
2304 DPRINT("hService %p\n", hServiceHandle
);
2305 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2307 if (lpdwTagId
!= NULL
)
2308 *lpdwTagId
= lpService
->dwTag
;
2312 if (lpService
!= NULL
&&
2313 lpService
->lpServiceName
!= NULL
)
2315 /* Release the display name buffer */
2316 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2321 /* Remove the service handle */
2322 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2325 if (lpService
!= NULL
)
2327 /* FIXME: remove the service entry */
2331 if (lpImagePath
!= NULL
)
2332 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2334 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2341 DWORD
REnumDependentServicesW(
2342 SC_RPC_HANDLE hService
,
2343 DWORD dwServiceState
,
2346 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2347 LPBOUNDED_DWORD_256K lpServicesReturned
)
2349 DWORD dwError
= ERROR_SUCCESS
;
2350 DWORD dwServicesReturned
= 0;
2351 DWORD dwServiceCount
;
2352 HKEY hServicesKey
= NULL
;
2353 PSERVICE_HANDLE hSvc
;
2354 PSERVICE lpService
= NULL
;
2355 PSERVICE
*lpServicesArray
= NULL
;
2356 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2359 *pcbBytesNeeded
= 0;
2360 *lpServicesReturned
= 0;
2362 DPRINT("REnumDependentServicesW() called\n");
2364 hSvc
= ScmGetServiceFromHandle(hService
);
2367 DPRINT1("Invalid service handle!\n");
2368 return ERROR_INVALID_HANDLE
;
2371 lpService
= hSvc
->ServiceEntry
;
2373 /* Check access rights */
2374 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2375 SC_MANAGER_ENUMERATE_SERVICE
))
2377 DPRINT("Insufficient access rights! 0x%lx\n",
2378 hSvc
->Handle
.DesiredAccess
);
2379 return ERROR_ACCESS_DENIED
;
2382 /* Open the Services Reg key */
2383 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2384 L
"System\\CurrentControlSet\\Services",
2388 if (dwError
!= ERROR_SUCCESS
)
2391 /* First determine the bytes needed and get the number of dependent services */
2392 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2397 &dwServicesReturned
);
2398 if (dwError
!= ERROR_SUCCESS
)
2401 /* If buffer size is less than the bytes needed or pointer is null */
2402 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2404 dwError
= ERROR_MORE_DATA
;
2408 /* Allocate memory for array of service pointers */
2409 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2411 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2412 if (!lpServicesArray
)
2414 DPRINT1("Could not allocate a buffer!!\n");
2415 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2419 dwServicesReturned
= 0;
2420 *pcbBytesNeeded
= 0;
2422 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2427 &dwServicesReturned
);
2428 if (dwError
!= ERROR_SUCCESS
)
2433 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2434 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2436 /* Copy EnumDepenedentService to Buffer */
2437 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2439 lpService
= lpServicesArray
[dwServiceCount
];
2441 /* Copy status info */
2442 memcpy(&lpServicesPtr
->ServiceStatus
,
2444 sizeof(SERVICE_STATUS
));
2446 /* Copy display name */
2447 wcscpy(lpStr
, lpService
->lpDisplayName
);
2448 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2449 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2451 /* Copy service name */
2452 wcscpy(lpStr
, lpService
->lpServiceName
);
2453 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2454 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2459 *lpServicesReturned
= dwServicesReturned
;
2462 if (lpServicesArray
!= NULL
)
2463 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2465 RegCloseKey(hServicesKey
);
2467 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2474 DWORD
REnumServicesStatusW(
2475 SC_RPC_HANDLE hSCManager
,
2476 DWORD dwServiceType
,
2477 DWORD dwServiceState
,
2480 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2481 LPBOUNDED_DWORD_256K lpServicesReturned
,
2482 LPBOUNDED_DWORD_256K lpResumeHandle
)
2484 PMANAGER_HANDLE hManager
;
2486 DWORD dwError
= ERROR_SUCCESS
;
2487 PLIST_ENTRY ServiceEntry
;
2488 PSERVICE CurrentService
;
2490 DWORD dwRequiredSize
;
2491 DWORD dwServiceCount
;
2493 DWORD dwLastResumeCount
= 0;
2494 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2497 DPRINT("REnumServicesStatusW() called\n");
2500 return ERROR_SHUTDOWN_IN_PROGRESS
;
2502 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2503 if (hManager
== NULL
)
2505 DPRINT1("Invalid service manager handle!\n");
2506 return ERROR_INVALID_HANDLE
;
2510 *pcbBytesNeeded
= 0;
2511 *lpServicesReturned
= 0;
2513 if ((dwServiceType
== 0) ||
2514 ((dwServiceType
& ~(SERVICE_DRIVER
| SERVICE_WIN32
)) != 0))
2516 DPRINT("Not a valid Service Type!\n");
2517 return ERROR_INVALID_PARAMETER
;
2520 if ((dwServiceState
!= SERVICE_ACTIVE
) &&
2521 (dwServiceState
!= SERVICE_INACTIVE
) &&
2522 (dwServiceState
!= SERVICE_STATE_ALL
))
2524 DPRINT("Not a valid Service State!\n");
2525 return ERROR_INVALID_PARAMETER
;
2528 /* Check access rights */
2529 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2530 SC_MANAGER_ENUMERATE_SERVICE
))
2532 DPRINT("Insufficient access rights! 0x%lx\n",
2533 hManager
->Handle
.DesiredAccess
);
2534 return ERROR_ACCESS_DENIED
;
2538 dwLastResumeCount
= *lpResumeHandle
;
2540 /* Lock the service database shared */
2541 ScmLockDatabaseShared();
2543 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2544 if (lpService
== NULL
)
2546 dwError
= ERROR_SUCCESS
;
2553 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2554 ServiceEntry
!= &ServiceListHead
;
2555 ServiceEntry
= ServiceEntry
->Flink
)
2557 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2561 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2564 dwState
= SERVICE_ACTIVE
;
2565 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2566 dwState
= SERVICE_INACTIVE
;
2568 if ((dwState
& dwServiceState
) == 0)
2571 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2572 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2573 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2575 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2577 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2581 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2582 dwRequiredSize
+= dwSize
;
2584 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2587 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2588 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2591 ServiceEntry
!= &ServiceListHead
;
2592 ServiceEntry
= ServiceEntry
->Flink
)
2594 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2598 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2601 dwState
= SERVICE_ACTIVE
;
2602 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2603 dwState
= SERVICE_INACTIVE
;
2605 if ((dwState
& dwServiceState
) == 0)
2608 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2609 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2610 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2612 dwError
= ERROR_MORE_DATA
;
2615 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2618 *lpResumeHandle
= dwLastResumeCount
;
2620 *lpServicesReturned
= dwServiceCount
;
2621 *pcbBytesNeeded
= dwRequiredSize
;
2623 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2624 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2625 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2628 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2629 ServiceEntry
!= &ServiceListHead
;
2630 ServiceEntry
= ServiceEntry
->Flink
)
2632 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2636 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2639 dwState
= SERVICE_ACTIVE
;
2640 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2641 dwState
= SERVICE_INACTIVE
;
2643 if ((dwState
& dwServiceState
) == 0)
2646 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2647 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2648 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2650 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2653 /* Copy the service name */
2654 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2655 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2656 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2658 /* Copy the display name */
2659 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2660 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2661 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2663 /* Copy the status information */
2664 memcpy(&lpStatusPtr
->ServiceStatus
,
2665 &CurrentService
->Status
,
2666 sizeof(SERVICE_STATUS
));
2669 dwRequiredSize
+= dwSize
;
2672 if (dwError
== ERROR_SUCCESS
)
2674 *pcbBytesNeeded
= 0;
2675 if (lpResumeHandle
) *lpResumeHandle
= 0;
2679 /* Unlock the service database */
2680 ScmUnlockDatabase();
2682 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2689 DWORD
ROpenSCManagerW(
2690 LPWSTR lpMachineName
,
2691 LPWSTR lpDatabaseName
,
2692 DWORD dwDesiredAccess
,
2693 LPSC_RPC_HANDLE lpScHandle
)
2698 DPRINT("ROpenSCManagerW() called\n");
2699 DPRINT("lpMachineName = %p\n", lpMachineName
);
2700 DPRINT("lpMachineName: %S\n", lpMachineName
);
2701 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2702 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2703 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2706 return ERROR_SHUTDOWN_IN_PROGRESS
;
2709 return ERROR_INVALID_PARAMETER
;
2711 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2713 if (dwError
!= ERROR_SUCCESS
)
2715 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2719 /* Check the desired access */
2720 dwError
= ScmCheckAccess(hHandle
,
2721 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2722 if (dwError
!= ERROR_SUCCESS
)
2724 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2725 HeapFree(GetProcessHeap(), 0, hHandle
);
2729 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2730 DPRINT("*hScm = %p\n", *lpScHandle
);
2732 DPRINT("ROpenSCManagerW() done\n");
2734 return ERROR_SUCCESS
;
2739 DWORD
ROpenServiceW(
2740 SC_RPC_HANDLE hSCManager
,
2741 LPWSTR lpServiceName
,
2742 DWORD dwDesiredAccess
,
2743 LPSC_RPC_HANDLE lpServiceHandle
)
2746 PMANAGER_HANDLE hManager
;
2748 DWORD dwError
= ERROR_SUCCESS
;
2750 DPRINT("ROpenServiceW() called\n");
2751 DPRINT("hSCManager = %p\n", hSCManager
);
2752 DPRINT("lpServiceName = %p\n", lpServiceName
);
2753 DPRINT("lpServiceName: %S\n", lpServiceName
);
2754 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2757 return ERROR_SHUTDOWN_IN_PROGRESS
;
2759 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2760 if (hManager
== NULL
)
2762 DPRINT1("Invalid service manager handle!\n");
2763 return ERROR_INVALID_HANDLE
;
2766 if (!lpServiceHandle
)
2767 return ERROR_INVALID_PARAMETER
;
2770 return ERROR_INVALID_ADDRESS
;
2772 /* Lock the service database exclusive */
2773 ScmLockDatabaseExclusive();
2775 /* Get service database entry */
2776 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2777 if (lpService
== NULL
)
2779 DPRINT("Could not find a service!\n");
2780 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2784 /* Create a service handle */
2785 dwError
= ScmCreateServiceHandle(lpService
,
2787 if (dwError
!= ERROR_SUCCESS
)
2789 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2793 /* Check the desired access */
2794 dwError
= ScmCheckAccess(hHandle
,
2796 if (dwError
!= ERROR_SUCCESS
)
2798 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2799 HeapFree(GetProcessHeap(), 0, hHandle
);
2803 lpService
->dwRefCount
++;
2804 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2806 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2807 DPRINT("*hService = %p\n", *lpServiceHandle
);
2810 /* Unlock the service database */
2811 ScmUnlockDatabase();
2813 DPRINT("ROpenServiceW() done\n");
2820 DWORD
RQueryServiceConfigW(
2821 SC_RPC_HANDLE hService
,
2822 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2824 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2826 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2827 DWORD dwError
= ERROR_SUCCESS
;
2828 PSERVICE_HANDLE hSvc
;
2829 PSERVICE lpService
= NULL
;
2830 HKEY hServiceKey
= NULL
;
2831 LPWSTR lpImagePath
= NULL
;
2832 LPWSTR lpServiceStartName
= NULL
;
2833 LPWSTR lpDependencies
= NULL
;
2834 DWORD dwDependenciesLength
= 0;
2835 DWORD dwRequiredSize
;
2836 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2837 WCHAR lpEmptyString
[] = {0,0};
2840 DPRINT("RQueryServiceConfigW() called\n");
2843 return ERROR_SHUTDOWN_IN_PROGRESS
;
2845 hSvc
= ScmGetServiceFromHandle(hService
);
2848 DPRINT1("Invalid service handle!\n");
2849 return ERROR_INVALID_HANDLE
;
2852 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2853 SERVICE_QUERY_CONFIG
))
2855 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2856 return ERROR_ACCESS_DENIED
;
2859 lpService
= hSvc
->ServiceEntry
;
2860 if (lpService
== NULL
)
2862 DPRINT("lpService == NULL!\n");
2863 return ERROR_INVALID_HANDLE
;
2866 /* Lock the service database shared */
2867 ScmLockDatabaseShared();
2869 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2872 if (dwError
!= ERROR_SUCCESS
)
2875 /* Read the image path */
2876 dwError
= ScmReadString(hServiceKey
,
2879 if (dwError
!= ERROR_SUCCESS
)
2882 /* Read the service start name */
2883 ScmReadString(hServiceKey
,
2885 &lpServiceStartName
);
2887 /* Read the dependencies */
2888 ScmReadDependencies(hServiceKey
,
2890 &dwDependenciesLength
);
2892 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2894 if (lpImagePath
!= NULL
)
2895 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2897 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2899 if (lpService
->lpGroup
!= NULL
)
2900 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2902 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2904 if (lpDependencies
!= NULL
)
2905 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2907 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2909 if (lpServiceStartName
!= NULL
)
2910 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2912 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2914 if (lpService
->lpDisplayName
!= NULL
)
2915 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2917 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2919 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2921 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2925 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2926 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2927 lpConfig
->dwStartType
= lpService
->dwStartType
;
2928 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2929 lpConfig
->dwTagId
= lpService
->dwTag
;
2931 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2933 /* Append the image path */
2934 if (lpImagePath
!= NULL
)
2936 wcscpy(lpStr
, lpImagePath
);
2940 wcscpy(lpStr
, lpEmptyString
);
2943 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2944 lpStr
+= (wcslen(lpStr
) + 1);
2946 /* Append the group name */
2947 if (lpService
->lpGroup
!= NULL
)
2949 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2953 wcscpy(lpStr
, lpEmptyString
);
2956 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2957 lpStr
+= (wcslen(lpStr
) + 1);
2959 /* Append Dependencies */
2960 if (lpDependencies
!= NULL
)
2964 dwDependenciesLength
* sizeof(WCHAR
));
2968 wcscpy(lpStr
, lpEmptyString
);
2971 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2972 if (lpDependencies
!= NULL
)
2973 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2975 lpStr
+= (wcslen(lpStr
) + 1);
2977 /* Append the service start name */
2978 if (lpServiceStartName
!= NULL
)
2980 wcscpy(lpStr
, lpServiceStartName
);
2984 wcscpy(lpStr
, lpEmptyString
);
2987 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2988 lpStr
+= (wcslen(lpStr
) + 1);
2990 /* Append the display name */
2991 if (lpService
->lpDisplayName
!= NULL
)
2993 wcscpy(lpStr
, lpService
->lpDisplayName
);
2997 wcscpy(lpStr
, lpEmptyString
);
3000 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3003 if (pcbBytesNeeded
!= NULL
)
3004 *pcbBytesNeeded
= dwRequiredSize
;
3007 /* Unlock the service database */
3008 ScmUnlockDatabase();
3010 if (lpImagePath
!= NULL
)
3011 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3013 if (lpServiceStartName
!= NULL
)
3014 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3016 if (lpDependencies
!= NULL
)
3017 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3019 if (hServiceKey
!= NULL
)
3020 RegCloseKey(hServiceKey
);
3022 DPRINT("RQueryServiceConfigW() done\n");
3029 DWORD
RQueryServiceLockStatusW(
3030 SC_RPC_HANDLE hSCManager
,
3031 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
3033 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3036 return ERROR_CALL_NOT_IMPLEMENTED
;
3041 DWORD
RStartServiceW(
3042 SC_RPC_HANDLE hService
,
3044 LPSTRING_PTRSW argv
)
3046 DWORD dwError
= ERROR_SUCCESS
;
3047 PSERVICE_HANDLE hSvc
;
3048 PSERVICE lpService
= NULL
;
3051 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3052 DPRINT(" argc: %lu\n", argc
);
3055 for (i
= 0; i
< argc
; i
++)
3057 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
]);
3062 return ERROR_SHUTDOWN_IN_PROGRESS
;
3064 hSvc
= ScmGetServiceFromHandle(hService
);
3067 DPRINT1("Invalid service handle!\n");
3068 return ERROR_INVALID_HANDLE
;
3071 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3074 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3075 return ERROR_ACCESS_DENIED
;
3078 lpService
= hSvc
->ServiceEntry
;
3079 if (lpService
== NULL
)
3081 DPRINT("lpService == NULL!\n");
3082 return ERROR_INVALID_HANDLE
;
3085 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3086 return ERROR_SERVICE_DISABLED
;
3088 if (lpService
->bDeleted
)
3089 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3091 /* Start the service */
3092 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3099 DWORD
RGetServiceDisplayNameW(
3100 SC_RPC_HANDLE hSCManager
,
3101 LPCWSTR lpServiceName
,
3102 LPWSTR lpDisplayName
,
3105 // PMANAGER_HANDLE hManager;
3110 DPRINT("RGetServiceDisplayNameW() called\n");
3111 DPRINT("hSCManager = %p\n", hSCManager
);
3112 DPRINT("lpServiceName: %S\n", lpServiceName
);
3113 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3114 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3116 // hManager = (PMANAGER_HANDLE)hSCManager;
3117 // if (hManager->Handle.Tag != MANAGER_TAG)
3119 // DPRINT("Invalid manager handle!\n");
3120 // return ERROR_INVALID_HANDLE;
3123 /* Get service database entry */
3124 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3125 if (lpService
== NULL
)
3127 DPRINT("Could not find a service!\n");
3129 /* If the service could not be found and lpcchBuffer is less than 2, windows
3130 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3131 if (*lpcchBuffer
< 2)
3134 if (lpDisplayName
!= NULL
)
3136 *lpDisplayName
= '\0';
3140 return ERROR_SERVICE_DOES_NOT_EXIST
;
3143 if (!lpService
->lpDisplayName
)
3145 dwLength
= wcslen(lpService
->lpServiceName
);
3147 if (lpDisplayName
!= NULL
&&
3148 *lpcchBuffer
> dwLength
)
3150 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3155 dwLength
= wcslen(lpService
->lpDisplayName
);
3157 if (lpDisplayName
!= NULL
&&
3158 *lpcchBuffer
> dwLength
)
3160 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3164 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3166 *lpcchBuffer
= dwLength
;
3173 DWORD
RGetServiceKeyNameW(
3174 SC_RPC_HANDLE hSCManager
,
3175 LPCWSTR lpDisplayName
,
3176 LPWSTR lpServiceName
,
3179 // PMANAGER_HANDLE hManager;
3184 DPRINT("RGetServiceKeyNameW() called\n");
3185 DPRINT("hSCManager = %p\n", hSCManager
);
3186 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3187 DPRINT("lpServiceName: %p\n", lpServiceName
);
3188 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3190 // hManager = (PMANAGER_HANDLE)hSCManager;
3191 // if (hManager->Handle.Tag != MANAGER_TAG)
3193 // DPRINT("Invalid manager handle!\n");
3194 // return ERROR_INVALID_HANDLE;
3197 /* Get service database entry */
3198 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3199 if (lpService
== NULL
)
3201 DPRINT("Could not find a service!\n");
3203 /* If the service could not be found and lpcchBuffer is less than 2, windows
3204 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3205 if (*lpcchBuffer
< 2)
3208 if (lpServiceName
!= NULL
)
3210 *lpServiceName
= '\0';
3214 return ERROR_SERVICE_DOES_NOT_EXIST
;
3217 dwLength
= wcslen(lpService
->lpServiceName
);
3219 if (lpServiceName
!= NULL
&&
3220 *lpcchBuffer
> dwLength
)
3222 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3223 *lpcchBuffer
= dwLength
;
3224 return ERROR_SUCCESS
;
3227 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3229 *lpcchBuffer
= dwLength
;
3236 DWORD
RI_ScSetServiceBitsA(
3237 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3238 DWORD dwServiceBits
,
3240 int bUpdateImmediately
,
3244 return ERROR_CALL_NOT_IMPLEMENTED
;
3249 DWORD
RChangeServiceConfigA(
3250 SC_RPC_HANDLE hService
,
3251 DWORD dwServiceType
,
3253 DWORD dwErrorControl
,
3254 LPSTR lpBinaryPathName
,
3255 LPSTR lpLoadOrderGroup
,
3257 LPSTR lpDependencies
,
3259 LPSTR lpServiceStartName
,
3262 LPSTR lpDisplayName
)
3264 DWORD dwError
= ERROR_SUCCESS
;
3265 PSERVICE_HANDLE hSvc
;
3266 PSERVICE lpService
= NULL
;
3267 HKEY hServiceKey
= NULL
;
3268 LPWSTR lpDisplayNameW
= NULL
;
3269 LPWSTR lpBinaryPathNameW
= NULL
;
3270 LPWSTR lpCanonicalImagePathW
= NULL
;
3271 LPWSTR lpLoadOrderGroupW
= NULL
;
3272 LPWSTR lpDependenciesW
= NULL
;
3273 // LPWSTR lpPasswordW = NULL;
3275 DPRINT("RChangeServiceConfigA() called\n");
3276 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3277 DPRINT("dwStartType = %lu\n", dwStartType
);
3278 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3279 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3280 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3281 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3284 return ERROR_SHUTDOWN_IN_PROGRESS
;
3286 hSvc
= ScmGetServiceFromHandle(hService
);
3289 DPRINT1("Invalid service handle!\n");
3290 return ERROR_INVALID_HANDLE
;
3293 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3294 SERVICE_CHANGE_CONFIG
))
3296 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3297 return ERROR_ACCESS_DENIED
;
3300 lpService
= hSvc
->ServiceEntry
;
3301 if (lpService
== NULL
)
3303 DPRINT("lpService == NULL!\n");
3304 return ERROR_INVALID_HANDLE
;
3307 /* Lock the service database exclusively */
3308 ScmLockDatabaseExclusive();
3310 if (lpService
->bDeleted
)
3312 DPRINT("The service has already been marked for delete!\n");
3313 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3317 /* Open the service key */
3318 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3321 if (dwError
!= ERROR_SUCCESS
)
3324 /* Write service data to the registry */
3326 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3328 /* Set the display name */
3329 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3331 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3332 if (lpDisplayNameW
== NULL
)
3334 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3338 MultiByteToWideChar(CP_ACP
,
3343 strlen(lpDisplayName
) + 1);
3345 RegSetValueExW(hServiceKey
,
3349 (LPBYTE
)lpDisplayNameW
,
3350 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3352 /* Update lpService->lpDisplayName */
3353 if (lpService
->lpDisplayName
)
3354 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3356 lpService
->lpDisplayName
= lpDisplayNameW
;
3359 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3361 /* Set the service type */
3362 dwError
= RegSetValueExW(hServiceKey
,
3366 (LPBYTE
)&dwServiceType
,
3368 if (dwError
!= ERROR_SUCCESS
)
3371 lpService
->Status
.dwServiceType
= dwServiceType
;
3374 if (dwStartType
!= SERVICE_NO_CHANGE
)
3376 /* Set the start value */
3377 dwError
= RegSetValueExW(hServiceKey
,
3381 (LPBYTE
)&dwStartType
,
3383 if (dwError
!= ERROR_SUCCESS
)
3386 lpService
->dwStartType
= dwStartType
;
3389 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3391 /* Set the error control value */
3392 dwError
= RegSetValueExW(hServiceKey
,
3396 (LPBYTE
)&dwErrorControl
,
3398 if (dwError
!= ERROR_SUCCESS
)
3401 lpService
->dwErrorControl
= dwErrorControl
;
3404 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3406 /* Set the image path */
3407 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(),
3409 (strlen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
3410 if (lpBinaryPathNameW
== NULL
)
3412 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3416 MultiByteToWideChar(CP_ACP
,
3421 strlen(lpBinaryPathName
) + 1);
3423 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
3425 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
3427 &lpCanonicalImagePathW
);
3429 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3431 if (dwError
!= ERROR_SUCCESS
)
3434 lpBinaryPathNameW
= lpCanonicalImagePathW
;
3437 dwError
= RegSetValueExW(hServiceKey
,
3441 (LPBYTE
)lpBinaryPathNameW
,
3442 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3444 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3446 if (dwError
!= ERROR_SUCCESS
)
3450 /* Set the group name */
3451 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3453 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3455 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3456 if (lpLoadOrderGroupW
== NULL
)
3458 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3462 MultiByteToWideChar(CP_ACP
,
3467 strlen(lpLoadOrderGroup
) + 1);
3469 dwError
= RegSetValueExW(hServiceKey
,
3473 (LPBYTE
)lpLoadOrderGroupW
,
3474 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3475 if (dwError
!= ERROR_SUCCESS
)
3477 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3481 dwError
= ScmSetServiceGroup(lpService
,
3484 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3486 if (dwError
!= ERROR_SUCCESS
)
3490 if (lpdwTagId
!= NULL
)
3492 dwError
= ScmAssignNewTag(lpService
);
3493 if (dwError
!= ERROR_SUCCESS
)
3496 dwError
= RegSetValueExW(hServiceKey
,
3500 (LPBYTE
)&lpService
->dwTag
,
3502 if (dwError
!= ERROR_SUCCESS
)
3505 *lpdwTagId
= lpService
->dwTag
;
3508 /* Write dependencies */
3509 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3511 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3513 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3514 if (lpDependenciesW
== NULL
)
3516 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3520 MultiByteToWideChar(CP_ACP
,
3525 strlen(lpDependencies
) + 1);
3527 dwError
= ScmWriteDependencies(hServiceKey
,
3528 (LPWSTR
)lpDependenciesW
,
3531 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3534 if (lpPassword
!= NULL
)
3536 /* FIXME: Write password */
3540 /* Unlock the service database */
3541 ScmUnlockDatabase();
3543 if (hServiceKey
!= NULL
)
3544 RegCloseKey(hServiceKey
);
3546 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3553 DWORD
RCreateServiceA(
3554 SC_RPC_HANDLE hSCManager
,
3555 LPSTR lpServiceName
,
3556 LPSTR lpDisplayName
,
3557 DWORD dwDesiredAccess
,
3558 DWORD dwServiceType
,
3560 DWORD dwErrorControl
,
3561 LPSTR lpBinaryPathName
,
3562 LPSTR lpLoadOrderGroup
,
3564 LPBYTE lpDependencies
,
3566 LPSTR lpServiceStartName
,
3569 LPSC_RPC_HANDLE lpServiceHandle
)
3571 DWORD dwError
= ERROR_SUCCESS
;
3572 LPWSTR lpServiceNameW
= NULL
;
3573 LPWSTR lpDisplayNameW
= NULL
;
3574 LPWSTR lpBinaryPathNameW
= NULL
;
3575 LPWSTR lpLoadOrderGroupW
= NULL
;
3576 LPWSTR lpDependenciesW
= NULL
;
3577 LPWSTR lpServiceStartNameW
= NULL
;
3578 DWORD dwDependenciesLength
= 0;
3585 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3586 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3587 if (!lpServiceNameW
)
3589 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3592 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3597 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3598 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3599 if (!lpDisplayNameW
)
3601 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3604 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3607 if (lpBinaryPathName
)
3609 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3610 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3611 if (!lpBinaryPathNameW
)
3613 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3616 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3619 if (lpLoadOrderGroup
)
3621 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3622 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3623 if (!lpLoadOrderGroupW
)
3625 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3628 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3633 lpStr
= (LPCSTR
)lpDependencies
;
3636 dwLength
= strlen(lpStr
) + 1;
3637 dwDependenciesLength
+= dwLength
;
3638 lpStr
= lpStr
+ dwLength
;
3640 dwDependenciesLength
++;
3642 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3643 if (!lpDependenciesW
)
3645 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3648 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3651 if (lpServiceStartName
)
3653 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3654 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3655 if (!lpServiceStartNameW
)
3657 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3660 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3663 dwError
= RCreateServiceW(hSCManager
,
3673 (LPBYTE
)lpDependenciesW
,
3674 dwDependenciesLength
,
3675 lpServiceStartNameW
,
3681 if (lpServiceNameW
!=NULL
)
3682 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3684 if (lpDisplayNameW
!= NULL
)
3685 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3687 if (lpBinaryPathNameW
!= NULL
)
3688 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3690 if (lpLoadOrderGroupW
!= NULL
)
3691 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3693 if (lpDependenciesW
!= NULL
)
3694 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3696 if (lpServiceStartNameW
!= NULL
)
3697 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3704 DWORD
REnumDependentServicesA(
3705 SC_RPC_HANDLE hService
,
3706 DWORD dwServiceState
,
3709 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3710 LPBOUNDED_DWORD_256K lpServicesReturned
)
3712 DWORD dwError
= ERROR_SUCCESS
;
3713 DWORD dwServicesReturned
= 0;
3714 DWORD dwServiceCount
;
3715 HKEY hServicesKey
= NULL
;
3716 PSERVICE_HANDLE hSvc
;
3717 PSERVICE lpService
= NULL
;
3718 PSERVICE
*lpServicesArray
= NULL
;
3719 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3722 *pcbBytesNeeded
= 0;
3723 *lpServicesReturned
= 0;
3725 DPRINT("REnumDependentServicesA() called\n");
3727 hSvc
= ScmGetServiceFromHandle(hService
);
3730 DPRINT1("Invalid service handle!\n");
3731 return ERROR_INVALID_HANDLE
;
3734 lpService
= hSvc
->ServiceEntry
;
3736 /* Check access rights */
3737 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3738 SC_MANAGER_ENUMERATE_SERVICE
))
3740 DPRINT("Insufficient access rights! 0x%lx\n",
3741 hSvc
->Handle
.DesiredAccess
);
3742 return ERROR_ACCESS_DENIED
;
3745 /* Open the Services Reg key */
3746 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3747 L
"System\\CurrentControlSet\\Services",
3752 if (dwError
!= ERROR_SUCCESS
)
3755 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3756 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3757 are the same for both. Verified in WINXP. */
3759 /* First determine the bytes needed and get the number of dependent services*/
3760 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3765 &dwServicesReturned
);
3766 if (dwError
!= ERROR_SUCCESS
)
3769 /* If buffer size is less than the bytes needed or pointer is null*/
3770 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3772 dwError
= ERROR_MORE_DATA
;
3776 /* Allocate memory for array of service pointers */
3777 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3779 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3780 if (!lpServicesArray
)
3782 DPRINT("Could not allocate a buffer!!\n");
3783 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3787 dwServicesReturned
= 0;
3788 *pcbBytesNeeded
= 0;
3790 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3795 &dwServicesReturned
);
3796 if (dwError
!= ERROR_SUCCESS
)
3801 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3802 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3804 /* Copy EnumDepenedentService to Buffer */
3805 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3807 lpService
= lpServicesArray
[dwServiceCount
];
3809 /* Copy the status info */
3810 memcpy(&lpServicesPtr
->ServiceStatus
,
3812 sizeof(SERVICE_STATUS
));
3814 /* Copy display name */
3815 WideCharToMultiByte(CP_ACP
,
3817 lpService
->lpDisplayName
,
3820 wcslen(lpService
->lpDisplayName
),
3823 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3824 lpStr
+= strlen(lpStr
) + 1;
3826 /* Copy service name */
3827 WideCharToMultiByte(CP_ACP
,
3829 lpService
->lpServiceName
,
3832 wcslen(lpService
->lpServiceName
),
3835 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3836 lpStr
+= strlen(lpStr
) + 1;
3841 *lpServicesReturned
= dwServicesReturned
;
3844 if (lpServicesArray
)
3845 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3847 RegCloseKey(hServicesKey
);
3849 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3856 DWORD
REnumServicesStatusA(
3857 SC_RPC_HANDLE hSCManager
,
3858 DWORD dwServiceType
,
3859 DWORD dwServiceState
,
3862 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3863 LPBOUNDED_DWORD_256K lpServicesReturned
,
3864 LPBOUNDED_DWORD_256K lpResumeHandle
)
3866 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3867 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3868 LPWSTR lpStringPtrW
;
3871 DWORD dwServiceCount
;
3873 DPRINT("REnumServicesStatusA() called\n");
3875 if ((dwBufSize
> 0) && (lpBuffer
))
3877 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3880 DPRINT("Failed to allocate buffer!\n");
3881 return ERROR_NOT_ENOUGH_MEMORY
;
3885 dwError
= REnumServicesStatusW(hSCManager
,
3888 (LPBYTE
)lpStatusPtrW
,
3894 /* if no services were returned then we are Done */
3895 if (*lpServicesReturned
== 0)
3898 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3899 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3900 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3901 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3902 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3904 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3906 /* Copy the service name */
3907 WideCharToMultiByte(CP_ACP
,
3912 wcslen(lpStringPtrW
),
3916 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3917 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3918 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3920 /* Copy the display name */
3921 WideCharToMultiByte(CP_ACP
,
3926 wcslen(lpStringPtrW
),
3930 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3931 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3932 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3934 /* Copy the status information */
3935 memcpy(&lpStatusPtrA
->ServiceStatus
,
3936 &lpStatusPtrW
->ServiceStatus
,
3937 sizeof(SERVICE_STATUS
));
3944 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3946 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3953 DWORD
ROpenSCManagerA(
3954 LPSTR lpMachineName
,
3955 LPSTR lpDatabaseName
,
3956 DWORD dwDesiredAccess
,
3957 LPSC_RPC_HANDLE lpScHandle
)
3959 UNICODE_STRING MachineName
;
3960 UNICODE_STRING DatabaseName
;
3963 DPRINT("ROpenSCManagerA() called\n");
3966 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3970 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3973 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3974 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3979 RtlFreeUnicodeString(&MachineName
);
3982 RtlFreeUnicodeString(&DatabaseName
);
3989 DWORD
ROpenServiceA(
3990 SC_RPC_HANDLE hSCManager
,
3991 LPSTR lpServiceName
,
3992 DWORD dwDesiredAccess
,
3993 LPSC_RPC_HANDLE lpServiceHandle
)
3995 UNICODE_STRING ServiceName
;
3998 DPRINT("ROpenServiceA() called\n");
4001 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
4004 dwError
= ROpenServiceW(hSCManager
,
4005 lpServiceName
? ServiceName
.Buffer
: NULL
,
4010 RtlFreeUnicodeString(&ServiceName
);
4017 DWORD
RQueryServiceConfigA(
4018 SC_RPC_HANDLE hService
,
4019 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4021 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4023 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
4024 DWORD dwError
= ERROR_SUCCESS
;
4025 PSERVICE_HANDLE hSvc
;
4026 PSERVICE lpService
= NULL
;
4027 HKEY hServiceKey
= NULL
;
4028 LPWSTR lpImagePath
= NULL
;
4029 LPWSTR lpServiceStartName
= NULL
;
4030 LPWSTR lpDependencies
= NULL
;
4031 DWORD dwDependenciesLength
= 0;
4032 DWORD dwRequiredSize
;
4033 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
4034 CHAR lpEmptyString
[]={0,0};
4037 DPRINT("RQueryServiceConfigA() called\n");
4040 return ERROR_SHUTDOWN_IN_PROGRESS
;
4042 hSvc
= ScmGetServiceFromHandle(hService
);
4045 DPRINT1("Invalid service handle!\n");
4046 return ERROR_INVALID_HANDLE
;
4049 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4050 SERVICE_QUERY_CONFIG
))
4052 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4053 return ERROR_ACCESS_DENIED
;
4056 lpService
= hSvc
->ServiceEntry
;
4057 if (lpService
== NULL
)
4059 DPRINT("lpService == NULL!\n");
4060 return ERROR_INVALID_HANDLE
;
4063 /* Lock the service database shared */
4064 ScmLockDatabaseShared();
4066 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4069 if (dwError
!= ERROR_SUCCESS
)
4072 /* Read the image path */
4073 dwError
= ScmReadString(hServiceKey
,
4076 if (dwError
!= ERROR_SUCCESS
)
4079 /* Read the service start name */
4080 ScmReadString(hServiceKey
,
4082 &lpServiceStartName
);
4084 /* Read the dependencies */
4085 ScmReadDependencies(hServiceKey
,
4087 &dwDependenciesLength
);
4089 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
4091 if (lpImagePath
!= NULL
)
4092 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
4094 dwRequiredSize
+= 2;
4096 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
4097 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
4099 dwRequiredSize
+= 2;
4101 /* Add Dependencies length */
4102 if (lpDependencies
!= NULL
)
4103 dwRequiredSize
+= dwDependenciesLength
;
4105 dwRequiredSize
+= 2;
4107 if (lpServiceStartName
!= NULL
)
4108 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
4110 dwRequiredSize
+= 2;
4112 if (lpService
->lpDisplayName
!= NULL
)
4113 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
4115 dwRequiredSize
+= 2;
4117 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
4119 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4123 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
4124 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
4125 lpConfig
->dwStartType
= lpService
->dwStartType
;
4126 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
4127 lpConfig
->dwTagId
= lpService
->dwTag
;
4129 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
4131 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4136 WideCharToMultiByte(CP_ACP
,
4141 wcslen(lpImagePath
) + 1,
4147 strcpy(lpStr
, lpEmptyString
);
4150 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4151 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4153 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4155 WideCharToMultiByte(CP_ACP
,
4157 lpService
->lpGroup
->lpGroupName
,
4160 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
4166 strcpy(lpStr
, lpEmptyString
);
4169 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4170 lpStr
+= (strlen(lpStr
) + 1);
4172 /* Append Dependencies */
4175 WideCharToMultiByte(CP_ACP
,
4178 dwDependenciesLength
,
4180 dwDependenciesLength
,
4186 strcpy(lpStr
, lpEmptyString
);
4189 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4191 lpStr
+= dwDependenciesLength
;
4193 lpStr
+= (strlen(lpStr
) + 1);
4195 if (lpServiceStartName
)
4197 WideCharToMultiByte(CP_ACP
,
4202 wcslen(lpServiceStartName
) + 1,
4208 strcpy(lpStr
, lpEmptyString
);
4211 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4212 lpStr
+= (strlen(lpStr
) + 1);
4214 if (lpService
->lpDisplayName
)
4216 WideCharToMultiByte(CP_ACP
,
4218 lpService
->lpDisplayName
,
4221 wcslen(lpService
->lpDisplayName
) + 1,
4227 strcpy(lpStr
, lpEmptyString
);
4230 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4233 if (pcbBytesNeeded
!= NULL
)
4234 *pcbBytesNeeded
= dwRequiredSize
;
4237 /* Unlock the service database */
4238 ScmUnlockDatabase();
4240 if (lpImagePath
!= NULL
)
4241 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4243 if (lpServiceStartName
!= NULL
)
4244 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4246 if (lpDependencies
!= NULL
)
4247 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4249 if (hServiceKey
!= NULL
)
4250 RegCloseKey(hServiceKey
);
4252 DPRINT("RQueryServiceConfigA() done\n");
4259 DWORD
RQueryServiceLockStatusA(
4260 SC_RPC_HANDLE hSCManager
,
4261 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4263 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4266 return ERROR_CALL_NOT_IMPLEMENTED
;
4271 DWORD
RStartServiceA(
4272 SC_RPC_HANDLE hService
,
4274 LPSTRING_PTRSA argv
)
4276 DWORD dwError
= ERROR_SUCCESS
;
4277 PSERVICE_HANDLE hSvc
;
4278 PSERVICE lpService
= NULL
;
4279 LPWSTR
*lpVector
= NULL
;
4283 DPRINT("RStartServiceA() called\n");
4286 return ERROR_SHUTDOWN_IN_PROGRESS
;
4288 hSvc
= ScmGetServiceFromHandle(hService
);
4291 DPRINT1("Invalid service handle!\n");
4292 return ERROR_INVALID_HANDLE
;
4295 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4298 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4299 return ERROR_ACCESS_DENIED
;
4302 lpService
= hSvc
->ServiceEntry
;
4303 if (lpService
== NULL
)
4305 DPRINT("lpService == NULL!\n");
4306 return ERROR_INVALID_HANDLE
;
4309 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4310 return ERROR_SERVICE_DISABLED
;
4312 if (lpService
->bDeleted
)
4313 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4315 /* Build a Unicode argument vector */
4318 lpVector
= HeapAlloc(GetProcessHeap(),
4320 argc
* sizeof(LPWSTR
));
4321 if (lpVector
== NULL
)
4322 return ERROR_NOT_ENOUGH_MEMORY
;
4324 for (i
= 0; i
< argc
; i
++)
4326 dwLength
= MultiByteToWideChar(CP_ACP
,
4333 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4335 dwLength
* sizeof(WCHAR
));
4336 if (lpVector
[i
] == NULL
)
4338 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4342 MultiByteToWideChar(CP_ACP
,
4351 /* Start the service */
4352 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4355 /* Free the Unicode argument vector */
4356 if (lpVector
!= NULL
)
4358 for (i
= 0; i
< argc
; i
++)
4360 if (lpVector
[i
] != NULL
)
4361 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4363 HeapFree(GetProcessHeap(), 0, lpVector
);
4371 DWORD
RGetServiceDisplayNameA(
4372 SC_RPC_HANDLE hSCManager
,
4373 LPCSTR lpServiceName
,
4374 LPSTR lpDisplayName
,
4375 LPBOUNDED_DWORD_4K lpcchBuffer
)
4377 // PMANAGER_HANDLE hManager;
4378 PSERVICE lpService
= NULL
;
4381 LPWSTR lpServiceNameW
;
4383 DPRINT("RGetServiceDisplayNameA() called\n");
4384 DPRINT("hSCManager = %p\n", hSCManager
);
4385 DPRINT("lpServiceName: %s\n", lpServiceName
);
4386 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4387 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4389 // hManager = (PMANAGER_HANDLE)hSCManager;
4390 // if (hManager->Handle.Tag != MANAGER_TAG)
4392 // DPRINT("Invalid manager handle!\n");
4393 // return ERROR_INVALID_HANDLE;
4396 if (lpServiceName
!= NULL
)
4398 dwLength
= strlen(lpServiceName
) + 1;
4399 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4401 dwLength
* sizeof(WCHAR
));
4402 if (!lpServiceNameW
)
4403 return ERROR_NOT_ENOUGH_MEMORY
;
4405 MultiByteToWideChar(CP_ACP
,
4412 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4414 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4417 if (lpService
== NULL
)
4419 DPRINT("Could not find a service!\n");
4421 /* If the service could not be found and lpcchBuffer is 0, windows
4422 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4423 if (*lpcchBuffer
== 0)
4426 if (lpDisplayName
!= NULL
)
4428 *lpDisplayName
= '\0';
4431 return ERROR_SERVICE_DOES_NOT_EXIST
;
4434 if (!lpService
->lpDisplayName
)
4436 dwLength
= wcslen(lpService
->lpServiceName
);
4437 if (lpDisplayName
!= NULL
&&
4438 *lpcchBuffer
> dwLength
)
4440 WideCharToMultiByte(CP_ACP
,
4442 lpService
->lpServiceName
,
4443 wcslen(lpService
->lpServiceName
),
4448 return ERROR_SUCCESS
;
4453 dwLength
= wcslen(lpService
->lpDisplayName
);
4454 if (lpDisplayName
!= NULL
&&
4455 *lpcchBuffer
> dwLength
)
4457 WideCharToMultiByte(CP_ACP
,
4459 lpService
->lpDisplayName
,
4460 wcslen(lpService
->lpDisplayName
),
4465 return ERROR_SUCCESS
;
4469 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4471 *lpcchBuffer
= dwLength
* 2;
4478 DWORD
RGetServiceKeyNameA(
4479 SC_RPC_HANDLE hSCManager
,
4480 LPCSTR lpDisplayName
,
4481 LPSTR lpServiceName
,
4482 LPBOUNDED_DWORD_4K lpcchBuffer
)
4487 LPWSTR lpDisplayNameW
;
4489 DPRINT("RGetServiceKeyNameA() called\n");
4490 DPRINT("hSCManager = %p\n", hSCManager
);
4491 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4492 DPRINT("lpServiceName: %p\n", lpServiceName
);
4493 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4495 dwLength
= strlen(lpDisplayName
) + 1;
4496 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4498 dwLength
* sizeof(WCHAR
));
4499 if (!lpDisplayNameW
)
4500 return ERROR_NOT_ENOUGH_MEMORY
;
4502 MultiByteToWideChar(CP_ACP
,
4509 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4511 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4513 if (lpService
== NULL
)
4515 DPRINT("Could not find the service!\n");
4517 /* If the service could not be found and lpcchBuffer is 0,
4518 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4519 if (*lpcchBuffer
== 0)
4522 if (lpServiceName
!= NULL
)
4524 *lpServiceName
= '\0';
4528 return ERROR_SERVICE_DOES_NOT_EXIST
;
4531 dwLength
= wcslen(lpService
->lpServiceName
);
4532 if (lpServiceName
!= NULL
&&
4533 *lpcchBuffer
> dwLength
)
4535 WideCharToMultiByte(CP_ACP
,
4537 lpService
->lpServiceName
,
4538 wcslen(lpService
->lpServiceName
),
4543 return ERROR_SUCCESS
;
4546 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4548 *lpcchBuffer
= dwLength
* 2;
4555 DWORD
RI_ScGetCurrentGroupStateW(
4556 SC_RPC_HANDLE hSCManager
,
4557 LPWSTR lpLoadOrderGroup
,
4561 return ERROR_CALL_NOT_IMPLEMENTED
;
4566 DWORD
REnumServiceGroupW(
4567 SC_RPC_HANDLE hSCManager
,
4568 DWORD dwServiceType
,
4569 DWORD dwServiceState
,
4572 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4573 LPBOUNDED_DWORD_256K lpServicesReturned
,
4574 LPBOUNDED_DWORD_256K lpResumeIndex
,
4575 LPCWSTR pszGroupName
)
4578 return ERROR_CALL_NOT_IMPLEMENTED
;
4583 // WARNING: This function is untested
4586 DWORD
RChangeServiceConfig2A(
4587 SC_RPC_HANDLE hService
,
4588 SC_RPC_CONFIG_INFOA Info
)
4590 SC_RPC_CONFIG_INFOW InfoW
;
4591 DWORD dwRet
, dwLength
;
4594 DPRINT("RChangeServiceConfig2A() called\n");
4595 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4597 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4599 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4601 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4602 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4604 //lpServiceDescriptonA = Info.psd;
4606 ///if (lpServiceDescriptonA &&
4607 ///lpServiceDescriptonA->lpDescription)
4609 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4611 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4613 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4614 if (!lpServiceDescriptonW
)
4616 return ERROR_NOT_ENOUGH_MEMORY
;
4619 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4621 MultiByteToWideChar(CP_ACP
,
4625 lpServiceDescriptonW
->lpDescription
,
4628 ptr
= lpServiceDescriptonW
;
4629 InfoW
.psd
= lpServiceDescriptonW
;
4632 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4634 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4635 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4636 DWORD dwRebootLen
= 0;
4637 DWORD dwCommandLen
= 0;
4639 lpServiceFailureActionsA
= Info
.psfa
;
4641 if (lpServiceFailureActionsA
)
4643 if (lpServiceFailureActionsA
->lpRebootMsg
)
4645 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4647 if (lpServiceFailureActionsA
->lpCommand
)
4649 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4651 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4653 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4656 if (!lpServiceFailureActionsW
)
4658 return ERROR_NOT_ENOUGH_MEMORY
;
4661 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4662 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4663 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4665 if (lpServiceFailureActionsA
->lpRebootMsg
)
4667 MultiByteToWideChar(CP_ACP
,
4669 lpServiceFailureActionsA
->lpRebootMsg
,
4671 lpServiceFailureActionsW
->lpRebootMsg
,
4675 if (lpServiceFailureActionsA
->lpCommand
)
4677 MultiByteToWideChar(CP_ACP
,
4679 lpServiceFailureActionsA
->lpCommand
,
4681 lpServiceFailureActionsW
->lpCommand
,
4685 ptr
= lpServiceFailureActionsW
;
4689 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4691 HeapFree(GetProcessHeap(), 0, ptr
);
4698 DWORD
RChangeServiceConfig2W(
4699 SC_RPC_HANDLE hService
,
4700 SC_RPC_CONFIG_INFOW Info
)
4702 DWORD dwError
= ERROR_SUCCESS
;
4703 PSERVICE_HANDLE hSvc
;
4704 PSERVICE lpService
= NULL
;
4705 HKEY hServiceKey
= NULL
;
4707 DPRINT("RChangeServiceConfig2W() called\n");
4708 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4711 return ERROR_SHUTDOWN_IN_PROGRESS
;
4713 hSvc
= ScmGetServiceFromHandle(hService
);
4716 DPRINT1("Invalid service handle!\n");
4717 return ERROR_INVALID_HANDLE
;
4720 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4721 SERVICE_CHANGE_CONFIG
))
4723 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4724 return ERROR_ACCESS_DENIED
;
4727 lpService
= hSvc
->ServiceEntry
;
4728 if (lpService
== NULL
)
4730 DPRINT("lpService == NULL!\n");
4731 return ERROR_INVALID_HANDLE
;
4734 /* Lock the service database exclusively */
4735 ScmLockDatabaseExclusive();
4737 if (lpService
->bDeleted
)
4739 DPRINT("The service has already been marked for delete!\n");
4740 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4744 /* Open the service key */
4745 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4748 if (dwError
!= ERROR_SUCCESS
)
4751 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4753 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4755 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4756 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4758 if (lpServiceDescription
!= NULL
&&
4759 lpServiceDescription
->lpDescription
!= NULL
)
4761 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4762 dwError
= RegSetValueExW(hServiceKey
,
4766 (LPBYTE
)lpServiceDescription
->lpDescription
,
4767 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4768 if (dwError
!= ERROR_SUCCESS
)
4772 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4775 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4780 /* Unlock the service database */
4781 ScmUnlockDatabase();
4783 if (hServiceKey
!= NULL
)
4784 RegCloseKey(hServiceKey
);
4786 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4793 DWORD
RQueryServiceConfig2A(
4794 SC_RPC_HANDLE hService
,
4798 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4800 DWORD dwError
= ERROR_SUCCESS
;
4801 PSERVICE_HANDLE hSvc
;
4802 PSERVICE lpService
= NULL
;
4803 HKEY hServiceKey
= NULL
;
4804 LPWSTR lpDescriptionW
= NULL
;
4806 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4807 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4810 return ERROR_INVALID_ADDRESS
;
4813 return ERROR_SHUTDOWN_IN_PROGRESS
;
4815 hSvc
= ScmGetServiceFromHandle(hService
);
4818 DPRINT1("Invalid service handle!\n");
4819 return ERROR_INVALID_HANDLE
;
4822 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4823 SERVICE_QUERY_CONFIG
))
4825 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4826 return ERROR_ACCESS_DENIED
;
4829 lpService
= hSvc
->ServiceEntry
;
4830 if (lpService
== NULL
)
4832 DPRINT("lpService == NULL!\n");
4833 return ERROR_INVALID_HANDLE
;
4836 /* Lock the service database shared */
4837 ScmLockDatabaseShared();
4839 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4842 if (dwError
!= ERROR_SUCCESS
)
4845 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4847 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4850 dwError
= ScmReadString(hServiceKey
,
4853 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4856 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4857 if (dwError
== ERROR_SUCCESS
)
4858 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4860 if (cbBufSize
< *pcbBytesNeeded
)
4862 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4866 if (dwError
== ERROR_SUCCESS
)
4868 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4870 WideCharToMultiByte(CP_ACP
,
4875 wcslen(lpDescriptionW
),
4878 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4882 lpServiceDescription
->lpDescription
= NULL
;
4883 dwError
= ERROR_SUCCESS
;
4887 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4890 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4895 /* Unlock the service database */
4896 ScmUnlockDatabase();
4898 if (lpDescriptionW
!= NULL
)
4899 HeapFree(GetProcessHeap(), 0, lpDescriptionW
);
4901 if (hServiceKey
!= NULL
)
4902 RegCloseKey(hServiceKey
);
4904 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4911 DWORD
RQueryServiceConfig2W(
4912 SC_RPC_HANDLE hService
,
4916 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4918 DWORD dwError
= ERROR_SUCCESS
;
4919 PSERVICE_HANDLE hSvc
;
4920 PSERVICE lpService
= NULL
;
4921 HKEY hServiceKey
= NULL
;
4922 DWORD dwRequiredSize
;
4923 LPWSTR lpDescription
= NULL
;
4924 LPWSTR lpFailureCommand
= NULL
;
4925 LPWSTR lpRebootMessage
= NULL
;
4927 DPRINT("RQueryServiceConfig2W() called\n");
4930 return ERROR_INVALID_ADDRESS
;
4933 return ERROR_SHUTDOWN_IN_PROGRESS
;
4935 hSvc
= ScmGetServiceFromHandle(hService
);
4938 DPRINT1("Invalid service handle!\n");
4939 return ERROR_INVALID_HANDLE
;
4942 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4943 SERVICE_QUERY_CONFIG
))
4945 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4946 return ERROR_ACCESS_DENIED
;
4949 lpService
= hSvc
->ServiceEntry
;
4950 if (lpService
== NULL
)
4952 DPRINT("lpService == NULL!\n");
4953 return ERROR_INVALID_HANDLE
;
4956 /* Lock the service database shared */
4957 ScmLockDatabaseShared();
4959 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4962 if (dwError
!= ERROR_SUCCESS
)
4965 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4967 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4970 dwError
= ScmReadString(hServiceKey
,
4973 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4976 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4977 if (dwError
== ERROR_SUCCESS
)
4978 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4980 if (cbBufSize
< *pcbBytesNeeded
)
4982 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4986 if (dwError
== ERROR_SUCCESS
)
4988 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4989 wcscpy(lpStr
, lpDescription
);
4990 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4994 lpServiceDescription
->lpDescription
= NULL
;
4995 dwError
= ERROR_SUCCESS
;
4998 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5001 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
5005 dwError
= ScmReadString(hServiceKey
,
5009 dwError
= ScmReadString(hServiceKey
,
5013 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5015 if (lpFailureCommand
)
5016 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
5018 if (lpRebootMessage
)
5019 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
5021 if (cbBufSize
< dwRequiredSize
)
5023 *pcbBytesNeeded
= dwRequiredSize
;
5024 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5028 lpFailureActions
->cActions
= 0;
5029 lpFailureActions
->dwResetPeriod
= 0;
5030 lpFailureActions
->lpCommand
= NULL
;
5031 lpFailureActions
->lpRebootMsg
= NULL
;
5032 lpFailureActions
->lpsaActions
= NULL
;
5034 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
5035 if (lpRebootMessage
)
5037 wcscpy(lpStr
, lpRebootMessage
);
5038 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
5039 lpStr
+= wcslen(lpRebootMessage
) + 1;
5042 if (lpFailureCommand
)
5044 wcscpy(lpStr
, lpFailureCommand
);
5045 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
5046 lpStr
+= wcslen(lpRebootMessage
) + 1;
5048 dwError
= STATUS_SUCCESS
;
5053 /* Unlock the service database */
5054 ScmUnlockDatabase();
5056 if (lpDescription
!= NULL
)
5057 HeapFree(GetProcessHeap(), 0, lpDescription
);
5059 if (lpRebootMessage
!= NULL
)
5060 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5062 if (lpFailureCommand
!= NULL
)
5063 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5065 if (hServiceKey
!= NULL
)
5066 RegCloseKey(hServiceKey
);
5068 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5075 DWORD
RQueryServiceStatusEx(
5076 SC_RPC_HANDLE hService
,
5077 SC_STATUS_TYPE InfoLevel
,
5080 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5082 LPSERVICE_STATUS_PROCESS lpStatus
;
5083 PSERVICE_HANDLE hSvc
;
5086 DPRINT("RQueryServiceStatusEx() called\n");
5089 return ERROR_SHUTDOWN_IN_PROGRESS
;
5091 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
5092 return ERROR_INVALID_LEVEL
;
5094 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
5096 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
5097 return ERROR_INSUFFICIENT_BUFFER
;
5099 hSvc
= ScmGetServiceFromHandle(hService
);
5102 DPRINT1("Invalid service handle!\n");
5103 return ERROR_INVALID_HANDLE
;
5106 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5107 SERVICE_QUERY_STATUS
))
5109 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5110 return ERROR_ACCESS_DENIED
;
5113 lpService
= hSvc
->ServiceEntry
;
5114 if (lpService
== NULL
)
5116 DPRINT("lpService == NULL!\n");
5117 return ERROR_INVALID_HANDLE
;
5120 /* Lock the service database shared */
5121 ScmLockDatabaseShared();
5123 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
5125 /* Return service status information */
5126 RtlCopyMemory(lpStatus
,
5128 sizeof(SERVICE_STATUS
));
5130 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
5131 lpStatus
->dwServiceFlags
= 0; /* FIXME */
5133 /* Unlock the service database */
5134 ScmUnlockDatabase();
5136 return ERROR_SUCCESS
;
5141 DWORD
REnumServicesStatusExA(
5142 SC_RPC_HANDLE hSCManager
,
5143 SC_ENUM_TYPE InfoLevel
,
5144 DWORD dwServiceType
,
5145 DWORD dwServiceState
,
5148 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5149 LPBOUNDED_DWORD_256K lpServicesReturned
,
5150 LPBOUNDED_DWORD_256K lpResumeIndex
,
5151 LPCSTR pszGroupName
)
5153 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
5154 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
5155 LPWSTR lpStringPtrW
;
5157 LPWSTR pszGroupNameW
= NULL
;
5159 DWORD dwServiceCount
;
5161 DPRINT("REnumServicesStatusExA() called\n");
5165 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
5168 DPRINT("Failed to allocate buffer!\n");
5169 return ERROR_NOT_ENOUGH_MEMORY
;
5172 MultiByteToWideChar(CP_ACP
,
5177 strlen(pszGroupName
) + 1);
5180 if ((cbBufSize
> 0) && (lpBuffer
))
5182 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
5185 DPRINT("Failed to allocate buffer!\n");
5186 return ERROR_NOT_ENOUGH_MEMORY
;
5190 dwError
= REnumServicesStatusExW(hSCManager
,
5194 (LPBYTE
)lpStatusPtrW
,
5201 /* if no services were returned then we are Done */
5202 if (*lpServicesReturned
== 0)
5205 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5206 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5207 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5208 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5209 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5211 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5213 /* Copy the service name */
5214 WideCharToMultiByte(CP_ACP
,
5219 wcslen(lpStringPtrW
),
5223 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5224 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5225 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5227 /* Copy the display name */
5228 WideCharToMultiByte(CP_ACP
,
5233 wcslen(lpStringPtrW
),
5237 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5238 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5239 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5241 /* Copy the status information */
5242 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5243 &lpStatusPtrW
->ServiceStatusProcess
,
5244 sizeof(SERVICE_STATUS
));
5246 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5247 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5253 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5256 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5258 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5265 DWORD
REnumServicesStatusExW(
5266 SC_RPC_HANDLE hSCManager
,
5267 SC_ENUM_TYPE InfoLevel
,
5268 DWORD dwServiceType
,
5269 DWORD dwServiceState
,
5272 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5273 LPBOUNDED_DWORD_256K lpServicesReturned
,
5274 LPBOUNDED_DWORD_256K lpResumeIndex
,
5275 LPCWSTR pszGroupName
)
5277 PMANAGER_HANDLE hManager
;
5279 DWORD dwError
= ERROR_SUCCESS
;
5280 PLIST_ENTRY ServiceEntry
;
5281 PSERVICE CurrentService
;
5283 DWORD dwRequiredSize
;
5284 DWORD dwServiceCount
;
5286 DWORD dwLastResumeCount
= 0;
5287 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5290 DPRINT("REnumServicesStatusExW() called\n");
5293 return ERROR_SHUTDOWN_IN_PROGRESS
;
5295 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5296 return ERROR_INVALID_LEVEL
;
5298 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5299 if (hManager
== NULL
)
5301 DPRINT1("Invalid service manager handle!\n");
5302 return ERROR_INVALID_HANDLE
;
5305 *pcbBytesNeeded
= 0;
5306 *lpServicesReturned
= 0;
5308 if ((dwServiceType
== 0) ||
5309 ((dwServiceType
& ~(SERVICE_DRIVER
| SERVICE_WIN32
)) != 0))
5311 DPRINT("Not a valid Service Type!\n");
5312 return ERROR_INVALID_PARAMETER
;
5315 if ((dwServiceState
!= SERVICE_ACTIVE
) &&
5316 (dwServiceState
!= SERVICE_INACTIVE
) &&
5317 (dwServiceState
!= SERVICE_STATE_ALL
))
5319 DPRINT("Not a valid Service State!\n");
5320 return ERROR_INVALID_PARAMETER
;
5323 /* Check access rights */
5324 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5325 SC_MANAGER_ENUMERATE_SERVICE
))
5327 DPRINT("Insufficient access rights! 0x%lx\n",
5328 hManager
->Handle
.DesiredAccess
);
5329 return ERROR_ACCESS_DENIED
;
5333 dwLastResumeCount
= *lpResumeIndex
;
5335 /* Lock the service database shared */
5336 ScmLockDatabaseShared();
5338 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5339 if (lpService
== NULL
)
5341 dwError
= ERROR_SUCCESS
;
5348 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5349 ServiceEntry
!= &ServiceListHead
;
5350 ServiceEntry
= ServiceEntry
->Flink
)
5352 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5356 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5359 dwState
= SERVICE_ACTIVE
;
5360 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5361 dwState
= SERVICE_INACTIVE
;
5363 if ((dwState
& dwServiceState
) == 0)
5368 if (*pszGroupName
== 0)
5370 if (CurrentService
->lpGroup
!= NULL
)
5375 if ((CurrentService
->lpGroup
== NULL
) ||
5376 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5381 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5382 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5383 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5385 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5387 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5388 dwRequiredSize
+= dwSize
;
5390 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5394 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5400 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5401 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5404 ServiceEntry
!= &ServiceListHead
;
5405 ServiceEntry
= ServiceEntry
->Flink
)
5407 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5411 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5414 dwState
= SERVICE_ACTIVE
;
5415 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5416 dwState
= SERVICE_INACTIVE
;
5418 if ((dwState
& dwServiceState
) == 0)
5423 if (*pszGroupName
== 0)
5425 if (CurrentService
->lpGroup
!= NULL
)
5430 if ((CurrentService
->lpGroup
== NULL
) ||
5431 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5436 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5437 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5438 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5440 dwError
= ERROR_MORE_DATA
;
5443 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5446 *lpResumeIndex
= dwLastResumeCount
;
5448 *lpServicesReturned
= dwServiceCount
;
5449 *pcbBytesNeeded
= dwRequiredSize
;
5451 /* If there was no services that matched */
5452 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5454 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5458 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5459 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5460 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5463 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5464 ServiceEntry
!= &ServiceListHead
;
5465 ServiceEntry
= ServiceEntry
->Flink
)
5467 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5471 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5474 dwState
= SERVICE_ACTIVE
;
5475 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5476 dwState
= SERVICE_INACTIVE
;
5478 if ((dwState
& dwServiceState
) == 0)
5483 if (*pszGroupName
== 0)
5485 if (CurrentService
->lpGroup
!= NULL
)
5490 if ((CurrentService
->lpGroup
== NULL
) ||
5491 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5496 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5497 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5498 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5500 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5502 /* Copy the service name */
5504 CurrentService
->lpServiceName
);
5505 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5506 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5508 /* Copy the display name */
5510 CurrentService
->lpDisplayName
);
5511 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5512 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5514 /* Copy the status information */
5515 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5516 &CurrentService
->Status
,
5517 sizeof(SERVICE_STATUS
));
5518 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5519 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5520 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5523 dwRequiredSize
+= dwSize
;
5533 *pcbBytesNeeded
= 0;
5539 /* Unlock the service database */
5540 ScmUnlockDatabase();
5542 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5549 DWORD
RSendTSMessage(
5550 handle_t BindingHandle
) /* FIXME */
5553 return ERROR_CALL_NOT_IMPLEMENTED
;
5558 DWORD
RCreateServiceWOW64A(
5559 handle_t BindingHandle
,
5560 LPSTR lpServiceName
,
5561 LPSTR lpDisplayName
,
5562 DWORD dwDesiredAccess
,
5563 DWORD dwServiceType
,
5565 DWORD dwErrorControl
,
5566 LPSTR lpBinaryPathName
,
5567 LPSTR lpLoadOrderGroup
,
5569 LPBYTE lpDependencies
,
5571 LPSTR lpServiceStartName
,
5574 LPSC_RPC_HANDLE lpServiceHandle
)
5577 return ERROR_CALL_NOT_IMPLEMENTED
;
5582 DWORD
RCreateServiceWOW64W(
5583 handle_t BindingHandle
,
5584 LPWSTR lpServiceName
,
5585 LPWSTR lpDisplayName
,
5586 DWORD dwDesiredAccess
,
5587 DWORD dwServiceType
,
5589 DWORD dwErrorControl
,
5590 LPWSTR lpBinaryPathName
,
5591 LPWSTR lpLoadOrderGroup
,
5593 LPBYTE lpDependencies
,
5595 LPWSTR lpServiceStartName
,
5598 LPSC_RPC_HANDLE lpServiceHandle
)
5601 return ERROR_CALL_NOT_IMPLEMENTED
;
5606 DWORD
RQueryServiceTagInfo(
5607 handle_t BindingHandle
) /* FIXME */
5610 return ERROR_CALL_NOT_IMPLEMENTED
;
5615 DWORD
RNotifyServiceStatusChange(
5616 SC_RPC_HANDLE hService
,
5617 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5618 GUID
*pClientProcessGuid
,
5619 GUID
*pSCMProcessGuid
,
5620 PBOOL pfCreateRemoteQueue
,
5621 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5624 return ERROR_CALL_NOT_IMPLEMENTED
;
5629 DWORD
RGetNotifyResults(
5630 SC_NOTIFY_RPC_HANDLE hNotify
,
5631 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5634 return ERROR_CALL_NOT_IMPLEMENTED
;
5639 DWORD
RCloseNotifyHandle(
5640 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5644 return ERROR_CALL_NOT_IMPLEMENTED
;
5649 DWORD
RControlServiceExA(
5650 SC_RPC_HANDLE hService
,
5655 return ERROR_CALL_NOT_IMPLEMENTED
;
5660 DWORD
RControlServiceExW(
5661 SC_RPC_HANDLE hService
,
5666 return ERROR_CALL_NOT_IMPLEMENTED
;
5671 DWORD
RSendPnPMessage(
5672 handle_t BindingHandle
) /* FIXME */
5675 return ERROR_CALL_NOT_IMPLEMENTED
;
5680 DWORD
RValidatePnPService(
5681 handle_t BindingHandle
) /* FIXME */
5684 return ERROR_CALL_NOT_IMPLEMENTED
;
5689 DWORD
ROpenServiceStatusHandle(
5690 handle_t BindingHandle
) /* FIXME */
5693 return ERROR_CALL_NOT_IMPLEMENTED
;
5699 handle_t BindingHandle
) /* FIXME */
5702 return ERROR_CALL_NOT_IMPLEMENTED
;
5706 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5708 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5712 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5714 HeapFree(GetProcessHeap(), 0, ptr
);
5718 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5723 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5728 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)