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
));
1245 DWORD
RDeleteService(
1246 SC_RPC_HANDLE hService
)
1248 PSERVICE_HANDLE hSvc
;
1252 DPRINT("RDeleteService() called\n");
1255 return ERROR_SHUTDOWN_IN_PROGRESS
;
1257 hSvc
= ScmGetServiceFromHandle(hService
);
1260 DPRINT1("Invalid service handle!\n");
1261 return ERROR_INVALID_HANDLE
;
1264 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1266 return ERROR_ACCESS_DENIED
;
1268 lpService
= hSvc
->ServiceEntry
;
1269 if (lpService
== NULL
)
1271 DPRINT("lpService == NULL!\n");
1272 return ERROR_INVALID_HANDLE
;
1275 /* Lock the service database exclusively */
1276 ScmLockDatabaseExclusive();
1278 if (lpService
->bDeleted
)
1280 DPRINT("The service has already been marked for delete!\n");
1281 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1285 /* Mark service for delete */
1286 lpService
->bDeleted
= TRUE
;
1288 dwError
= ScmMarkServiceForDelete(lpService
);
1291 /* Unlock the service database */
1292 ScmUnlockDatabase();
1294 DPRINT("RDeleteService() done\n");
1301 DWORD
RLockServiceDatabase(
1302 SC_RPC_HANDLE hSCManager
,
1303 LPSC_RPC_LOCK lpLock
)
1305 PMANAGER_HANDLE hMgr
;
1307 DPRINT("RLockServiceDatabase() called\n");
1311 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
1314 DPRINT1("Invalid service manager handle!\n");
1315 return ERROR_INVALID_HANDLE
;
1318 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
1320 return ERROR_ACCESS_DENIED
;
1322 // return ScmLockDatabase(0, hMgr->0xC, hLock);
1324 /* FIXME: Lock the database */
1325 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
1327 return ERROR_SUCCESS
;
1332 DWORD
RQueryServiceObjectSecurity(
1333 SC_RPC_HANDLE hService
,
1334 SECURITY_INFORMATION dwSecurityInformation
,
1335 LPBYTE lpSecurityDescriptor
,
1337 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
1339 PSERVICE_HANDLE hSvc
;
1341 ULONG DesiredAccess
= 0;
1343 DWORD dwBytesNeeded
;
1347 SECURITY_DESCRIPTOR ObjectDescriptor
;
1349 DPRINT("RQueryServiceObjectSecurity() called\n");
1351 hSvc
= ScmGetServiceFromHandle(hService
);
1354 DPRINT1("Invalid service handle!\n");
1355 return ERROR_INVALID_HANDLE
;
1358 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
1359 GROUP_SECURITY_INFORMATION
|
1360 OWNER_SECURITY_INFORMATION
))
1361 DesiredAccess
|= READ_CONTROL
;
1363 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1364 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1366 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1369 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1370 return ERROR_ACCESS_DENIED
;
1373 lpService
= hSvc
->ServiceEntry
;
1374 if (lpService
== NULL
)
1376 DPRINT("lpService == NULL!\n");
1377 return ERROR_INVALID_HANDLE
;
1380 /* Lock the service database */
1381 ScmLockDatabaseShared();
1385 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
1387 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
1388 dwSecurityInformation
,
1389 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1393 /* Unlock the service database */
1394 ScmUnlockDatabase();
1396 if (NT_SUCCESS(Status
))
1398 *pcbBytesNeeded
= dwBytesNeeded
;
1399 dwError
= STATUS_SUCCESS
;
1401 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1403 *pcbBytesNeeded
= dwBytesNeeded
;
1404 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1406 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1408 dwError
= ERROR_GEN_FAILURE
;
1412 dwError
= RtlNtStatusToDosError(Status
);
1420 DWORD
RSetServiceObjectSecurity(
1421 SC_RPC_HANDLE hService
,
1422 DWORD dwSecurityInformation
,
1423 LPBYTE lpSecurityDescriptor
,
1424 DWORD dwSecuityDescriptorSize
)
1426 PSERVICE_HANDLE hSvc
;
1428 ULONG DesiredAccess
= 0;
1429 /* HANDLE hToken = NULL; */
1431 /* NTSTATUS Status; */
1434 DPRINT("RSetServiceObjectSecurity() called\n");
1436 hSvc
= ScmGetServiceFromHandle(hService
);
1439 DPRINT1("Invalid service handle!\n");
1440 return ERROR_INVALID_HANDLE
;
1443 if (dwSecurityInformation
== 0 ||
1444 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1445 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1446 return ERROR_INVALID_PARAMETER
;
1448 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1449 return ERROR_INVALID_PARAMETER
;
1451 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1452 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1454 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1455 DesiredAccess
|= WRITE_DAC
;
1457 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1458 DesiredAccess
|= WRITE_OWNER
;
1460 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1461 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1462 return ERROR_INVALID_PARAMETER
;
1464 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1465 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1466 return ERROR_INVALID_PARAMETER
;
1468 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1471 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1472 return ERROR_ACCESS_DENIED
;
1475 lpService
= hSvc
->ServiceEntry
;
1476 if (lpService
== NULL
)
1478 DPRINT("lpService == NULL!\n");
1479 return ERROR_INVALID_HANDLE
;
1482 if (lpService
->bDeleted
)
1483 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1486 RpcImpersonateClient(NULL
);
1488 Status
= NtOpenThreadToken(NtCurrentThread(),
1492 if (!NT_SUCCESS(Status
))
1493 return RtlNtStatusToDosError(Status
);
1498 /* Lock the service database exclusive */
1499 ScmLockDatabaseExclusive();
1502 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1503 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1504 &lpService
->lpSecurityDescriptor
,
1507 if (!NT_SUCCESS(Status
))
1509 dwError
= RtlNtStatusToDosError(Status
);
1514 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1515 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1517 if (dwError
!= ERROR_SUCCESS
)
1521 dwError
= ERROR_SUCCESS
;
1522 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1523 // lpService->lpSecurityDescriptor);
1525 RegFlushKey(hServiceKey
);
1526 RegCloseKey(hServiceKey
);
1535 /* Unlock service database */
1536 ScmUnlockDatabase();
1538 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1545 DWORD
RQueryServiceStatus(
1546 SC_RPC_HANDLE hService
,
1547 LPSERVICE_STATUS lpServiceStatus
)
1549 PSERVICE_HANDLE hSvc
;
1552 DPRINT("RQueryServiceStatus() called\n");
1555 return ERROR_SHUTDOWN_IN_PROGRESS
;
1557 hSvc
= ScmGetServiceFromHandle(hService
);
1560 DPRINT1("Invalid service handle!\n");
1561 return ERROR_INVALID_HANDLE
;
1564 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1565 SERVICE_QUERY_STATUS
))
1567 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1568 return ERROR_ACCESS_DENIED
;
1571 lpService
= hSvc
->ServiceEntry
;
1572 if (lpService
== NULL
)
1574 DPRINT("lpService == NULL!\n");
1575 return ERROR_INVALID_HANDLE
;
1578 /* Lock the service database shared */
1579 ScmLockDatabaseShared();
1581 /* Return service status information */
1582 RtlCopyMemory(lpServiceStatus
,
1584 sizeof(SERVICE_STATUS
));
1586 /* Unlock the service database */
1587 ScmUnlockDatabase();
1589 return ERROR_SUCCESS
;
1594 ScmIsValidServiceState(DWORD dwCurrentState
)
1596 switch (dwCurrentState
)
1598 case SERVICE_STOPPED
:
1599 case SERVICE_START_PENDING
:
1600 case SERVICE_STOP_PENDING
:
1601 case SERVICE_RUNNING
:
1602 case SERVICE_CONTINUE_PENDING
:
1603 case SERVICE_PAUSE_PENDING
:
1604 case SERVICE_PAUSED
:
1614 DWORD
RSetServiceStatus(
1615 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1616 LPSERVICE_STATUS lpServiceStatus
)
1619 DWORD dwPreviousState
;
1620 LPCWSTR lpErrorStrings
[2];
1621 WCHAR szErrorBuffer
[32];
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 /* Save the current service state */
1672 dwPreviousState
= lpService
->Status
.dwCurrentState
;
1674 RtlCopyMemory(&lpService
->Status
,
1676 sizeof(SERVICE_STATUS
));
1678 /* Unlock the service database */
1679 ScmUnlockDatabase();
1681 /* Log a failed service stop */
1682 if ((lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
) &&
1683 (dwPreviousState
!= SERVICE_STOPPED
))
1685 if (lpServiceStatus
->dwWin32ExitCode
!= ERROR_SUCCESS
)
1687 swprintf(szErrorBuffer
, L
"%lu", lpServiceStatus
->dwWin32ExitCode
);
1688 lpErrorStrings
[0] = lpService
->lpDisplayName
;
1689 lpErrorStrings
[1] = szErrorBuffer
;
1691 ScmLogError(EVENT_SERVICE_EXIT_FAILED
,
1697 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1698 DPRINT("RSetServiceStatus() done\n");
1700 return ERROR_SUCCESS
;
1705 DWORD
RUnlockServiceDatabase(
1709 return ERROR_SUCCESS
;
1714 DWORD
RNotifyBootConfigStatus(
1715 SVCCTL_HANDLEW lpMachineName
,
1716 DWORD BootAcceptable
)
1718 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1719 return ERROR_SUCCESS
;
1722 // return ERROR_CALL_NOT_IMPLEMENTED;
1727 DWORD
RI_ScSetServiceBitsW(
1728 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1729 DWORD dwServiceBits
,
1731 int bUpdateImmediately
,
1735 return ERROR_CALL_NOT_IMPLEMENTED
;
1740 DWORD
RChangeServiceConfigW(
1741 SC_RPC_HANDLE hService
,
1742 DWORD dwServiceType
,
1744 DWORD dwErrorControl
,
1745 LPWSTR lpBinaryPathName
,
1746 LPWSTR lpLoadOrderGroup
,
1748 LPBYTE lpDependencies
,
1750 LPWSTR lpServiceStartName
,
1753 LPWSTR lpDisplayName
)
1755 DWORD dwError
= ERROR_SUCCESS
;
1756 PSERVICE_HANDLE hSvc
;
1757 PSERVICE lpService
= NULL
;
1758 HKEY hServiceKey
= NULL
;
1759 LPWSTR lpDisplayNameW
= NULL
;
1760 LPWSTR lpImagePathW
= NULL
;
1762 DPRINT("RChangeServiceConfigW() called\n");
1763 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1764 DPRINT("dwStartType = %lu\n", dwStartType
);
1765 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1766 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1767 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1768 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1771 return ERROR_SHUTDOWN_IN_PROGRESS
;
1773 hSvc
= ScmGetServiceFromHandle(hService
);
1776 DPRINT1("Invalid service handle!\n");
1777 return ERROR_INVALID_HANDLE
;
1780 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1781 SERVICE_CHANGE_CONFIG
))
1783 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1784 return ERROR_ACCESS_DENIED
;
1787 lpService
= hSvc
->ServiceEntry
;
1788 if (lpService
== NULL
)
1790 DPRINT("lpService == NULL!\n");
1791 return ERROR_INVALID_HANDLE
;
1794 /* Lock the service database exclusively */
1795 ScmLockDatabaseExclusive();
1797 if (lpService
->bDeleted
)
1799 DPRINT("The service has already been marked for delete!\n");
1800 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1804 /* Open the service key */
1805 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1808 if (dwError
!= ERROR_SUCCESS
)
1811 /* Write service data to the registry */
1812 /* Set the display name */
1813 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1815 RegSetValueExW(hServiceKey
,
1819 (LPBYTE
)lpDisplayName
,
1820 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1822 /* Update the display name */
1823 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
1825 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1826 if (lpDisplayNameW
== NULL
)
1828 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1832 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1833 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1835 lpService
->lpDisplayName
= lpDisplayNameW
;
1838 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1840 /* Set the service type */
1841 dwError
= RegSetValueExW(hServiceKey
,
1845 (LPBYTE
)&dwServiceType
,
1847 if (dwError
!= ERROR_SUCCESS
)
1850 lpService
->Status
.dwServiceType
= dwServiceType
;
1853 if (dwStartType
!= SERVICE_NO_CHANGE
)
1855 /* Set the start value */
1856 dwError
= RegSetValueExW(hServiceKey
,
1860 (LPBYTE
)&dwStartType
,
1862 if (dwError
!= ERROR_SUCCESS
)
1865 lpService
->dwStartType
= dwStartType
;
1868 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1870 /* Set the error control value */
1871 dwError
= RegSetValueExW(hServiceKey
,
1875 (LPBYTE
)&dwErrorControl
,
1877 if (dwError
!= ERROR_SUCCESS
)
1880 lpService
->dwErrorControl
= dwErrorControl
;
1883 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1885 /* Set the image path */
1886 lpImagePathW
= lpBinaryPathName
;
1888 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
1890 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
1894 if (dwError
!= ERROR_SUCCESS
)
1898 dwError
= RegSetValueExW(hServiceKey
,
1902 (LPBYTE
)lpImagePathW
,
1903 (wcslen(lpImagePathW
) + 1) * sizeof(WCHAR
));
1905 if (lpImagePathW
!= lpBinaryPathName
)
1906 HeapFree(GetProcessHeap(), 0, lpImagePathW
);
1908 if (dwError
!= ERROR_SUCCESS
)
1912 /* Set the group name */
1913 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1915 dwError
= RegSetValueExW(hServiceKey
,
1919 (LPBYTE
)lpLoadOrderGroup
,
1920 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1921 if (dwError
!= ERROR_SUCCESS
)
1924 dwError
= ScmSetServiceGroup(lpService
,
1926 if (dwError
!= ERROR_SUCCESS
)
1930 if (lpdwTagId
!= NULL
)
1932 dwError
= ScmAssignNewTag(lpService
);
1933 if (dwError
!= ERROR_SUCCESS
)
1936 dwError
= RegSetValueExW(hServiceKey
,
1940 (LPBYTE
)&lpService
->dwTag
,
1942 if (dwError
!= ERROR_SUCCESS
)
1945 *lpdwTagId
= lpService
->dwTag
;
1948 /* Write dependencies */
1949 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1951 dwError
= ScmWriteDependencies(hServiceKey
,
1952 (LPWSTR
)lpDependencies
,
1954 if (dwError
!= ERROR_SUCCESS
)
1958 if (lpPassword
!= NULL
)
1960 /* FIXME: Write password */
1964 if (hServiceKey
!= NULL
)
1965 RegCloseKey(hServiceKey
);
1967 /* Unlock the service database */
1968 ScmUnlockDatabase();
1970 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1977 DWORD
RCreateServiceW(
1978 SC_RPC_HANDLE hSCManager
,
1979 LPCWSTR lpServiceName
,
1980 LPCWSTR lpDisplayName
,
1981 DWORD dwDesiredAccess
,
1982 DWORD dwServiceType
,
1984 DWORD dwErrorControl
,
1985 LPCWSTR lpBinaryPathName
,
1986 LPCWSTR lpLoadOrderGroup
,
1988 LPBYTE lpDependencies
,
1990 LPCWSTR lpServiceStartName
,
1993 LPSC_RPC_HANDLE lpServiceHandle
)
1995 PMANAGER_HANDLE hManager
;
1996 DWORD dwError
= ERROR_SUCCESS
;
1997 PSERVICE lpService
= NULL
;
1998 SC_HANDLE hServiceHandle
= NULL
;
1999 LPWSTR lpImagePath
= NULL
;
2000 HKEY hServiceKey
= NULL
;
2001 LPWSTR lpObjectName
;
2003 DPRINT("RCreateServiceW() called\n");
2004 DPRINT("lpServiceName = %S\n", lpServiceName
);
2005 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
2006 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
2007 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2008 DPRINT("dwStartType = %lu\n", dwStartType
);
2009 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2010 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
2011 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
2012 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
2015 return ERROR_SHUTDOWN_IN_PROGRESS
;
2017 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2018 if (hManager
== NULL
)
2020 DPRINT1("Invalid service manager handle!\n");
2021 return ERROR_INVALID_HANDLE
;
2024 /* Check access rights */
2025 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2026 SC_MANAGER_CREATE_SERVICE
))
2028 DPRINT("Insufficient access rights! 0x%lx\n",
2029 hManager
->Handle
.DesiredAccess
);
2030 return ERROR_ACCESS_DENIED
;
2033 if (wcslen(lpServiceName
) == 0)
2035 return ERROR_INVALID_NAME
;
2038 if (wcslen(lpBinaryPathName
) == 0)
2040 return ERROR_INVALID_PARAMETER
;
2043 /* Check for invalid service type value */
2044 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2045 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2046 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2047 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2048 return ERROR_INVALID_PARAMETER
;
2050 /* Check for invalid start type value */
2051 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2052 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2053 (dwStartType
!= SERVICE_AUTO_START
) &&
2054 (dwStartType
!= SERVICE_DEMAND_START
) &&
2055 (dwStartType
!= SERVICE_DISABLED
))
2056 return ERROR_INVALID_PARAMETER
;
2058 /* Only drivers can be boot start or system start services */
2059 if ((dwStartType
== SERVICE_BOOT_START
) ||
2060 (dwStartType
== SERVICE_SYSTEM_START
))
2062 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2063 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2064 return ERROR_INVALID_PARAMETER
;
2067 /* Check for invalid error control value */
2068 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2069 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2070 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2071 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2072 return ERROR_INVALID_PARAMETER
;
2074 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2075 (lpServiceStartName
))
2077 return ERROR_INVALID_PARAMETER
;
2080 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2082 return ERROR_INVALID_PARAMETER
;
2085 /* Lock the service database exclusively */
2086 ScmLockDatabaseExclusive();
2088 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2091 /* Unlock the service database */
2092 ScmUnlockDatabase();
2094 /* Check if it is marked for deletion */
2095 if (lpService
->bDeleted
)
2096 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2098 /* Return Error exist */
2099 return ERROR_SERVICE_EXISTS
;
2102 if (lpDisplayName
!= NULL
&&
2103 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2105 /* Unlock the service database */
2106 ScmUnlockDatabase();
2108 return ERROR_DUPLICATE_SERVICE_NAME
;
2111 if (dwServiceType
& SERVICE_DRIVER
)
2113 dwError
= ScmCanonDriverImagePath(dwStartType
,
2116 if (dwError
!= ERROR_SUCCESS
)
2121 if (dwStartType
== SERVICE_BOOT_START
||
2122 dwStartType
== SERVICE_SYSTEM_START
)
2124 /* Unlock the service database */
2125 ScmUnlockDatabase();
2127 return ERROR_INVALID_PARAMETER
;
2131 /* Allocate a new service entry */
2132 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2134 if (dwError
!= ERROR_SUCCESS
)
2137 /* Fill the new service entry */
2138 lpService
->Status
.dwServiceType
= dwServiceType
;
2139 lpService
->dwStartType
= dwStartType
;
2140 lpService
->dwErrorControl
= dwErrorControl
;
2142 /* Fill the display name */
2143 if (lpDisplayName
!= NULL
&&
2144 *lpDisplayName
!= 0 &&
2145 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2147 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(), 0,
2148 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2149 if (lpService
->lpDisplayName
== NULL
)
2151 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2154 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2157 /* Assign the service to a group */
2158 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2160 dwError
= ScmSetServiceGroup(lpService
,
2162 if (dwError
!= ERROR_SUCCESS
)
2166 /* Assign a new tag */
2167 if (lpdwTagId
!= NULL
)
2169 dwError
= ScmAssignNewTag(lpService
);
2170 if (dwError
!= ERROR_SUCCESS
)
2174 /* Write service data to the registry */
2175 /* Create the service key */
2176 dwError
= ScmCreateServiceKey(lpServiceName
,
2179 if (dwError
!= ERROR_SUCCESS
)
2182 /* Set the display name */
2183 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2185 RegSetValueExW(hServiceKey
,
2189 (LPBYTE
)lpDisplayName
,
2190 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2193 /* Set the service type */
2194 dwError
= RegSetValueExW(hServiceKey
,
2198 (LPBYTE
)&dwServiceType
,
2200 if (dwError
!= ERROR_SUCCESS
)
2203 /* Set the start value */
2204 dwError
= RegSetValueExW(hServiceKey
,
2208 (LPBYTE
)&dwStartType
,
2210 if (dwError
!= ERROR_SUCCESS
)
2213 /* Set the error control value */
2214 dwError
= RegSetValueExW(hServiceKey
,
2218 (LPBYTE
)&dwErrorControl
,
2220 if (dwError
!= ERROR_SUCCESS
)
2223 /* Set the image path */
2224 if (dwServiceType
& SERVICE_WIN32
)
2226 dwError
= RegSetValueExW(hServiceKey
,
2230 (LPBYTE
)lpBinaryPathName
,
2231 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2232 if (dwError
!= ERROR_SUCCESS
)
2235 else if (dwServiceType
& SERVICE_DRIVER
)
2237 dwError
= RegSetValueExW(hServiceKey
,
2241 (LPBYTE
)lpImagePath
,
2242 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2243 if (dwError
!= ERROR_SUCCESS
)
2247 /* Set the group name */
2248 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2250 dwError
= RegSetValueExW(hServiceKey
,
2254 (LPBYTE
)lpLoadOrderGroup
,
2255 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2256 if (dwError
!= ERROR_SUCCESS
)
2260 if (lpdwTagId
!= NULL
)
2262 dwError
= RegSetValueExW(hServiceKey
,
2266 (LPBYTE
)&lpService
->dwTag
,
2268 if (dwError
!= ERROR_SUCCESS
)
2272 /* Write dependencies */
2273 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2275 dwError
= ScmWriteDependencies(hServiceKey
,
2276 (LPCWSTR
)lpDependencies
,
2278 if (dwError
!= ERROR_SUCCESS
)
2282 /* Write service start name */
2283 if (dwServiceType
& SERVICE_WIN32
)
2285 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2286 dwError
= RegSetValueExW(hServiceKey
,
2290 (LPBYTE
)lpObjectName
,
2291 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2292 if (dwError
!= ERROR_SUCCESS
)
2296 if (lpPassword
!= NULL
)
2298 /* FIXME: Write password */
2301 dwError
= ScmCreateServiceHandle(lpService
,
2303 if (dwError
!= ERROR_SUCCESS
)
2306 dwError
= ScmCheckAccess(hServiceHandle
,
2308 if (dwError
!= ERROR_SUCCESS
)
2311 lpService
->dwRefCount
= 1;
2312 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2315 /* Unlock the service database */
2316 ScmUnlockDatabase();
2318 if (hServiceKey
!= NULL
)
2319 RegCloseKey(hServiceKey
);
2321 if (dwError
== ERROR_SUCCESS
)
2323 DPRINT("hService %p\n", hServiceHandle
);
2324 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2326 if (lpdwTagId
!= NULL
)
2327 *lpdwTagId
= lpService
->dwTag
;
2331 if (lpService
!= NULL
&&
2332 lpService
->lpServiceName
!= NULL
)
2334 /* Release the display name buffer */
2335 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2340 /* Remove the service handle */
2341 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2344 if (lpService
!= NULL
)
2346 /* FIXME: remove the service entry */
2350 if (lpImagePath
!= NULL
)
2351 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2353 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2360 DWORD
REnumDependentServicesW(
2361 SC_RPC_HANDLE hService
,
2362 DWORD dwServiceState
,
2365 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2366 LPBOUNDED_DWORD_256K lpServicesReturned
)
2368 DWORD dwError
= ERROR_SUCCESS
;
2369 DWORD dwServicesReturned
= 0;
2370 DWORD dwServiceCount
;
2371 HKEY hServicesKey
= NULL
;
2372 PSERVICE_HANDLE hSvc
;
2373 PSERVICE lpService
= NULL
;
2374 PSERVICE
*lpServicesArray
= NULL
;
2375 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2378 *pcbBytesNeeded
= 0;
2379 *lpServicesReturned
= 0;
2381 DPRINT("REnumDependentServicesW() called\n");
2383 hSvc
= ScmGetServiceFromHandle(hService
);
2386 DPRINT1("Invalid service handle!\n");
2387 return ERROR_INVALID_HANDLE
;
2390 lpService
= hSvc
->ServiceEntry
;
2392 /* Check access rights */
2393 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2394 SC_MANAGER_ENUMERATE_SERVICE
))
2396 DPRINT("Insufficient access rights! 0x%lx\n",
2397 hSvc
->Handle
.DesiredAccess
);
2398 return ERROR_ACCESS_DENIED
;
2401 /* Open the Services Reg key */
2402 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2403 L
"System\\CurrentControlSet\\Services",
2407 if (dwError
!= ERROR_SUCCESS
)
2410 /* First determine the bytes needed and get the number of dependent services */
2411 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2416 &dwServicesReturned
);
2417 if (dwError
!= ERROR_SUCCESS
)
2420 /* If buffer size is less than the bytes needed or pointer is null */
2421 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2423 dwError
= ERROR_MORE_DATA
;
2427 /* Allocate memory for array of service pointers */
2428 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2430 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2431 if (!lpServicesArray
)
2433 DPRINT1("Could not allocate a buffer!!\n");
2434 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2438 dwServicesReturned
= 0;
2439 *pcbBytesNeeded
= 0;
2441 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2446 &dwServicesReturned
);
2447 if (dwError
!= ERROR_SUCCESS
)
2452 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2453 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2455 /* Copy EnumDepenedentService to Buffer */
2456 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2458 lpService
= lpServicesArray
[dwServiceCount
];
2460 /* Copy status info */
2461 memcpy(&lpServicesPtr
->ServiceStatus
,
2463 sizeof(SERVICE_STATUS
));
2465 /* Copy display name */
2466 wcscpy(lpStr
, lpService
->lpDisplayName
);
2467 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2468 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2470 /* Copy service name */
2471 wcscpy(lpStr
, lpService
->lpServiceName
);
2472 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2473 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2478 *lpServicesReturned
= dwServicesReturned
;
2481 if (lpServicesArray
!= NULL
)
2482 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2484 RegCloseKey(hServicesKey
);
2486 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2493 DWORD
REnumServicesStatusW(
2494 SC_RPC_HANDLE hSCManager
,
2495 DWORD dwServiceType
,
2496 DWORD dwServiceState
,
2499 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2500 LPBOUNDED_DWORD_256K lpServicesReturned
,
2501 LPBOUNDED_DWORD_256K lpResumeHandle
)
2503 PMANAGER_HANDLE hManager
;
2505 DWORD dwError
= ERROR_SUCCESS
;
2506 PLIST_ENTRY ServiceEntry
;
2507 PSERVICE CurrentService
;
2509 DWORD dwRequiredSize
;
2510 DWORD dwServiceCount
;
2512 DWORD dwLastResumeCount
= 0;
2513 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2516 DPRINT("REnumServicesStatusW() called\n");
2519 return ERROR_SHUTDOWN_IN_PROGRESS
;
2521 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2522 if (hManager
== NULL
)
2524 DPRINT1("Invalid service manager handle!\n");
2525 return ERROR_INVALID_HANDLE
;
2529 *pcbBytesNeeded
= 0;
2530 *lpServicesReturned
= 0;
2532 if ((dwServiceType
== 0) ||
2533 ((dwServiceType
& ~(SERVICE_DRIVER
| SERVICE_WIN32
)) != 0))
2535 DPRINT("Not a valid Service Type!\n");
2536 return ERROR_INVALID_PARAMETER
;
2539 if ((dwServiceState
!= SERVICE_ACTIVE
) &&
2540 (dwServiceState
!= SERVICE_INACTIVE
) &&
2541 (dwServiceState
!= SERVICE_STATE_ALL
))
2543 DPRINT("Not a valid Service State!\n");
2544 return ERROR_INVALID_PARAMETER
;
2547 /* Check access rights */
2548 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2549 SC_MANAGER_ENUMERATE_SERVICE
))
2551 DPRINT("Insufficient access rights! 0x%lx\n",
2552 hManager
->Handle
.DesiredAccess
);
2553 return ERROR_ACCESS_DENIED
;
2557 dwLastResumeCount
= *lpResumeHandle
;
2559 /* Lock the service database shared */
2560 ScmLockDatabaseShared();
2562 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2563 if (lpService
== NULL
)
2565 dwError
= ERROR_SUCCESS
;
2572 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2573 ServiceEntry
!= &ServiceListHead
;
2574 ServiceEntry
= ServiceEntry
->Flink
)
2576 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2580 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2583 dwState
= SERVICE_ACTIVE
;
2584 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2585 dwState
= SERVICE_INACTIVE
;
2587 if ((dwState
& dwServiceState
) == 0)
2590 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2591 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2592 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2594 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2596 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2600 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2601 dwRequiredSize
+= dwSize
;
2603 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2606 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2607 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2610 ServiceEntry
!= &ServiceListHead
;
2611 ServiceEntry
= ServiceEntry
->Flink
)
2613 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2617 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2620 dwState
= SERVICE_ACTIVE
;
2621 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2622 dwState
= SERVICE_INACTIVE
;
2624 if ((dwState
& dwServiceState
) == 0)
2627 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2628 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2629 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2631 dwError
= ERROR_MORE_DATA
;
2634 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2637 *lpResumeHandle
= dwLastResumeCount
;
2639 *lpServicesReturned
= dwServiceCount
;
2640 *pcbBytesNeeded
= dwRequiredSize
;
2642 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2643 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2644 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2647 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2648 ServiceEntry
!= &ServiceListHead
;
2649 ServiceEntry
= ServiceEntry
->Flink
)
2651 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2655 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2658 dwState
= SERVICE_ACTIVE
;
2659 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2660 dwState
= SERVICE_INACTIVE
;
2662 if ((dwState
& dwServiceState
) == 0)
2665 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2666 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2667 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2669 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2672 /* Copy the service name */
2673 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2674 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2675 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2677 /* Copy the display name */
2678 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2679 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2680 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2682 /* Copy the status information */
2683 memcpy(&lpStatusPtr
->ServiceStatus
,
2684 &CurrentService
->Status
,
2685 sizeof(SERVICE_STATUS
));
2688 dwRequiredSize
+= dwSize
;
2691 if (dwError
== ERROR_SUCCESS
)
2693 *pcbBytesNeeded
= 0;
2694 if (lpResumeHandle
) *lpResumeHandle
= 0;
2698 /* Unlock the service database */
2699 ScmUnlockDatabase();
2701 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2708 DWORD
ROpenSCManagerW(
2709 LPWSTR lpMachineName
,
2710 LPWSTR lpDatabaseName
,
2711 DWORD dwDesiredAccess
,
2712 LPSC_RPC_HANDLE lpScHandle
)
2717 DPRINT("ROpenSCManagerW() called\n");
2718 DPRINT("lpMachineName = %p\n", lpMachineName
);
2719 DPRINT("lpMachineName: %S\n", lpMachineName
);
2720 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2721 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2722 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2725 return ERROR_SHUTDOWN_IN_PROGRESS
;
2728 return ERROR_INVALID_PARAMETER
;
2730 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2732 if (dwError
!= ERROR_SUCCESS
)
2734 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2738 /* Check the desired access */
2739 dwError
= ScmCheckAccess(hHandle
,
2740 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2741 if (dwError
!= ERROR_SUCCESS
)
2743 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2744 HeapFree(GetProcessHeap(), 0, hHandle
);
2748 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2749 DPRINT("*hScm = %p\n", *lpScHandle
);
2751 DPRINT("ROpenSCManagerW() done\n");
2753 return ERROR_SUCCESS
;
2758 DWORD
ROpenServiceW(
2759 SC_RPC_HANDLE hSCManager
,
2760 LPWSTR lpServiceName
,
2761 DWORD dwDesiredAccess
,
2762 LPSC_RPC_HANDLE lpServiceHandle
)
2765 PMANAGER_HANDLE hManager
;
2767 DWORD dwError
= ERROR_SUCCESS
;
2769 DPRINT("ROpenServiceW() called\n");
2770 DPRINT("hSCManager = %p\n", hSCManager
);
2771 DPRINT("lpServiceName = %p\n", lpServiceName
);
2772 DPRINT("lpServiceName: %S\n", lpServiceName
);
2773 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2776 return ERROR_SHUTDOWN_IN_PROGRESS
;
2778 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2779 if (hManager
== NULL
)
2781 DPRINT1("Invalid service manager handle!\n");
2782 return ERROR_INVALID_HANDLE
;
2785 if (!lpServiceHandle
)
2786 return ERROR_INVALID_PARAMETER
;
2789 return ERROR_INVALID_ADDRESS
;
2791 /* Lock the service database exclusive */
2792 ScmLockDatabaseExclusive();
2794 /* Get service database entry */
2795 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2796 if (lpService
== NULL
)
2798 DPRINT("Could not find a service!\n");
2799 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2803 /* Create a service handle */
2804 dwError
= ScmCreateServiceHandle(lpService
,
2806 if (dwError
!= ERROR_SUCCESS
)
2808 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2812 /* Check the desired access */
2813 dwError
= ScmCheckAccess(hHandle
,
2815 if (dwError
!= ERROR_SUCCESS
)
2817 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2818 HeapFree(GetProcessHeap(), 0, hHandle
);
2822 lpService
->dwRefCount
++;
2823 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2825 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2826 DPRINT("*hService = %p\n", *lpServiceHandle
);
2829 /* Unlock the service database */
2830 ScmUnlockDatabase();
2832 DPRINT("ROpenServiceW() done\n");
2839 DWORD
RQueryServiceConfigW(
2840 SC_RPC_HANDLE hService
,
2841 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2843 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2845 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2846 DWORD dwError
= ERROR_SUCCESS
;
2847 PSERVICE_HANDLE hSvc
;
2848 PSERVICE lpService
= NULL
;
2849 HKEY hServiceKey
= NULL
;
2850 LPWSTR lpImagePath
= NULL
;
2851 LPWSTR lpServiceStartName
= NULL
;
2852 LPWSTR lpDependencies
= NULL
;
2853 DWORD dwDependenciesLength
= 0;
2854 DWORD dwRequiredSize
;
2855 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2856 WCHAR lpEmptyString
[] = {0,0};
2859 DPRINT("RQueryServiceConfigW() called\n");
2862 return ERROR_SHUTDOWN_IN_PROGRESS
;
2864 hSvc
= ScmGetServiceFromHandle(hService
);
2867 DPRINT1("Invalid service handle!\n");
2868 return ERROR_INVALID_HANDLE
;
2871 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2872 SERVICE_QUERY_CONFIG
))
2874 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2875 return ERROR_ACCESS_DENIED
;
2878 lpService
= hSvc
->ServiceEntry
;
2879 if (lpService
== NULL
)
2881 DPRINT("lpService == NULL!\n");
2882 return ERROR_INVALID_HANDLE
;
2885 /* Lock the service database shared */
2886 ScmLockDatabaseShared();
2888 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2891 if (dwError
!= ERROR_SUCCESS
)
2894 /* Read the image path */
2895 dwError
= ScmReadString(hServiceKey
,
2898 if (dwError
!= ERROR_SUCCESS
)
2901 /* Read the service start name */
2902 ScmReadString(hServiceKey
,
2904 &lpServiceStartName
);
2906 /* Read the dependencies */
2907 ScmReadDependencies(hServiceKey
,
2909 &dwDependenciesLength
);
2911 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2913 if (lpImagePath
!= NULL
)
2914 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2916 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2918 if (lpService
->lpGroup
!= NULL
)
2919 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2921 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2923 if (lpDependencies
!= NULL
)
2924 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2926 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2928 if (lpServiceStartName
!= NULL
)
2929 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2931 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2933 if (lpService
->lpDisplayName
!= NULL
)
2934 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2936 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2938 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2940 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2944 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2945 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2946 lpConfig
->dwStartType
= lpService
->dwStartType
;
2947 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2948 lpConfig
->dwTagId
= lpService
->dwTag
;
2950 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2952 /* Append the image path */
2953 if (lpImagePath
!= NULL
)
2955 wcscpy(lpStr
, lpImagePath
);
2959 wcscpy(lpStr
, lpEmptyString
);
2962 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2963 lpStr
+= (wcslen(lpStr
) + 1);
2965 /* Append the group name */
2966 if (lpService
->lpGroup
!= NULL
)
2968 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2972 wcscpy(lpStr
, lpEmptyString
);
2975 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2976 lpStr
+= (wcslen(lpStr
) + 1);
2978 /* Append Dependencies */
2979 if (lpDependencies
!= NULL
)
2983 dwDependenciesLength
* sizeof(WCHAR
));
2987 wcscpy(lpStr
, lpEmptyString
);
2990 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2991 if (lpDependencies
!= NULL
)
2992 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2994 lpStr
+= (wcslen(lpStr
) + 1);
2996 /* Append the service start name */
2997 if (lpServiceStartName
!= NULL
)
2999 wcscpy(lpStr
, lpServiceStartName
);
3003 wcscpy(lpStr
, lpEmptyString
);
3006 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3007 lpStr
+= (wcslen(lpStr
) + 1);
3009 /* Append the display name */
3010 if (lpService
->lpDisplayName
!= NULL
)
3012 wcscpy(lpStr
, lpService
->lpDisplayName
);
3016 wcscpy(lpStr
, lpEmptyString
);
3019 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3022 if (pcbBytesNeeded
!= NULL
)
3023 *pcbBytesNeeded
= dwRequiredSize
;
3026 /* Unlock the service database */
3027 ScmUnlockDatabase();
3029 if (lpImagePath
!= NULL
)
3030 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3032 if (lpServiceStartName
!= NULL
)
3033 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3035 if (lpDependencies
!= NULL
)
3036 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3038 if (hServiceKey
!= NULL
)
3039 RegCloseKey(hServiceKey
);
3041 DPRINT("RQueryServiceConfigW() done\n");
3048 DWORD
RQueryServiceLockStatusW(
3049 SC_RPC_HANDLE hSCManager
,
3050 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
3052 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3055 return ERROR_CALL_NOT_IMPLEMENTED
;
3060 DWORD
RStartServiceW(
3061 SC_RPC_HANDLE hService
,
3063 LPSTRING_PTRSW argv
)
3065 DWORD dwError
= ERROR_SUCCESS
;
3066 PSERVICE_HANDLE hSvc
;
3067 PSERVICE lpService
= NULL
;
3070 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3071 DPRINT(" argc: %lu\n", argc
);
3074 for (i
= 0; i
< argc
; i
++)
3076 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
]);
3081 return ERROR_SHUTDOWN_IN_PROGRESS
;
3083 hSvc
= ScmGetServiceFromHandle(hService
);
3086 DPRINT1("Invalid service handle!\n");
3087 return ERROR_INVALID_HANDLE
;
3090 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3093 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3094 return ERROR_ACCESS_DENIED
;
3097 lpService
= hSvc
->ServiceEntry
;
3098 if (lpService
== NULL
)
3100 DPRINT("lpService == NULL!\n");
3101 return ERROR_INVALID_HANDLE
;
3104 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3105 return ERROR_SERVICE_DISABLED
;
3107 if (lpService
->bDeleted
)
3108 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3110 /* Start the service */
3111 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3118 DWORD
RGetServiceDisplayNameW(
3119 SC_RPC_HANDLE hSCManager
,
3120 LPCWSTR lpServiceName
,
3121 LPWSTR lpDisplayName
,
3124 // PMANAGER_HANDLE hManager;
3129 DPRINT("RGetServiceDisplayNameW() called\n");
3130 DPRINT("hSCManager = %p\n", hSCManager
);
3131 DPRINT("lpServiceName: %S\n", lpServiceName
);
3132 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3133 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3135 // hManager = (PMANAGER_HANDLE)hSCManager;
3136 // if (hManager->Handle.Tag != MANAGER_TAG)
3138 // DPRINT("Invalid manager handle!\n");
3139 // return ERROR_INVALID_HANDLE;
3142 /* Get service database entry */
3143 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3144 if (lpService
== NULL
)
3146 DPRINT("Could not find a service!\n");
3148 /* If the service could not be found and lpcchBuffer is less than 2, windows
3149 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3150 if (*lpcchBuffer
< 2)
3153 if (lpDisplayName
!= NULL
)
3155 *lpDisplayName
= '\0';
3159 return ERROR_SERVICE_DOES_NOT_EXIST
;
3162 if (!lpService
->lpDisplayName
)
3164 dwLength
= wcslen(lpService
->lpServiceName
);
3166 if (lpDisplayName
!= NULL
&&
3167 *lpcchBuffer
> dwLength
)
3169 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3174 dwLength
= wcslen(lpService
->lpDisplayName
);
3176 if (lpDisplayName
!= NULL
&&
3177 *lpcchBuffer
> dwLength
)
3179 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3183 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3185 *lpcchBuffer
= dwLength
;
3192 DWORD
RGetServiceKeyNameW(
3193 SC_RPC_HANDLE hSCManager
,
3194 LPCWSTR lpDisplayName
,
3195 LPWSTR lpServiceName
,
3198 // PMANAGER_HANDLE hManager;
3203 DPRINT("RGetServiceKeyNameW() called\n");
3204 DPRINT("hSCManager = %p\n", hSCManager
);
3205 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3206 DPRINT("lpServiceName: %p\n", lpServiceName
);
3207 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3209 // hManager = (PMANAGER_HANDLE)hSCManager;
3210 // if (hManager->Handle.Tag != MANAGER_TAG)
3212 // DPRINT("Invalid manager handle!\n");
3213 // return ERROR_INVALID_HANDLE;
3216 /* Get service database entry */
3217 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3218 if (lpService
== NULL
)
3220 DPRINT("Could not find a service!\n");
3222 /* If the service could not be found and lpcchBuffer is less than 2, windows
3223 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3224 if (*lpcchBuffer
< 2)
3227 if (lpServiceName
!= NULL
)
3229 *lpServiceName
= '\0';
3233 return ERROR_SERVICE_DOES_NOT_EXIST
;
3236 dwLength
= wcslen(lpService
->lpServiceName
);
3238 if (lpServiceName
!= NULL
&&
3239 *lpcchBuffer
> dwLength
)
3241 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3242 *lpcchBuffer
= dwLength
;
3243 return ERROR_SUCCESS
;
3246 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3248 *lpcchBuffer
= dwLength
;
3255 DWORD
RI_ScSetServiceBitsA(
3256 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3257 DWORD dwServiceBits
,
3259 int bUpdateImmediately
,
3263 return ERROR_CALL_NOT_IMPLEMENTED
;
3268 DWORD
RChangeServiceConfigA(
3269 SC_RPC_HANDLE hService
,
3270 DWORD dwServiceType
,
3272 DWORD dwErrorControl
,
3273 LPSTR lpBinaryPathName
,
3274 LPSTR lpLoadOrderGroup
,
3276 LPSTR lpDependencies
,
3278 LPSTR lpServiceStartName
,
3281 LPSTR lpDisplayName
)
3283 DWORD dwError
= ERROR_SUCCESS
;
3284 PSERVICE_HANDLE hSvc
;
3285 PSERVICE lpService
= NULL
;
3286 HKEY hServiceKey
= NULL
;
3287 LPWSTR lpDisplayNameW
= NULL
;
3288 LPWSTR lpBinaryPathNameW
= NULL
;
3289 LPWSTR lpCanonicalImagePathW
= NULL
;
3290 LPWSTR lpLoadOrderGroupW
= NULL
;
3291 LPWSTR lpDependenciesW
= NULL
;
3292 // LPWSTR lpPasswordW = NULL;
3294 DPRINT("RChangeServiceConfigA() called\n");
3295 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3296 DPRINT("dwStartType = %lu\n", dwStartType
);
3297 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3298 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3299 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3300 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3303 return ERROR_SHUTDOWN_IN_PROGRESS
;
3305 hSvc
= ScmGetServiceFromHandle(hService
);
3308 DPRINT1("Invalid service handle!\n");
3309 return ERROR_INVALID_HANDLE
;
3312 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3313 SERVICE_CHANGE_CONFIG
))
3315 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3316 return ERROR_ACCESS_DENIED
;
3319 lpService
= hSvc
->ServiceEntry
;
3320 if (lpService
== NULL
)
3322 DPRINT("lpService == NULL!\n");
3323 return ERROR_INVALID_HANDLE
;
3326 /* Lock the service database exclusively */
3327 ScmLockDatabaseExclusive();
3329 if (lpService
->bDeleted
)
3331 DPRINT("The service has already been marked for delete!\n");
3332 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3336 /* Open the service key */
3337 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3340 if (dwError
!= ERROR_SUCCESS
)
3343 /* Write service data to the registry */
3345 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3347 /* Set the display name */
3348 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3350 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3351 if (lpDisplayNameW
== NULL
)
3353 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3357 MultiByteToWideChar(CP_ACP
,
3362 strlen(lpDisplayName
) + 1);
3364 RegSetValueExW(hServiceKey
,
3368 (LPBYTE
)lpDisplayNameW
,
3369 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3371 /* Update lpService->lpDisplayName */
3372 if (lpService
->lpDisplayName
)
3373 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3375 lpService
->lpDisplayName
= lpDisplayNameW
;
3378 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3380 /* Set the service type */
3381 dwError
= RegSetValueExW(hServiceKey
,
3385 (LPBYTE
)&dwServiceType
,
3387 if (dwError
!= ERROR_SUCCESS
)
3390 lpService
->Status
.dwServiceType
= dwServiceType
;
3393 if (dwStartType
!= SERVICE_NO_CHANGE
)
3395 /* Set the start value */
3396 dwError
= RegSetValueExW(hServiceKey
,
3400 (LPBYTE
)&dwStartType
,
3402 if (dwError
!= ERROR_SUCCESS
)
3405 lpService
->dwStartType
= dwStartType
;
3408 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3410 /* Set the error control value */
3411 dwError
= RegSetValueExW(hServiceKey
,
3415 (LPBYTE
)&dwErrorControl
,
3417 if (dwError
!= ERROR_SUCCESS
)
3420 lpService
->dwErrorControl
= dwErrorControl
;
3423 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3425 /* Set the image path */
3426 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(),
3428 (strlen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
3429 if (lpBinaryPathNameW
== NULL
)
3431 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3435 MultiByteToWideChar(CP_ACP
,
3440 strlen(lpBinaryPathName
) + 1);
3442 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
3444 dwError
= ScmCanonDriverImagePath(lpService
->dwStartType
,
3446 &lpCanonicalImagePathW
);
3448 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3450 if (dwError
!= ERROR_SUCCESS
)
3453 lpBinaryPathNameW
= lpCanonicalImagePathW
;
3456 dwError
= RegSetValueExW(hServiceKey
,
3460 (LPBYTE
)lpBinaryPathNameW
,
3461 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3463 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3465 if (dwError
!= ERROR_SUCCESS
)
3469 /* Set the group name */
3470 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3472 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3474 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3475 if (lpLoadOrderGroupW
== NULL
)
3477 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3481 MultiByteToWideChar(CP_ACP
,
3486 strlen(lpLoadOrderGroup
) + 1);
3488 dwError
= RegSetValueExW(hServiceKey
,
3492 (LPBYTE
)lpLoadOrderGroupW
,
3493 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3494 if (dwError
!= ERROR_SUCCESS
)
3496 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3500 dwError
= ScmSetServiceGroup(lpService
,
3503 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3505 if (dwError
!= ERROR_SUCCESS
)
3509 if (lpdwTagId
!= NULL
)
3511 dwError
= ScmAssignNewTag(lpService
);
3512 if (dwError
!= ERROR_SUCCESS
)
3515 dwError
= RegSetValueExW(hServiceKey
,
3519 (LPBYTE
)&lpService
->dwTag
,
3521 if (dwError
!= ERROR_SUCCESS
)
3524 *lpdwTagId
= lpService
->dwTag
;
3527 /* Write dependencies */
3528 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3530 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3532 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3533 if (lpDependenciesW
== NULL
)
3535 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3539 MultiByteToWideChar(CP_ACP
,
3544 strlen(lpDependencies
) + 1);
3546 dwError
= ScmWriteDependencies(hServiceKey
,
3547 (LPWSTR
)lpDependenciesW
,
3550 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3553 if (lpPassword
!= NULL
)
3555 /* FIXME: Write password */
3559 /* Unlock the service database */
3560 ScmUnlockDatabase();
3562 if (hServiceKey
!= NULL
)
3563 RegCloseKey(hServiceKey
);
3565 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3572 DWORD
RCreateServiceA(
3573 SC_RPC_HANDLE hSCManager
,
3574 LPSTR lpServiceName
,
3575 LPSTR lpDisplayName
,
3576 DWORD dwDesiredAccess
,
3577 DWORD dwServiceType
,
3579 DWORD dwErrorControl
,
3580 LPSTR lpBinaryPathName
,
3581 LPSTR lpLoadOrderGroup
,
3583 LPBYTE lpDependencies
,
3585 LPSTR lpServiceStartName
,
3588 LPSC_RPC_HANDLE lpServiceHandle
)
3590 DWORD dwError
= ERROR_SUCCESS
;
3591 LPWSTR lpServiceNameW
= NULL
;
3592 LPWSTR lpDisplayNameW
= NULL
;
3593 LPWSTR lpBinaryPathNameW
= NULL
;
3594 LPWSTR lpLoadOrderGroupW
= NULL
;
3595 LPWSTR lpDependenciesW
= NULL
;
3596 LPWSTR lpServiceStartNameW
= NULL
;
3597 DWORD dwDependenciesLength
= 0;
3604 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3605 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3606 if (!lpServiceNameW
)
3608 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3611 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3616 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3617 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3618 if (!lpDisplayNameW
)
3620 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3623 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3626 if (lpBinaryPathName
)
3628 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3629 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3630 if (!lpBinaryPathNameW
)
3632 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3635 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3638 if (lpLoadOrderGroup
)
3640 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3641 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3642 if (!lpLoadOrderGroupW
)
3644 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3647 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3652 lpStr
= (LPCSTR
)lpDependencies
;
3655 dwLength
= strlen(lpStr
) + 1;
3656 dwDependenciesLength
+= dwLength
;
3657 lpStr
= lpStr
+ dwLength
;
3659 dwDependenciesLength
++;
3661 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3662 if (!lpDependenciesW
)
3664 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3667 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3670 if (lpServiceStartName
)
3672 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3673 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3674 if (!lpServiceStartNameW
)
3676 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3679 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3682 dwError
= RCreateServiceW(hSCManager
,
3692 (LPBYTE
)lpDependenciesW
,
3693 dwDependenciesLength
,
3694 lpServiceStartNameW
,
3700 if (lpServiceNameW
!=NULL
)
3701 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3703 if (lpDisplayNameW
!= NULL
)
3704 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3706 if (lpBinaryPathNameW
!= NULL
)
3707 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3709 if (lpLoadOrderGroupW
!= NULL
)
3710 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3712 if (lpDependenciesW
!= NULL
)
3713 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3715 if (lpServiceStartNameW
!= NULL
)
3716 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3723 DWORD
REnumDependentServicesA(
3724 SC_RPC_HANDLE hService
,
3725 DWORD dwServiceState
,
3728 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3729 LPBOUNDED_DWORD_256K lpServicesReturned
)
3731 DWORD dwError
= ERROR_SUCCESS
;
3732 DWORD dwServicesReturned
= 0;
3733 DWORD dwServiceCount
;
3734 HKEY hServicesKey
= NULL
;
3735 PSERVICE_HANDLE hSvc
;
3736 PSERVICE lpService
= NULL
;
3737 PSERVICE
*lpServicesArray
= NULL
;
3738 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3741 *pcbBytesNeeded
= 0;
3742 *lpServicesReturned
= 0;
3744 DPRINT("REnumDependentServicesA() called\n");
3746 hSvc
= ScmGetServiceFromHandle(hService
);
3749 DPRINT1("Invalid service handle!\n");
3750 return ERROR_INVALID_HANDLE
;
3753 lpService
= hSvc
->ServiceEntry
;
3755 /* Check access rights */
3756 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3757 SC_MANAGER_ENUMERATE_SERVICE
))
3759 DPRINT("Insufficient access rights! 0x%lx\n",
3760 hSvc
->Handle
.DesiredAccess
);
3761 return ERROR_ACCESS_DENIED
;
3764 /* Open the Services Reg key */
3765 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3766 L
"System\\CurrentControlSet\\Services",
3771 if (dwError
!= ERROR_SUCCESS
)
3774 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3775 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3776 are the same for both. Verified in WINXP. */
3778 /* First determine the bytes needed and get the number of dependent services*/
3779 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3784 &dwServicesReturned
);
3785 if (dwError
!= ERROR_SUCCESS
)
3788 /* If buffer size is less than the bytes needed or pointer is null*/
3789 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3791 dwError
= ERROR_MORE_DATA
;
3795 /* Allocate memory for array of service pointers */
3796 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3798 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3799 if (!lpServicesArray
)
3801 DPRINT("Could not allocate a buffer!!\n");
3802 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3806 dwServicesReturned
= 0;
3807 *pcbBytesNeeded
= 0;
3809 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3814 &dwServicesReturned
);
3815 if (dwError
!= ERROR_SUCCESS
)
3820 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3821 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3823 /* Copy EnumDepenedentService to Buffer */
3824 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3826 lpService
= lpServicesArray
[dwServiceCount
];
3828 /* Copy the status info */
3829 memcpy(&lpServicesPtr
->ServiceStatus
,
3831 sizeof(SERVICE_STATUS
));
3833 /* Copy display name */
3834 WideCharToMultiByte(CP_ACP
,
3836 lpService
->lpDisplayName
,
3839 wcslen(lpService
->lpDisplayName
),
3842 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3843 lpStr
+= strlen(lpStr
) + 1;
3845 /* Copy service name */
3846 WideCharToMultiByte(CP_ACP
,
3848 lpService
->lpServiceName
,
3851 wcslen(lpService
->lpServiceName
),
3854 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3855 lpStr
+= strlen(lpStr
) + 1;
3860 *lpServicesReturned
= dwServicesReturned
;
3863 if (lpServicesArray
)
3864 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3866 RegCloseKey(hServicesKey
);
3868 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3875 DWORD
REnumServicesStatusA(
3876 SC_RPC_HANDLE hSCManager
,
3877 DWORD dwServiceType
,
3878 DWORD dwServiceState
,
3881 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3882 LPBOUNDED_DWORD_256K lpServicesReturned
,
3883 LPBOUNDED_DWORD_256K lpResumeHandle
)
3885 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3886 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3887 LPWSTR lpStringPtrW
;
3890 DWORD dwServiceCount
;
3892 DPRINT("REnumServicesStatusA() called\n");
3894 if ((dwBufSize
> 0) && (lpBuffer
))
3896 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3899 DPRINT("Failed to allocate buffer!\n");
3900 return ERROR_NOT_ENOUGH_MEMORY
;
3904 dwError
= REnumServicesStatusW(hSCManager
,
3907 (LPBYTE
)lpStatusPtrW
,
3913 /* if no services were returned then we are Done */
3914 if (*lpServicesReturned
== 0)
3917 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3918 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3919 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3920 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3921 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3923 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3925 /* Copy the service name */
3926 WideCharToMultiByte(CP_ACP
,
3931 wcslen(lpStringPtrW
),
3935 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3936 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3937 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3939 /* Copy the display name */
3940 WideCharToMultiByte(CP_ACP
,
3945 wcslen(lpStringPtrW
),
3949 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3950 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3951 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3953 /* Copy the status information */
3954 memcpy(&lpStatusPtrA
->ServiceStatus
,
3955 &lpStatusPtrW
->ServiceStatus
,
3956 sizeof(SERVICE_STATUS
));
3963 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3965 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3972 DWORD
ROpenSCManagerA(
3973 LPSTR lpMachineName
,
3974 LPSTR lpDatabaseName
,
3975 DWORD dwDesiredAccess
,
3976 LPSC_RPC_HANDLE lpScHandle
)
3978 UNICODE_STRING MachineName
;
3979 UNICODE_STRING DatabaseName
;
3982 DPRINT("ROpenSCManagerA() called\n");
3985 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3989 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3992 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3993 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3998 RtlFreeUnicodeString(&MachineName
);
4001 RtlFreeUnicodeString(&DatabaseName
);
4008 DWORD
ROpenServiceA(
4009 SC_RPC_HANDLE hSCManager
,
4010 LPSTR lpServiceName
,
4011 DWORD dwDesiredAccess
,
4012 LPSC_RPC_HANDLE lpServiceHandle
)
4014 UNICODE_STRING ServiceName
;
4017 DPRINT("ROpenServiceA() called\n");
4020 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
4023 dwError
= ROpenServiceW(hSCManager
,
4024 lpServiceName
? ServiceName
.Buffer
: NULL
,
4029 RtlFreeUnicodeString(&ServiceName
);
4036 DWORD
RQueryServiceConfigA(
4037 SC_RPC_HANDLE hService
,
4038 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4040 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4042 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
4043 DWORD dwError
= ERROR_SUCCESS
;
4044 PSERVICE_HANDLE hSvc
;
4045 PSERVICE lpService
= NULL
;
4046 HKEY hServiceKey
= NULL
;
4047 LPWSTR lpImagePath
= NULL
;
4048 LPWSTR lpServiceStartName
= NULL
;
4049 LPWSTR lpDependencies
= NULL
;
4050 DWORD dwDependenciesLength
= 0;
4051 DWORD dwRequiredSize
;
4052 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
4053 CHAR lpEmptyString
[]={0,0};
4056 DPRINT("RQueryServiceConfigA() called\n");
4059 return ERROR_SHUTDOWN_IN_PROGRESS
;
4061 hSvc
= ScmGetServiceFromHandle(hService
);
4064 DPRINT1("Invalid service handle!\n");
4065 return ERROR_INVALID_HANDLE
;
4068 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4069 SERVICE_QUERY_CONFIG
))
4071 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4072 return ERROR_ACCESS_DENIED
;
4075 lpService
= hSvc
->ServiceEntry
;
4076 if (lpService
== NULL
)
4078 DPRINT("lpService == NULL!\n");
4079 return ERROR_INVALID_HANDLE
;
4082 /* Lock the service database shared */
4083 ScmLockDatabaseShared();
4085 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4088 if (dwError
!= ERROR_SUCCESS
)
4091 /* Read the image path */
4092 dwError
= ScmReadString(hServiceKey
,
4095 if (dwError
!= ERROR_SUCCESS
)
4098 /* Read the service start name */
4099 ScmReadString(hServiceKey
,
4101 &lpServiceStartName
);
4103 /* Read the dependencies */
4104 ScmReadDependencies(hServiceKey
,
4106 &dwDependenciesLength
);
4108 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
4110 if (lpImagePath
!= NULL
)
4111 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
4113 dwRequiredSize
+= 2;
4115 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
4116 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
4118 dwRequiredSize
+= 2;
4120 /* Add Dependencies length */
4121 if (lpDependencies
!= NULL
)
4122 dwRequiredSize
+= dwDependenciesLength
;
4124 dwRequiredSize
+= 2;
4126 if (lpServiceStartName
!= NULL
)
4127 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
4129 dwRequiredSize
+= 2;
4131 if (lpService
->lpDisplayName
!= NULL
)
4132 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
4134 dwRequiredSize
+= 2;
4136 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
4138 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4142 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
4143 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
4144 lpConfig
->dwStartType
= lpService
->dwStartType
;
4145 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
4146 lpConfig
->dwTagId
= lpService
->dwTag
;
4148 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
4150 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4155 WideCharToMultiByte(CP_ACP
,
4160 wcslen(lpImagePath
) + 1,
4166 strcpy(lpStr
, lpEmptyString
);
4169 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4170 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4172 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4174 WideCharToMultiByte(CP_ACP
,
4176 lpService
->lpGroup
->lpGroupName
,
4179 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
4185 strcpy(lpStr
, lpEmptyString
);
4188 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4189 lpStr
+= (strlen(lpStr
) + 1);
4191 /* Append Dependencies */
4194 WideCharToMultiByte(CP_ACP
,
4197 dwDependenciesLength
,
4199 dwDependenciesLength
,
4205 strcpy(lpStr
, lpEmptyString
);
4208 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4210 lpStr
+= dwDependenciesLength
;
4212 lpStr
+= (strlen(lpStr
) + 1);
4214 if (lpServiceStartName
)
4216 WideCharToMultiByte(CP_ACP
,
4221 wcslen(lpServiceStartName
) + 1,
4227 strcpy(lpStr
, lpEmptyString
);
4230 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4231 lpStr
+= (strlen(lpStr
) + 1);
4233 if (lpService
->lpDisplayName
)
4235 WideCharToMultiByte(CP_ACP
,
4237 lpService
->lpDisplayName
,
4240 wcslen(lpService
->lpDisplayName
) + 1,
4246 strcpy(lpStr
, lpEmptyString
);
4249 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4252 if (pcbBytesNeeded
!= NULL
)
4253 *pcbBytesNeeded
= dwRequiredSize
;
4256 /* Unlock the service database */
4257 ScmUnlockDatabase();
4259 if (lpImagePath
!= NULL
)
4260 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4262 if (lpServiceStartName
!= NULL
)
4263 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4265 if (lpDependencies
!= NULL
)
4266 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4268 if (hServiceKey
!= NULL
)
4269 RegCloseKey(hServiceKey
);
4271 DPRINT("RQueryServiceConfigA() done\n");
4278 DWORD
RQueryServiceLockStatusA(
4279 SC_RPC_HANDLE hSCManager
,
4280 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4282 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4285 return ERROR_CALL_NOT_IMPLEMENTED
;
4290 DWORD
RStartServiceA(
4291 SC_RPC_HANDLE hService
,
4293 LPSTRING_PTRSA argv
)
4295 DWORD dwError
= ERROR_SUCCESS
;
4296 PSERVICE_HANDLE hSvc
;
4297 PSERVICE lpService
= NULL
;
4298 LPWSTR
*lpVector
= NULL
;
4302 DPRINT("RStartServiceA() called\n");
4305 return ERROR_SHUTDOWN_IN_PROGRESS
;
4307 hSvc
= ScmGetServiceFromHandle(hService
);
4310 DPRINT1("Invalid service handle!\n");
4311 return ERROR_INVALID_HANDLE
;
4314 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4317 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4318 return ERROR_ACCESS_DENIED
;
4321 lpService
= hSvc
->ServiceEntry
;
4322 if (lpService
== NULL
)
4324 DPRINT("lpService == NULL!\n");
4325 return ERROR_INVALID_HANDLE
;
4328 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4329 return ERROR_SERVICE_DISABLED
;
4331 if (lpService
->bDeleted
)
4332 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4334 /* Build a Unicode argument vector */
4337 lpVector
= HeapAlloc(GetProcessHeap(),
4339 argc
* sizeof(LPWSTR
));
4340 if (lpVector
== NULL
)
4341 return ERROR_NOT_ENOUGH_MEMORY
;
4343 for (i
= 0; i
< argc
; i
++)
4345 dwLength
= MultiByteToWideChar(CP_ACP
,
4352 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4354 dwLength
* sizeof(WCHAR
));
4355 if (lpVector
[i
] == NULL
)
4357 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4361 MultiByteToWideChar(CP_ACP
,
4370 /* Start the service */
4371 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4374 /* Free the Unicode argument vector */
4375 if (lpVector
!= NULL
)
4377 for (i
= 0; i
< argc
; i
++)
4379 if (lpVector
[i
] != NULL
)
4380 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4382 HeapFree(GetProcessHeap(), 0, lpVector
);
4390 DWORD
RGetServiceDisplayNameA(
4391 SC_RPC_HANDLE hSCManager
,
4392 LPCSTR lpServiceName
,
4393 LPSTR lpDisplayName
,
4394 LPBOUNDED_DWORD_4K lpcchBuffer
)
4396 // PMANAGER_HANDLE hManager;
4397 PSERVICE lpService
= NULL
;
4400 LPWSTR lpServiceNameW
;
4402 DPRINT("RGetServiceDisplayNameA() called\n");
4403 DPRINT("hSCManager = %p\n", hSCManager
);
4404 DPRINT("lpServiceName: %s\n", lpServiceName
);
4405 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4406 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4408 // hManager = (PMANAGER_HANDLE)hSCManager;
4409 // if (hManager->Handle.Tag != MANAGER_TAG)
4411 // DPRINT("Invalid manager handle!\n");
4412 // return ERROR_INVALID_HANDLE;
4415 if (lpServiceName
!= NULL
)
4417 dwLength
= strlen(lpServiceName
) + 1;
4418 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4420 dwLength
* sizeof(WCHAR
));
4421 if (!lpServiceNameW
)
4422 return ERROR_NOT_ENOUGH_MEMORY
;
4424 MultiByteToWideChar(CP_ACP
,
4431 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4433 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4436 if (lpService
== NULL
)
4438 DPRINT("Could not find a service!\n");
4440 /* If the service could not be found and lpcchBuffer is 0, windows
4441 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4442 if (*lpcchBuffer
== 0)
4445 if (lpDisplayName
!= NULL
)
4447 *lpDisplayName
= '\0';
4450 return ERROR_SERVICE_DOES_NOT_EXIST
;
4453 if (!lpService
->lpDisplayName
)
4455 dwLength
= wcslen(lpService
->lpServiceName
);
4456 if (lpDisplayName
!= NULL
&&
4457 *lpcchBuffer
> dwLength
)
4459 WideCharToMultiByte(CP_ACP
,
4461 lpService
->lpServiceName
,
4462 wcslen(lpService
->lpServiceName
),
4467 return ERROR_SUCCESS
;
4472 dwLength
= wcslen(lpService
->lpDisplayName
);
4473 if (lpDisplayName
!= NULL
&&
4474 *lpcchBuffer
> dwLength
)
4476 WideCharToMultiByte(CP_ACP
,
4478 lpService
->lpDisplayName
,
4479 wcslen(lpService
->lpDisplayName
),
4484 return ERROR_SUCCESS
;
4488 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4490 *lpcchBuffer
= dwLength
* 2;
4497 DWORD
RGetServiceKeyNameA(
4498 SC_RPC_HANDLE hSCManager
,
4499 LPCSTR lpDisplayName
,
4500 LPSTR lpServiceName
,
4501 LPBOUNDED_DWORD_4K lpcchBuffer
)
4506 LPWSTR lpDisplayNameW
;
4508 DPRINT("RGetServiceKeyNameA() called\n");
4509 DPRINT("hSCManager = %p\n", hSCManager
);
4510 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4511 DPRINT("lpServiceName: %p\n", lpServiceName
);
4512 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4514 dwLength
= strlen(lpDisplayName
) + 1;
4515 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4517 dwLength
* sizeof(WCHAR
));
4518 if (!lpDisplayNameW
)
4519 return ERROR_NOT_ENOUGH_MEMORY
;
4521 MultiByteToWideChar(CP_ACP
,
4528 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4530 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4532 if (lpService
== NULL
)
4534 DPRINT("Could not find the service!\n");
4536 /* If the service could not be found and lpcchBuffer is 0,
4537 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4538 if (*lpcchBuffer
== 0)
4541 if (lpServiceName
!= NULL
)
4543 *lpServiceName
= '\0';
4547 return ERROR_SERVICE_DOES_NOT_EXIST
;
4550 dwLength
= wcslen(lpService
->lpServiceName
);
4551 if (lpServiceName
!= NULL
&&
4552 *lpcchBuffer
> dwLength
)
4554 WideCharToMultiByte(CP_ACP
,
4556 lpService
->lpServiceName
,
4557 wcslen(lpService
->lpServiceName
),
4562 return ERROR_SUCCESS
;
4565 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4567 *lpcchBuffer
= dwLength
* 2;
4574 DWORD
RI_ScGetCurrentGroupStateW(
4575 SC_RPC_HANDLE hSCManager
,
4576 LPWSTR lpLoadOrderGroup
,
4580 return ERROR_CALL_NOT_IMPLEMENTED
;
4585 DWORD
REnumServiceGroupW(
4586 SC_RPC_HANDLE hSCManager
,
4587 DWORD dwServiceType
,
4588 DWORD dwServiceState
,
4591 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4592 LPBOUNDED_DWORD_256K lpServicesReturned
,
4593 LPBOUNDED_DWORD_256K lpResumeIndex
,
4594 LPCWSTR pszGroupName
)
4597 return ERROR_CALL_NOT_IMPLEMENTED
;
4602 // WARNING: This function is untested
4605 DWORD
RChangeServiceConfig2A(
4606 SC_RPC_HANDLE hService
,
4607 SC_RPC_CONFIG_INFOA Info
)
4609 SC_RPC_CONFIG_INFOW InfoW
;
4610 DWORD dwRet
, dwLength
;
4613 DPRINT("RChangeServiceConfig2A() called\n");
4614 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4616 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4618 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4620 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4621 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4623 //lpServiceDescriptonA = Info.psd;
4625 ///if (lpServiceDescriptonA &&
4626 ///lpServiceDescriptonA->lpDescription)
4628 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4630 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4632 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4633 if (!lpServiceDescriptonW
)
4635 return ERROR_NOT_ENOUGH_MEMORY
;
4638 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4640 MultiByteToWideChar(CP_ACP
,
4644 lpServiceDescriptonW
->lpDescription
,
4647 ptr
= lpServiceDescriptonW
;
4648 InfoW
.psd
= lpServiceDescriptonW
;
4651 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4653 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4654 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4655 DWORD dwRebootLen
= 0;
4656 DWORD dwCommandLen
= 0;
4658 lpServiceFailureActionsA
= Info
.psfa
;
4660 if (lpServiceFailureActionsA
)
4662 if (lpServiceFailureActionsA
->lpRebootMsg
)
4664 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4666 if (lpServiceFailureActionsA
->lpCommand
)
4668 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4670 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4672 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4675 if (!lpServiceFailureActionsW
)
4677 return ERROR_NOT_ENOUGH_MEMORY
;
4680 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4681 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4682 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4684 if (lpServiceFailureActionsA
->lpRebootMsg
)
4686 MultiByteToWideChar(CP_ACP
,
4688 lpServiceFailureActionsA
->lpRebootMsg
,
4690 lpServiceFailureActionsW
->lpRebootMsg
,
4694 if (lpServiceFailureActionsA
->lpCommand
)
4696 MultiByteToWideChar(CP_ACP
,
4698 lpServiceFailureActionsA
->lpCommand
,
4700 lpServiceFailureActionsW
->lpCommand
,
4704 ptr
= lpServiceFailureActionsW
;
4708 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4710 HeapFree(GetProcessHeap(), 0, ptr
);
4717 DWORD
RChangeServiceConfig2W(
4718 SC_RPC_HANDLE hService
,
4719 SC_RPC_CONFIG_INFOW Info
)
4721 DWORD dwError
= ERROR_SUCCESS
;
4722 PSERVICE_HANDLE hSvc
;
4723 PSERVICE lpService
= NULL
;
4724 HKEY hServiceKey
= NULL
;
4726 DPRINT("RChangeServiceConfig2W() called\n");
4727 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4730 return ERROR_SHUTDOWN_IN_PROGRESS
;
4732 hSvc
= ScmGetServiceFromHandle(hService
);
4735 DPRINT1("Invalid service handle!\n");
4736 return ERROR_INVALID_HANDLE
;
4739 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4740 SERVICE_CHANGE_CONFIG
))
4742 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4743 return ERROR_ACCESS_DENIED
;
4746 lpService
= hSvc
->ServiceEntry
;
4747 if (lpService
== NULL
)
4749 DPRINT("lpService == NULL!\n");
4750 return ERROR_INVALID_HANDLE
;
4753 /* Lock the service database exclusively */
4754 ScmLockDatabaseExclusive();
4756 if (lpService
->bDeleted
)
4758 DPRINT("The service has already been marked for delete!\n");
4759 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4763 /* Open the service key */
4764 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4767 if (dwError
!= ERROR_SUCCESS
)
4770 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4772 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4774 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4776 if (lpServiceDescription
!= NULL
&&
4777 lpServiceDescription
->lpDescription
!= NULL
)
4779 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4780 dwError
= RegSetValueExW(hServiceKey
,
4784 (LPBYTE
)lpServiceDescription
->lpDescription
,
4785 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4786 if (dwError
!= ERROR_SUCCESS
)
4790 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4793 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4798 /* Unlock the service database */
4799 ScmUnlockDatabase();
4801 if (hServiceKey
!= NULL
)
4802 RegCloseKey(hServiceKey
);
4804 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4811 DWORD
RQueryServiceConfig2A(
4812 SC_RPC_HANDLE hService
,
4816 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4818 DWORD dwError
= ERROR_SUCCESS
;
4819 PSERVICE_HANDLE hSvc
;
4820 PSERVICE lpService
= NULL
;
4821 HKEY hServiceKey
= NULL
;
4822 LPWSTR lpDescriptionW
= NULL
;
4824 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4825 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4828 return ERROR_INVALID_ADDRESS
;
4831 return ERROR_SHUTDOWN_IN_PROGRESS
;
4833 hSvc
= ScmGetServiceFromHandle(hService
);
4836 DPRINT1("Invalid service handle!\n");
4837 return ERROR_INVALID_HANDLE
;
4840 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4841 SERVICE_QUERY_CONFIG
))
4843 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4844 return ERROR_ACCESS_DENIED
;
4847 lpService
= hSvc
->ServiceEntry
;
4848 if (lpService
== NULL
)
4850 DPRINT("lpService == NULL!\n");
4851 return ERROR_INVALID_HANDLE
;
4854 /* Lock the service database shared */
4855 ScmLockDatabaseShared();
4857 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4860 if (dwError
!= ERROR_SUCCESS
)
4863 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4865 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4868 dwError
= ScmReadString(hServiceKey
,
4871 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4874 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4875 if (dwError
== ERROR_SUCCESS
)
4876 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4878 if (cbBufSize
< *pcbBytesNeeded
)
4880 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4884 if (dwError
== ERROR_SUCCESS
)
4886 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4888 WideCharToMultiByte(CP_ACP
,
4893 wcslen(lpDescriptionW
),
4896 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4900 lpServiceDescription
->lpDescription
= NULL
;
4901 dwError
= ERROR_SUCCESS
;
4905 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4908 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4913 /* Unlock the service database */
4914 ScmUnlockDatabase();
4916 if (lpDescriptionW
!= NULL
)
4917 HeapFree(GetProcessHeap(), 0, lpDescriptionW
);
4919 if (hServiceKey
!= NULL
)
4920 RegCloseKey(hServiceKey
);
4922 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4929 DWORD
RQueryServiceConfig2W(
4930 SC_RPC_HANDLE hService
,
4934 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4936 DWORD dwError
= ERROR_SUCCESS
;
4937 PSERVICE_HANDLE hSvc
;
4938 PSERVICE lpService
= NULL
;
4939 HKEY hServiceKey
= NULL
;
4940 DWORD dwRequiredSize
;
4941 LPWSTR lpDescription
= NULL
;
4942 LPWSTR lpFailureCommand
= NULL
;
4943 LPWSTR lpRebootMessage
= NULL
;
4945 DPRINT("RQueryServiceConfig2W() called\n");
4948 return ERROR_INVALID_ADDRESS
;
4951 return ERROR_SHUTDOWN_IN_PROGRESS
;
4953 hSvc
= ScmGetServiceFromHandle(hService
);
4956 DPRINT1("Invalid service handle!\n");
4957 return ERROR_INVALID_HANDLE
;
4960 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4961 SERVICE_QUERY_CONFIG
))
4963 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4964 return ERROR_ACCESS_DENIED
;
4967 lpService
= hSvc
->ServiceEntry
;
4968 if (lpService
== NULL
)
4970 DPRINT("lpService == NULL!\n");
4971 return ERROR_INVALID_HANDLE
;
4974 /* Lock the service database shared */
4975 ScmLockDatabaseShared();
4977 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4980 if (dwError
!= ERROR_SUCCESS
)
4983 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4985 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4988 dwError
= ScmReadString(hServiceKey
,
4991 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4994 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4995 if (dwError
== ERROR_SUCCESS
)
4996 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4998 if (cbBufSize
< *pcbBytesNeeded
)
5000 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5004 if (dwError
== ERROR_SUCCESS
)
5006 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
5007 wcscpy(lpStr
, lpDescription
);
5008 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
5012 lpServiceDescription
->lpDescription
= NULL
;
5013 dwError
= ERROR_SUCCESS
;
5016 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
5019 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
5023 dwError
= ScmReadString(hServiceKey
,
5027 dwError
= ScmReadString(hServiceKey
,
5031 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
5033 if (lpFailureCommand
)
5034 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
5036 if (lpRebootMessage
)
5037 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
5039 if (cbBufSize
< dwRequiredSize
)
5041 *pcbBytesNeeded
= dwRequiredSize
;
5042 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5046 lpFailureActions
->cActions
= 0;
5047 lpFailureActions
->dwResetPeriod
= 0;
5048 lpFailureActions
->lpCommand
= NULL
;
5049 lpFailureActions
->lpRebootMsg
= NULL
;
5050 lpFailureActions
->lpsaActions
= NULL
;
5052 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
5053 if (lpRebootMessage
)
5055 wcscpy(lpStr
, lpRebootMessage
);
5056 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
5057 lpStr
+= wcslen(lpRebootMessage
) + 1;
5060 if (lpFailureCommand
)
5062 wcscpy(lpStr
, lpFailureCommand
);
5063 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
5064 lpStr
+= wcslen(lpRebootMessage
) + 1;
5066 dwError
= STATUS_SUCCESS
;
5071 /* Unlock the service database */
5072 ScmUnlockDatabase();
5074 if (lpDescription
!= NULL
)
5075 HeapFree(GetProcessHeap(), 0, lpDescription
);
5077 if (lpRebootMessage
!= NULL
)
5078 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5080 if (lpFailureCommand
!= NULL
)
5081 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5083 if (hServiceKey
!= NULL
)
5084 RegCloseKey(hServiceKey
);
5086 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5093 DWORD
RQueryServiceStatusEx(
5094 SC_RPC_HANDLE hService
,
5095 SC_STATUS_TYPE InfoLevel
,
5098 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5100 LPSERVICE_STATUS_PROCESS lpStatus
;
5101 PSERVICE_HANDLE hSvc
;
5104 DPRINT("RQueryServiceStatusEx() called\n");
5107 return ERROR_SHUTDOWN_IN_PROGRESS
;
5109 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
5110 return ERROR_INVALID_LEVEL
;
5112 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
5114 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
5115 return ERROR_INSUFFICIENT_BUFFER
;
5117 hSvc
= ScmGetServiceFromHandle(hService
);
5120 DPRINT1("Invalid service handle!\n");
5121 return ERROR_INVALID_HANDLE
;
5124 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5125 SERVICE_QUERY_STATUS
))
5127 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5128 return ERROR_ACCESS_DENIED
;
5131 lpService
= hSvc
->ServiceEntry
;
5132 if (lpService
== NULL
)
5134 DPRINT("lpService == NULL!\n");
5135 return ERROR_INVALID_HANDLE
;
5138 /* Lock the service database shared */
5139 ScmLockDatabaseShared();
5141 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
5143 /* Return service status information */
5144 RtlCopyMemory(lpStatus
,
5146 sizeof(SERVICE_STATUS
));
5148 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
5149 lpStatus
->dwServiceFlags
= 0; /* FIXME */
5151 /* Unlock the service database */
5152 ScmUnlockDatabase();
5154 return ERROR_SUCCESS
;
5159 DWORD
REnumServicesStatusExA(
5160 SC_RPC_HANDLE hSCManager
,
5161 SC_ENUM_TYPE InfoLevel
,
5162 DWORD dwServiceType
,
5163 DWORD dwServiceState
,
5166 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5167 LPBOUNDED_DWORD_256K lpServicesReturned
,
5168 LPBOUNDED_DWORD_256K lpResumeIndex
,
5169 LPCSTR pszGroupName
)
5171 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
5172 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
5173 LPWSTR lpStringPtrW
;
5175 LPWSTR pszGroupNameW
= NULL
;
5177 DWORD dwServiceCount
;
5179 DPRINT("REnumServicesStatusExA() called\n");
5183 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
5186 DPRINT("Failed to allocate buffer!\n");
5187 return ERROR_NOT_ENOUGH_MEMORY
;
5190 MultiByteToWideChar(CP_ACP
,
5195 strlen(pszGroupName
) + 1);
5198 if ((cbBufSize
> 0) && (lpBuffer
))
5200 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
5203 DPRINT("Failed to allocate buffer!\n");
5204 return ERROR_NOT_ENOUGH_MEMORY
;
5208 dwError
= REnumServicesStatusExW(hSCManager
,
5212 (LPBYTE
)lpStatusPtrW
,
5219 /* if no services were returned then we are Done */
5220 if (*lpServicesReturned
== 0)
5223 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5224 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5225 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5226 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5227 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5229 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5231 /* Copy the service name */
5232 WideCharToMultiByte(CP_ACP
,
5237 wcslen(lpStringPtrW
),
5241 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5242 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5243 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5245 /* Copy the display name */
5246 WideCharToMultiByte(CP_ACP
,
5251 wcslen(lpStringPtrW
),
5255 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5256 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5257 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5259 /* Copy the status information */
5260 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5261 &lpStatusPtrW
->ServiceStatusProcess
,
5262 sizeof(SERVICE_STATUS
));
5264 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5265 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5271 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5274 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5276 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5283 DWORD
REnumServicesStatusExW(
5284 SC_RPC_HANDLE hSCManager
,
5285 SC_ENUM_TYPE InfoLevel
,
5286 DWORD dwServiceType
,
5287 DWORD dwServiceState
,
5290 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5291 LPBOUNDED_DWORD_256K lpServicesReturned
,
5292 LPBOUNDED_DWORD_256K lpResumeIndex
,
5293 LPCWSTR pszGroupName
)
5295 PMANAGER_HANDLE hManager
;
5297 DWORD dwError
= ERROR_SUCCESS
;
5298 PLIST_ENTRY ServiceEntry
;
5299 PSERVICE CurrentService
;
5301 DWORD dwRequiredSize
;
5302 DWORD dwServiceCount
;
5304 DWORD dwLastResumeCount
= 0;
5305 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5308 DPRINT("REnumServicesStatusExW() called\n");
5311 return ERROR_SHUTDOWN_IN_PROGRESS
;
5313 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5314 return ERROR_INVALID_LEVEL
;
5316 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5317 if (hManager
== NULL
)
5319 DPRINT1("Invalid service manager handle!\n");
5320 return ERROR_INVALID_HANDLE
;
5323 *pcbBytesNeeded
= 0;
5324 *lpServicesReturned
= 0;
5326 if ((dwServiceType
== 0) ||
5327 ((dwServiceType
& ~(SERVICE_DRIVER
| SERVICE_WIN32
)) != 0))
5329 DPRINT("Not a valid Service Type!\n");
5330 return ERROR_INVALID_PARAMETER
;
5333 if ((dwServiceState
!= SERVICE_ACTIVE
) &&
5334 (dwServiceState
!= SERVICE_INACTIVE
) &&
5335 (dwServiceState
!= SERVICE_STATE_ALL
))
5337 DPRINT("Not a valid Service State!\n");
5338 return ERROR_INVALID_PARAMETER
;
5341 /* Check access rights */
5342 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5343 SC_MANAGER_ENUMERATE_SERVICE
))
5345 DPRINT("Insufficient access rights! 0x%lx\n",
5346 hManager
->Handle
.DesiredAccess
);
5347 return ERROR_ACCESS_DENIED
;
5351 dwLastResumeCount
= *lpResumeIndex
;
5353 /* Lock the service database shared */
5354 ScmLockDatabaseShared();
5356 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5357 if (lpService
== NULL
)
5359 dwError
= ERROR_SUCCESS
;
5366 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5367 ServiceEntry
!= &ServiceListHead
;
5368 ServiceEntry
= ServiceEntry
->Flink
)
5370 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5374 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5377 dwState
= SERVICE_ACTIVE
;
5378 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5379 dwState
= SERVICE_INACTIVE
;
5381 if ((dwState
& dwServiceState
) == 0)
5386 if (*pszGroupName
== 0)
5388 if (CurrentService
->lpGroup
!= NULL
)
5393 if ((CurrentService
->lpGroup
== NULL
) ||
5394 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5399 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5400 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5401 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5403 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5405 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5406 dwRequiredSize
+= dwSize
;
5408 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5412 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5418 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5419 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5422 ServiceEntry
!= &ServiceListHead
;
5423 ServiceEntry
= ServiceEntry
->Flink
)
5425 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5429 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5432 dwState
= SERVICE_ACTIVE
;
5433 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5434 dwState
= SERVICE_INACTIVE
;
5436 if ((dwState
& dwServiceState
) == 0)
5441 if (*pszGroupName
== 0)
5443 if (CurrentService
->lpGroup
!= NULL
)
5448 if ((CurrentService
->lpGroup
== NULL
) ||
5449 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5454 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5455 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5456 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5458 dwError
= ERROR_MORE_DATA
;
5461 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5464 *lpResumeIndex
= dwLastResumeCount
;
5466 *lpServicesReturned
= dwServiceCount
;
5467 *pcbBytesNeeded
= dwRequiredSize
;
5469 /* If there was no services that matched */
5470 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5472 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5476 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5477 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5478 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5481 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5482 ServiceEntry
!= &ServiceListHead
;
5483 ServiceEntry
= ServiceEntry
->Flink
)
5485 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5489 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5492 dwState
= SERVICE_ACTIVE
;
5493 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5494 dwState
= SERVICE_INACTIVE
;
5496 if ((dwState
& dwServiceState
) == 0)
5501 if (*pszGroupName
== 0)
5503 if (CurrentService
->lpGroup
!= NULL
)
5508 if ((CurrentService
->lpGroup
== NULL
) ||
5509 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5514 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5515 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5516 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5518 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5520 /* Copy the service name */
5522 CurrentService
->lpServiceName
);
5523 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5524 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5526 /* Copy the display name */
5528 CurrentService
->lpDisplayName
);
5529 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5530 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5532 /* Copy the status information */
5533 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5534 &CurrentService
->Status
,
5535 sizeof(SERVICE_STATUS
));
5536 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5537 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5538 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5541 dwRequiredSize
+= dwSize
;
5551 *pcbBytesNeeded
= 0;
5557 /* Unlock the service database */
5558 ScmUnlockDatabase();
5560 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5567 DWORD
RSendTSMessage(
5568 handle_t BindingHandle
) /* FIXME */
5571 return ERROR_CALL_NOT_IMPLEMENTED
;
5576 DWORD
RCreateServiceWOW64A(
5577 handle_t BindingHandle
,
5578 LPSTR lpServiceName
,
5579 LPSTR lpDisplayName
,
5580 DWORD dwDesiredAccess
,
5581 DWORD dwServiceType
,
5583 DWORD dwErrorControl
,
5584 LPSTR lpBinaryPathName
,
5585 LPSTR lpLoadOrderGroup
,
5587 LPBYTE lpDependencies
,
5589 LPSTR lpServiceStartName
,
5592 LPSC_RPC_HANDLE lpServiceHandle
)
5595 return ERROR_CALL_NOT_IMPLEMENTED
;
5600 DWORD
RCreateServiceWOW64W(
5601 handle_t BindingHandle
,
5602 LPWSTR lpServiceName
,
5603 LPWSTR lpDisplayName
,
5604 DWORD dwDesiredAccess
,
5605 DWORD dwServiceType
,
5607 DWORD dwErrorControl
,
5608 LPWSTR lpBinaryPathName
,
5609 LPWSTR lpLoadOrderGroup
,
5611 LPBYTE lpDependencies
,
5613 LPWSTR lpServiceStartName
,
5616 LPSC_RPC_HANDLE lpServiceHandle
)
5619 return ERROR_CALL_NOT_IMPLEMENTED
;
5624 DWORD
RQueryServiceTagInfo(
5625 handle_t BindingHandle
) /* FIXME */
5628 return ERROR_CALL_NOT_IMPLEMENTED
;
5633 DWORD
RNotifyServiceStatusChange(
5634 SC_RPC_HANDLE hService
,
5635 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5636 GUID
*pClientProcessGuid
,
5637 GUID
*pSCMProcessGuid
,
5638 PBOOL pfCreateRemoteQueue
,
5639 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5642 return ERROR_CALL_NOT_IMPLEMENTED
;
5647 DWORD
RGetNotifyResults(
5648 SC_NOTIFY_RPC_HANDLE hNotify
,
5649 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5652 return ERROR_CALL_NOT_IMPLEMENTED
;
5657 DWORD
RCloseNotifyHandle(
5658 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5662 return ERROR_CALL_NOT_IMPLEMENTED
;
5667 DWORD
RControlServiceExA(
5668 SC_RPC_HANDLE hService
,
5673 return ERROR_CALL_NOT_IMPLEMENTED
;
5678 DWORD
RControlServiceExW(
5679 SC_RPC_HANDLE hService
,
5684 return ERROR_CALL_NOT_IMPLEMENTED
;
5689 DWORD
RSendPnPMessage(
5690 handle_t BindingHandle
) /* FIXME */
5693 return ERROR_CALL_NOT_IMPLEMENTED
;
5698 DWORD
RValidatePnPService(
5699 handle_t BindingHandle
) /* FIXME */
5702 return ERROR_CALL_NOT_IMPLEMENTED
;
5707 DWORD
ROpenServiceStatusHandle(
5708 handle_t BindingHandle
) /* FIXME */
5711 return ERROR_CALL_NOT_IMPLEMENTED
;
5717 handle_t BindingHandle
) /* FIXME */
5720 return ERROR_CALL_NOT_IMPLEMENTED
;
5724 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5726 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5730 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5732 HeapFree(GetProcessHeap(), 0, ptr
);
5736 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5741 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5746 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)