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 ****************************************************************/
19 /* GLOBALS *****************************************************************/
21 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
22 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
24 typedef struct _SCMGR_HANDLE
32 typedef struct _MANAGER_HANDLE
36 /* FIXME: Insert more data here */
38 WCHAR DatabaseName
[1];
39 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
42 typedef struct _SERVICE_HANDLE
47 PSERVICE ServiceEntry
;
49 /* FIXME: Insert more data here */
51 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
54 #define SC_MANAGER_READ \
55 (STANDARD_RIGHTS_READ | \
56 SC_MANAGER_QUERY_LOCK_STATUS | \
57 SC_MANAGER_ENUMERATE_SERVICE)
59 #define SC_MANAGER_WRITE \
60 (STANDARD_RIGHTS_WRITE | \
61 SC_MANAGER_MODIFY_BOOT_CONFIG | \
62 SC_MANAGER_CREATE_SERVICE)
64 #define SC_MANAGER_EXECUTE \
65 (STANDARD_RIGHTS_EXECUTE | \
67 SC_MANAGER_ENUMERATE_SERVICE | \
68 SC_MANAGER_CONNECT | \
69 SC_MANAGER_CREATE_SERVICE)
72 #define SERVICE_READ \
73 (STANDARD_RIGHTS_READ | \
74 SERVICE_INTERROGATE | \
75 SERVICE_ENUMERATE_DEPENDENTS | \
76 SERVICE_QUERY_STATUS | \
79 #define SERVICE_WRITE \
80 (STANDARD_RIGHTS_WRITE | \
81 SERVICE_CHANGE_CONFIG)
83 #define SERVICE_EXECUTE \
84 (STANDARD_RIGHTS_EXECUTE | \
85 SERVICE_USER_DEFINED_CONTROL | \
86 SERVICE_PAUSE_CONTINUE | \
91 /* VARIABLES ***************************************************************/
93 static GENERIC_MAPPING
94 ScmManagerMapping
= {SC_MANAGER_READ
,
97 SC_MANAGER_ALL_ACCESS
};
99 static GENERIC_MAPPING
100 ScmServiceMapping
= {SERVICE_READ
,
103 SC_MANAGER_ALL_ACCESS
};
106 /* FUNCTIONS ***************************************************************/
109 ScmStartRpcServer(VOID
)
113 DPRINT("ScmStartRpcServer() called\n");
115 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
125 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
128 if (Status
!= RPC_S_OK
)
130 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
134 Status
= RpcServerListen(1, 20, TRUE
);
135 if (Status
!= RPC_S_OK
)
137 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
141 DPRINT("ScmStartRpcServer() done\n");
146 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
151 if (lpDatabaseName
== NULL
)
152 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
154 if (wcsicmp(lpDatabaseName
,SERVICES_FAILED_DATABASEW
)==0)
156 DPRINT1("Database %S, does not exist\n",lpDatabaseName
);
157 return ERROR_DATABASE_DOES_NOT_EXIST
;
159 else if (wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
161 DPRINT1("Invalid Database name %S.\n",lpDatabaseName
);
162 return ERROR_INVALID_NAME
;
165 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
167 sizeof(MANAGER_HANDLE
) + (wcslen(lpDatabaseName
) + 1) * sizeof(WCHAR
));
169 return ERROR_NOT_ENOUGH_MEMORY
;
171 Ptr
->Handle
.Tag
= MANAGER_TAG
;
172 Ptr
->Handle
.RefCount
= 1;
174 /* FIXME: initialize more data here */
176 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
178 *Handle
= (SC_HANDLE
)Ptr
;
180 return ERROR_SUCCESS
;
185 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
190 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
192 sizeof(SERVICE_HANDLE
));
194 return ERROR_NOT_ENOUGH_MEMORY
;
196 Ptr
->Handle
.Tag
= SERVICE_TAG
;
197 Ptr
->Handle
.RefCount
= 1;
199 /* FIXME: initialize more data here */
200 Ptr
->ServiceEntry
= lpServiceEntry
;
202 *Handle
= (SC_HANDLE
)Ptr
;
204 return ERROR_SUCCESS
;
209 ScmCheckAccess(SC_HANDLE Handle
,
210 DWORD dwDesiredAccess
)
212 PMANAGER_HANDLE hMgr
;
214 hMgr
= (PMANAGER_HANDLE
)Handle
;
215 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
217 RtlMapGenericMask(&dwDesiredAccess
,
220 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
222 return ERROR_SUCCESS
;
224 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
226 RtlMapGenericMask(&dwDesiredAccess
,
229 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
231 return ERROR_SUCCESS
;
234 return ERROR_INVALID_HANDLE
;
239 ScmAssignNewTag(PSERVICE lpService
)
242 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
243 lpService
->dwTag
= 0;
244 return ERROR_SUCCESS
;
248 /* Internal recursive function */
249 /* Need to search for every dependency on every service */
251 Int_EnumDependentServicesW(HKEY hServicesKey
,
253 DWORD dwServiceState
,
254 PSERVICE
*lpServices
,
255 LPDWORD pcbBytesNeeded
,
256 LPDWORD lpServicesReturned
)
258 DWORD dwError
= ERROR_SUCCESS
;
259 WCHAR szNameBuf
[MAX_PATH
];
260 WCHAR szValueBuf
[MAX_PATH
];
261 WCHAR
*lpszNameBuf
= szNameBuf
;
262 WCHAR
*lpszValueBuf
= szValueBuf
;
266 PSERVICE lpCurrentService
;
267 HKEY hServiceEnumKey
;
268 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
269 DWORD dwDependServiceStrPtr
= 0;
270 DWORD dwRequiredSize
= 0;
272 /* Get the number of service keys */
273 dwError
= RegQueryInfoKeyW(hServicesKey
,
285 if (dwError
!= ERROR_SUCCESS
)
287 DPRINT1("ERROR! Unable to get number of services keys.\n");
291 /* Iterate the service keys to see if another service depends on the this service */
292 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
295 dwError
= RegEnumKeyExW(hServicesKey
,
303 if (dwError
!= ERROR_SUCCESS
)
306 /* Open the Service key */
307 dwError
= RegOpenKeyExW(hServicesKey
,
312 if (dwError
!= ERROR_SUCCESS
)
317 /* Check for the DependOnService Value */
318 dwError
= RegQueryValueExW(hServiceEnumKey
,
322 (LPBYTE
)lpszValueBuf
,
325 /* FIXME: Handle load order. */
327 /* If the service found has a DependOnService value */
328 if (dwError
== ERROR_SUCCESS
)
330 dwDependServiceStrPtr
= 0;
332 /* Can be more than one Dependencies in the DependOnService string */
333 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
335 if (wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
337 /* Get the current enumed service pointer */
338 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
340 /* Check for valid Service */
341 if (!lpCurrentService
)
343 /* This should never happen! */
344 DPRINT1("This should not happen at this point, report to Developer\n");
345 return ERROR_NOT_FOUND
;
348 /* Determine state the service is in */
349 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
350 dwCurrentServiceState
= SERVICE_INACTIVE
;
352 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
353 if ((dwCurrentServiceState
== dwServiceState
) ||
354 (dwServiceState
== SERVICE_STATE_ALL
))
356 /* Calculate the required size */
357 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
358 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
359 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
361 /* Add the size for service name and display name pointers */
362 dwRequiredSize
+= (2 * sizeof(PVOID
));
364 /* increase the BytesNeeded size */
365 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
367 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
370 /* Recursive call to check for its dependencies */
371 Int_EnumDependentServicesW(hServicesKey
,
378 /* If the lpServices is valid set the service pointer */
380 lpServices
[*lpServicesReturned
] = lpCurrentService
;
382 *lpServicesReturned
= *lpServicesReturned
+ 1;
386 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
389 else if (*pcbBytesNeeded
)
391 dwError
= ERROR_SUCCESS
;
394 RegCloseKey(hServiceEnumKey
);
402 DWORD
RCloseServiceHandle(
403 handle_t BindingHandle
,
404 LPSC_RPC_HANDLE hSCObject
)
406 PMANAGER_HANDLE hManager
;
407 PSERVICE_HANDLE hService
;
411 DWORD pcbBytesNeeded
= 0;
412 DWORD dwServicesReturned
= 0;
414 DPRINT("RCloseServiceHandle() called\n");
416 DPRINT("hSCObject = %p\n", *hSCObject
);
419 return ERROR_INVALID_HANDLE
;
421 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
422 hService
= (PSERVICE_HANDLE
)*hSCObject
;
423 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
425 DPRINT("Found manager handle\n");
427 hManager
->Handle
.RefCount
--;
428 if (hManager
->Handle
.RefCount
== 0)
430 /* FIXME: add handle cleanup code */
432 HeapFree(GetProcessHeap(), 0, hManager
);
436 DPRINT("RCloseServiceHandle() done\n");
437 return ERROR_SUCCESS
;
439 else if (hService
->Handle
.Tag
== SERVICE_TAG
)
441 DPRINT("Found service handle\n");
443 /* Get the pointer to the service record */
444 lpService
= hService
->ServiceEntry
;
446 ASSERT(hService
->Handle
.RefCount
> 0);
448 hService
->Handle
.RefCount
--;
449 if (hService
->Handle
.RefCount
== 0)
451 /* FIXME: add handle cleanup code */
453 /* Free the handle */
454 HeapFree(GetProcessHeap(), 0, hService
);
458 ASSERT(lpService
->dwRefCount
> 0);
460 lpService
->dwRefCount
--;
461 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
462 lpService
->dwRefCount
);
464 if (lpService
->dwRefCount
== 0)
466 /* If this service has been marked for deletion */
467 if (lpService
->bDeleted
)
469 /* Open the Services Reg key */
470 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
471 L
"System\\CurrentControlSet\\Services",
473 KEY_SET_VALUE
| KEY_READ
,
475 if (dwError
!= ERROR_SUCCESS
)
477 DPRINT1("Failed to open services key\n");
481 /* Call the internal function with NULL, just to get bytes we need */
482 Int_EnumDependentServicesW(hServicesKey
,
487 &dwServicesReturned
);
489 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
492 DPRINT1("Deletion failed due to running dependencies.\n");
493 RegCloseKey(hServicesKey
);
494 return ERROR_SUCCESS
;
497 /* There are no references and no runnning dependencies,
498 it is now safe to delete the service */
500 /* Delete the Service Key */
501 dwError
= RegDeleteKey(hServicesKey
,
502 lpService
->lpServiceName
);
504 RegCloseKey(hServicesKey
);
506 if (dwError
!= ERROR_SUCCESS
)
508 DPRINT1("Failed to Delete the Service Registry key\n");
512 /* Delete the Service */
513 ScmDeleteServiceRecord(lpService
);
517 DPRINT("RCloseServiceHandle() done\n");
518 return ERROR_SUCCESS
;
521 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
523 return ERROR_INVALID_HANDLE
;
528 DWORD
RControlService(
529 handle_t BindingHandle
,
530 SC_RPC_HANDLE hService
,
532 LPSERVICE_STATUS lpServiceStatus
)
534 PSERVICE_HANDLE hSvc
;
536 ACCESS_MASK DesiredAccess
;
537 DWORD dwError
= ERROR_SUCCESS
;
538 DWORD pcbBytesNeeded
= 0;
539 DWORD dwServicesReturned
= 0;
540 HKEY hServicesKey
= NULL
;
542 DPRINT("RControlService() called\n");
545 return ERROR_SHUTDOWN_IN_PROGRESS
;
547 /* Check the service handle */
548 hSvc
= (PSERVICE_HANDLE
)hService
;
549 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
551 DPRINT1("Invalid handle tag!\n");
552 return ERROR_INVALID_HANDLE
;
555 /* Check the service entry point */
556 lpService
= hSvc
->ServiceEntry
;
557 if (lpService
== NULL
)
559 DPRINT1("lpService == NULL!\n");
560 return ERROR_INVALID_HANDLE
;
563 /* Check access rights */
566 case SERVICE_CONTROL_STOP
:
567 DesiredAccess
= SERVICE_STOP
;
570 case SERVICE_CONTROL_PAUSE
:
571 case SERVICE_CONTROL_CONTINUE
:
572 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
575 case SERVICE_INTERROGATE
:
576 DesiredAccess
= SERVICE_INTERROGATE
;
580 if (dwControl
>= 128 && dwControl
<= 255)
581 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
583 DesiredAccess
= SERVICE_QUERY_CONFIG
|
584 SERVICE_CHANGE_CONFIG
|
585 SERVICE_QUERY_STATUS
|
587 SERVICE_PAUSE_CONTINUE
;
591 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
593 return ERROR_ACCESS_DENIED
;
595 if (dwControl
== SERVICE_CONTROL_STOP
)
597 /* Check if the service has dependencies running as windows
598 doesn't stop a service that does */
600 /* Open the Services Reg key */
601 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
602 L
"System\\CurrentControlSet\\Services",
606 if (dwError
!= ERROR_SUCCESS
)
608 DPRINT1("Failed to open services key\n");
612 /* Call the internal function with NULL, just to get bytes we need */
613 Int_EnumDependentServicesW(hServicesKey
,
618 &dwServicesReturned
);
620 RegCloseKey(hServicesKey
);
622 /* If pcbBytesNeeded is not zero then there are services running that
623 are dependent on this service */
624 if (pcbBytesNeeded
!= 0)
626 DPRINT("Service has running dependencies. Failed to stop service.\n");
627 return ERROR_DEPENDENT_SERVICES_RUNNING
;
631 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
633 /* Send control code to the driver */
634 dwError
= ScmControlDriver(lpService
,
640 /* Send control code to the service */
641 dwError
= ScmControlService(lpService
,
646 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
647 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
649 /* Return service status information */
650 RtlCopyMemory(lpServiceStatus
,
652 sizeof(SERVICE_STATUS
));
659 DWORD
RDeleteService(
660 handle_t BindingHandle
,
661 SC_RPC_HANDLE hService
)
663 PSERVICE_HANDLE hSvc
;
667 DPRINT("RDeleteService() called\n");
670 return ERROR_SHUTDOWN_IN_PROGRESS
;
672 hSvc
= (PSERVICE_HANDLE
)hService
;
673 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
674 return ERROR_INVALID_HANDLE
;
676 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
678 return ERROR_ACCESS_DENIED
;
680 lpService
= hSvc
->ServiceEntry
;
681 if (lpService
== NULL
)
683 DPRINT1("lpService == NULL!\n");
684 return ERROR_INVALID_HANDLE
;
687 /* FIXME: Acquire service database lock exclusively */
689 if (lpService
->bDeleted
)
691 DPRINT1("The service has already been marked for delete!\n");
692 return ERROR_SERVICE_MARKED_FOR_DELETE
;
695 /* Mark service for delete */
696 lpService
->bDeleted
= TRUE
;
698 dwError
= ScmMarkServiceForDelete(lpService
);
700 /* FIXME: Release service database lock */
702 DPRINT("RDeleteService() done\n");
709 DWORD
RLockServiceDatabase(
710 handle_t BindingHandle
,
711 SC_RPC_HANDLE hSCManager
,
712 LPSC_RPC_LOCK lpLock
)
714 PMANAGER_HANDLE hMgr
;
716 DPRINT("RLockServiceDatabase() called\n");
720 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
721 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
722 return ERROR_INVALID_HANDLE
;
724 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
726 return ERROR_ACCESS_DENIED
;
728 // return ScmLockDatabase(0, hMgr->0xC, hLock);
730 /* FIXME: Lock the database */
731 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
733 return ERROR_SUCCESS
;
738 DWORD
RQueryServiceObjectSecurity(
739 handle_t BindingHandle
,
740 SC_RPC_HANDLE hService
,
741 SECURITY_INFORMATION dwSecurityInformation
,
742 LPBYTE lpSecurityDescriptor
,
744 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
747 PSERVICE_HANDLE hSvc
;
749 ULONG DesiredAccess
= 0;
754 DPRINT("RQueryServiceObjectSecurity() called\n");
756 hSvc
= (PSERVICE_HANDLE
)hService
;
757 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
759 DPRINT1("Invalid handle tag!\n");
760 return ERROR_INVALID_HANDLE
;
763 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
764 GROUP_SECURITY_INFORMATION
||
765 OWNER_SECURITY_INFORMATION
))
766 DesiredAccess
|= READ_CONTROL
;
768 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
769 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
771 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
774 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
775 return ERROR_ACCESS_DENIED
;
778 lpService
= hSvc
->ServiceEntry
;
779 if (lpService
== NULL
)
781 DPRINT1("lpService == NULL!\n");
782 return ERROR_INVALID_HANDLE
;
785 /* FIXME: Lock the service list */
787 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
788 dwSecurityInformation
,
789 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
790 dwSecuityDescriptorSize
,
793 /* FIXME: Unlock the service list */
795 if (NT_SUCCESS(Status
))
797 *pcbBytesNeeded
= dwBytesNeeded
;
798 dwError
= STATUS_SUCCESS
;
800 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
802 *pcbBytesNeeded
= dwBytesNeeded
;
803 dwError
= ERROR_INSUFFICIENT_BUFFER
;
805 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
807 dwError
= ERROR_GEN_FAILURE
;
811 dwError
= RtlNtStatusToDosError(Status
);
817 return ERROR_CALL_NOT_IMPLEMENTED
;
822 DWORD
RSetServiceObjectSecurity(
823 handle_t BindingHandle
,
824 SC_RPC_HANDLE hService
,
825 DWORD dwSecurityInformation
,
826 LPBYTE lpSecurityDescriptor
,
827 DWORD dwSecuityDescriptorSize
)
829 PSERVICE_HANDLE hSvc
;
831 ULONG DesiredAccess
= 0;
832 HANDLE hToken
= NULL
;
837 DPRINT1("RSetServiceObjectSecurity() called\n");
839 hSvc
= (PSERVICE_HANDLE
)hService
;
840 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
842 DPRINT1("Invalid handle tag!\n");
843 return ERROR_INVALID_HANDLE
;
846 if (dwSecurityInformation
== 0 ||
847 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
848 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
849 return ERROR_INVALID_PARAMETER
;
851 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
852 return ERROR_INVALID_PARAMETER
;
854 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
855 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
857 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
858 DesiredAccess
|= WRITE_DAC
;
860 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
861 DesiredAccess
|= WRITE_OWNER
;
863 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
864 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
865 return ERROR_INVALID_PARAMETER
;
867 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
868 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
869 return ERROR_INVALID_PARAMETER
;
871 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
874 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
875 return ERROR_ACCESS_DENIED
;
878 lpService
= hSvc
->ServiceEntry
;
879 if (lpService
== NULL
)
881 DPRINT1("lpService == NULL!\n");
882 return ERROR_INVALID_HANDLE
;
885 if (lpService
->bDeleted
)
886 return ERROR_SERVICE_MARKED_FOR_DELETE
;
888 RpcImpersonateClient(NULL
);
890 Status
= NtOpenThreadToken(NtCurrentThread(),
894 if (!NT_SUCCESS(Status
))
895 return RtlNtStatusToDosError(Status
);
899 /* FIXME: Lock service database */
902 Status
= RtlSetSecurityObject(dwSecurityInformation
,
903 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
904 &lpService
->lpSecurityDescriptor
,
907 if (!NT_SUCCESS(Status
))
909 dwError
= RtlNtStatusToDosError(Status
);
914 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
915 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
917 if (dwError
!= ERROR_SUCCESS
)
921 dwError
= ERROR_SUCCESS
;
922 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
923 // lpService->lpSecurityDescriptor);
925 RegFlushKey(hServiceKey
);
926 RegCloseKey(hServiceKey
);
933 /* FIXME: Unlock service database */
935 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
942 DWORD
RQueryServiceStatus(
943 handle_t BindingHandle
,
944 SC_RPC_HANDLE hService
,
945 LPSERVICE_STATUS lpServiceStatus
)
947 PSERVICE_HANDLE hSvc
;
950 DPRINT("RQueryServiceStatus() called\n");
953 return ERROR_SHUTDOWN_IN_PROGRESS
;
955 hSvc
= (PSERVICE_HANDLE
)hService
;
956 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
958 DPRINT1("Invalid handle tag!\n");
959 return ERROR_INVALID_HANDLE
;
962 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
963 SERVICE_QUERY_STATUS
))
965 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
966 return ERROR_ACCESS_DENIED
;
969 lpService
= hSvc
->ServiceEntry
;
970 if (lpService
== NULL
)
972 DPRINT1("lpService == NULL!\n");
973 return ERROR_INVALID_HANDLE
;
976 /* Return service status information */
977 RtlCopyMemory(lpServiceStatus
,
979 sizeof(SERVICE_STATUS
));
981 return ERROR_SUCCESS
;
986 ScmIsValidServiceState(DWORD dwCurrentState
)
988 switch (dwCurrentState
)
990 case SERVICE_STOPPED
:
991 case SERVICE_START_PENDING
:
992 case SERVICE_STOP_PENDING
:
993 case SERVICE_RUNNING
:
994 case SERVICE_CONTINUE_PENDING
:
995 case SERVICE_PAUSE_PENDING
:
1006 DWORD
RSetServiceStatus(
1007 handle_t BindingHandle
,
1008 SC_RPC_HANDLE hServiceStatus
,
1009 LPSERVICE_STATUS lpServiceStatus
)
1013 DPRINT("RSetServiceStatus() called\n");
1014 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1015 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1016 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1017 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1018 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1019 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1020 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1021 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1023 if (hServiceStatus
== 0)
1025 DPRINT1("hServiceStatus == NULL!\n");
1026 return ERROR_INVALID_HANDLE
;
1029 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
1030 if (lpService
== NULL
)
1032 DPRINT1("lpService == NULL!\n");
1033 return ERROR_INVALID_HANDLE
;
1036 /* Check current state */
1037 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1039 DPRINT1("Invalid service state!\n");
1040 return ERROR_INVALID_DATA
;
1043 /* Check service type */
1044 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1045 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1047 DPRINT1("Invalid service type!\n");
1048 return ERROR_INVALID_DATA
;
1051 /* Check accepted controls */
1052 if (lpServiceStatus
->dwControlsAccepted
== 0 ||
1053 lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1055 DPRINT1("Invalid controls accepted!\n");
1056 return ERROR_INVALID_DATA
;
1060 RtlCopyMemory(&lpService
->Status
,
1062 sizeof(SERVICE_STATUS
));
1064 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1065 DPRINT("RSetServiceStatus() done\n");
1067 return ERROR_SUCCESS
;
1072 DWORD
RUnlockServiceDatabase(
1073 handle_t BindingHandle
,
1077 return ERROR_SUCCESS
;
1082 DWORD
RNotifyBootConfigStatus(
1083 handle_t BindingHandle
,
1084 SVCCTL_HANDLEW lpMachineName
,
1085 DWORD BootAcceptable
)
1088 return ERROR_CALL_NOT_IMPLEMENTED
;
1093 DWORD
RI_ScSetServiceBitsW(
1094 handle_t BindingHandle
,
1095 SC_RPC_HANDLE hServiceStatus
,
1096 DWORD dwServiceBits
,
1098 int bUpdateImmediately
,
1102 return ERROR_CALL_NOT_IMPLEMENTED
;
1107 DWORD
RChangeServiceConfigW(
1108 handle_t BindingHandle
,
1109 SC_RPC_HANDLE hService
,
1110 DWORD dwServiceType
,
1112 DWORD dwErrorControl
,
1113 LPWSTR lpBinaryPathName
,
1114 LPWSTR lpLoadOrderGroup
,
1116 LPBYTE lpDependencies
,
1118 LPWSTR lpServiceStartName
,
1121 LPWSTR lpDisplayName
)
1123 DWORD dwError
= ERROR_SUCCESS
;
1124 PSERVICE_HANDLE hSvc
;
1125 PSERVICE lpService
= NULL
;
1126 HKEY hServiceKey
= NULL
;
1127 LPWSTR lpDisplayNameW
= NULL
;
1129 DPRINT("RChangeServiceConfigW() called\n");
1130 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1131 DPRINT("dwStartType = %lu\n", dwStartType
);
1132 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1133 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1134 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1135 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1138 return ERROR_SHUTDOWN_IN_PROGRESS
;
1140 hSvc
= (PSERVICE_HANDLE
)hService
;
1141 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1143 DPRINT1("Invalid handle tag!\n");
1144 return ERROR_INVALID_HANDLE
;
1147 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1148 SERVICE_CHANGE_CONFIG
))
1150 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1151 return ERROR_ACCESS_DENIED
;
1154 lpService
= hSvc
->ServiceEntry
;
1155 if (lpService
== NULL
)
1157 DPRINT1("lpService == NULL!\n");
1158 return ERROR_INVALID_HANDLE
;
1161 /* FIXME: Lock database exclusively */
1163 if (lpService
->bDeleted
)
1165 /* FIXME: Unlock database */
1166 DPRINT1("The service has already been marked for delete!\n");
1167 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1170 /* Open the service key */
1171 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1174 if (dwError
!= ERROR_SUCCESS
)
1177 /* Write service data to the registry */
1178 /* Set the display name */
1179 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1181 RegSetValueExW(hServiceKey
,
1185 (LPBYTE
)lpDisplayName
,
1186 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1188 /* Update the display name */
1189 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1191 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1192 if (lpDisplayNameW
== NULL
)
1194 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1198 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1199 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1201 lpService
->lpDisplayName
= lpDisplayNameW
;
1204 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1206 /* Set the service type */
1207 dwError
= RegSetValueExW(hServiceKey
,
1211 (LPBYTE
)&dwServiceType
,
1213 if (dwError
!= ERROR_SUCCESS
)
1216 lpService
->Status
.dwServiceType
= dwServiceType
;
1219 if (dwStartType
!= SERVICE_NO_CHANGE
)
1221 /* Set the start value */
1222 dwError
= RegSetValueExW(hServiceKey
,
1226 (LPBYTE
)&dwStartType
,
1228 if (dwError
!= ERROR_SUCCESS
)
1231 lpService
->dwStartType
= dwStartType
;
1234 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1236 /* Set the error control value */
1237 dwError
= RegSetValueExW(hServiceKey
,
1241 (LPBYTE
)&dwErrorControl
,
1243 if (dwError
!= ERROR_SUCCESS
)
1246 lpService
->dwErrorControl
= dwErrorControl
;
1250 /* FIXME: set the new ImagePath value */
1252 /* Set the image path */
1253 if (dwServiceType
& SERVICE_WIN32
)
1255 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1257 dwError
= RegSetValueExW(hServiceKey
,
1261 (LPBYTE
)lpBinaryPathName
,
1262 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1263 if (dwError
!= ERROR_SUCCESS
)
1267 else if (dwServiceType
& SERVICE_DRIVER
)
1269 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1271 dwError
= RegSetValueExW(hServiceKey
,
1275 (LPBYTE
)lpImagePath
,
1276 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1277 if (dwError
!= ERROR_SUCCESS
)
1283 /* Set the group name */
1284 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1286 dwError
= RegSetValueExW(hServiceKey
,
1290 (LPBYTE
)lpLoadOrderGroup
,
1291 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1292 if (dwError
!= ERROR_SUCCESS
)
1294 /* FIXME: Update lpService->lpServiceGroup */
1297 if (lpdwTagId
!= NULL
)
1299 dwError
= ScmAssignNewTag(lpService
);
1300 if (dwError
!= ERROR_SUCCESS
)
1303 dwError
= RegSetValueExW(hServiceKey
,
1307 (LPBYTE
)&lpService
->dwTag
,
1309 if (dwError
!= ERROR_SUCCESS
)
1312 *lpdwTagId
= lpService
->dwTag
;
1315 /* Write dependencies */
1316 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1318 dwError
= ScmWriteDependencies(hServiceKey
,
1319 (LPWSTR
)lpDependencies
,
1321 if (dwError
!= ERROR_SUCCESS
)
1325 if (lpPassword
!= NULL
)
1327 /* FIXME: Write password */
1330 /* FIXME: Unlock database */
1333 if (hServiceKey
!= NULL
)
1334 RegCloseKey(hServiceKey
);
1336 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1342 /* Create a path suitable for the bootloader out of the full path */
1344 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1346 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1349 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1350 OBJECT_ATTRIBUTES ObjectAttributes
;
1352 HANDLE SymbolicLinkHandle
;
1354 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1356 ServiceNameLen
= wcslen(CanonName
);
1358 /* First check, if it's already good */
1359 if (ServiceNameLen
> 12 &&
1360 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1362 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1363 if (*RelativeName
== NULL
)
1365 DPRINT1("Error allocating memory for boot driver name!\n");
1366 return ERROR_NOT_ENOUGH_MEMORY
;
1370 wcscpy(*RelativeName
, CanonName
);
1372 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1373 return ERROR_SUCCESS
;
1376 /* If it has %SystemRoot% prefix, substitute it to \System*/
1377 if (ServiceNameLen
> 13 &&
1378 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1380 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1381 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1383 if (*RelativeName
== NULL
)
1385 DPRINT1("Error allocating memory for boot driver name!\n");
1386 return ERROR_NOT_ENOUGH_MEMORY
;
1390 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1391 wcscat(*RelativeName
, CanonName
+ 13);
1393 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1394 return ERROR_SUCCESS
;
1397 /* Get buffer size needed for expanding env strings */
1398 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1400 if (BufferSize
<= 1)
1402 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1403 return ERROR_INVALID_ENVIRONMENT
;
1406 /* Allocate memory, since the size is known now */
1407 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1410 DPRINT1("Error allocating memory for boot driver name!\n");
1411 return ERROR_NOT_ENOUGH_MEMORY
;
1415 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1418 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1419 LocalFree(Expanded
);
1420 return ERROR_NOT_ENOUGH_MEMORY
;
1423 /* Convert to NY-style path */
1424 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1426 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1427 return ERROR_INVALID_ENVIRONMENT
;
1430 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1432 /* No need to keep the dos-path anymore */
1433 LocalFree(Expanded
);
1435 /* Copy it to the allocated place */
1436 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1439 DPRINT1("Error allocating memory for boot driver name!\n");
1440 return ERROR_NOT_ENOUGH_MEMORY
;
1443 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1444 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1445 Expanded
[ExpandedLen
] = 0;
1447 if (ServiceNameLen
> ExpandedLen
&&
1448 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1450 /* Only \SystemRoot\ is missing */
1451 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1452 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1453 if (*RelativeName
== NULL
)
1455 DPRINT1("Error allocating memory for boot driver name!\n");
1456 LocalFree(Expanded
);
1457 return ERROR_NOT_ENOUGH_MEMORY
;
1460 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1461 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1463 RtlFreeUnicodeString(&NtPathName
);
1464 return ERROR_SUCCESS
;
1467 /* The most complex case starts here */
1468 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1469 InitializeObjectAttributes(&ObjectAttributes
,
1471 OBJ_CASE_INSENSITIVE
,
1475 /* Open this symlink */
1476 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1478 if (NT_SUCCESS(Status
))
1480 LinkTarget
.Length
= 0;
1481 LinkTarget
.MaximumLength
= 0;
1483 DPRINT("Opened symbolic link object\n");
1485 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1486 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1488 /* Check if required buffer size is sane */
1489 if (BufferSize
> 0xFFFD)
1491 DPRINT1("Too large buffer required\n");
1494 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1495 LocalFree(Expanded
);
1496 return ERROR_NOT_ENOUGH_MEMORY
;
1499 /* Alloc the string */
1500 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1501 if (!LinkTarget
.Buffer
)
1503 DPRINT1("Unable to alloc buffer\n");
1504 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1505 LocalFree(Expanded
);
1506 return ERROR_NOT_ENOUGH_MEMORY
;
1509 /* Do a real query now */
1510 LinkTarget
.Length
= BufferSize
;
1511 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1513 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1514 if (NT_SUCCESS(Status
))
1516 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1518 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1519 if ((ServiceNameLen
> ExpandedLen
) &&
1520 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1522 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1523 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1525 if (*RelativeName
== NULL
)
1527 DPRINT1("Unable to alloc buffer\n");
1528 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1529 LocalFree(Expanded
);
1530 RtlFreeUnicodeString(&NtPathName
);
1531 return ERROR_NOT_ENOUGH_MEMORY
;
1534 /* Copy it over, substituting the first part
1536 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1537 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1540 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1541 LocalFree(Expanded
);
1542 RtlFreeUnicodeString(&NtPathName
);
1544 /* Return success */
1545 return ERROR_SUCCESS
;
1549 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1550 LocalFree(Expanded
);
1551 RtlFreeUnicodeString(&NtPathName
);
1552 return ERROR_INVALID_PARAMETER
;
1557 DPRINT1("Error, Status = %08X\n", Status
);
1558 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1559 LocalFree(Expanded
);
1560 RtlFreeUnicodeString(&NtPathName
);
1561 return ERROR_INVALID_PARAMETER
;
1566 DPRINT1("Error, Status = %08X\n", Status
);
1567 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1568 LocalFree(Expanded
);
1569 RtlFreeUnicodeString(&NtPathName
);
1570 return ERROR_INVALID_PARAMETER
;
1575 DPRINT1("Error, Status = %08X\n", Status
);
1576 LocalFree(Expanded
);
1577 return ERROR_INVALID_PARAMETER
;
1581 *RelativeName
= NULL
;
1582 return ERROR_INVALID_PARAMETER
;
1586 ScmCanonDriverImagePath(DWORD dwStartType
,
1587 wchar_t *lpServiceName
,
1588 wchar_t **lpCanonName
)
1590 DWORD ServiceNameLen
, Result
;
1591 UNICODE_STRING NtServiceName
;
1592 WCHAR
*RelativeName
;
1593 WCHAR
*SourceName
= lpServiceName
;
1595 /* Calculate the length of the service's name */
1596 ServiceNameLen
= wcslen(lpServiceName
);
1598 /* 12 is wcslen(L"\\SystemRoot\\") */
1599 if (ServiceNameLen
> 12 &&
1600 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1602 /* SystemRoot prefix is already included */
1604 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1606 if (*lpCanonName
== NULL
)
1608 DPRINT1("Error allocating memory for canonized service name!\n");
1609 return ERROR_NOT_ENOUGH_MEMORY
;
1612 /* If it's a boot-time driver, it must be systemroot relative */
1613 if (dwStartType
== SERVICE_BOOT_START
)
1617 wcscpy(*lpCanonName
, SourceName
);
1619 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1623 /* Check if it has %SystemRoot% (len=13) */
1624 if (ServiceNameLen
> 13 &&
1625 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1627 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1628 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1630 if (*lpCanonName
== NULL
)
1632 DPRINT1("Error allocating memory for canonized service name!\n");
1633 return ERROR_NOT_ENOUGH_MEMORY
;
1636 /* If it's a boot-time driver, it must be systemroot relative */
1637 if (dwStartType
== SERVICE_BOOT_START
)
1638 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1640 wcscat(*lpCanonName
, lpServiceName
+ 13);
1642 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1646 /* Check if it's a relative path name */
1647 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1649 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1651 if (*lpCanonName
== NULL
)
1653 DPRINT1("Error allocating memory for canonized service name!\n");
1654 return ERROR_NOT_ENOUGH_MEMORY
;
1657 /* Just copy it over without changing */
1658 wcscpy(*lpCanonName
, lpServiceName
);
1663 /* It seems to be a DOS path, convert it */
1664 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1666 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1667 return ERROR_INVALID_PARAMETER
;
1670 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1672 if (*lpCanonName
== NULL
)
1674 DPRINT1("Error allocating memory for canonized service name!\n");
1675 RtlFreeUnicodeString(&NtServiceName
);
1676 return ERROR_NOT_ENOUGH_MEMORY
;
1679 /* Copy the string */
1680 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1682 /* The unicode string is not needed anymore */
1683 RtlFreeUnicodeString(&NtServiceName
);
1685 if (dwStartType
!= SERVICE_BOOT_START
)
1687 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1691 /* The service is boot-started, so must be relative */
1692 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1695 /* There is a problem, free name and return */
1696 LocalFree(*lpCanonName
);
1697 DPRINT1("Error converting named!\n");
1701 ASSERT(RelativeName
);
1703 /* Copy that string */
1704 wcscpy(*lpCanonName
, RelativeName
+ 12);
1706 /* Free the allocated buffer */
1707 LocalFree(RelativeName
);
1709 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1717 DWORD
RCreateServiceW(
1718 handle_t BindingHandle
,
1719 SC_RPC_HANDLE hSCManager
,
1720 LPWSTR lpServiceName
,
1721 LPWSTR lpDisplayName
,
1722 DWORD dwDesiredAccess
,
1723 DWORD dwServiceType
,
1725 DWORD dwErrorControl
,
1726 LPWSTR lpBinaryPathName
,
1727 LPWSTR lpLoadOrderGroup
,
1729 LPBYTE lpDependencies
,
1731 LPWSTR lpServiceStartName
,
1734 LPSC_RPC_HANDLE lpServiceHandle
)
1736 PMANAGER_HANDLE hManager
;
1737 DWORD dwError
= ERROR_SUCCESS
;
1738 PSERVICE lpService
= NULL
;
1739 SC_HANDLE hServiceHandle
= NULL
;
1740 LPWSTR lpImagePath
= NULL
;
1741 HKEY hServiceKey
= NULL
;
1743 DPRINT("RCreateServiceW() called\n");
1744 DPRINT("lpServiceName = %S\n", lpServiceName
);
1745 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1746 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1747 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1748 DPRINT("dwStartType = %lu\n", dwStartType
);
1749 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1750 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1751 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1754 return ERROR_SHUTDOWN_IN_PROGRESS
;
1756 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1757 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1759 DPRINT1("Invalid manager handle!\n");
1760 return ERROR_INVALID_HANDLE
;
1763 /* Check access rights */
1764 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1765 SC_MANAGER_CREATE_SERVICE
))
1767 DPRINT1("Insufficient access rights! 0x%lx\n",
1768 hManager
->Handle
.DesiredAccess
);
1769 return ERROR_ACCESS_DENIED
;
1772 if (wcslen(lpServiceName
) == 0)
1774 return ERROR_INVALID_NAME
;
1777 if (wcslen(lpBinaryPathName
) == 0)
1779 return ERROR_INVALID_PARAMETER
;
1782 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1783 (lpServiceStartName
))
1785 return ERROR_INVALID_PARAMETER
;
1788 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1789 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1790 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1792 return ERROR_INVALID_PARAMETER
;
1795 if (dwStartType
> SERVICE_DISABLED
)
1797 return ERROR_INVALID_PARAMETER
;
1800 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1803 /* check if it is marked for deletion */
1804 if (lpService
->bDeleted
)
1805 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1806 /* Return Error exist */
1807 return ERROR_SERVICE_EXISTS
;
1810 if (lpDisplayName
!= NULL
&&
1811 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1812 return ERROR_DUPLICATE_SERVICE_NAME
;
1814 if (dwServiceType
& SERVICE_DRIVER
)
1816 dwError
= ScmCanonDriverImagePath(dwStartType
,
1819 if (dwError
!= ERROR_SUCCESS
)
1824 if (dwStartType
== SERVICE_BOOT_START
||
1825 dwStartType
== SERVICE_SYSTEM_START
)
1827 return ERROR_INVALID_PARAMETER
;
1831 /* Allocate a new service entry */
1832 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1834 if (dwError
!= ERROR_SUCCESS
)
1837 /* Fill the new service entry */
1838 lpService
->Status
.dwServiceType
= dwServiceType
;
1839 lpService
->dwStartType
= dwStartType
;
1840 lpService
->dwErrorControl
= dwErrorControl
;
1842 /* Fill the display name */
1843 if (lpDisplayName
!= NULL
&&
1844 *lpDisplayName
!= 0 &&
1845 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1847 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1848 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1849 if (lpService
->lpDisplayName
== NULL
)
1851 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1854 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1857 /* Assign the service to a group */
1858 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1860 dwError
= ScmSetServiceGroup(lpService
,
1862 if (dwError
!= ERROR_SUCCESS
)
1866 /* Assign a new tag */
1867 if (lpdwTagId
!= NULL
)
1869 dwError
= ScmAssignNewTag(lpService
);
1870 if (dwError
!= ERROR_SUCCESS
)
1874 /* Write service data to the registry */
1875 /* Create the service key */
1876 dwError
= ScmCreateServiceKey(lpServiceName
,
1879 if (dwError
!= ERROR_SUCCESS
)
1882 /* Set the display name */
1883 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1885 RegSetValueExW(hServiceKey
,
1889 (LPBYTE
)lpDisplayName
,
1890 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1893 /* Set the service type */
1894 dwError
= RegSetValueExW(hServiceKey
,
1898 (LPBYTE
)&dwServiceType
,
1900 if (dwError
!= ERROR_SUCCESS
)
1903 /* Set the start value */
1904 dwError
= RegSetValueExW(hServiceKey
,
1908 (LPBYTE
)&dwStartType
,
1910 if (dwError
!= ERROR_SUCCESS
)
1913 /* Set the error control value */
1914 dwError
= RegSetValueExW(hServiceKey
,
1918 (LPBYTE
)&dwErrorControl
,
1920 if (dwError
!= ERROR_SUCCESS
)
1923 /* Set the image path */
1924 if (dwServiceType
& SERVICE_WIN32
)
1926 dwError
= RegSetValueExW(hServiceKey
,
1930 (LPBYTE
)lpBinaryPathName
,
1931 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1932 if (dwError
!= ERROR_SUCCESS
)
1935 else if (dwServiceType
& SERVICE_DRIVER
)
1937 dwError
= RegSetValueExW(hServiceKey
,
1941 (LPBYTE
)lpImagePath
,
1942 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1943 if (dwError
!= ERROR_SUCCESS
)
1947 /* Set the group name */
1948 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1950 dwError
= RegSetValueExW(hServiceKey
,
1954 (LPBYTE
)lpLoadOrderGroup
,
1955 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1956 if (dwError
!= ERROR_SUCCESS
)
1960 if (lpdwTagId
!= NULL
)
1962 dwError
= RegSetValueExW(hServiceKey
,
1966 (LPBYTE
)&lpService
->dwTag
,
1968 if (dwError
!= ERROR_SUCCESS
)
1972 /* Write dependencies */
1973 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1975 dwError
= ScmWriteDependencies(hServiceKey
,
1976 (LPWSTR
)lpDependencies
,
1978 if (dwError
!= ERROR_SUCCESS
)
1982 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1983 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1985 dwError
= RegSetValueExW(hServiceKey
,
1989 (LPBYTE
)L
"LocalSystem",
1991 if (dwError
!= ERROR_SUCCESS
)
1995 if (lpPassword
!= NULL
)
1997 /* FIXME: Write password */
2000 dwError
= ScmCreateServiceHandle(lpService
,
2002 if (dwError
!= ERROR_SUCCESS
)
2005 dwError
= ScmCheckAccess(hServiceHandle
,
2007 if (dwError
!= ERROR_SUCCESS
)
2010 lpService
->dwRefCount
= 1;
2011 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2014 if (hServiceKey
!= NULL
)
2015 RegCloseKey(hServiceKey
);
2017 if (dwError
== ERROR_SUCCESS
)
2019 DPRINT("hService %p\n", hServiceHandle
);
2020 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2022 if (lpdwTagId
!= NULL
)
2023 *lpdwTagId
= lpService
->dwTag
;
2027 /* Release the display name buffer */
2028 if (lpService
->lpServiceName
!= NULL
)
2029 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2033 /* Remove the service handle */
2034 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2037 if (lpService
!= NULL
)
2039 /* FIXME: remove the service entry */
2043 if (lpImagePath
!= NULL
)
2044 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2046 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2053 DWORD
REnumDependentServicesW(
2054 handle_t BindingHandle
,
2055 SC_RPC_HANDLE hService
,
2056 DWORD dwServiceState
,
2059 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2060 LPBOUNDED_DWORD_256K lpServicesReturned
)
2062 DWORD dwError
= ERROR_SUCCESS
;
2063 DWORD dwServicesReturned
= 0;
2064 DWORD dwServiceCount
;
2065 HKEY hServicesKey
= NULL
;
2066 LPSC_RPC_HANDLE hSCObject
;
2067 PSERVICE_HANDLE hSvc
;
2068 PSERVICE lpService
= NULL
;
2069 PSERVICE
*lpServicesArray
= NULL
;
2070 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2073 *pcbBytesNeeded
= 0;
2074 *lpServicesReturned
= 0;
2076 DPRINT("REnumDependentServicesW() called\n");
2078 hSCObject
= &hService
;
2079 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2080 lpService
= hSvc
->ServiceEntry
;
2082 /* Check access rights */
2083 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2084 SC_MANAGER_ENUMERATE_SERVICE
))
2086 DPRINT1("Insufficient access rights! 0x%lx\n",
2087 hSvc
->Handle
.DesiredAccess
);
2088 return ERROR_ACCESS_DENIED
;
2091 /* Open the Services Reg key */
2092 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2093 L
"System\\CurrentControlSet\\Services",
2097 if (dwError
!= ERROR_SUCCESS
)
2100 /* First determine the bytes needed and get the number of dependent services */
2101 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2106 &dwServicesReturned
);
2107 if (dwError
!= ERROR_SUCCESS
)
2110 /* If buffer size is less than the bytes needed or pointer is null */
2111 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2113 dwError
= ERROR_MORE_DATA
;
2117 /* Allocate memory for array of service pointers */
2118 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2120 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2121 if (!lpServicesArray
)
2123 DPRINT1("Could not allocate a buffer!!\n");
2124 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2128 dwServicesReturned
= 0;
2129 *pcbBytesNeeded
= 0;
2131 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2136 &dwServicesReturned
);
2137 if (dwError
!= ERROR_SUCCESS
)
2142 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2143 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2145 /* Copy EnumDepenedentService to Buffer */
2146 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2148 lpService
= lpServicesArray
[dwServiceCount
];
2150 /* Copy status info */
2151 memcpy(&lpServicesPtr
->ServiceStatus
,
2153 sizeof(SERVICE_STATUS
));
2155 /* Copy display name */
2156 wcscpy(lpStr
, lpService
->lpDisplayName
);
2157 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2158 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2160 /* Copy service name */
2161 wcscpy(lpStr
, lpService
->lpServiceName
);
2162 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2163 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2168 *lpServicesReturned
= dwServicesReturned
;
2171 if (lpServicesArray
!= NULL
)
2172 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2174 RegCloseKey(hServicesKey
);
2176 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2183 DWORD
REnumServicesStatusW(
2184 handle_t BindingHandle
,
2185 SC_RPC_HANDLE hSCManager
,
2186 DWORD dwServiceType
,
2187 DWORD dwServiceState
,
2190 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2191 LPBOUNDED_DWORD_256K lpServicesReturned
,
2192 LPBOUNDED_DWORD_256K lpResumeHandle
)
2194 PMANAGER_HANDLE hManager
;
2196 DWORD dwError
= ERROR_SUCCESS
;
2197 PLIST_ENTRY ServiceEntry
;
2198 PSERVICE CurrentService
;
2200 DWORD dwRequiredSize
;
2201 DWORD dwServiceCount
;
2203 DWORD dwLastResumeCount
= 0;
2204 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2207 DPRINT("REnumServicesStatusW() called\n");
2210 return ERROR_SHUTDOWN_IN_PROGRESS
;
2212 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2213 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2215 DPRINT1("Invalid manager handle!\n");
2216 return ERROR_INVALID_HANDLE
;
2219 *pcbBytesNeeded
= 0;
2220 *lpServicesReturned
= 0;
2222 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2224 DPRINT("Not a valid Service Type!\n");
2225 return ERROR_INVALID_PARAMETER
;
2228 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2230 DPRINT("Not a valid Service State!\n");
2231 return ERROR_INVALID_PARAMETER
;
2234 /* Check access rights */
2235 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2236 SC_MANAGER_ENUMERATE_SERVICE
))
2238 DPRINT1("Insufficient access rights! 0x%lx\n",
2239 hManager
->Handle
.DesiredAccess
);
2240 return ERROR_ACCESS_DENIED
;
2243 if (lpResumeHandle
) dwLastResumeCount
= *lpResumeHandle
;
2245 /* FIXME: Lock the service list shared */
2247 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2248 if (lpService
== NULL
)
2250 dwError
= ERROR_SUCCESS
;
2257 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2258 ServiceEntry
!= &ServiceListHead
;
2259 ServiceEntry
= ServiceEntry
->Flink
)
2261 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2265 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2268 dwState
= SERVICE_ACTIVE
;
2269 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2270 dwState
= SERVICE_INACTIVE
;
2272 if ((dwState
& dwServiceState
) == 0)
2275 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2276 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2277 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2279 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2281 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2285 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2286 dwRequiredSize
+= dwSize
;
2288 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2291 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2292 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2295 ServiceEntry
!= &ServiceListHead
;
2296 ServiceEntry
= ServiceEntry
->Flink
)
2298 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2302 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2305 dwState
= SERVICE_ACTIVE
;
2306 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2307 dwState
= SERVICE_INACTIVE
;
2309 if ((dwState
& dwServiceState
) == 0)
2312 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2313 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2314 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2316 dwError
= ERROR_MORE_DATA
;
2319 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2321 if (lpResumeHandle
) *lpResumeHandle
= dwLastResumeCount
;
2322 *lpServicesReturned
= dwServiceCount
;
2323 *pcbBytesNeeded
= dwRequiredSize
;
2325 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2326 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2327 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2330 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2331 ServiceEntry
!= &ServiceListHead
;
2332 ServiceEntry
= ServiceEntry
->Flink
)
2334 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2338 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2341 dwState
= SERVICE_ACTIVE
;
2342 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2343 dwState
= SERVICE_INACTIVE
;
2345 if ((dwState
& dwServiceState
) == 0)
2348 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2349 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2350 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2352 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2355 /* Copy the service name */
2356 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2357 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2358 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2360 /* Copy the display name */
2361 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2362 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2363 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2365 /* Copy the status information */
2366 memcpy(&lpStatusPtr
->ServiceStatus
,
2367 &CurrentService
->Status
,
2368 sizeof(SERVICE_STATUS
));
2371 dwRequiredSize
+= dwSize
;
2376 *pcbBytesNeeded
= 0;
2377 if (lpResumeHandle
) *lpResumeHandle
= 0;
2381 /* FIXME: Unlock the service list */
2383 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2390 DWORD
ROpenSCManagerW(
2391 handle_t BindingHandle
,
2392 LPWSTR lpMachineName
,
2393 LPWSTR lpDatabaseName
,
2394 DWORD dwDesiredAccess
,
2395 LPSC_RPC_HANDLE lpScHandle
)
2400 DPRINT("ROpenSCManagerW() called\n");
2401 DPRINT("lpMachineName = %p\n", lpMachineName
);
2402 DPRINT("lpMachineName: %S\n", lpMachineName
);
2403 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2404 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2405 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2408 return ERROR_SHUTDOWN_IN_PROGRESS
;
2411 return ERROR_INVALID_PARAMETER
;
2413 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2415 if (dwError
!= ERROR_SUCCESS
)
2417 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2421 /* Check the desired access */
2422 dwError
= ScmCheckAccess(hHandle
,
2423 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2424 if (dwError
!= ERROR_SUCCESS
)
2426 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2427 HeapFree(GetProcessHeap(), 0, hHandle
);
2431 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2432 DPRINT("*hScm = %p\n", *lpScHandle
);
2434 DPRINT("ROpenSCManagerW() done\n");
2436 return ERROR_SUCCESS
;
2441 DWORD
ROpenServiceW(
2442 handle_t BindingHandle
,
2443 SC_RPC_HANDLE hSCManager
,
2444 LPWSTR lpServiceName
,
2445 DWORD dwDesiredAccess
,
2446 LPSC_RPC_HANDLE lpServiceHandle
)
2449 PMANAGER_HANDLE hManager
;
2453 DPRINT("ROpenServiceW() called\n");
2454 DPRINT("hSCManager = %p\n", hSCManager
);
2455 DPRINT("lpServiceName = %p\n", lpServiceName
);
2456 DPRINT("lpServiceName: %S\n", lpServiceName
);
2457 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2460 return ERROR_SHUTDOWN_IN_PROGRESS
;
2462 if (!lpServiceHandle
)
2463 return ERROR_INVALID_PARAMETER
;
2466 return ERROR_INVALID_ADDRESS
;
2468 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2469 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2471 DPRINT1("Invalid manager handle!\n");
2472 return ERROR_INVALID_HANDLE
;
2475 /* FIXME: Lock the service list */
2477 /* Get service database entry */
2478 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2479 if (lpService
== NULL
)
2481 DPRINT("Could not find a service!\n");
2482 return ERROR_SERVICE_DOES_NOT_EXIST
;
2485 /* Create a service handle */
2486 dwError
= ScmCreateServiceHandle(lpService
,
2488 if (dwError
!= ERROR_SUCCESS
)
2490 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2494 /* Check the desired access */
2495 dwError
= ScmCheckAccess(hHandle
,
2497 if (dwError
!= ERROR_SUCCESS
)
2499 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2500 HeapFree(GetProcessHeap(), 0, hHandle
);
2504 lpService
->dwRefCount
++;
2505 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2507 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2508 DPRINT("*hService = %p\n", *lpServiceHandle
);
2510 DPRINT("ROpenServiceW() done\n");
2512 return ERROR_SUCCESS
;
2517 DWORD
RQueryServiceConfigW(
2518 handle_t BindingHandle
,
2519 SC_RPC_HANDLE hService
,
2520 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2522 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2524 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2525 DWORD dwError
= ERROR_SUCCESS
;
2526 PSERVICE_HANDLE hSvc
;
2527 PSERVICE lpService
= NULL
;
2528 HKEY hServiceKey
= NULL
;
2529 LPWSTR lpImagePath
= NULL
;
2530 LPWSTR lpServiceStartName
= NULL
;
2531 DWORD dwRequiredSize
;
2532 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2533 WCHAR lpEmptyString
[] = {0,0};
2536 DPRINT("RQueryServiceConfigW() called\n");
2539 return ERROR_SHUTDOWN_IN_PROGRESS
;
2541 hSvc
= (PSERVICE_HANDLE
)hService
;
2542 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2544 DPRINT1("Invalid handle tag!\n");
2545 return ERROR_INVALID_HANDLE
;
2548 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2549 SERVICE_QUERY_CONFIG
))
2551 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2552 return ERROR_ACCESS_DENIED
;
2555 lpService
= hSvc
->ServiceEntry
;
2556 if (lpService
== NULL
)
2558 DPRINT1("lpService == NULL!\n");
2559 return ERROR_INVALID_HANDLE
;
2562 /* FIXME: Lock the service database shared */
2564 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2567 if (dwError
!= ERROR_SUCCESS
)
2570 dwError
= ScmReadString(hServiceKey
,
2573 if (dwError
!= ERROR_SUCCESS
)
2576 ScmReadString(hServiceKey
,
2578 &lpServiceStartName
);
2580 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2582 if (lpImagePath
!= NULL
)
2583 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2585 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2587 if (lpService
->lpGroup
!= NULL
)
2588 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2590 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2592 /* FIXME: Add Dependencies length*/
2594 if (lpServiceStartName
!= NULL
)
2595 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2597 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2599 if (lpService
->lpDisplayName
!= NULL
)
2600 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2602 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2604 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2606 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2610 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2611 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2612 lpConfig
->dwStartType
= lpService
->dwStartType
;
2613 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2614 lpConfig
->dwTagId
= lpService
->dwTag
;
2616 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2618 if (lpImagePath
!= NULL
)
2620 wcscpy(lpStr
, lpImagePath
);
2624 wcscpy(lpStr
, lpEmptyString
);
2627 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2628 lpStr
+= (wcslen(lpStr
) + 1);
2630 if (lpService
->lpGroup
!= NULL
)
2632 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2636 wcscpy(lpStr
, lpEmptyString
);
2639 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2640 lpStr
+= (wcslen(lpStr
) + 1);
2642 /* FIXME: Append Dependencies */
2643 wcscpy(lpStr
, lpEmptyString
);
2645 lpStr
+= (wcslen(lpStr
) + 1);
2646 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2648 if (lpServiceStartName
!= NULL
)
2650 wcscpy(lpStr
, lpServiceStartName
);
2654 wcscpy(lpStr
, lpEmptyString
);
2657 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2658 lpStr
+= (wcslen(lpStr
) + 1);
2660 if (lpService
->lpDisplayName
!= NULL
)
2662 wcscpy(lpStr
, lpService
->lpDisplayName
);
2666 wcscpy(lpStr
, lpEmptyString
);
2669 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2672 if (pcbBytesNeeded
!= NULL
)
2673 *pcbBytesNeeded
= dwRequiredSize
;
2676 if (lpImagePath
!= NULL
)
2677 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2679 if (lpServiceStartName
!= NULL
)
2680 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2682 if (hServiceKey
!= NULL
)
2683 RegCloseKey(hServiceKey
);
2685 /* FIXME: Unlock the service database */
2687 DPRINT("RQueryServiceConfigW() done\n");
2694 DWORD
RQueryServiceLockStatusW(
2695 handle_t BindingHandle
,
2696 SC_RPC_HANDLE hSCManager
,
2697 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2699 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2702 return ERROR_CALL_NOT_IMPLEMENTED
;
2707 DWORD
RStartServiceW(
2708 handle_t BindingHandle
,
2709 SC_RPC_HANDLE hService
,
2711 LPSTRING_PTRSW argv
)
2713 DWORD dwError
= ERROR_SUCCESS
;
2714 PSERVICE_HANDLE hSvc
;
2715 PSERVICE lpService
= NULL
;
2717 DPRINT("RStartServiceW() called\n");
2720 return ERROR_SHUTDOWN_IN_PROGRESS
;
2722 hSvc
= (PSERVICE_HANDLE
)hService
;
2723 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2725 DPRINT1("Invalid handle tag!\n");
2726 return ERROR_INVALID_HANDLE
;
2729 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2732 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2733 return ERROR_ACCESS_DENIED
;
2736 lpService
= hSvc
->ServiceEntry
;
2737 if (lpService
== NULL
)
2739 DPRINT1("lpService == NULL!\n");
2740 return ERROR_INVALID_HANDLE
;
2743 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2744 return ERROR_SERVICE_DISABLED
;
2746 if (lpService
->bDeleted
)
2747 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2754 /* Start the service */
2755 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2762 DWORD
RGetServiceDisplayNameW(
2763 handle_t BindingHandle
,
2764 SC_RPC_HANDLE hSCManager
,
2765 LPWSTR lpServiceName
,
2766 LPWSTR lpDisplayName
,
2769 // PMANAGER_HANDLE hManager;
2774 DPRINT("RGetServiceDisplayNameW() called\n");
2775 DPRINT("hSCManager = %p\n", hSCManager
);
2776 DPRINT("lpServiceName: %S\n", lpServiceName
);
2777 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2778 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2780 // hManager = (PMANAGER_HANDLE)hSCManager;
2781 // if (hManager->Handle.Tag != MANAGER_TAG)
2783 // DPRINT1("Invalid manager handle!\n");
2784 // return ERROR_INVALID_HANDLE;
2787 /* Get service database entry */
2788 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2789 if (lpService
== NULL
)
2791 DPRINT1("Could not find a service!\n");
2793 /* If the service could not be found and lpcchBuffer is 0, windows
2794 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2795 if (*lpcchBuffer
== 0)
2798 *lpDisplayName
= '\0';
2801 return ERROR_SERVICE_DOES_NOT_EXIST
;
2804 if (!lpService
->lpDisplayName
)
2806 dwLength
= wcslen(lpService
->lpServiceName
);
2808 if (lpServiceName
!= NULL
&&
2809 *lpcchBuffer
> dwLength
)
2811 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2816 dwLength
= wcslen(lpService
->lpDisplayName
);
2818 if (lpDisplayName
!= NULL
&&
2819 *lpcchBuffer
> dwLength
)
2821 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2825 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2827 *lpcchBuffer
= dwLength
;
2834 DWORD
RGetServiceKeyNameW(
2835 handle_t BindingHandle
,
2836 SC_RPC_HANDLE hSCManager
,
2837 LPWSTR lpDisplayName
,
2838 LPWSTR lpServiceName
,
2841 // PMANAGER_HANDLE hManager;
2846 DPRINT("RGetServiceKeyNameW() called\n");
2847 DPRINT("hSCManager = %p\n", hSCManager
);
2848 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2849 DPRINT("lpServiceName: %p\n", lpServiceName
);
2850 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2852 // hManager = (PMANAGER_HANDLE)hSCManager;
2853 // if (hManager->Handle.Tag != MANAGER_TAG)
2855 // DPRINT1("Invalid manager handle!\n");
2856 // return ERROR_INVALID_HANDLE;
2859 /* Get service database entry */
2860 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2861 if (lpService
== NULL
)
2863 DPRINT1("Could not find a service!\n");
2865 /* If the service could not be found and lpcchBuffer is 0, windows
2866 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2867 if (*lpcchBuffer
== 0)
2870 *lpServiceName
= '\0';
2873 return ERROR_SERVICE_DOES_NOT_EXIST
;
2876 dwLength
= wcslen(lpService
->lpServiceName
);
2878 if (lpServiceName
!= NULL
&&
2879 *lpcchBuffer
> dwLength
)
2881 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2882 *lpcchBuffer
= dwLength
;
2883 return ERROR_SUCCESS
;
2886 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2888 *lpcchBuffer
= dwLength
* 2;
2895 DWORD
RI_ScSetServiceBitsA(
2896 handle_t BindingHandle
,
2897 SC_RPC_HANDLE hServiceStatus
,
2898 DWORD dwServiceBits
,
2900 int bUpdateImmediately
,
2904 return ERROR_CALL_NOT_IMPLEMENTED
;
2909 DWORD
RChangeServiceConfigA(
2910 handle_t BindingHandle
,
2911 SC_RPC_HANDLE hService
,
2912 DWORD dwServiceType
,
2914 DWORD dwErrorControl
,
2915 LPSTR lpBinaryPathName
,
2916 LPSTR lpLoadOrderGroup
,
2918 LPSTR lpDependencies
,
2920 LPSTR lpServiceStartName
,
2923 LPSTR lpDisplayName
)
2925 DWORD dwError
= ERROR_SUCCESS
;
2926 PSERVICE_HANDLE hSvc
;
2927 PSERVICE lpService
= NULL
;
2928 HKEY hServiceKey
= NULL
;
2929 LPWSTR lpDisplayNameW
= NULL
;
2930 // LPWSTR lpBinaryPathNameW = NULL;
2931 LPWSTR lpLoadOrderGroupW
= NULL
;
2932 LPWSTR lpDependenciesW
= NULL
;
2933 // LPWSTR lpPasswordW = NULL;
2935 DPRINT("RChangeServiceConfigA() called\n");
2936 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2937 DPRINT("dwStartType = %lu\n", dwStartType
);
2938 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2939 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2940 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2941 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2944 return ERROR_SHUTDOWN_IN_PROGRESS
;
2946 hSvc
= (PSERVICE_HANDLE
)hService
;
2947 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2949 DPRINT1("Invalid handle tag!\n");
2950 return ERROR_INVALID_HANDLE
;
2953 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2954 SERVICE_CHANGE_CONFIG
))
2956 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2957 return ERROR_ACCESS_DENIED
;
2960 lpService
= hSvc
->ServiceEntry
;
2961 if (lpService
== NULL
)
2963 DPRINT1("lpService == NULL!\n");
2964 return ERROR_INVALID_HANDLE
;
2967 /* FIXME: Lock database exclusively */
2969 if (lpService
->bDeleted
)
2971 /* FIXME: Unlock database */
2972 DPRINT1("The service has already been marked for delete!\n");
2973 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2976 /* Open the service key */
2977 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2980 if (dwError
!= ERROR_SUCCESS
)
2983 /* Write service data to the registry */
2985 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2987 /* Set the display name */
2988 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2990 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2991 if (lpDisplayNameW
== NULL
)
2993 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2997 MultiByteToWideChar(CP_ACP
,
3002 wcslen(lpDisplayNameW
) + 1);
3004 RegSetValueExW(hServiceKey
,
3008 (LPBYTE
)lpDisplayNameW
,
3009 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3011 /* Update lpService->lpDisplayName */
3012 if (lpService
->lpDisplayName
)
3013 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3015 lpService
->lpDisplayName
= lpDisplayNameW
;
3018 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3020 /* Set the service type */
3021 dwError
= RegSetValueExW(hServiceKey
,
3025 (LPBYTE
)&dwServiceType
,
3027 if (dwError
!= ERROR_SUCCESS
)
3030 lpService
->Status
.dwServiceType
= dwServiceType
;
3033 if (dwStartType
!= SERVICE_NO_CHANGE
)
3035 /* Set the start value */
3036 dwError
= RegSetValueExW(hServiceKey
,
3040 (LPBYTE
)&dwStartType
,
3042 if (dwError
!= ERROR_SUCCESS
)
3045 lpService
->dwStartType
= dwStartType
;
3048 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3050 /* Set the error control value */
3051 dwError
= RegSetValueExW(hServiceKey
,
3055 (LPBYTE
)&dwErrorControl
,
3057 if (dwError
!= ERROR_SUCCESS
)
3060 lpService
->dwErrorControl
= dwErrorControl
;
3064 /* FIXME: set the new ImagePath value */
3066 /* Set the image path */
3067 if (dwServiceType
& SERVICE_WIN32
)
3069 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3071 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3072 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3073 dwError
= RegSetValueExW(hServiceKey
,
3077 (LPBYTE
)lpBinaryPathNameW
,
3078 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3079 if (dwError
!= ERROR_SUCCESS
)
3083 else if (dwServiceType
& SERVICE_DRIVER
)
3085 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3087 dwError
= RegSetValueExW(hServiceKey
,
3091 (LPBYTE
)lpImagePath
,
3092 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3093 if (dwError
!= ERROR_SUCCESS
)
3099 /* Set the group name */
3100 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3102 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3104 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3105 if (lpLoadOrderGroupW
== NULL
)
3107 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3111 MultiByteToWideChar(CP_ACP
,
3116 wcslen(lpLoadOrderGroupW
) + 1);
3118 dwError
= RegSetValueExW(hServiceKey
,
3122 (LPBYTE
)lpLoadOrderGroupW
,
3123 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3124 if (dwError
!= ERROR_SUCCESS
)
3127 /* FIXME: Update lpService->lpServiceGroup */
3129 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3132 if (lpdwTagId
!= NULL
)
3134 dwError
= ScmAssignNewTag(lpService
);
3135 if (dwError
!= ERROR_SUCCESS
)
3138 dwError
= RegSetValueExW(hServiceKey
,
3142 (LPBYTE
)&lpService
->dwTag
,
3144 if (dwError
!= ERROR_SUCCESS
)
3147 *lpdwTagId
= lpService
->dwTag
;
3150 /* Write dependencies */
3151 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3153 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3155 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3156 if (lpDependenciesW
== NULL
)
3158 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3162 MultiByteToWideChar(CP_ACP
,
3167 wcslen(lpDependenciesW
)+1);
3169 dwError
= ScmWriteDependencies(hServiceKey
,
3170 (LPWSTR
)lpDependenciesW
,
3173 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3176 if (lpPassword
!= NULL
)
3178 /* FIXME: Write password */
3181 /* FIXME: Unlock database */
3184 if (hServiceKey
!= NULL
)
3185 RegCloseKey(hServiceKey
);
3187 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3194 DWORD
RCreateServiceA(
3195 handle_t BindingHandle
,
3196 SC_RPC_HANDLE hSCManager
,
3197 LPSTR lpServiceName
,
3198 LPSTR lpDisplayName
,
3199 DWORD dwDesiredAccess
,
3200 DWORD dwServiceType
,
3202 DWORD dwErrorControl
,
3203 LPSTR lpBinaryPathName
,
3204 LPSTR lpLoadOrderGroup
,
3206 LPBYTE lpDependencies
,
3208 LPSTR lpServiceStartName
,
3211 LPSC_RPC_HANDLE lpServiceHandle
)
3214 return ERROR_CALL_NOT_IMPLEMENTED
;
3219 DWORD
REnumDependentServicesA(
3220 handle_t BindingHandle
,
3221 SC_RPC_HANDLE hService
,
3222 DWORD dwServiceState
,
3225 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3226 LPBOUNDED_DWORD_256K lpServicesReturned
)
3228 DWORD dwError
= ERROR_SUCCESS
;
3229 DWORD dwServicesReturned
= 0;
3230 DWORD dwServiceCount
;
3231 HKEY hServicesKey
= NULL
;
3232 LPSC_RPC_HANDLE hSCObject
;
3233 PSERVICE_HANDLE hSvc
;
3234 PSERVICE lpService
= NULL
;
3235 PSERVICE
*lpServicesArray
= NULL
;
3236 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3239 *pcbBytesNeeded
= 0;
3240 *lpServicesReturned
= 0;
3242 DPRINT("REnumDependentServicesA() called\n");
3244 hSCObject
= &hService
;
3245 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3246 lpService
= hSvc
->ServiceEntry
;
3248 /* Check access rights */
3249 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3250 SC_MANAGER_ENUMERATE_SERVICE
))
3252 DPRINT1("Insufficient access rights! 0x%lx\n",
3253 hSvc
->Handle
.DesiredAccess
);
3254 return ERROR_ACCESS_DENIED
;
3257 /* Open the Services Reg key */
3258 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3259 L
"System\\CurrentControlSet\\Services",
3264 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3266 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3267 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3268 are the same for both. Verified in WINXP. */
3270 /* First determine the bytes needed and get the number of dependent services*/
3271 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3276 &dwServicesReturned
);
3277 if (dwError
!= ERROR_SUCCESS
)
3280 /* If buffer size is less than the bytes needed or pointer is null*/
3281 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3283 dwError
= ERROR_MORE_DATA
;
3287 /* Allocate memory for array of service pointers */
3288 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3290 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3291 if (!lpServicesArray
)
3293 DPRINT1("Could not allocate a buffer!!\n");
3294 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3298 dwServicesReturned
= 0;
3299 *pcbBytesNeeded
= 0;
3301 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3306 &dwServicesReturned
);
3307 if (dwError
!= ERROR_SUCCESS
)
3312 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3313 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3315 /* Copy EnumDepenedentService to Buffer */
3316 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3318 lpService
= lpServicesArray
[dwServiceCount
];
3320 /* Copy the status info */
3321 memcpy(&lpServicesPtr
->ServiceStatus
,
3323 sizeof(SERVICE_STATUS
));
3325 /* Copy display name */
3326 WideCharToMultiByte(CP_ACP
,
3328 lpService
->lpDisplayName
,
3331 wcslen(lpService
->lpDisplayName
),
3334 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3335 lpStr
+= strlen(lpStr
) + 1;
3337 /* Copy service name */
3338 WideCharToMultiByte(CP_ACP
,
3340 lpService
->lpServiceName
,
3343 wcslen(lpService
->lpServiceName
),
3346 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3347 lpStr
+= strlen(lpStr
) + 1;
3352 *lpServicesReturned
= dwServicesReturned
;
3355 if (lpServicesArray
)
3356 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3358 RegCloseKey(hServicesKey
);
3360 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3367 DWORD
REnumServicesStatusA(
3368 handle_t BindingHandle
,
3369 SC_RPC_HANDLE hSCManager
,
3370 DWORD dwServiceType
,
3371 DWORD dwServiceState
,
3374 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3375 LPBOUNDED_DWORD_256K lpServicesReturned
,
3376 LPBOUNDED_DWORD_256K lpResumeHandle
)
3378 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3379 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3380 LPWSTR lpStringPtrW
;
3383 DWORD dwServiceCount
;
3385 DPRINT("REnumServicesStatusA() called\n");
3387 if ((dwBufSize
> 0) && (lpBuffer
))
3389 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3392 DPRINT1("Failed to allocate buffer!\n");
3393 return ERROR_NOT_ENOUGH_MEMORY
;
3397 dwError
= REnumServicesStatusW(BindingHandle
,
3401 (LPBYTE
)lpStatusPtrW
,
3407 /* if no services were returned then we are Done */
3408 if (*lpServicesReturned
== 0) goto Done
;
3410 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3411 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3412 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3413 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3414 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3416 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3418 /* Copy the service name */
3419 WideCharToMultiByte(CP_ACP
,
3424 wcslen(lpStringPtrW
),
3428 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3429 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3430 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3432 /* Copy the display name */
3433 WideCharToMultiByte(CP_ACP
,
3438 wcslen(lpStringPtrW
),
3442 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3443 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3444 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3446 /* Copy the status information */
3447 memcpy(&lpStatusPtrA
->ServiceStatus
,
3448 &lpStatusPtrW
->ServiceStatus
,
3449 sizeof(SERVICE_STATUS
));
3455 if (lpStatusPtrW
) HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3457 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3464 DWORD
ROpenSCManagerA(
3465 handle_t BindingHandle
,
3466 LPSTR lpMachineName
,
3467 LPSTR lpDatabaseName
,
3468 DWORD dwDesiredAccess
,
3469 LPSC_RPC_HANDLE lpScHandle
)
3471 UNICODE_STRING MachineName
;
3472 UNICODE_STRING DatabaseName
;
3475 DPRINT("ROpenSCManagerA() called\n");
3478 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3482 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3485 dwError
= ROpenSCManagerW(BindingHandle
,
3486 lpMachineName
? MachineName
.Buffer
: NULL
,
3487 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3492 RtlFreeUnicodeString(&MachineName
);
3495 RtlFreeUnicodeString(&DatabaseName
);
3502 DWORD
ROpenServiceA(
3503 handle_t BindingHandle
,
3504 SC_RPC_HANDLE hSCManager
,
3505 LPSTR lpServiceName
,
3506 DWORD dwDesiredAccess
,
3507 LPSC_RPC_HANDLE lpServiceHandle
)
3509 UNICODE_STRING ServiceName
;
3512 DPRINT("ROpenServiceA() called\n");
3515 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3518 dwError
= ROpenServiceW(BindingHandle
,
3520 lpServiceName
? ServiceName
.Buffer
: NULL
,
3525 RtlFreeUnicodeString(&ServiceName
);
3532 DWORD
RQueryServiceConfigA(
3533 handle_t BindingHandle
,
3534 SC_RPC_HANDLE hService
,
3535 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3537 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3539 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3540 DWORD dwError
= ERROR_SUCCESS
;
3541 PSERVICE_HANDLE hSvc
;
3542 PSERVICE lpService
= NULL
;
3543 HKEY hServiceKey
= NULL
;
3544 LPWSTR lpImagePath
= NULL
;
3545 LPWSTR lpServiceStartName
= NULL
;
3546 DWORD dwRequiredSize
;
3547 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3548 CHAR lpEmptyString
[]={0,0};
3551 DPRINT("RQueryServiceConfigA() called\n");
3554 return ERROR_SHUTDOWN_IN_PROGRESS
;
3556 hSvc
= (PSERVICE_HANDLE
)hService
;
3557 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3559 DPRINT1("Invalid handle tag!\n");
3560 return ERROR_INVALID_HANDLE
;
3563 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3564 SERVICE_QUERY_CONFIG
))
3566 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3567 return ERROR_ACCESS_DENIED
;
3570 lpService
= hSvc
->ServiceEntry
;
3571 if (lpService
== NULL
)
3573 DPRINT1("lpService == NULL!\n");
3574 return ERROR_INVALID_HANDLE
;
3577 /* FIXME: Lock the service database shared */
3579 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3582 if (dwError
!= ERROR_SUCCESS
)
3585 dwError
= ScmReadString(hServiceKey
,
3588 if (dwError
!= ERROR_SUCCESS
)
3591 ScmReadString(hServiceKey
,
3593 &lpServiceStartName
);
3595 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3597 if (lpImagePath
!= NULL
)
3598 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3600 dwRequiredSize
+= 2;
3602 if (lpService
->lpGroup
!= NULL
)
3603 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3605 dwRequiredSize
+= 2;
3607 /* FIXME: Add Dependencies length*/
3608 dwRequiredSize
+= 2;
3610 if (lpServiceStartName
!= NULL
)
3611 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3613 dwRequiredSize
+= 2;
3615 if (lpService
->lpDisplayName
!= NULL
)
3616 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3618 dwRequiredSize
+= 2;
3620 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3622 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3626 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3627 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3628 lpConfig
->dwStartType
= lpService
->dwStartType
;
3629 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3630 lpConfig
->dwTagId
= lpService
->dwTag
;
3632 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3634 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3639 WideCharToMultiByte(CP_ACP
,
3644 wcslen(lpImagePath
),
3650 strcpy(lpStr
, lpEmptyString
);
3653 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3654 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3656 if (lpService
->lpGroup
)
3658 WideCharToMultiByte(CP_ACP
,
3660 lpService
->lpGroup
->lpGroupName
,
3663 wcslen(lpService
->lpGroup
->lpGroupName
),
3669 strcpy(lpStr
, lpEmptyString
);
3672 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3673 lpStr
+= (strlen(lpStr
) + 1);
3675 /* FIXME: Append Dependencies */
3676 strcpy(lpStr
, lpEmptyString
);
3678 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3679 lpStr
+= (strlen(lpStr
) + 1);
3681 if (lpServiceStartName
)
3683 WideCharToMultiByte(CP_ACP
,
3688 wcslen(lpServiceStartName
),
3694 strcpy(lpStr
, lpEmptyString
);
3697 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3698 lpStr
+= (strlen(lpStr
) + 1);
3700 if (lpService
->lpDisplayName
)
3702 WideCharToMultiByte(CP_ACP
,
3704 lpService
->lpDisplayName
,
3707 wcslen(lpService
->lpDisplayName
),
3713 strcpy(lpStr
, lpEmptyString
);
3716 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3719 if (pcbBytesNeeded
!= NULL
)
3720 *pcbBytesNeeded
= dwRequiredSize
;
3723 if (lpImagePath
!= NULL
)
3724 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3726 if (lpServiceStartName
!= NULL
)
3727 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3729 if (hServiceKey
!= NULL
)
3730 RegCloseKey(hServiceKey
);
3732 /* FIXME: Unlock the service database */
3734 DPRINT("RQueryServiceConfigA() done\n");
3741 DWORD
RQueryServiceLockStatusA(
3742 handle_t BindingHandle
,
3743 SC_RPC_HANDLE hSCManager
,
3744 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3746 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3749 return ERROR_CALL_NOT_IMPLEMENTED
;
3754 DWORD
RStartServiceA(
3755 handle_t BindingHandle
,
3756 SC_RPC_HANDLE hService
,
3758 LPSTRING_PTRSA argv
)
3760 DWORD dwError
= ERROR_SUCCESS
;
3761 PSERVICE_HANDLE hSvc
;
3762 PSERVICE lpService
= NULL
;
3764 DPRINT1("RStartServiceA() called\n");
3767 return ERROR_SHUTDOWN_IN_PROGRESS
;
3769 hSvc
= (PSERVICE_HANDLE
)hService
;
3770 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3772 DPRINT1("Invalid handle tag!\n");
3773 return ERROR_INVALID_HANDLE
;
3776 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3779 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3780 return ERROR_ACCESS_DENIED
;
3783 lpService
= hSvc
->ServiceEntry
;
3784 if (lpService
== NULL
)
3786 DPRINT1("lpService == NULL!\n");
3787 return ERROR_INVALID_HANDLE
;
3790 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3791 return ERROR_SERVICE_DISABLED
;
3793 if (lpService
->bDeleted
)
3794 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3796 /* FIXME: Convert argument vector to Unicode */
3798 /* Start the service */
3799 dwError
= ScmStartService(lpService
, 0, NULL
);
3801 /* FIXME: Free argument vector */
3808 DWORD
RGetServiceDisplayNameA(
3809 handle_t BindingHandle
,
3810 SC_RPC_HANDLE hSCManager
,
3811 LPSTR lpServiceName
,
3812 LPSTR lpDisplayName
,
3813 LPBOUNDED_DWORD_4K lpcchBuffer
)
3815 // PMANAGER_HANDLE hManager;
3819 LPWSTR lpServiceNameW
;
3821 DPRINT("RGetServiceDisplayNameA() called\n");
3822 DPRINT("hSCManager = %p\n", hSCManager
);
3823 DPRINT("lpServiceName: %s\n", lpServiceName
);
3824 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3825 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3827 // hManager = (PMANAGER_HANDLE)hSCManager;
3828 // if (hManager->Handle.Tag != MANAGER_TAG)
3830 // DPRINT1("Invalid manager handle!\n");
3831 // return ERROR_INVALID_HANDLE;
3834 dwLength
= strlen(lpServiceName
) + 1;
3835 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3837 dwLength
* sizeof(WCHAR
));
3838 if (!lpServiceNameW
)
3839 return ERROR_NOT_ENOUGH_MEMORY
;
3841 MultiByteToWideChar(CP_ACP
,
3844 strlen(lpServiceName
),
3848 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3850 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3852 if (lpService
== NULL
)
3854 DPRINT1("Could not find a service!\n");
3856 /* If the service could not be found and lpcchBuffer is 0, windows
3857 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3858 if (*lpcchBuffer
== 0)
3861 *lpDisplayName
= '\0';
3863 return ERROR_SERVICE_DOES_NOT_EXIST
;
3866 if (!lpService
->lpDisplayName
)
3868 dwLength
= wcslen(lpService
->lpServiceName
);
3869 if (lpServiceName
!= NULL
&&
3870 *lpcchBuffer
> dwLength
)
3872 WideCharToMultiByte(CP_ACP
,
3874 lpService
->lpServiceName
,
3875 wcslen(lpService
->lpServiceName
),
3880 return ERROR_SUCCESS
;
3885 dwLength
= wcslen(lpService
->lpDisplayName
);
3886 if (lpDisplayName
!= NULL
&&
3887 *lpcchBuffer
> dwLength
)
3889 WideCharToMultiByte(CP_ACP
,
3891 lpService
->lpDisplayName
,
3892 wcslen(lpService
->lpDisplayName
),
3897 return ERROR_SUCCESS
;
3901 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3903 *lpcchBuffer
= dwLength
* 2;
3910 DWORD
RGetServiceKeyNameA(
3911 handle_t BindingHandle
,
3912 SC_RPC_HANDLE hSCManager
,
3913 LPSTR lpDisplayName
,
3914 LPSTR lpServiceName
,
3915 LPBOUNDED_DWORD_4K lpcchBuffer
)
3920 LPWSTR lpDisplayNameW
;
3922 DPRINT("RGetServiceKeyNameA() called\n");
3923 DPRINT("hSCManager = %p\n", hSCManager
);
3924 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3925 DPRINT("lpServiceName: %p\n", lpServiceName
);
3926 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3928 dwLength
= strlen(lpDisplayName
) + 1;
3929 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3931 dwLength
* sizeof(WCHAR
));
3932 if (!lpDisplayNameW
)
3933 return ERROR_NOT_ENOUGH_MEMORY
;
3935 MultiByteToWideChar(CP_ACP
,
3938 strlen(lpDisplayName
),
3942 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
3944 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3946 if (lpService
== NULL
)
3948 DPRINT1("Could not find the service!\n");
3950 /* If the service could not be found and lpcchBuffer is 0,
3951 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
3952 if (*lpcchBuffer
== 0)
3955 *lpServiceName
= '\0';
3958 return ERROR_SERVICE_DOES_NOT_EXIST
;
3961 dwLength
= wcslen(lpService
->lpServiceName
);
3962 if (lpService
!= NULL
&&
3963 *lpcchBuffer
> dwLength
)
3965 WideCharToMultiByte(CP_ACP
,
3967 lpService
->lpServiceName
,
3968 wcslen(lpService
->lpServiceName
),
3973 return ERROR_SUCCESS
;
3976 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3978 *lpcchBuffer
= dwLength
* 2;
3985 DWORD
RI_ScGetCurrentGroupStateW(
3986 handle_t BindingHandle
,
3987 SC_RPC_HANDLE hSCManager
,
3988 LPWSTR lpLoadOrderGroup
,
3992 return ERROR_CALL_NOT_IMPLEMENTED
;
3997 DWORD
REnumServiceGroupW(
3998 handle_t BindingHandle
,
3999 SC_RPC_HANDLE hSCManager
,
4000 DWORD dwServiceType
,
4001 DWORD dwServiceState
,
4004 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4005 LPBOUNDED_DWORD_256K lpServicesReturned
,
4006 LPBOUNDED_DWORD_256K lpResumeIndex
,
4007 LPCWSTR pszGroupName
)
4010 return ERROR_CALL_NOT_IMPLEMENTED
;
4015 DWORD
RChangeServiceConfig2A(
4016 handle_t BindingHandle
,
4017 SC_RPC_HANDLE hService
,
4018 SC_RPC_CONFIG_INFOA Info
)
4021 return ERROR_CALL_NOT_IMPLEMENTED
;
4026 DWORD
RChangeServiceConfig2W(
4027 handle_t BindingHandle
,
4028 SC_RPC_HANDLE hService
,
4029 SC_RPC_CONFIG_INFOW Info
)
4031 DWORD dwError
= ERROR_SUCCESS
;
4032 PSERVICE_HANDLE hSvc
;
4033 PSERVICE lpService
= NULL
;
4034 HKEY hServiceKey
= NULL
;
4036 DPRINT("RChangeServiceConfig2W() called\n");
4037 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4040 return ERROR_SHUTDOWN_IN_PROGRESS
;
4042 hSvc
= (PSERVICE_HANDLE
)hService
;
4043 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4045 DPRINT1("Invalid handle tag!\n");
4046 return ERROR_INVALID_HANDLE
;
4049 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4050 SERVICE_CHANGE_CONFIG
))
4052 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4053 return ERROR_ACCESS_DENIED
;
4056 lpService
= hSvc
->ServiceEntry
;
4057 if (lpService
== NULL
)
4059 DPRINT1("lpService == NULL!\n");
4060 return ERROR_INVALID_HANDLE
;
4063 /* FIXME: Lock database exclusively */
4065 if (lpService
->bDeleted
)
4067 /* FIXME: Unlock database */
4068 DPRINT1("The service has already been marked for delete!\n");
4069 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4072 /* Open the service key */
4073 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4076 if (dwError
!= ERROR_SUCCESS
)
4079 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4081 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4083 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
4084 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4086 if (lpServiceDescription
!= NULL
&&
4087 lpServiceDescription
->lpDescription
!= NULL
)
4089 RegSetValueExW(hServiceKey
,
4093 (LPBYTE
)lpServiceDescription
->lpDescription
,
4094 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4096 if (dwError
!= ERROR_SUCCESS
)
4100 else if (Info
.dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4103 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4108 /* FIXME: Unlock database */
4109 if (hServiceKey
!= NULL
)
4110 RegCloseKey(hServiceKey
);
4112 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4119 DWORD
RQueryServiceConfig2A(
4120 handle_t BindingHandle
,
4121 SC_RPC_HANDLE hService
,
4125 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4127 DWORD dwError
= ERROR_SUCCESS
;
4128 PSERVICE_HANDLE hSvc
;
4129 PSERVICE lpService
= NULL
;
4130 HKEY hServiceKey
= NULL
;
4131 DWORD dwRequiredSize
;
4132 LPWSTR lpDescriptionW
= NULL
;
4133 LPSTR lpDescription
= NULL
;
4135 DPRINT("RQueryServiceConfig2W() called\n");
4138 return ERROR_INVALID_ADDRESS
;
4141 return ERROR_SHUTDOWN_IN_PROGRESS
;
4143 hSvc
= (PSERVICE_HANDLE
)hService
;
4144 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4146 DPRINT1("Invalid handle tag!\n");
4147 return ERROR_INVALID_HANDLE
;
4150 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4151 SERVICE_QUERY_CONFIG
))
4153 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4154 return ERROR_ACCESS_DENIED
;
4157 lpService
= hSvc
->ServiceEntry
;
4158 if (lpService
== NULL
)
4160 DPRINT1("lpService == NULL!\n");
4161 return ERROR_INVALID_HANDLE
;
4164 /* FIXME: Lock the service database shared */
4166 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4169 if (dwError
!= ERROR_SUCCESS
)
4172 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4174 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4177 dwError
= ScmReadString(hServiceKey
,
4180 if (dwError
!= ERROR_SUCCESS
)
4183 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONA
) + ((wcslen(lpDescriptionW
) + 1));
4185 if (cbBufSize
< dwRequiredSize
)
4187 *pcbBytesNeeded
= dwRequiredSize
;
4188 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4192 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4194 WideCharToMultiByte(CP_ACP
,
4199 wcslen(lpDescriptionW
),
4202 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4204 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4207 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4212 if (lpDescription
!= NULL
)
4213 HeapFree(GetProcessHeap(), 0, lpDescription
);
4215 if (hServiceKey
!= NULL
)
4216 RegCloseKey(hServiceKey
);
4218 /* FIXME: Unlock database */
4220 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4227 DWORD
RQueryServiceConfig2W(
4228 handle_t BindingHandle
,
4229 SC_RPC_HANDLE hService
,
4233 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4235 DWORD dwError
= ERROR_SUCCESS
;
4236 PSERVICE_HANDLE hSvc
;
4237 PSERVICE lpService
= NULL
;
4238 HKEY hServiceKey
= NULL
;
4239 DWORD dwRequiredSize
;
4240 LPWSTR lpDescription
= NULL
;
4242 DPRINT("RQueryServiceConfig2W() called\n");
4245 return ERROR_INVALID_ADDRESS
;
4248 return ERROR_SHUTDOWN_IN_PROGRESS
;
4250 hSvc
= (PSERVICE_HANDLE
)hService
;
4251 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4253 DPRINT1("Invalid handle tag!\n");
4254 return ERROR_INVALID_HANDLE
;
4257 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4258 SERVICE_QUERY_CONFIG
))
4260 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4261 return ERROR_ACCESS_DENIED
;
4264 lpService
= hSvc
->ServiceEntry
;
4265 if (lpService
== NULL
)
4267 DPRINT1("lpService == NULL!\n");
4268 return ERROR_INVALID_HANDLE
;
4271 /* FIXME: Lock the service database shared */
4273 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4276 if (dwError
!= ERROR_SUCCESS
)
4279 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4281 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4284 dwError
= ScmReadString(hServiceKey
,
4287 if (dwError
!= ERROR_SUCCESS
)
4290 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4292 if (cbBufSize
< dwRequiredSize
)
4294 *pcbBytesNeeded
= dwRequiredSize
;
4295 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4299 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4300 wcscpy(lpStr
, lpDescription
);
4301 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4303 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4306 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4311 if (lpDescription
!= NULL
)
4312 HeapFree(GetProcessHeap(), 0, lpDescription
);
4314 if (hServiceKey
!= NULL
)
4315 RegCloseKey(hServiceKey
);
4317 /* FIXME: Unlock database */
4319 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4326 DWORD
RQueryServiceStatusEx(
4327 handle_t BindingHandle
,
4328 SC_RPC_HANDLE hService
,
4329 SC_STATUS_TYPE InfoLevel
,
4332 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4334 LPSERVICE_STATUS_PROCESS lpStatus
;
4335 PSERVICE_HANDLE hSvc
;
4338 DPRINT("RQueryServiceStatusEx() called\n");
4341 return ERROR_SHUTDOWN_IN_PROGRESS
;
4343 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4344 return ERROR_INVALID_LEVEL
;
4346 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4348 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4349 return ERROR_INSUFFICIENT_BUFFER
;
4351 hSvc
= (PSERVICE_HANDLE
)hService
;
4352 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4354 DPRINT1("Invalid handle tag!\n");
4355 return ERROR_INVALID_HANDLE
;
4358 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4359 SERVICE_QUERY_STATUS
))
4361 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4362 return ERROR_ACCESS_DENIED
;
4365 lpService
= hSvc
->ServiceEntry
;
4366 if (lpService
== NULL
)
4368 DPRINT1("lpService == NULL!\n");
4369 return ERROR_INVALID_HANDLE
;
4372 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4374 /* Return service status information */
4375 RtlCopyMemory(lpStatus
,
4377 sizeof(SERVICE_STATUS
));
4379 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4380 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4382 return ERROR_SUCCESS
;
4387 DWORD
REnumServicesStatusExA(
4388 handle_t BindingHandle
,
4389 SC_RPC_HANDLE hSCManager
,
4390 SC_ENUM_TYPE InfoLevel
,
4391 DWORD dwServiceType
,
4392 DWORD dwServiceState
,
4395 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4396 LPBOUNDED_DWORD_256K lpServicesReturned
,
4397 LPBOUNDED_DWORD_256K lpResumeIndex
,
4398 LPCSTR pszGroupName
)
4400 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4401 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4402 LPWSTR lpStringPtrW
;
4404 LPWSTR pszGroupNameW
= NULL
;
4406 DWORD dwServiceCount
;
4408 DPRINT("REnumServicesStatusExA() called\n");
4412 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4415 DPRINT1("Failed to allocate buffer!\n");
4416 return ERROR_NOT_ENOUGH_MEMORY
;
4418 MultiByteToWideChar(CP_ACP
,
4423 strlen(pszGroupName
) + 1);
4426 if ((cbBufSize
> 0) && (lpBuffer
))
4428 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4431 DPRINT1("Failed to allocate buffer!\n");
4432 return ERROR_NOT_ENOUGH_MEMORY
;
4436 dwError
= REnumServicesStatusExW(BindingHandle
,
4441 (LPBYTE
)lpStatusPtrW
,
4448 /* if no services were returned then we are Done */
4449 if (*lpServicesReturned
== 0) goto Done
;
4451 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4452 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4453 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4454 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4455 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4457 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4459 /* Copy the service name */
4460 WideCharToMultiByte(CP_ACP
,
4465 wcslen(lpStringPtrW
),
4469 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4470 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4471 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4473 /* Copy the display name */
4474 WideCharToMultiByte(CP_ACP
,
4479 wcslen(lpStringPtrW
),
4483 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4484 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4485 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4487 /* Copy the status information */
4488 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4489 &lpStatusPtrW
->ServiceStatusProcess
,
4490 sizeof(SERVICE_STATUS
));
4492 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4493 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4498 if (pszGroupNameW
) HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4500 if (lpStatusPtrW
) HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4502 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4509 DWORD
REnumServicesStatusExW(
4510 handle_t BindingHandle
,
4511 SC_RPC_HANDLE hSCManager
,
4512 SC_ENUM_TYPE InfoLevel
,
4513 DWORD dwServiceType
,
4514 DWORD dwServiceState
,
4517 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4518 LPBOUNDED_DWORD_256K lpServicesReturned
,
4519 LPBOUNDED_DWORD_256K lpResumeIndex
,
4520 LPCWSTR pszGroupName
)
4522 PMANAGER_HANDLE hManager
;
4524 DWORD dwError
= ERROR_SUCCESS
;
4525 PLIST_ENTRY ServiceEntry
;
4526 PSERVICE CurrentService
;
4528 DWORD dwRequiredSize
;
4529 DWORD dwServiceCount
;
4531 DWORD dwLastResumeCount
= 0;
4532 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4535 DPRINT("REnumServicesStatusExW() called\n");
4538 return ERROR_SHUTDOWN_IN_PROGRESS
;
4540 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4541 return ERROR_INVALID_LEVEL
;
4543 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4544 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4546 DPRINT1("Invalid manager handle!\n");
4547 return ERROR_INVALID_HANDLE
;
4550 *pcbBytesNeeded
= 0;
4551 *lpServicesReturned
= 0;
4553 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4555 DPRINT1("Not a valid Service Type!\n");
4556 return ERROR_INVALID_PARAMETER
;
4559 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4561 DPRINT1("Not a valid Service State!\n");
4562 return ERROR_INVALID_PARAMETER
;
4565 /* Check access rights */
4566 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4567 SC_MANAGER_ENUMERATE_SERVICE
))
4569 DPRINT1("Insufficient access rights! 0x%lx\n",
4570 hManager
->Handle
.DesiredAccess
);
4571 return ERROR_ACCESS_DENIED
;
4574 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4576 /* Lock the service list shared */
4578 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4579 if (lpService
== NULL
)
4581 dwError
= ERROR_SUCCESS
;
4588 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4589 ServiceEntry
!= &ServiceListHead
;
4590 ServiceEntry
= ServiceEntry
->Flink
)
4592 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4596 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4599 dwState
= SERVICE_ACTIVE
;
4600 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4601 dwState
= SERVICE_INACTIVE
;
4603 if ((dwState
& dwServiceState
) == 0)
4608 if (*pszGroupName
== 0)
4610 if (CurrentService
->lpGroup
!= NULL
)
4615 if ((CurrentService
->lpGroup
== NULL
) ||
4616 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4621 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4622 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4623 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4625 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4627 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4628 dwRequiredSize
+= dwSize
;
4630 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4634 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4640 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4641 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4644 ServiceEntry
!= &ServiceListHead
;
4645 ServiceEntry
= ServiceEntry
->Flink
)
4647 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4651 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4654 dwState
= SERVICE_ACTIVE
;
4655 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4656 dwState
= SERVICE_INACTIVE
;
4658 if ((dwState
& dwServiceState
) == 0)
4663 if (*pszGroupName
== 0)
4665 if (CurrentService
->lpGroup
!= NULL
)
4670 if ((CurrentService
->lpGroup
== NULL
) ||
4671 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4676 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4677 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4678 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4680 dwError
= ERROR_MORE_DATA
;
4683 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4685 if (lpResumeIndex
) *lpResumeIndex
= dwLastResumeCount
;
4686 *lpServicesReturned
= dwServiceCount
;
4687 *pcbBytesNeeded
= dwRequiredSize
;
4689 /* If there was no services that matched */
4690 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
4692 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
4696 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
4697 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4698 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4701 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4702 ServiceEntry
!= &ServiceListHead
;
4703 ServiceEntry
= ServiceEntry
->Flink
)
4705 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4709 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4712 dwState
= SERVICE_ACTIVE
;
4713 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4714 dwState
= SERVICE_INACTIVE
;
4716 if ((dwState
& dwServiceState
) == 0)
4721 if (*pszGroupName
== 0)
4723 if (CurrentService
->lpGroup
!= NULL
)
4728 if ((CurrentService
->lpGroup
== NULL
) ||
4729 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4734 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4735 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4736 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4738 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4740 /* Copy the service name */
4742 CurrentService
->lpServiceName
);
4743 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4744 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4746 /* Copy the display name */
4748 CurrentService
->lpDisplayName
);
4749 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4750 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4752 /* Copy the status information */
4753 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
4754 &CurrentService
->Status
,
4755 sizeof(SERVICE_STATUS
));
4756 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
4757 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4760 dwRequiredSize
+= dwSize
;
4770 *pcbBytesNeeded
= 0;
4771 if (lpResumeIndex
) *lpResumeIndex
= 0;
4775 /* Unlock the service list */
4777 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
4784 DWORD
RSendTSMessage(
4785 handle_t BindingHandle
)
4788 return ERROR_CALL_NOT_IMPLEMENTED
;
4793 DWORD
RCreateServiceWOW64A(
4794 handle_t BindingHandle
,
4795 LPSTR lpServiceName
,
4796 LPSTR lpDisplayName
,
4797 DWORD dwDesiredAccess
,
4798 DWORD dwServiceType
,
4800 DWORD dwErrorControl
,
4801 LPSTR lpBinaryPathName
,
4802 LPSTR lpLoadOrderGroup
,
4804 LPBYTE lpDependencies
,
4806 LPSTR lpServiceStartName
,
4809 LPSC_RPC_HANDLE lpServiceHandle
)
4812 return ERROR_CALL_NOT_IMPLEMENTED
;
4817 DWORD
RCreateServiceWOW64W(
4818 handle_t BindingHandle
,
4819 LPWSTR lpServiceName
,
4820 LPWSTR lpDisplayName
,
4821 DWORD dwDesiredAccess
,
4822 DWORD dwServiceType
,
4824 DWORD dwErrorControl
,
4825 LPWSTR lpBinaryPathName
,
4826 LPWSTR lpLoadOrderGroup
,
4828 LPBYTE lpDependencies
,
4830 LPWSTR lpServiceStartName
,
4833 LPSC_RPC_HANDLE lpServiceHandle
)
4836 return ERROR_CALL_NOT_IMPLEMENTED
;
4841 DWORD
RQueryServiceTagInfo(
4842 handle_t BindingHandle
)
4845 return ERROR_CALL_NOT_IMPLEMENTED
;
4850 DWORD
RNotifyServiceStatusChange(
4851 handle_t BindingHandle
,
4852 SC_RPC_HANDLE hService
,
4853 SC_RPC_NOTIFY_PARAMS NotifyParams
,
4854 GUID
*pClientProcessGuid
,
4855 GUID
*pSCMProcessGuid
,
4856 PBOOL pfCreateRemoteQueue
,
4857 LPSC_NOTIFY_RPC_HANDLE phNotify
)
4860 return ERROR_CALL_NOT_IMPLEMENTED
;
4865 DWORD
RGetNotifyResults(
4866 handle_t BindingHandle
,
4867 SC_NOTIFY_RPC_HANDLE hNotify
,
4868 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
4871 return ERROR_CALL_NOT_IMPLEMENTED
;
4876 DWORD
RCloseNotifyHandle(
4877 handle_t BindingHandle
,
4878 LPSC_NOTIFY_RPC_HANDLE phNotify
,
4882 return ERROR_CALL_NOT_IMPLEMENTED
;
4887 DWORD
RControlServiceExA(
4888 handle_t BindingHandle
,
4889 SC_RPC_HANDLE hService
,
4894 return ERROR_CALL_NOT_IMPLEMENTED
;
4899 DWORD
RControlServiceExW(
4900 handle_t BindingHandle
,
4901 SC_RPC_HANDLE hService
,
4906 return ERROR_CALL_NOT_IMPLEMENTED
;
4911 DWORD
RSendPnPMessage(
4912 handle_t BindingHandle
)
4915 return ERROR_CALL_NOT_IMPLEMENTED
;
4920 DWORD
RValidatePnPService(
4921 handle_t BindingHandle
)
4924 return ERROR_CALL_NOT_IMPLEMENTED
;
4929 DWORD
ROpenServiceStatusHandle(
4930 handle_t BindingHandle
)
4933 return ERROR_CALL_NOT_IMPLEMENTED
;
4939 handle_t BindingHandle
)
4942 return ERROR_CALL_NOT_IMPLEMENTED
;
4946 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
4948 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
4952 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
4954 HeapFree(GetProcessHeap(), 0, ptr
);
4958 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
4963 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
4968 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)