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 LPSC_RPC_HANDLE hSCObject
)
405 PMANAGER_HANDLE hManager
;
406 PSERVICE_HANDLE hService
;
410 DWORD pcbBytesNeeded
= 0;
411 DWORD dwServicesReturned
= 0;
413 DPRINT("RCloseServiceHandle() called\n");
415 DPRINT("hSCObject = %p\n", *hSCObject
);
418 return ERROR_INVALID_HANDLE
;
420 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
421 hService
= (PSERVICE_HANDLE
)*hSCObject
;
422 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
424 DPRINT("Found manager handle\n");
426 hManager
->Handle
.RefCount
--;
427 if (hManager
->Handle
.RefCount
== 0)
429 /* FIXME: add handle cleanup code */
431 HeapFree(GetProcessHeap(), 0, hManager
);
435 DPRINT("RCloseServiceHandle() done\n");
436 return ERROR_SUCCESS
;
438 else if (hService
->Handle
.Tag
== SERVICE_TAG
)
440 DPRINT("Found service handle\n");
442 /* Get the pointer to the service record */
443 lpService
= hService
->ServiceEntry
;
445 ASSERT(hService
->Handle
.RefCount
> 0);
447 hService
->Handle
.RefCount
--;
448 if (hService
->Handle
.RefCount
== 0)
450 /* FIXME: add handle cleanup code */
452 /* Free the handle */
453 HeapFree(GetProcessHeap(), 0, hService
);
457 ASSERT(lpService
->dwRefCount
> 0);
459 lpService
->dwRefCount
--;
460 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
461 lpService
->dwRefCount
);
463 if (lpService
->dwRefCount
== 0)
465 /* If this service has been marked for deletion */
466 if (lpService
->bDeleted
)
468 /* Open the Services Reg key */
469 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
470 L
"System\\CurrentControlSet\\Services",
472 KEY_SET_VALUE
| KEY_READ
,
474 if (dwError
!= ERROR_SUCCESS
)
476 DPRINT1("Failed to open services key\n");
480 /* Call the internal function with NULL, just to get bytes we need */
481 Int_EnumDependentServicesW(hServicesKey
,
486 &dwServicesReturned
);
488 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
491 DPRINT1("Deletion failed due to running dependencies.\n");
492 RegCloseKey(hServicesKey
);
493 return ERROR_SUCCESS
;
496 /* There are no references and no runnning dependencies,
497 it is now safe to delete the service */
499 /* Delete the Service Key */
500 dwError
= RegDeleteKey(hServicesKey
,
501 lpService
->lpServiceName
);
503 RegCloseKey(hServicesKey
);
505 if (dwError
!= ERROR_SUCCESS
)
507 DPRINT1("Failed to Delete the Service Registry key\n");
511 /* Delete the Service */
512 ScmDeleteServiceRecord(lpService
);
516 DPRINT("RCloseServiceHandle() done\n");
517 return ERROR_SUCCESS
;
520 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
522 return ERROR_INVALID_HANDLE
;
527 DWORD
RControlService(
528 SC_RPC_HANDLE hService
,
530 LPSERVICE_STATUS lpServiceStatus
)
532 PSERVICE_HANDLE hSvc
;
534 ACCESS_MASK DesiredAccess
;
535 DWORD dwError
= ERROR_SUCCESS
;
536 DWORD pcbBytesNeeded
= 0;
537 DWORD dwServicesReturned
= 0;
538 HKEY hServicesKey
= NULL
;
540 DPRINT("RControlService() called\n");
543 return ERROR_SHUTDOWN_IN_PROGRESS
;
545 /* Check the service handle */
546 hSvc
= (PSERVICE_HANDLE
)hService
;
547 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
549 DPRINT1("Invalid handle tag!\n");
550 return ERROR_INVALID_HANDLE
;
553 /* Check the service entry point */
554 lpService
= hSvc
->ServiceEntry
;
555 if (lpService
== NULL
)
557 DPRINT1("lpService == NULL!\n");
558 return ERROR_INVALID_HANDLE
;
561 /* Check access rights */
564 case SERVICE_CONTROL_STOP
:
565 DesiredAccess
= SERVICE_STOP
;
568 case SERVICE_CONTROL_PAUSE
:
569 case SERVICE_CONTROL_CONTINUE
:
570 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
573 case SERVICE_INTERROGATE
:
574 DesiredAccess
= SERVICE_INTERROGATE
;
578 if (dwControl
>= 128 && dwControl
<= 255)
579 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
581 DesiredAccess
= SERVICE_QUERY_CONFIG
|
582 SERVICE_CHANGE_CONFIG
|
583 SERVICE_QUERY_STATUS
|
585 SERVICE_PAUSE_CONTINUE
;
589 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
591 return ERROR_ACCESS_DENIED
;
593 if (dwControl
== SERVICE_CONTROL_STOP
)
595 /* Check if the service has dependencies running as windows
596 doesn't stop a service that does */
598 /* Open the Services Reg key */
599 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
600 L
"System\\CurrentControlSet\\Services",
604 if (dwError
!= ERROR_SUCCESS
)
606 DPRINT1("Failed to open services key\n");
610 /* Call the internal function with NULL, just to get bytes we need */
611 Int_EnumDependentServicesW(hServicesKey
,
616 &dwServicesReturned
);
618 RegCloseKey(hServicesKey
);
620 /* If pcbBytesNeeded is not zero then there are services running that
621 are dependent on this service */
622 if (pcbBytesNeeded
!= 0)
624 DPRINT("Service has running dependencies. Failed to stop service.\n");
625 return ERROR_DEPENDENT_SERVICES_RUNNING
;
629 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
631 /* Send control code to the driver */
632 dwError
= ScmControlDriver(lpService
,
638 /* Send control code to the service */
639 dwError
= ScmControlService(lpService
,
644 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
645 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
647 /* Return service status information */
648 RtlCopyMemory(lpServiceStatus
,
650 sizeof(SERVICE_STATUS
));
657 DWORD
RDeleteService(
658 SC_RPC_HANDLE hService
)
660 PSERVICE_HANDLE hSvc
;
664 DPRINT("RDeleteService() called\n");
667 return ERROR_SHUTDOWN_IN_PROGRESS
;
669 hSvc
= (PSERVICE_HANDLE
)hService
;
670 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
671 return ERROR_INVALID_HANDLE
;
673 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
675 return ERROR_ACCESS_DENIED
;
677 lpService
= hSvc
->ServiceEntry
;
678 if (lpService
== NULL
)
680 DPRINT1("lpService == NULL!\n");
681 return ERROR_INVALID_HANDLE
;
684 /* FIXME: Acquire service database lock exclusively */
686 if (lpService
->bDeleted
)
688 DPRINT1("The service has already been marked for delete!\n");
689 return ERROR_SERVICE_MARKED_FOR_DELETE
;
692 /* Mark service for delete */
693 lpService
->bDeleted
= TRUE
;
695 dwError
= ScmMarkServiceForDelete(lpService
);
697 /* FIXME: Release service database lock */
699 DPRINT("RDeleteService() done\n");
706 DWORD
RLockServiceDatabase(
707 SC_RPC_HANDLE hSCManager
,
708 LPSC_RPC_LOCK lpLock
)
710 PMANAGER_HANDLE hMgr
;
712 DPRINT("RLockServiceDatabase() called\n");
716 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
717 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
718 return ERROR_INVALID_HANDLE
;
720 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
722 return ERROR_ACCESS_DENIED
;
724 // return ScmLockDatabase(0, hMgr->0xC, hLock);
726 /* FIXME: Lock the database */
727 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
729 return ERROR_SUCCESS
;
734 DWORD
RQueryServiceObjectSecurity(
735 SC_RPC_HANDLE hService
,
736 SECURITY_INFORMATION dwSecurityInformation
,
737 LPBYTE lpSecurityDescriptor
,
739 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
742 PSERVICE_HANDLE hSvc
;
744 ULONG DesiredAccess
= 0;
749 DPRINT("RQueryServiceObjectSecurity() called\n");
751 hSvc
= (PSERVICE_HANDLE
)hService
;
752 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
754 DPRINT1("Invalid handle tag!\n");
755 return ERROR_INVALID_HANDLE
;
758 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
759 GROUP_SECURITY_INFORMATION
||
760 OWNER_SECURITY_INFORMATION
))
761 DesiredAccess
|= READ_CONTROL
;
763 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
764 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
766 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
769 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
770 return ERROR_ACCESS_DENIED
;
773 lpService
= hSvc
->ServiceEntry
;
774 if (lpService
== NULL
)
776 DPRINT1("lpService == NULL!\n");
777 return ERROR_INVALID_HANDLE
;
780 /* FIXME: Lock the service list */
782 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
783 dwSecurityInformation
,
784 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
785 dwSecuityDescriptorSize
,
788 /* FIXME: Unlock the service list */
790 if (NT_SUCCESS(Status
))
792 *pcbBytesNeeded
= dwBytesNeeded
;
793 dwError
= STATUS_SUCCESS
;
795 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
797 *pcbBytesNeeded
= dwBytesNeeded
;
798 dwError
= ERROR_INSUFFICIENT_BUFFER
;
800 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
802 dwError
= ERROR_GEN_FAILURE
;
806 dwError
= RtlNtStatusToDosError(Status
);
812 return ERROR_CALL_NOT_IMPLEMENTED
;
817 DWORD
RSetServiceObjectSecurity(
818 SC_RPC_HANDLE hService
,
819 DWORD dwSecurityInformation
,
820 LPBYTE lpSecurityDescriptor
,
821 DWORD dwSecuityDescriptorSize
)
823 PSERVICE_HANDLE hSvc
;
825 ULONG DesiredAccess
= 0;
826 HANDLE hToken
= NULL
;
831 DPRINT1("RSetServiceObjectSecurity() called\n");
833 hSvc
= (PSERVICE_HANDLE
)hService
;
834 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
836 DPRINT1("Invalid handle tag!\n");
837 return ERROR_INVALID_HANDLE
;
840 if (dwSecurityInformation
== 0 ||
841 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
842 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
843 return ERROR_INVALID_PARAMETER
;
845 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
846 return ERROR_INVALID_PARAMETER
;
848 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
849 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
851 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
852 DesiredAccess
|= WRITE_DAC
;
854 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
855 DesiredAccess
|= WRITE_OWNER
;
857 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
858 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
859 return ERROR_INVALID_PARAMETER
;
861 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
862 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
863 return ERROR_INVALID_PARAMETER
;
865 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
868 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
869 return ERROR_ACCESS_DENIED
;
872 lpService
= hSvc
->ServiceEntry
;
873 if (lpService
== NULL
)
875 DPRINT1("lpService == NULL!\n");
876 return ERROR_INVALID_HANDLE
;
879 if (lpService
->bDeleted
)
880 return ERROR_SERVICE_MARKED_FOR_DELETE
;
882 RpcImpersonateClient(NULL
);
884 Status
= NtOpenThreadToken(NtCurrentThread(),
888 if (!NT_SUCCESS(Status
))
889 return RtlNtStatusToDosError(Status
);
893 /* FIXME: Lock service database */
896 Status
= RtlSetSecurityObject(dwSecurityInformation
,
897 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
898 &lpService
->lpSecurityDescriptor
,
901 if (!NT_SUCCESS(Status
))
903 dwError
= RtlNtStatusToDosError(Status
);
908 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
909 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
911 if (dwError
!= ERROR_SUCCESS
)
915 dwError
= ERROR_SUCCESS
;
916 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
917 // lpService->lpSecurityDescriptor);
919 RegFlushKey(hServiceKey
);
920 RegCloseKey(hServiceKey
);
927 /* FIXME: Unlock service database */
929 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
936 DWORD
RQueryServiceStatus(
937 SC_RPC_HANDLE hService
,
938 LPSERVICE_STATUS lpServiceStatus
)
940 PSERVICE_HANDLE hSvc
;
943 DPRINT("RQueryServiceStatus() called\n");
946 return ERROR_SHUTDOWN_IN_PROGRESS
;
948 hSvc
= (PSERVICE_HANDLE
)hService
;
949 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
951 DPRINT1("Invalid handle tag!\n");
952 return ERROR_INVALID_HANDLE
;
955 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
956 SERVICE_QUERY_STATUS
))
958 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
959 return ERROR_ACCESS_DENIED
;
962 lpService
= hSvc
->ServiceEntry
;
963 if (lpService
== NULL
)
965 DPRINT1("lpService == NULL!\n");
966 return ERROR_INVALID_HANDLE
;
969 /* Return service status information */
970 RtlCopyMemory(lpServiceStatus
,
972 sizeof(SERVICE_STATUS
));
974 return ERROR_SUCCESS
;
979 ScmIsValidServiceState(DWORD dwCurrentState
)
981 switch (dwCurrentState
)
983 case SERVICE_STOPPED
:
984 case SERVICE_START_PENDING
:
985 case SERVICE_STOP_PENDING
:
986 case SERVICE_RUNNING
:
987 case SERVICE_CONTINUE_PENDING
:
988 case SERVICE_PAUSE_PENDING
:
999 DWORD
RSetServiceStatus(
1000 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1001 LPSERVICE_STATUS lpServiceStatus
)
1005 DPRINT("RSetServiceStatus() called\n");
1006 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1007 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1008 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1009 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1010 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1011 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1012 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1013 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1015 if (hServiceStatus
== 0)
1017 DPRINT1("hServiceStatus == NULL!\n");
1018 return ERROR_INVALID_HANDLE
;
1021 lpService
= ScmGetServiceEntryByClientHandle((HANDLE
)hServiceStatus
);
1022 if (lpService
== NULL
)
1024 DPRINT1("lpService == NULL!\n");
1025 return ERROR_INVALID_HANDLE
;
1028 /* Check current state */
1029 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1031 DPRINT1("Invalid service state!\n");
1032 return ERROR_INVALID_DATA
;
1035 /* Check service type */
1036 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1037 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1039 DPRINT1("Invalid service type!\n");
1040 return ERROR_INVALID_DATA
;
1043 /* Check accepted controls */
1044 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1046 DPRINT1("Invalid controls accepted!\n");
1047 return ERROR_INVALID_DATA
;
1051 RtlCopyMemory(&lpService
->Status
,
1053 sizeof(SERVICE_STATUS
));
1055 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1056 DPRINT("RSetServiceStatus() done\n");
1058 return ERROR_SUCCESS
;
1063 DWORD
RUnlockServiceDatabase(
1067 return ERROR_SUCCESS
;
1072 DWORD
RNotifyBootConfigStatus(
1073 SVCCTL_HANDLEW lpMachineName
,
1074 DWORD BootAcceptable
)
1077 return ERROR_CALL_NOT_IMPLEMENTED
;
1082 DWORD
RI_ScSetServiceBitsW(
1083 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1084 DWORD dwServiceBits
,
1086 int bUpdateImmediately
,
1090 return ERROR_CALL_NOT_IMPLEMENTED
;
1095 DWORD
RChangeServiceConfigW(
1096 SC_RPC_HANDLE hService
,
1097 DWORD dwServiceType
,
1099 DWORD dwErrorControl
,
1100 LPWSTR lpBinaryPathName
,
1101 LPWSTR lpLoadOrderGroup
,
1103 LPBYTE lpDependencies
,
1105 LPWSTR lpServiceStartName
,
1108 LPWSTR lpDisplayName
)
1110 DWORD dwError
= ERROR_SUCCESS
;
1111 PSERVICE_HANDLE hSvc
;
1112 PSERVICE lpService
= NULL
;
1113 HKEY hServiceKey
= NULL
;
1114 LPWSTR lpDisplayNameW
= NULL
;
1116 DPRINT("RChangeServiceConfigW() called\n");
1117 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1118 DPRINT("dwStartType = %lu\n", dwStartType
);
1119 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1120 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1121 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1122 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1125 return ERROR_SHUTDOWN_IN_PROGRESS
;
1127 hSvc
= (PSERVICE_HANDLE
)hService
;
1128 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1130 DPRINT1("Invalid handle tag!\n");
1131 return ERROR_INVALID_HANDLE
;
1134 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1135 SERVICE_CHANGE_CONFIG
))
1137 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1138 return ERROR_ACCESS_DENIED
;
1141 lpService
= hSvc
->ServiceEntry
;
1142 if (lpService
== NULL
)
1144 DPRINT1("lpService == NULL!\n");
1145 return ERROR_INVALID_HANDLE
;
1148 /* FIXME: Lock database exclusively */
1150 if (lpService
->bDeleted
)
1152 /* FIXME: Unlock database */
1153 DPRINT1("The service has already been marked for delete!\n");
1154 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1157 /* Open the service key */
1158 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1161 if (dwError
!= ERROR_SUCCESS
)
1164 /* Write service data to the registry */
1165 /* Set the display name */
1166 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1168 RegSetValueExW(hServiceKey
,
1172 (LPBYTE
)lpDisplayName
,
1173 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1175 /* Update the display name */
1176 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1178 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1179 if (lpDisplayNameW
== NULL
)
1181 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1185 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1186 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1188 lpService
->lpDisplayName
= lpDisplayNameW
;
1191 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1193 /* Set the service type */
1194 dwError
= RegSetValueExW(hServiceKey
,
1198 (LPBYTE
)&dwServiceType
,
1200 if (dwError
!= ERROR_SUCCESS
)
1203 lpService
->Status
.dwServiceType
= dwServiceType
;
1206 if (dwStartType
!= SERVICE_NO_CHANGE
)
1208 /* Set the start value */
1209 dwError
= RegSetValueExW(hServiceKey
,
1213 (LPBYTE
)&dwStartType
,
1215 if (dwError
!= ERROR_SUCCESS
)
1218 lpService
->dwStartType
= dwStartType
;
1221 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1223 /* Set the error control value */
1224 dwError
= RegSetValueExW(hServiceKey
,
1228 (LPBYTE
)&dwErrorControl
,
1230 if (dwError
!= ERROR_SUCCESS
)
1233 lpService
->dwErrorControl
= dwErrorControl
;
1237 /* FIXME: set the new ImagePath value */
1239 /* Set the image path */
1240 if (dwServiceType
& SERVICE_WIN32
)
1242 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1244 dwError
= RegSetValueExW(hServiceKey
,
1248 (LPBYTE
)lpBinaryPathName
,
1249 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1250 if (dwError
!= ERROR_SUCCESS
)
1254 else if (dwServiceType
& SERVICE_DRIVER
)
1256 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1258 dwError
= RegSetValueExW(hServiceKey
,
1262 (LPBYTE
)lpImagePath
,
1263 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1264 if (dwError
!= ERROR_SUCCESS
)
1270 /* Set the group name */
1271 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1273 dwError
= RegSetValueExW(hServiceKey
,
1277 (LPBYTE
)lpLoadOrderGroup
,
1278 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1279 if (dwError
!= ERROR_SUCCESS
)
1281 /* FIXME: Update lpService->lpServiceGroup */
1284 if (lpdwTagId
!= NULL
)
1286 dwError
= ScmAssignNewTag(lpService
);
1287 if (dwError
!= ERROR_SUCCESS
)
1290 dwError
= RegSetValueExW(hServiceKey
,
1294 (LPBYTE
)&lpService
->dwTag
,
1296 if (dwError
!= ERROR_SUCCESS
)
1299 *lpdwTagId
= lpService
->dwTag
;
1302 /* Write dependencies */
1303 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1305 dwError
= ScmWriteDependencies(hServiceKey
,
1306 (LPWSTR
)lpDependencies
,
1308 if (dwError
!= ERROR_SUCCESS
)
1312 if (lpPassword
!= NULL
)
1314 /* FIXME: Write password */
1317 /* FIXME: Unlock database */
1320 if (hServiceKey
!= NULL
)
1321 RegCloseKey(hServiceKey
);
1323 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1329 /* Create a path suitable for the bootloader out of the full path */
1331 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1333 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1336 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1337 OBJECT_ATTRIBUTES ObjectAttributes
;
1339 HANDLE SymbolicLinkHandle
;
1341 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1343 ServiceNameLen
= wcslen(CanonName
);
1345 /* First check, if it's already good */
1346 if (ServiceNameLen
> 12 &&
1347 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1349 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1350 if (*RelativeName
== NULL
)
1352 DPRINT1("Error allocating memory for boot driver name!\n");
1353 return ERROR_NOT_ENOUGH_MEMORY
;
1357 wcscpy(*RelativeName
, CanonName
);
1359 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1360 return ERROR_SUCCESS
;
1363 /* If it has %SystemRoot% prefix, substitute it to \System*/
1364 if (ServiceNameLen
> 13 &&
1365 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1367 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1368 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1370 if (*RelativeName
== NULL
)
1372 DPRINT1("Error allocating memory for boot driver name!\n");
1373 return ERROR_NOT_ENOUGH_MEMORY
;
1377 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1378 wcscat(*RelativeName
, CanonName
+ 13);
1380 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1381 return ERROR_SUCCESS
;
1384 /* Get buffer size needed for expanding env strings */
1385 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1387 if (BufferSize
<= 1)
1389 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1390 return ERROR_INVALID_ENVIRONMENT
;
1393 /* Allocate memory, since the size is known now */
1394 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1397 DPRINT1("Error allocating memory for boot driver name!\n");
1398 return ERROR_NOT_ENOUGH_MEMORY
;
1402 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1405 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1406 LocalFree(Expanded
);
1407 return ERROR_NOT_ENOUGH_MEMORY
;
1410 /* Convert to NY-style path */
1411 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1413 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1414 return ERROR_INVALID_ENVIRONMENT
;
1417 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1419 /* No need to keep the dos-path anymore */
1420 LocalFree(Expanded
);
1422 /* Copy it to the allocated place */
1423 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1426 DPRINT1("Error allocating memory for boot driver name!\n");
1427 return ERROR_NOT_ENOUGH_MEMORY
;
1430 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1431 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1432 Expanded
[ExpandedLen
] = 0;
1434 if (ServiceNameLen
> ExpandedLen
&&
1435 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1437 /* Only \SystemRoot\ is missing */
1438 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1439 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1440 if (*RelativeName
== NULL
)
1442 DPRINT1("Error allocating memory for boot driver name!\n");
1443 LocalFree(Expanded
);
1444 return ERROR_NOT_ENOUGH_MEMORY
;
1447 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1448 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1450 RtlFreeUnicodeString(&NtPathName
);
1451 return ERROR_SUCCESS
;
1454 /* The most complex case starts here */
1455 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1456 InitializeObjectAttributes(&ObjectAttributes
,
1458 OBJ_CASE_INSENSITIVE
,
1462 /* Open this symlink */
1463 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1465 if (NT_SUCCESS(Status
))
1467 LinkTarget
.Length
= 0;
1468 LinkTarget
.MaximumLength
= 0;
1470 DPRINT("Opened symbolic link object\n");
1472 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1473 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1475 /* Check if required buffer size is sane */
1476 if (BufferSize
> 0xFFFD)
1478 DPRINT1("Too large buffer required\n");
1481 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1482 LocalFree(Expanded
);
1483 return ERROR_NOT_ENOUGH_MEMORY
;
1486 /* Alloc the string */
1487 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1488 if (!LinkTarget
.Buffer
)
1490 DPRINT1("Unable to alloc buffer\n");
1491 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1492 LocalFree(Expanded
);
1493 return ERROR_NOT_ENOUGH_MEMORY
;
1496 /* Do a real query now */
1497 LinkTarget
.Length
= BufferSize
;
1498 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1500 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1501 if (NT_SUCCESS(Status
))
1503 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1505 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1506 if ((ServiceNameLen
> ExpandedLen
) &&
1507 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1509 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1510 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1512 if (*RelativeName
== NULL
)
1514 DPRINT1("Unable to alloc buffer\n");
1515 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1516 LocalFree(Expanded
);
1517 RtlFreeUnicodeString(&NtPathName
);
1518 return ERROR_NOT_ENOUGH_MEMORY
;
1521 /* Copy it over, substituting the first part
1523 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1524 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1527 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1528 LocalFree(Expanded
);
1529 RtlFreeUnicodeString(&NtPathName
);
1531 /* Return success */
1532 return ERROR_SUCCESS
;
1536 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1537 LocalFree(Expanded
);
1538 RtlFreeUnicodeString(&NtPathName
);
1539 return ERROR_INVALID_PARAMETER
;
1544 DPRINT1("Error, Status = %08X\n", Status
);
1545 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1546 LocalFree(Expanded
);
1547 RtlFreeUnicodeString(&NtPathName
);
1548 return ERROR_INVALID_PARAMETER
;
1553 DPRINT1("Error, Status = %08X\n", Status
);
1554 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1555 LocalFree(Expanded
);
1556 RtlFreeUnicodeString(&NtPathName
);
1557 return ERROR_INVALID_PARAMETER
;
1562 DPRINT1("Error, Status = %08X\n", Status
);
1563 LocalFree(Expanded
);
1564 return ERROR_INVALID_PARAMETER
;
1568 *RelativeName
= NULL
;
1569 return ERROR_INVALID_PARAMETER
;
1573 ScmCanonDriverImagePath(DWORD dwStartType
,
1574 const wchar_t *lpServiceName
,
1575 wchar_t **lpCanonName
)
1577 DWORD ServiceNameLen
, Result
;
1578 UNICODE_STRING NtServiceName
;
1579 WCHAR
*RelativeName
;
1580 const WCHAR
*SourceName
= lpServiceName
;
1582 /* Calculate the length of the service's name */
1583 ServiceNameLen
= wcslen(lpServiceName
);
1585 /* 12 is wcslen(L"\\SystemRoot\\") */
1586 if (ServiceNameLen
> 12 &&
1587 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1589 /* SystemRoot prefix is already included */
1591 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1593 if (*lpCanonName
== NULL
)
1595 DPRINT1("Error allocating memory for canonized service name!\n");
1596 return ERROR_NOT_ENOUGH_MEMORY
;
1599 /* If it's a boot-time driver, it must be systemroot relative */
1600 if (dwStartType
== SERVICE_BOOT_START
)
1604 wcscpy(*lpCanonName
, SourceName
);
1606 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1610 /* Check if it has %SystemRoot% (len=13) */
1611 if (ServiceNameLen
> 13 &&
1612 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1614 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1615 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1617 if (*lpCanonName
== NULL
)
1619 DPRINT1("Error allocating memory for canonized service name!\n");
1620 return ERROR_NOT_ENOUGH_MEMORY
;
1623 /* If it's a boot-time driver, it must be systemroot relative */
1624 if (dwStartType
== SERVICE_BOOT_START
)
1625 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1627 wcscat(*lpCanonName
, lpServiceName
+ 13);
1629 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1633 /* Check if it's a relative path name */
1634 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1636 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1638 if (*lpCanonName
== NULL
)
1640 DPRINT1("Error allocating memory for canonized service name!\n");
1641 return ERROR_NOT_ENOUGH_MEMORY
;
1644 /* Just copy it over without changing */
1645 wcscpy(*lpCanonName
, lpServiceName
);
1650 /* It seems to be a DOS path, convert it */
1651 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1653 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1654 return ERROR_INVALID_PARAMETER
;
1657 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1659 if (*lpCanonName
== NULL
)
1661 DPRINT1("Error allocating memory for canonized service name!\n");
1662 RtlFreeUnicodeString(&NtServiceName
);
1663 return ERROR_NOT_ENOUGH_MEMORY
;
1666 /* Copy the string */
1667 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1669 /* The unicode string is not needed anymore */
1670 RtlFreeUnicodeString(&NtServiceName
);
1672 if (dwStartType
!= SERVICE_BOOT_START
)
1674 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1678 /* The service is boot-started, so must be relative */
1679 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1682 /* There is a problem, free name and return */
1683 LocalFree(*lpCanonName
);
1684 DPRINT1("Error converting named!\n");
1688 ASSERT(RelativeName
);
1690 /* Copy that string */
1691 wcscpy(*lpCanonName
, RelativeName
+ 12);
1693 /* Free the allocated buffer */
1694 LocalFree(RelativeName
);
1696 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1704 DWORD
RCreateServiceW(
1705 SC_RPC_HANDLE hSCManager
,
1706 LPCWSTR lpServiceName
,
1707 LPCWSTR lpDisplayName
,
1708 DWORD dwDesiredAccess
,
1709 DWORD dwServiceType
,
1711 DWORD dwErrorControl
,
1712 LPCWSTR lpBinaryPathName
,
1713 LPCWSTR lpLoadOrderGroup
,
1715 LPBYTE lpDependencies
,
1717 LPCWSTR lpServiceStartName
,
1720 LPSC_RPC_HANDLE lpServiceHandle
)
1722 PMANAGER_HANDLE hManager
;
1723 DWORD dwError
= ERROR_SUCCESS
;
1724 PSERVICE lpService
= NULL
;
1725 SC_HANDLE hServiceHandle
= NULL
;
1726 LPWSTR lpImagePath
= NULL
;
1727 HKEY hServiceKey
= NULL
;
1729 DPRINT("RCreateServiceW() called\n");
1730 DPRINT("lpServiceName = %S\n", lpServiceName
);
1731 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1732 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1733 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1734 DPRINT("dwStartType = %lu\n", dwStartType
);
1735 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1736 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1737 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1740 return ERROR_SHUTDOWN_IN_PROGRESS
;
1742 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1743 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1745 DPRINT1("Invalid manager handle!\n");
1746 return ERROR_INVALID_HANDLE
;
1749 /* Check access rights */
1750 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1751 SC_MANAGER_CREATE_SERVICE
))
1753 DPRINT1("Insufficient access rights! 0x%lx\n",
1754 hManager
->Handle
.DesiredAccess
);
1755 return ERROR_ACCESS_DENIED
;
1758 if (wcslen(lpServiceName
) == 0)
1760 return ERROR_INVALID_NAME
;
1763 if (wcslen(lpBinaryPathName
) == 0)
1765 return ERROR_INVALID_PARAMETER
;
1768 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1769 (lpServiceStartName
))
1771 return ERROR_INVALID_PARAMETER
;
1774 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1775 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1776 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1778 return ERROR_INVALID_PARAMETER
;
1781 if (dwStartType
> SERVICE_DISABLED
)
1783 return ERROR_INVALID_PARAMETER
;
1786 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1789 /* check if it is marked for deletion */
1790 if (lpService
->bDeleted
)
1791 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1792 /* Return Error exist */
1793 return ERROR_SERVICE_EXISTS
;
1796 if (lpDisplayName
!= NULL
&&
1797 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1798 return ERROR_DUPLICATE_SERVICE_NAME
;
1800 if (dwServiceType
& SERVICE_DRIVER
)
1802 dwError
= ScmCanonDriverImagePath(dwStartType
,
1805 if (dwError
!= ERROR_SUCCESS
)
1810 if (dwStartType
== SERVICE_BOOT_START
||
1811 dwStartType
== SERVICE_SYSTEM_START
)
1813 return ERROR_INVALID_PARAMETER
;
1817 /* Allocate a new service entry */
1818 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1820 if (dwError
!= ERROR_SUCCESS
)
1823 /* Fill the new service entry */
1824 lpService
->Status
.dwServiceType
= dwServiceType
;
1825 lpService
->dwStartType
= dwStartType
;
1826 lpService
->dwErrorControl
= dwErrorControl
;
1828 /* Fill the display name */
1829 if (lpDisplayName
!= NULL
&&
1830 *lpDisplayName
!= 0 &&
1831 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1833 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1834 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1835 if (lpService
->lpDisplayName
== NULL
)
1837 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1840 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1843 /* Assign the service to a group */
1844 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1846 dwError
= ScmSetServiceGroup(lpService
,
1848 if (dwError
!= ERROR_SUCCESS
)
1852 /* Assign a new tag */
1853 if (lpdwTagId
!= NULL
)
1855 dwError
= ScmAssignNewTag(lpService
);
1856 if (dwError
!= ERROR_SUCCESS
)
1860 /* Write service data to the registry */
1861 /* Create the service key */
1862 dwError
= ScmCreateServiceKey(lpServiceName
,
1865 if (dwError
!= ERROR_SUCCESS
)
1868 /* Set the display name */
1869 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1871 RegSetValueExW(hServiceKey
,
1875 (LPBYTE
)lpDisplayName
,
1876 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1879 /* Set the service type */
1880 dwError
= RegSetValueExW(hServiceKey
,
1884 (LPBYTE
)&dwServiceType
,
1886 if (dwError
!= ERROR_SUCCESS
)
1889 /* Set the start value */
1890 dwError
= RegSetValueExW(hServiceKey
,
1894 (LPBYTE
)&dwStartType
,
1896 if (dwError
!= ERROR_SUCCESS
)
1899 /* Set the error control value */
1900 dwError
= RegSetValueExW(hServiceKey
,
1904 (LPBYTE
)&dwErrorControl
,
1906 if (dwError
!= ERROR_SUCCESS
)
1909 /* Set the image path */
1910 if (dwServiceType
& SERVICE_WIN32
)
1912 dwError
= RegSetValueExW(hServiceKey
,
1916 (LPBYTE
)lpBinaryPathName
,
1917 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1918 if (dwError
!= ERROR_SUCCESS
)
1921 else if (dwServiceType
& SERVICE_DRIVER
)
1923 dwError
= RegSetValueExW(hServiceKey
,
1927 (LPBYTE
)lpImagePath
,
1928 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1929 if (dwError
!= ERROR_SUCCESS
)
1933 /* Set the group name */
1934 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1936 dwError
= RegSetValueExW(hServiceKey
,
1940 (LPBYTE
)lpLoadOrderGroup
,
1941 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1942 if (dwError
!= ERROR_SUCCESS
)
1946 if (lpdwTagId
!= NULL
)
1948 dwError
= RegSetValueExW(hServiceKey
,
1952 (LPBYTE
)&lpService
->dwTag
,
1954 if (dwError
!= ERROR_SUCCESS
)
1958 /* Write dependencies */
1959 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1961 dwError
= ScmWriteDependencies(hServiceKey
,
1962 (LPWSTR
)lpDependencies
,
1964 if (dwError
!= ERROR_SUCCESS
)
1968 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1969 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1971 dwError
= RegSetValueExW(hServiceKey
,
1975 (LPBYTE
)L
"LocalSystem",
1977 if (dwError
!= ERROR_SUCCESS
)
1981 if (lpPassword
!= NULL
)
1983 /* FIXME: Write password */
1986 dwError
= ScmCreateServiceHandle(lpService
,
1988 if (dwError
!= ERROR_SUCCESS
)
1991 dwError
= ScmCheckAccess(hServiceHandle
,
1993 if (dwError
!= ERROR_SUCCESS
)
1996 lpService
->dwRefCount
= 1;
1997 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2000 if (hServiceKey
!= NULL
)
2001 RegCloseKey(hServiceKey
);
2003 if (dwError
== ERROR_SUCCESS
)
2005 DPRINT("hService %p\n", hServiceHandle
);
2006 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2008 if (lpdwTagId
!= NULL
)
2009 *lpdwTagId
= lpService
->dwTag
;
2013 /* Release the display name buffer */
2014 if (lpService
->lpServiceName
!= NULL
)
2015 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2019 /* Remove the service handle */
2020 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2023 if (lpService
!= NULL
)
2025 /* FIXME: remove the service entry */
2029 if (lpImagePath
!= NULL
)
2030 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2032 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2039 DWORD
REnumDependentServicesW(
2040 SC_RPC_HANDLE hService
,
2041 DWORD dwServiceState
,
2044 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2045 LPBOUNDED_DWORD_256K lpServicesReturned
)
2047 DWORD dwError
= ERROR_SUCCESS
;
2048 DWORD dwServicesReturned
= 0;
2049 DWORD dwServiceCount
;
2050 HKEY hServicesKey
= NULL
;
2051 LPSC_RPC_HANDLE hSCObject
;
2052 PSERVICE_HANDLE hSvc
;
2053 PSERVICE lpService
= NULL
;
2054 PSERVICE
*lpServicesArray
= NULL
;
2055 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2058 *pcbBytesNeeded
= 0;
2059 *lpServicesReturned
= 0;
2061 DPRINT("REnumDependentServicesW() called\n");
2063 hSCObject
= &hService
;
2064 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2065 lpService
= hSvc
->ServiceEntry
;
2067 /* Check access rights */
2068 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2069 SC_MANAGER_ENUMERATE_SERVICE
))
2071 DPRINT1("Insufficient access rights! 0x%lx\n",
2072 hSvc
->Handle
.DesiredAccess
);
2073 return ERROR_ACCESS_DENIED
;
2076 /* Open the Services Reg key */
2077 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2078 L
"System\\CurrentControlSet\\Services",
2082 if (dwError
!= ERROR_SUCCESS
)
2085 /* First determine the bytes needed and get the number of dependent services */
2086 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2091 &dwServicesReturned
);
2092 if (dwError
!= ERROR_SUCCESS
)
2095 /* If buffer size is less than the bytes needed or pointer is null */
2096 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2098 dwError
= ERROR_MORE_DATA
;
2102 /* Allocate memory for array of service pointers */
2103 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2105 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2106 if (!lpServicesArray
)
2108 DPRINT1("Could not allocate a buffer!!\n");
2109 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2113 dwServicesReturned
= 0;
2114 *pcbBytesNeeded
= 0;
2116 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2121 &dwServicesReturned
);
2122 if (dwError
!= ERROR_SUCCESS
)
2127 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2128 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2130 /* Copy EnumDepenedentService to Buffer */
2131 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2133 lpService
= lpServicesArray
[dwServiceCount
];
2135 /* Copy status info */
2136 memcpy(&lpServicesPtr
->ServiceStatus
,
2138 sizeof(SERVICE_STATUS
));
2140 /* Copy display name */
2141 wcscpy(lpStr
, lpService
->lpDisplayName
);
2142 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2143 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2145 /* Copy service name */
2146 wcscpy(lpStr
, lpService
->lpServiceName
);
2147 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2148 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2153 *lpServicesReturned
= dwServicesReturned
;
2156 if (lpServicesArray
!= NULL
)
2157 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2159 RegCloseKey(hServicesKey
);
2161 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2168 DWORD
REnumServicesStatusW(
2169 SC_RPC_HANDLE hSCManager
,
2170 DWORD dwServiceType
,
2171 DWORD dwServiceState
,
2174 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2175 LPBOUNDED_DWORD_256K lpServicesReturned
,
2176 LPBOUNDED_DWORD_256K lpResumeHandle
)
2178 PMANAGER_HANDLE hManager
;
2180 DWORD dwError
= ERROR_SUCCESS
;
2181 PLIST_ENTRY ServiceEntry
;
2182 PSERVICE CurrentService
;
2184 DWORD dwRequiredSize
;
2185 DWORD dwServiceCount
;
2187 DWORD dwLastResumeCount
= 0;
2188 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2191 DPRINT("REnumServicesStatusW() called\n");
2194 return ERROR_SHUTDOWN_IN_PROGRESS
;
2196 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2197 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2199 DPRINT1("Invalid manager handle!\n");
2200 return ERROR_INVALID_HANDLE
;
2203 *pcbBytesNeeded
= 0;
2204 *lpServicesReturned
= 0;
2206 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2208 DPRINT("Not a valid Service Type!\n");
2209 return ERROR_INVALID_PARAMETER
;
2212 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2214 DPRINT("Not a valid Service State!\n");
2215 return ERROR_INVALID_PARAMETER
;
2218 /* Check access rights */
2219 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2220 SC_MANAGER_ENUMERATE_SERVICE
))
2222 DPRINT1("Insufficient access rights! 0x%lx\n",
2223 hManager
->Handle
.DesiredAccess
);
2224 return ERROR_ACCESS_DENIED
;
2227 if (lpResumeHandle
) dwLastResumeCount
= *lpResumeHandle
;
2229 /* FIXME: Lock the service list shared */
2231 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2232 if (lpService
== NULL
)
2234 dwError
= ERROR_SUCCESS
;
2241 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2242 ServiceEntry
!= &ServiceListHead
;
2243 ServiceEntry
= ServiceEntry
->Flink
)
2245 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2249 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2252 dwState
= SERVICE_ACTIVE
;
2253 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2254 dwState
= SERVICE_INACTIVE
;
2256 if ((dwState
& dwServiceState
) == 0)
2259 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2260 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2261 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2263 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2265 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2269 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2270 dwRequiredSize
+= dwSize
;
2272 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2275 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2276 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2279 ServiceEntry
!= &ServiceListHead
;
2280 ServiceEntry
= ServiceEntry
->Flink
)
2282 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2286 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2289 dwState
= SERVICE_ACTIVE
;
2290 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2291 dwState
= SERVICE_INACTIVE
;
2293 if ((dwState
& dwServiceState
) == 0)
2296 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2297 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2298 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2300 dwError
= ERROR_MORE_DATA
;
2303 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2305 if (lpResumeHandle
) *lpResumeHandle
= dwLastResumeCount
;
2306 *lpServicesReturned
= dwServiceCount
;
2307 *pcbBytesNeeded
= dwRequiredSize
;
2309 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2310 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2311 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2314 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2315 ServiceEntry
!= &ServiceListHead
;
2316 ServiceEntry
= ServiceEntry
->Flink
)
2318 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2322 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2325 dwState
= SERVICE_ACTIVE
;
2326 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2327 dwState
= SERVICE_INACTIVE
;
2329 if ((dwState
& dwServiceState
) == 0)
2332 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2333 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2334 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2336 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2339 /* Copy the service name */
2340 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2341 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2342 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2344 /* Copy the display name */
2345 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2346 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2347 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2349 /* Copy the status information */
2350 memcpy(&lpStatusPtr
->ServiceStatus
,
2351 &CurrentService
->Status
,
2352 sizeof(SERVICE_STATUS
));
2355 dwRequiredSize
+= dwSize
;
2360 *pcbBytesNeeded
= 0;
2361 if (lpResumeHandle
) *lpResumeHandle
= 0;
2365 /* FIXME: Unlock the service list */
2367 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2374 DWORD
ROpenSCManagerW(
2375 LPWSTR lpMachineName
,
2376 LPWSTR lpDatabaseName
,
2377 DWORD dwDesiredAccess
,
2378 LPSC_RPC_HANDLE lpScHandle
)
2383 DPRINT("ROpenSCManagerW() called\n");
2384 DPRINT("lpMachineName = %p\n", lpMachineName
);
2385 DPRINT("lpMachineName: %S\n", lpMachineName
);
2386 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2387 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2388 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2391 return ERROR_SHUTDOWN_IN_PROGRESS
;
2394 return ERROR_INVALID_PARAMETER
;
2396 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2398 if (dwError
!= ERROR_SUCCESS
)
2400 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2404 /* Check the desired access */
2405 dwError
= ScmCheckAccess(hHandle
,
2406 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2407 if (dwError
!= ERROR_SUCCESS
)
2409 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2410 HeapFree(GetProcessHeap(), 0, hHandle
);
2414 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2415 DPRINT("*hScm = %p\n", *lpScHandle
);
2417 DPRINT("ROpenSCManagerW() done\n");
2419 return ERROR_SUCCESS
;
2424 DWORD
ROpenServiceW(
2425 SC_RPC_HANDLE hSCManager
,
2426 LPWSTR lpServiceName
,
2427 DWORD dwDesiredAccess
,
2428 LPSC_RPC_HANDLE lpServiceHandle
)
2431 PMANAGER_HANDLE hManager
;
2435 DPRINT("ROpenServiceW() called\n");
2436 DPRINT("hSCManager = %p\n", hSCManager
);
2437 DPRINT("lpServiceName = %p\n", lpServiceName
);
2438 DPRINT("lpServiceName: %S\n", lpServiceName
);
2439 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2442 return ERROR_SHUTDOWN_IN_PROGRESS
;
2444 if (!lpServiceHandle
)
2445 return ERROR_INVALID_PARAMETER
;
2448 return ERROR_INVALID_ADDRESS
;
2450 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2451 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2453 DPRINT1("Invalid manager handle!\n");
2454 return ERROR_INVALID_HANDLE
;
2457 /* FIXME: Lock the service list */
2459 /* Get service database entry */
2460 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2461 if (lpService
== NULL
)
2463 DPRINT("Could not find a service!\n");
2464 return ERROR_SERVICE_DOES_NOT_EXIST
;
2467 /* Create a service handle */
2468 dwError
= ScmCreateServiceHandle(lpService
,
2470 if (dwError
!= ERROR_SUCCESS
)
2472 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2476 /* Check the desired access */
2477 dwError
= ScmCheckAccess(hHandle
,
2479 if (dwError
!= ERROR_SUCCESS
)
2481 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2482 HeapFree(GetProcessHeap(), 0, hHandle
);
2486 lpService
->dwRefCount
++;
2487 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2489 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2490 DPRINT("*hService = %p\n", *lpServiceHandle
);
2492 DPRINT("ROpenServiceW() done\n");
2494 return ERROR_SUCCESS
;
2499 DWORD
RQueryServiceConfigW(
2500 SC_RPC_HANDLE hService
,
2501 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2503 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2505 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2506 DWORD dwError
= ERROR_SUCCESS
;
2507 PSERVICE_HANDLE hSvc
;
2508 PSERVICE lpService
= NULL
;
2509 HKEY hServiceKey
= NULL
;
2510 LPWSTR lpImagePath
= NULL
;
2511 LPWSTR lpServiceStartName
= NULL
;
2512 DWORD dwRequiredSize
;
2513 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2514 WCHAR lpEmptyString
[] = {0,0};
2517 DPRINT("RQueryServiceConfigW() called\n");
2520 return ERROR_SHUTDOWN_IN_PROGRESS
;
2522 hSvc
= (PSERVICE_HANDLE
)hService
;
2523 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2525 DPRINT1("Invalid handle tag!\n");
2526 return ERROR_INVALID_HANDLE
;
2529 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2530 SERVICE_QUERY_CONFIG
))
2532 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2533 return ERROR_ACCESS_DENIED
;
2536 lpService
= hSvc
->ServiceEntry
;
2537 if (lpService
== NULL
)
2539 DPRINT1("lpService == NULL!\n");
2540 return ERROR_INVALID_HANDLE
;
2543 /* FIXME: Lock the service database shared */
2545 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2548 if (dwError
!= ERROR_SUCCESS
)
2551 dwError
= ScmReadString(hServiceKey
,
2554 if (dwError
!= ERROR_SUCCESS
)
2557 ScmReadString(hServiceKey
,
2559 &lpServiceStartName
);
2561 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2563 if (lpImagePath
!= NULL
)
2564 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2566 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2568 if (lpService
->lpGroup
!= NULL
)
2569 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2571 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2573 /* FIXME: Add Dependencies length*/
2575 if (lpServiceStartName
!= NULL
)
2576 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2578 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2580 if (lpService
->lpDisplayName
!= NULL
)
2581 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2583 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2585 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2587 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2591 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2592 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2593 lpConfig
->dwStartType
= lpService
->dwStartType
;
2594 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2595 lpConfig
->dwTagId
= lpService
->dwTag
;
2597 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2599 if (lpImagePath
!= NULL
)
2601 wcscpy(lpStr
, lpImagePath
);
2605 wcscpy(lpStr
, lpEmptyString
);
2608 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2609 lpStr
+= (wcslen(lpStr
) + 1);
2611 if (lpService
->lpGroup
!= NULL
)
2613 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2617 wcscpy(lpStr
, lpEmptyString
);
2620 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2621 lpStr
+= (wcslen(lpStr
) + 1);
2623 /* FIXME: Append Dependencies */
2624 wcscpy(lpStr
, lpEmptyString
);
2626 lpStr
+= (wcslen(lpStr
) + 1);
2627 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2629 if (lpServiceStartName
!= NULL
)
2631 wcscpy(lpStr
, lpServiceStartName
);
2635 wcscpy(lpStr
, lpEmptyString
);
2638 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2639 lpStr
+= (wcslen(lpStr
) + 1);
2641 if (lpService
->lpDisplayName
!= NULL
)
2643 wcscpy(lpStr
, lpService
->lpDisplayName
);
2647 wcscpy(lpStr
, lpEmptyString
);
2650 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2653 if (pcbBytesNeeded
!= NULL
)
2654 *pcbBytesNeeded
= dwRequiredSize
;
2657 if (lpImagePath
!= NULL
)
2658 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2660 if (lpServiceStartName
!= NULL
)
2661 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2663 if (hServiceKey
!= NULL
)
2664 RegCloseKey(hServiceKey
);
2666 /* FIXME: Unlock the service database */
2668 DPRINT("RQueryServiceConfigW() done\n");
2675 DWORD
RQueryServiceLockStatusW(
2676 SC_RPC_HANDLE hSCManager
,
2677 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2679 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2682 return ERROR_CALL_NOT_IMPLEMENTED
;
2687 DWORD
RStartServiceW(
2688 SC_RPC_HANDLE hService
,
2690 LPSTRING_PTRSW argv
)
2692 DWORD dwError
= ERROR_SUCCESS
;
2693 PSERVICE_HANDLE hSvc
;
2694 PSERVICE lpService
= NULL
;
2696 DPRINT("RStartServiceW() called\n");
2699 return ERROR_SHUTDOWN_IN_PROGRESS
;
2701 hSvc
= (PSERVICE_HANDLE
)hService
;
2702 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2704 DPRINT1("Invalid handle tag!\n");
2705 return ERROR_INVALID_HANDLE
;
2708 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2711 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2712 return ERROR_ACCESS_DENIED
;
2715 lpService
= hSvc
->ServiceEntry
;
2716 if (lpService
== NULL
)
2718 DPRINT1("lpService == NULL!\n");
2719 return ERROR_INVALID_HANDLE
;
2722 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2723 return ERROR_SERVICE_DISABLED
;
2725 if (lpService
->bDeleted
)
2726 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2733 /* Start the service */
2734 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2741 DWORD
RGetServiceDisplayNameW(
2742 SC_RPC_HANDLE hSCManager
,
2743 LPCWSTR lpServiceName
,
2744 LPWSTR lpDisplayName
,
2747 // PMANAGER_HANDLE hManager;
2752 DPRINT("RGetServiceDisplayNameW() called\n");
2753 DPRINT("hSCManager = %p\n", hSCManager
);
2754 DPRINT("lpServiceName: %S\n", lpServiceName
);
2755 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2756 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2758 // hManager = (PMANAGER_HANDLE)hSCManager;
2759 // if (hManager->Handle.Tag != MANAGER_TAG)
2761 // DPRINT1("Invalid manager handle!\n");
2762 // return ERROR_INVALID_HANDLE;
2765 /* Get service database entry */
2766 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2767 if (lpService
== NULL
)
2769 DPRINT1("Could not find a service!\n");
2771 /* If the service could not be found and lpcchBuffer is 0, windows
2772 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2773 if (*lpcchBuffer
== 0)
2776 if (lpDisplayName
!= NULL
)
2778 *lpDisplayName
= '\0';
2782 return ERROR_SERVICE_DOES_NOT_EXIST
;
2785 if (!lpService
->lpDisplayName
)
2787 dwLength
= wcslen(lpService
->lpServiceName
);
2789 if (lpDisplayName
!= NULL
&&
2790 *lpcchBuffer
> dwLength
)
2792 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2797 dwLength
= wcslen(lpService
->lpDisplayName
);
2799 if (lpDisplayName
!= NULL
&&
2800 *lpcchBuffer
> dwLength
)
2802 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2806 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2808 *lpcchBuffer
= dwLength
;
2815 DWORD
RGetServiceKeyNameW(
2816 SC_RPC_HANDLE hSCManager
,
2817 LPCWSTR lpDisplayName
,
2818 LPWSTR lpServiceName
,
2821 // PMANAGER_HANDLE hManager;
2826 DPRINT("RGetServiceKeyNameW() called\n");
2827 DPRINT("hSCManager = %p\n", hSCManager
);
2828 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2829 DPRINT("lpServiceName: %p\n", lpServiceName
);
2830 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2832 // hManager = (PMANAGER_HANDLE)hSCManager;
2833 // if (hManager->Handle.Tag != MANAGER_TAG)
2835 // DPRINT1("Invalid manager handle!\n");
2836 // return ERROR_INVALID_HANDLE;
2839 /* Get service database entry */
2840 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2841 if (lpService
== NULL
)
2843 DPRINT1("Could not find a service!\n");
2845 /* If the service could not be found and lpcchBuffer is 0, windows
2846 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2847 if (*lpcchBuffer
== 0)
2850 if (lpServiceName
!= NULL
)
2852 *lpServiceName
= '\0';
2856 return ERROR_SERVICE_DOES_NOT_EXIST
;
2859 dwLength
= wcslen(lpService
->lpServiceName
);
2861 if (lpServiceName
!= NULL
&&
2862 *lpcchBuffer
> dwLength
)
2864 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2865 *lpcchBuffer
= dwLength
;
2866 return ERROR_SUCCESS
;
2869 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2871 *lpcchBuffer
= dwLength
* 2;
2878 DWORD
RI_ScSetServiceBitsA(
2879 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
2880 DWORD dwServiceBits
,
2882 int bUpdateImmediately
,
2886 return ERROR_CALL_NOT_IMPLEMENTED
;
2891 DWORD
RChangeServiceConfigA(
2892 SC_RPC_HANDLE hService
,
2893 DWORD dwServiceType
,
2895 DWORD dwErrorControl
,
2896 LPSTR lpBinaryPathName
,
2897 LPSTR lpLoadOrderGroup
,
2899 LPSTR lpDependencies
,
2901 LPSTR lpServiceStartName
,
2904 LPSTR lpDisplayName
)
2906 DWORD dwError
= ERROR_SUCCESS
;
2907 PSERVICE_HANDLE hSvc
;
2908 PSERVICE lpService
= NULL
;
2909 HKEY hServiceKey
= NULL
;
2910 LPWSTR lpDisplayNameW
= NULL
;
2911 // LPWSTR lpBinaryPathNameW = NULL;
2912 LPWSTR lpLoadOrderGroupW
= NULL
;
2913 LPWSTR lpDependenciesW
= NULL
;
2914 // LPWSTR lpPasswordW = NULL;
2916 DPRINT("RChangeServiceConfigA() called\n");
2917 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2918 DPRINT("dwStartType = %lu\n", dwStartType
);
2919 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2920 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2921 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2922 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2925 return ERROR_SHUTDOWN_IN_PROGRESS
;
2927 hSvc
= (PSERVICE_HANDLE
)hService
;
2928 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2930 DPRINT1("Invalid handle tag!\n");
2931 return ERROR_INVALID_HANDLE
;
2934 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2935 SERVICE_CHANGE_CONFIG
))
2937 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2938 return ERROR_ACCESS_DENIED
;
2941 lpService
= hSvc
->ServiceEntry
;
2942 if (lpService
== NULL
)
2944 DPRINT1("lpService == NULL!\n");
2945 return ERROR_INVALID_HANDLE
;
2948 /* FIXME: Lock database exclusively */
2950 if (lpService
->bDeleted
)
2952 /* FIXME: Unlock database */
2953 DPRINT1("The service has already been marked for delete!\n");
2954 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2957 /* Open the service key */
2958 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2961 if (dwError
!= ERROR_SUCCESS
)
2964 /* Write service data to the registry */
2966 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2968 /* Set the display name */
2969 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2971 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2972 if (lpDisplayNameW
== NULL
)
2974 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2978 MultiByteToWideChar(CP_ACP
,
2983 wcslen(lpDisplayNameW
) + 1);
2985 RegSetValueExW(hServiceKey
,
2989 (LPBYTE
)lpDisplayNameW
,
2990 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2992 /* Update lpService->lpDisplayName */
2993 if (lpService
->lpDisplayName
)
2994 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2996 lpService
->lpDisplayName
= lpDisplayNameW
;
2999 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3001 /* Set the service type */
3002 dwError
= RegSetValueExW(hServiceKey
,
3006 (LPBYTE
)&dwServiceType
,
3008 if (dwError
!= ERROR_SUCCESS
)
3011 lpService
->Status
.dwServiceType
= dwServiceType
;
3014 if (dwStartType
!= SERVICE_NO_CHANGE
)
3016 /* Set the start value */
3017 dwError
= RegSetValueExW(hServiceKey
,
3021 (LPBYTE
)&dwStartType
,
3023 if (dwError
!= ERROR_SUCCESS
)
3026 lpService
->dwStartType
= dwStartType
;
3029 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3031 /* Set the error control value */
3032 dwError
= RegSetValueExW(hServiceKey
,
3036 (LPBYTE
)&dwErrorControl
,
3038 if (dwError
!= ERROR_SUCCESS
)
3041 lpService
->dwErrorControl
= dwErrorControl
;
3045 /* FIXME: set the new ImagePath value */
3047 /* Set the image path */
3048 if (dwServiceType
& SERVICE_WIN32
)
3050 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3052 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3053 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3054 dwError
= RegSetValueExW(hServiceKey
,
3058 (LPBYTE
)lpBinaryPathNameW
,
3059 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3060 if (dwError
!= ERROR_SUCCESS
)
3064 else if (dwServiceType
& SERVICE_DRIVER
)
3066 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3068 dwError
= RegSetValueExW(hServiceKey
,
3072 (LPBYTE
)lpImagePath
,
3073 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3074 if (dwError
!= ERROR_SUCCESS
)
3080 /* Set the group name */
3081 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3083 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3085 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3086 if (lpLoadOrderGroupW
== NULL
)
3088 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3092 MultiByteToWideChar(CP_ACP
,
3097 wcslen(lpLoadOrderGroupW
) + 1);
3099 dwError
= RegSetValueExW(hServiceKey
,
3103 (LPBYTE
)lpLoadOrderGroupW
,
3104 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3105 if (dwError
!= ERROR_SUCCESS
)
3108 /* FIXME: Update lpService->lpServiceGroup */
3110 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3113 if (lpdwTagId
!= NULL
)
3115 dwError
= ScmAssignNewTag(lpService
);
3116 if (dwError
!= ERROR_SUCCESS
)
3119 dwError
= RegSetValueExW(hServiceKey
,
3123 (LPBYTE
)&lpService
->dwTag
,
3125 if (dwError
!= ERROR_SUCCESS
)
3128 *lpdwTagId
= lpService
->dwTag
;
3131 /* Write dependencies */
3132 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3134 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3136 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3137 if (lpDependenciesW
== NULL
)
3139 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3143 MultiByteToWideChar(CP_ACP
,
3148 wcslen(lpDependenciesW
)+1);
3150 dwError
= ScmWriteDependencies(hServiceKey
,
3151 (LPWSTR
)lpDependenciesW
,
3154 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3157 if (lpPassword
!= NULL
)
3159 /* FIXME: Write password */
3162 /* FIXME: Unlock database */
3165 if (hServiceKey
!= NULL
)
3166 RegCloseKey(hServiceKey
);
3168 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3175 DWORD
RCreateServiceA(
3176 SC_RPC_HANDLE hSCManager
,
3177 LPSTR lpServiceName
,
3178 LPSTR lpDisplayName
,
3179 DWORD dwDesiredAccess
,
3180 DWORD dwServiceType
,
3182 DWORD dwErrorControl
,
3183 LPSTR lpBinaryPathName
,
3184 LPSTR lpLoadOrderGroup
,
3186 LPBYTE lpDependencies
,
3188 LPSTR lpServiceStartName
,
3191 LPSC_RPC_HANDLE lpServiceHandle
)
3194 return ERROR_CALL_NOT_IMPLEMENTED
;
3199 DWORD
REnumDependentServicesA(
3200 SC_RPC_HANDLE hService
,
3201 DWORD dwServiceState
,
3204 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3205 LPBOUNDED_DWORD_256K lpServicesReturned
)
3207 DWORD dwError
= ERROR_SUCCESS
;
3208 DWORD dwServicesReturned
= 0;
3209 DWORD dwServiceCount
;
3210 HKEY hServicesKey
= NULL
;
3211 LPSC_RPC_HANDLE hSCObject
;
3212 PSERVICE_HANDLE hSvc
;
3213 PSERVICE lpService
= NULL
;
3214 PSERVICE
*lpServicesArray
= NULL
;
3215 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3218 *pcbBytesNeeded
= 0;
3219 *lpServicesReturned
= 0;
3221 DPRINT("REnumDependentServicesA() called\n");
3223 hSCObject
= &hService
;
3224 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3225 lpService
= hSvc
->ServiceEntry
;
3227 /* Check access rights */
3228 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3229 SC_MANAGER_ENUMERATE_SERVICE
))
3231 DPRINT1("Insufficient access rights! 0x%lx\n",
3232 hSvc
->Handle
.DesiredAccess
);
3233 return ERROR_ACCESS_DENIED
;
3236 /* Open the Services Reg key */
3237 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3238 L
"System\\CurrentControlSet\\Services",
3243 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3245 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3246 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3247 are the same for both. Verified in WINXP. */
3249 /* First determine the bytes needed and get the number of dependent services*/
3250 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3255 &dwServicesReturned
);
3256 if (dwError
!= ERROR_SUCCESS
)
3259 /* If buffer size is less than the bytes needed or pointer is null*/
3260 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3262 dwError
= ERROR_MORE_DATA
;
3266 /* Allocate memory for array of service pointers */
3267 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3269 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3270 if (!lpServicesArray
)
3272 DPRINT1("Could not allocate a buffer!!\n");
3273 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3277 dwServicesReturned
= 0;
3278 *pcbBytesNeeded
= 0;
3280 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3285 &dwServicesReturned
);
3286 if (dwError
!= ERROR_SUCCESS
)
3291 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3292 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3294 /* Copy EnumDepenedentService to Buffer */
3295 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3297 lpService
= lpServicesArray
[dwServiceCount
];
3299 /* Copy the status info */
3300 memcpy(&lpServicesPtr
->ServiceStatus
,
3302 sizeof(SERVICE_STATUS
));
3304 /* Copy display name */
3305 WideCharToMultiByte(CP_ACP
,
3307 lpService
->lpDisplayName
,
3310 wcslen(lpService
->lpDisplayName
),
3313 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3314 lpStr
+= strlen(lpStr
) + 1;
3316 /* Copy service name */
3317 WideCharToMultiByte(CP_ACP
,
3319 lpService
->lpServiceName
,
3322 wcslen(lpService
->lpServiceName
),
3325 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3326 lpStr
+= strlen(lpStr
) + 1;
3331 *lpServicesReturned
= dwServicesReturned
;
3334 if (lpServicesArray
)
3335 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3337 RegCloseKey(hServicesKey
);
3339 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3346 DWORD
REnumServicesStatusA(
3347 SC_RPC_HANDLE hSCManager
,
3348 DWORD dwServiceType
,
3349 DWORD dwServiceState
,
3352 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3353 LPBOUNDED_DWORD_256K lpServicesReturned
,
3354 LPBOUNDED_DWORD_256K lpResumeHandle
)
3356 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3357 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3358 LPWSTR lpStringPtrW
;
3361 DWORD dwServiceCount
;
3363 DPRINT("REnumServicesStatusA() called\n");
3365 if ((dwBufSize
> 0) && (lpBuffer
))
3367 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3370 DPRINT1("Failed to allocate buffer!\n");
3371 return ERROR_NOT_ENOUGH_MEMORY
;
3375 dwError
= REnumServicesStatusW(//BindingHandle,
3379 (LPBYTE
)lpStatusPtrW
,
3385 /* if no services were returned then we are Done */
3386 if (*lpServicesReturned
== 0) goto Done
;
3388 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3389 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3390 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3391 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3392 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3394 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3396 /* Copy the service name */
3397 WideCharToMultiByte(CP_ACP
,
3402 wcslen(lpStringPtrW
),
3406 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3407 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3408 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3410 /* Copy the display name */
3411 WideCharToMultiByte(CP_ACP
,
3416 wcslen(lpStringPtrW
),
3420 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3421 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3422 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3424 /* Copy the status information */
3425 memcpy(&lpStatusPtrA
->ServiceStatus
,
3426 &lpStatusPtrW
->ServiceStatus
,
3427 sizeof(SERVICE_STATUS
));
3433 if (lpStatusPtrW
) HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3435 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3442 DWORD
ROpenSCManagerA(
3443 LPSTR lpMachineName
,
3444 LPSTR lpDatabaseName
,
3445 DWORD dwDesiredAccess
,
3446 LPSC_RPC_HANDLE lpScHandle
)
3448 UNICODE_STRING MachineName
;
3449 UNICODE_STRING DatabaseName
;
3452 DPRINT("ROpenSCManagerA() called\n");
3455 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3459 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3462 dwError
= ROpenSCManagerW(//BindingHandle,
3463 lpMachineName
? MachineName
.Buffer
: NULL
,
3464 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3469 RtlFreeUnicodeString(&MachineName
);
3472 RtlFreeUnicodeString(&DatabaseName
);
3479 DWORD
ROpenServiceA(
3480 SC_RPC_HANDLE hSCManager
,
3481 LPSTR lpServiceName
,
3482 DWORD dwDesiredAccess
,
3483 LPSC_RPC_HANDLE lpServiceHandle
)
3485 UNICODE_STRING ServiceName
;
3488 DPRINT("ROpenServiceA() called\n");
3491 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3494 dwError
= ROpenServiceW(//BindingHandle,
3496 lpServiceName
? ServiceName
.Buffer
: NULL
,
3501 RtlFreeUnicodeString(&ServiceName
);
3508 DWORD
RQueryServiceConfigA(
3509 SC_RPC_HANDLE hService
,
3510 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3512 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3514 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3515 DWORD dwError
= ERROR_SUCCESS
;
3516 PSERVICE_HANDLE hSvc
;
3517 PSERVICE lpService
= NULL
;
3518 HKEY hServiceKey
= NULL
;
3519 LPWSTR lpImagePath
= NULL
;
3520 LPWSTR lpServiceStartName
= NULL
;
3521 DWORD dwRequiredSize
;
3522 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3523 CHAR lpEmptyString
[]={0,0};
3526 DPRINT("RQueryServiceConfigA() called\n");
3529 return ERROR_SHUTDOWN_IN_PROGRESS
;
3531 hSvc
= (PSERVICE_HANDLE
)hService
;
3532 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3534 DPRINT1("Invalid handle tag!\n");
3535 return ERROR_INVALID_HANDLE
;
3538 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3539 SERVICE_QUERY_CONFIG
))
3541 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3542 return ERROR_ACCESS_DENIED
;
3545 lpService
= hSvc
->ServiceEntry
;
3546 if (lpService
== NULL
)
3548 DPRINT1("lpService == NULL!\n");
3549 return ERROR_INVALID_HANDLE
;
3552 /* FIXME: Lock the service database shared */
3554 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3557 if (dwError
!= ERROR_SUCCESS
)
3560 dwError
= ScmReadString(hServiceKey
,
3563 if (dwError
!= ERROR_SUCCESS
)
3566 ScmReadString(hServiceKey
,
3568 &lpServiceStartName
);
3570 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3572 if (lpImagePath
!= NULL
)
3573 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3575 dwRequiredSize
+= 2;
3577 if (lpService
->lpGroup
!= NULL
)
3578 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3580 dwRequiredSize
+= 2;
3582 /* FIXME: Add Dependencies length*/
3583 dwRequiredSize
+= 2;
3585 if (lpServiceStartName
!= NULL
)
3586 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3588 dwRequiredSize
+= 2;
3590 if (lpService
->lpDisplayName
!= NULL
)
3591 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3593 dwRequiredSize
+= 2;
3595 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3597 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3601 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3602 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3603 lpConfig
->dwStartType
= lpService
->dwStartType
;
3604 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3605 lpConfig
->dwTagId
= lpService
->dwTag
;
3607 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3609 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3614 WideCharToMultiByte(CP_ACP
,
3619 wcslen(lpImagePath
),
3625 strcpy(lpStr
, lpEmptyString
);
3628 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3629 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3631 if (lpService
->lpGroup
)
3633 WideCharToMultiByte(CP_ACP
,
3635 lpService
->lpGroup
->lpGroupName
,
3638 wcslen(lpService
->lpGroup
->lpGroupName
),
3644 strcpy(lpStr
, lpEmptyString
);
3647 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3648 lpStr
+= (strlen(lpStr
) + 1);
3650 /* FIXME: Append Dependencies */
3651 strcpy(lpStr
, lpEmptyString
);
3653 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3654 lpStr
+= (strlen(lpStr
) + 1);
3656 if (lpServiceStartName
)
3658 WideCharToMultiByte(CP_ACP
,
3663 wcslen(lpServiceStartName
),
3669 strcpy(lpStr
, lpEmptyString
);
3672 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3673 lpStr
+= (strlen(lpStr
) + 1);
3675 if (lpService
->lpDisplayName
)
3677 WideCharToMultiByte(CP_ACP
,
3679 lpService
->lpDisplayName
,
3682 wcslen(lpService
->lpDisplayName
),
3688 strcpy(lpStr
, lpEmptyString
);
3691 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3694 if (pcbBytesNeeded
!= NULL
)
3695 *pcbBytesNeeded
= dwRequiredSize
;
3698 if (lpImagePath
!= NULL
)
3699 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3701 if (lpServiceStartName
!= NULL
)
3702 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3704 if (hServiceKey
!= NULL
)
3705 RegCloseKey(hServiceKey
);
3707 /* FIXME: Unlock the service database */
3709 DPRINT("RQueryServiceConfigA() done\n");
3716 DWORD
RQueryServiceLockStatusA(
3717 SC_RPC_HANDLE hSCManager
,
3718 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3720 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3723 return ERROR_CALL_NOT_IMPLEMENTED
;
3728 DWORD
RStartServiceA(
3729 SC_RPC_HANDLE hService
,
3731 LPSTRING_PTRSA argv
)
3733 DWORD dwError
= ERROR_SUCCESS
;
3734 PSERVICE_HANDLE hSvc
;
3735 PSERVICE lpService
= NULL
;
3737 DPRINT1("RStartServiceA() called\n");
3740 return ERROR_SHUTDOWN_IN_PROGRESS
;
3742 hSvc
= (PSERVICE_HANDLE
)hService
;
3743 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3745 DPRINT1("Invalid handle tag!\n");
3746 return ERROR_INVALID_HANDLE
;
3749 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3752 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3753 return ERROR_ACCESS_DENIED
;
3756 lpService
= hSvc
->ServiceEntry
;
3757 if (lpService
== NULL
)
3759 DPRINT1("lpService == NULL!\n");
3760 return ERROR_INVALID_HANDLE
;
3763 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3764 return ERROR_SERVICE_DISABLED
;
3766 if (lpService
->bDeleted
)
3767 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3769 /* FIXME: Convert argument vector to Unicode */
3771 /* Start the service */
3772 dwError
= ScmStartService(lpService
, 0, NULL
);
3774 /* FIXME: Free argument vector */
3781 DWORD
RGetServiceDisplayNameA(
3782 SC_RPC_HANDLE hSCManager
,
3783 LPCSTR lpServiceName
,
3784 LPSTR lpDisplayName
,
3785 LPBOUNDED_DWORD_4K lpcchBuffer
)
3787 // PMANAGER_HANDLE hManager;
3788 PSERVICE lpService
= NULL
;
3791 LPWSTR lpServiceNameW
;
3793 DPRINT("RGetServiceDisplayNameA() called\n");
3794 DPRINT("hSCManager = %p\n", hSCManager
);
3795 DPRINT("lpServiceName: %s\n", lpServiceName
);
3796 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3797 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3799 // hManager = (PMANAGER_HANDLE)hSCManager;
3800 // if (hManager->Handle.Tag != MANAGER_TAG)
3802 // DPRINT1("Invalid manager handle!\n");
3803 // return ERROR_INVALID_HANDLE;
3806 if (lpServiceName
!= NULL
)
3808 dwLength
= strlen(lpServiceName
) + 1;
3809 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3811 dwLength
* sizeof(WCHAR
));
3812 if (!lpServiceNameW
)
3813 return ERROR_NOT_ENOUGH_MEMORY
;
3815 MultiByteToWideChar(CP_ACP
,
3822 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3824 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3827 if (lpService
== NULL
)
3829 DPRINT1("Could not find a service!\n");
3831 /* If the service could not be found and lpcchBuffer is 0, windows
3832 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3833 if (*lpcchBuffer
== 0)
3836 if (lpDisplayName
!= NULL
)
3838 *lpDisplayName
= '\0';
3841 return ERROR_SERVICE_DOES_NOT_EXIST
;
3844 if (!lpService
->lpDisplayName
)
3846 dwLength
= wcslen(lpService
->lpServiceName
);
3847 if (lpDisplayName
!= NULL
&&
3848 *lpcchBuffer
> dwLength
)
3850 WideCharToMultiByte(CP_ACP
,
3852 lpService
->lpServiceName
,
3853 wcslen(lpService
->lpServiceName
),
3858 return ERROR_SUCCESS
;
3863 dwLength
= wcslen(lpService
->lpDisplayName
);
3864 if (lpDisplayName
!= NULL
&&
3865 *lpcchBuffer
> dwLength
)
3867 WideCharToMultiByte(CP_ACP
,
3869 lpService
->lpDisplayName
,
3870 wcslen(lpService
->lpDisplayName
),
3875 return ERROR_SUCCESS
;
3879 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3881 *lpcchBuffer
= dwLength
* 2;
3888 DWORD
RGetServiceKeyNameA(
3889 SC_RPC_HANDLE hSCManager
,
3890 LPCSTR lpDisplayName
,
3891 LPSTR lpServiceName
,
3892 LPBOUNDED_DWORD_4K lpcchBuffer
)
3897 LPWSTR lpDisplayNameW
;
3899 DPRINT("RGetServiceKeyNameA() called\n");
3900 DPRINT("hSCManager = %p\n", hSCManager
);
3901 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3902 DPRINT("lpServiceName: %p\n", lpServiceName
);
3903 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3905 dwLength
= strlen(lpDisplayName
) + 1;
3906 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3908 dwLength
* sizeof(WCHAR
));
3909 if (!lpDisplayNameW
)
3910 return ERROR_NOT_ENOUGH_MEMORY
;
3912 MultiByteToWideChar(CP_ACP
,
3919 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
3921 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3923 if (lpService
== NULL
)
3925 DPRINT1("Could not find the service!\n");
3927 /* If the service could not be found and lpcchBuffer is 0,
3928 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
3929 if (*lpcchBuffer
== 0)
3932 if (lpServiceName
!= NULL
)
3934 *lpServiceName
= '\0';
3938 return ERROR_SERVICE_DOES_NOT_EXIST
;
3941 dwLength
= wcslen(lpService
->lpServiceName
);
3942 if (lpServiceName
!= NULL
&&
3943 *lpcchBuffer
> dwLength
)
3945 WideCharToMultiByte(CP_ACP
,
3947 lpService
->lpServiceName
,
3948 wcslen(lpService
->lpServiceName
),
3953 return ERROR_SUCCESS
;
3956 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3958 *lpcchBuffer
= dwLength
* 2;
3965 DWORD
RI_ScGetCurrentGroupStateW(
3966 SC_RPC_HANDLE hSCManager
,
3967 LPWSTR lpLoadOrderGroup
,
3971 return ERROR_CALL_NOT_IMPLEMENTED
;
3976 DWORD
REnumServiceGroupW(
3977 SC_RPC_HANDLE hSCManager
,
3978 DWORD dwServiceType
,
3979 DWORD dwServiceState
,
3982 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3983 LPBOUNDED_DWORD_256K lpServicesReturned
,
3984 LPBOUNDED_DWORD_256K lpResumeIndex
,
3985 LPCWSTR pszGroupName
)
3988 return ERROR_CALL_NOT_IMPLEMENTED
;
3993 DWORD
RChangeServiceConfig2A(
3994 SC_RPC_HANDLE hService
,
3995 SC_RPC_CONFIG_INFOA Info
)
3998 return ERROR_CALL_NOT_IMPLEMENTED
;
4003 DWORD
RChangeServiceConfig2W(
4004 SC_RPC_HANDLE hService
,
4005 SC_RPC_CONFIG_INFOW Info
)
4007 DWORD dwError
= ERROR_SUCCESS
;
4008 PSERVICE_HANDLE hSvc
;
4009 PSERVICE lpService
= NULL
;
4010 HKEY hServiceKey
= NULL
;
4012 DPRINT("RChangeServiceConfig2W() called\n");
4013 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4016 return ERROR_SHUTDOWN_IN_PROGRESS
;
4018 hSvc
= (PSERVICE_HANDLE
)hService
;
4019 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4021 DPRINT1("Invalid handle tag!\n");
4022 return ERROR_INVALID_HANDLE
;
4025 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4026 SERVICE_CHANGE_CONFIG
))
4028 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4029 return ERROR_ACCESS_DENIED
;
4032 lpService
= hSvc
->ServiceEntry
;
4033 if (lpService
== NULL
)
4035 DPRINT1("lpService == NULL!\n");
4036 return ERROR_INVALID_HANDLE
;
4039 /* FIXME: Lock database exclusively */
4041 if (lpService
->bDeleted
)
4043 /* FIXME: Unlock database */
4044 DPRINT1("The service has already been marked for delete!\n");
4045 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4048 /* Open the service key */
4049 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4052 if (dwError
!= ERROR_SUCCESS
)
4055 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4057 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4059 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
4060 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4062 if (lpServiceDescription
!= NULL
&&
4063 lpServiceDescription
->lpDescription
!= NULL
)
4065 RegSetValueExW(hServiceKey
,
4069 (LPBYTE
)lpServiceDescription
->lpDescription
,
4070 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4072 if (dwError
!= ERROR_SUCCESS
)
4076 else if (Info
.dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4079 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4084 /* FIXME: Unlock database */
4085 if (hServiceKey
!= NULL
)
4086 RegCloseKey(hServiceKey
);
4088 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4095 DWORD
RQueryServiceConfig2A(
4096 SC_RPC_HANDLE hService
,
4100 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4102 DWORD dwError
= ERROR_SUCCESS
;
4103 PSERVICE_HANDLE hSvc
;
4104 PSERVICE lpService
= NULL
;
4105 HKEY hServiceKey
= NULL
;
4106 DWORD dwRequiredSize
;
4107 LPWSTR lpDescriptionW
= NULL
;
4108 LPSTR lpDescription
= NULL
;
4110 DPRINT("RQueryServiceConfig2W() called\n");
4113 return ERROR_INVALID_ADDRESS
;
4116 return ERROR_SHUTDOWN_IN_PROGRESS
;
4118 hSvc
= (PSERVICE_HANDLE
)hService
;
4119 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4121 DPRINT1("Invalid handle tag!\n");
4122 return ERROR_INVALID_HANDLE
;
4125 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4126 SERVICE_QUERY_CONFIG
))
4128 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4129 return ERROR_ACCESS_DENIED
;
4132 lpService
= hSvc
->ServiceEntry
;
4133 if (lpService
== NULL
)
4135 DPRINT1("lpService == NULL!\n");
4136 return ERROR_INVALID_HANDLE
;
4139 /* FIXME: Lock the service database shared */
4141 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4144 if (dwError
!= ERROR_SUCCESS
)
4147 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4149 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4152 dwError
= ScmReadString(hServiceKey
,
4155 if (dwError
!= ERROR_SUCCESS
)
4158 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONA
) + ((wcslen(lpDescriptionW
) + 1));
4160 if (cbBufSize
< dwRequiredSize
)
4162 *pcbBytesNeeded
= dwRequiredSize
;
4163 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4167 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4169 WideCharToMultiByte(CP_ACP
,
4174 wcslen(lpDescriptionW
),
4177 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4179 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4182 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4187 if (lpDescription
!= NULL
)
4188 HeapFree(GetProcessHeap(), 0, lpDescription
);
4190 if (hServiceKey
!= NULL
)
4191 RegCloseKey(hServiceKey
);
4193 /* FIXME: Unlock database */
4195 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4202 DWORD
RQueryServiceConfig2W(
4203 SC_RPC_HANDLE hService
,
4207 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4209 DWORD dwError
= ERROR_SUCCESS
;
4210 PSERVICE_HANDLE hSvc
;
4211 PSERVICE lpService
= NULL
;
4212 HKEY hServiceKey
= NULL
;
4213 DWORD dwRequiredSize
;
4214 LPWSTR lpDescription
= NULL
;
4216 DPRINT("RQueryServiceConfig2W() called\n");
4219 return ERROR_INVALID_ADDRESS
;
4222 return ERROR_SHUTDOWN_IN_PROGRESS
;
4224 hSvc
= (PSERVICE_HANDLE
)hService
;
4225 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4227 DPRINT1("Invalid handle tag!\n");
4228 return ERROR_INVALID_HANDLE
;
4231 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4232 SERVICE_QUERY_CONFIG
))
4234 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4235 return ERROR_ACCESS_DENIED
;
4238 lpService
= hSvc
->ServiceEntry
;
4239 if (lpService
== NULL
)
4241 DPRINT1("lpService == NULL!\n");
4242 return ERROR_INVALID_HANDLE
;
4245 /* FIXME: Lock the service database shared */
4247 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4250 if (dwError
!= ERROR_SUCCESS
)
4253 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4255 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4258 dwError
= ScmReadString(hServiceKey
,
4261 if (dwError
!= ERROR_SUCCESS
)
4264 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4266 if (cbBufSize
< dwRequiredSize
)
4268 *pcbBytesNeeded
= dwRequiredSize
;
4269 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4273 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4274 wcscpy(lpStr
, lpDescription
);
4275 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4277 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4280 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4285 if (lpDescription
!= NULL
)
4286 HeapFree(GetProcessHeap(), 0, lpDescription
);
4288 if (hServiceKey
!= NULL
)
4289 RegCloseKey(hServiceKey
);
4291 /* FIXME: Unlock database */
4293 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4300 DWORD
RQueryServiceStatusEx(
4301 SC_RPC_HANDLE hService
,
4302 SC_STATUS_TYPE InfoLevel
,
4305 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4307 LPSERVICE_STATUS_PROCESS lpStatus
;
4308 PSERVICE_HANDLE hSvc
;
4311 DPRINT("RQueryServiceStatusEx() called\n");
4314 return ERROR_SHUTDOWN_IN_PROGRESS
;
4316 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4317 return ERROR_INVALID_LEVEL
;
4319 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4321 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4322 return ERROR_INSUFFICIENT_BUFFER
;
4324 hSvc
= (PSERVICE_HANDLE
)hService
;
4325 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4327 DPRINT1("Invalid handle tag!\n");
4328 return ERROR_INVALID_HANDLE
;
4331 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4332 SERVICE_QUERY_STATUS
))
4334 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4335 return ERROR_ACCESS_DENIED
;
4338 lpService
= hSvc
->ServiceEntry
;
4339 if (lpService
== NULL
)
4341 DPRINT1("lpService == NULL!\n");
4342 return ERROR_INVALID_HANDLE
;
4345 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4347 /* Return service status information */
4348 RtlCopyMemory(lpStatus
,
4350 sizeof(SERVICE_STATUS
));
4352 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4353 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4355 return ERROR_SUCCESS
;
4360 DWORD
REnumServicesStatusExA(
4361 SC_RPC_HANDLE hSCManager
,
4362 SC_ENUM_TYPE InfoLevel
,
4363 DWORD dwServiceType
,
4364 DWORD dwServiceState
,
4367 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4368 LPBOUNDED_DWORD_256K lpServicesReturned
,
4369 LPBOUNDED_DWORD_256K lpResumeIndex
,
4370 LPCSTR pszGroupName
)
4372 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4373 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4374 LPWSTR lpStringPtrW
;
4376 LPWSTR pszGroupNameW
= NULL
;
4378 DWORD dwServiceCount
;
4380 DPRINT("REnumServicesStatusExA() called\n");
4384 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4387 DPRINT1("Failed to allocate buffer!\n");
4388 return ERROR_NOT_ENOUGH_MEMORY
;
4390 MultiByteToWideChar(CP_ACP
,
4395 strlen(pszGroupName
) + 1);
4398 if ((cbBufSize
> 0) && (lpBuffer
))
4400 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4403 DPRINT1("Failed to allocate buffer!\n");
4404 return ERROR_NOT_ENOUGH_MEMORY
;
4408 dwError
= REnumServicesStatusExW(hSCManager
,
4412 (LPBYTE
)lpStatusPtrW
,
4419 /* if no services were returned then we are Done */
4420 if (*lpServicesReturned
== 0) goto Done
;
4422 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4423 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4424 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4425 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4426 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4428 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4430 /* Copy the service name */
4431 WideCharToMultiByte(CP_ACP
,
4436 wcslen(lpStringPtrW
),
4440 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4441 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4442 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4444 /* Copy the display name */
4445 WideCharToMultiByte(CP_ACP
,
4450 wcslen(lpStringPtrW
),
4454 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4455 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4456 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4458 /* Copy the status information */
4459 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4460 &lpStatusPtrW
->ServiceStatusProcess
,
4461 sizeof(SERVICE_STATUS
));
4463 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4464 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4469 if (pszGroupNameW
) HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4471 if (lpStatusPtrW
) HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4473 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4480 DWORD
REnumServicesStatusExW(
4481 SC_RPC_HANDLE hSCManager
,
4482 SC_ENUM_TYPE InfoLevel
,
4483 DWORD dwServiceType
,
4484 DWORD dwServiceState
,
4487 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4488 LPBOUNDED_DWORD_256K lpServicesReturned
,
4489 LPBOUNDED_DWORD_256K lpResumeIndex
,
4490 LPCWSTR pszGroupName
)
4492 PMANAGER_HANDLE hManager
;
4494 DWORD dwError
= ERROR_SUCCESS
;
4495 PLIST_ENTRY ServiceEntry
;
4496 PSERVICE CurrentService
;
4498 DWORD dwRequiredSize
;
4499 DWORD dwServiceCount
;
4501 DWORD dwLastResumeCount
= 0;
4502 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4505 DPRINT("REnumServicesStatusExW() called\n");
4508 return ERROR_SHUTDOWN_IN_PROGRESS
;
4510 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4511 return ERROR_INVALID_LEVEL
;
4513 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4514 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4516 DPRINT1("Invalid manager handle!\n");
4517 return ERROR_INVALID_HANDLE
;
4520 *pcbBytesNeeded
= 0;
4521 *lpServicesReturned
= 0;
4523 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4525 DPRINT1("Not a valid Service Type!\n");
4526 return ERROR_INVALID_PARAMETER
;
4529 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4531 DPRINT1("Not a valid Service State!\n");
4532 return ERROR_INVALID_PARAMETER
;
4535 /* Check access rights */
4536 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4537 SC_MANAGER_ENUMERATE_SERVICE
))
4539 DPRINT1("Insufficient access rights! 0x%lx\n",
4540 hManager
->Handle
.DesiredAccess
);
4541 return ERROR_ACCESS_DENIED
;
4544 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4546 /* Lock the service list shared */
4548 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4549 if (lpService
== NULL
)
4551 dwError
= ERROR_SUCCESS
;
4558 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4559 ServiceEntry
!= &ServiceListHead
;
4560 ServiceEntry
= ServiceEntry
->Flink
)
4562 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4566 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4569 dwState
= SERVICE_ACTIVE
;
4570 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4571 dwState
= SERVICE_INACTIVE
;
4573 if ((dwState
& dwServiceState
) == 0)
4578 if (*pszGroupName
== 0)
4580 if (CurrentService
->lpGroup
!= NULL
)
4585 if ((CurrentService
->lpGroup
== NULL
) ||
4586 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4591 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4592 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4593 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4595 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4597 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4598 dwRequiredSize
+= dwSize
;
4600 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4604 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4610 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4611 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4614 ServiceEntry
!= &ServiceListHead
;
4615 ServiceEntry
= ServiceEntry
->Flink
)
4617 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4621 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4624 dwState
= SERVICE_ACTIVE
;
4625 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4626 dwState
= SERVICE_INACTIVE
;
4628 if ((dwState
& dwServiceState
) == 0)
4633 if (*pszGroupName
== 0)
4635 if (CurrentService
->lpGroup
!= NULL
)
4640 if ((CurrentService
->lpGroup
== NULL
) ||
4641 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4646 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4647 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4648 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4650 dwError
= ERROR_MORE_DATA
;
4653 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4655 if (lpResumeIndex
) *lpResumeIndex
= dwLastResumeCount
;
4656 *lpServicesReturned
= dwServiceCount
;
4657 *pcbBytesNeeded
= dwRequiredSize
;
4659 /* If there was no services that matched */
4660 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
4662 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
4666 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
4667 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4668 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4671 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4672 ServiceEntry
!= &ServiceListHead
;
4673 ServiceEntry
= ServiceEntry
->Flink
)
4675 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4679 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4682 dwState
= SERVICE_ACTIVE
;
4683 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4684 dwState
= SERVICE_INACTIVE
;
4686 if ((dwState
& dwServiceState
) == 0)
4691 if (*pszGroupName
== 0)
4693 if (CurrentService
->lpGroup
!= NULL
)
4698 if ((CurrentService
->lpGroup
== NULL
) ||
4699 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4704 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4705 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4706 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4708 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4710 /* Copy the service name */
4712 CurrentService
->lpServiceName
);
4713 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4714 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4716 /* Copy the display name */
4718 CurrentService
->lpDisplayName
);
4719 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4720 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4722 /* Copy the status information */
4723 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
4724 &CurrentService
->Status
,
4725 sizeof(SERVICE_STATUS
));
4726 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
4727 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4730 dwRequiredSize
+= dwSize
;
4740 *pcbBytesNeeded
= 0;
4741 if (lpResumeIndex
) *lpResumeIndex
= 0;
4745 /* Unlock the service list */
4747 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
4754 DWORD
RSendTSMessage(
4755 handle_t BindingHandle
) /* FIXME */
4758 return ERROR_CALL_NOT_IMPLEMENTED
;
4763 DWORD
RCreateServiceWOW64A(
4764 handle_t BindingHandle
,
4765 LPSTR lpServiceName
,
4766 LPSTR lpDisplayName
,
4767 DWORD dwDesiredAccess
,
4768 DWORD dwServiceType
,
4770 DWORD dwErrorControl
,
4771 LPSTR lpBinaryPathName
,
4772 LPSTR lpLoadOrderGroup
,
4774 LPBYTE lpDependencies
,
4776 LPSTR lpServiceStartName
,
4779 LPSC_RPC_HANDLE lpServiceHandle
)
4782 return ERROR_CALL_NOT_IMPLEMENTED
;
4787 DWORD
RCreateServiceWOW64W(
4788 handle_t BindingHandle
,
4789 LPWSTR lpServiceName
,
4790 LPWSTR lpDisplayName
,
4791 DWORD dwDesiredAccess
,
4792 DWORD dwServiceType
,
4794 DWORD dwErrorControl
,
4795 LPWSTR lpBinaryPathName
,
4796 LPWSTR lpLoadOrderGroup
,
4798 LPBYTE lpDependencies
,
4800 LPWSTR lpServiceStartName
,
4803 LPSC_RPC_HANDLE lpServiceHandle
)
4806 return ERROR_CALL_NOT_IMPLEMENTED
;
4811 DWORD
RQueryServiceTagInfo(
4812 handle_t BindingHandle
) /* FIXME */
4815 return ERROR_CALL_NOT_IMPLEMENTED
;
4820 DWORD
RNotifyServiceStatusChange(
4821 SC_RPC_HANDLE hService
,
4822 SC_RPC_NOTIFY_PARAMS NotifyParams
,
4823 GUID
*pClientProcessGuid
,
4824 GUID
*pSCMProcessGuid
,
4825 PBOOL pfCreateRemoteQueue
,
4826 LPSC_NOTIFY_RPC_HANDLE phNotify
)
4829 return ERROR_CALL_NOT_IMPLEMENTED
;
4834 DWORD
RGetNotifyResults(
4835 SC_NOTIFY_RPC_HANDLE hNotify
,
4836 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
4839 return ERROR_CALL_NOT_IMPLEMENTED
;
4844 DWORD
RCloseNotifyHandle(
4845 LPSC_NOTIFY_RPC_HANDLE phNotify
,
4849 return ERROR_CALL_NOT_IMPLEMENTED
;
4854 DWORD
RControlServiceExA(
4855 SC_RPC_HANDLE hService
,
4860 return ERROR_CALL_NOT_IMPLEMENTED
;
4865 DWORD
RControlServiceExW(
4866 SC_RPC_HANDLE hService
,
4871 return ERROR_CALL_NOT_IMPLEMENTED
;
4876 DWORD
RSendPnPMessage(
4877 handle_t BindingHandle
) /* FIXME */
4880 return ERROR_CALL_NOT_IMPLEMENTED
;
4885 DWORD
RValidatePnPService(
4886 handle_t BindingHandle
) /* FIXME */
4889 return ERROR_CALL_NOT_IMPLEMENTED
;
4894 DWORD
ROpenServiceStatusHandle(
4895 handle_t BindingHandle
) /* FIXME */
4898 return ERROR_CALL_NOT_IMPLEMENTED
;
4904 handle_t BindingHandle
) /* FIXME */
4907 return ERROR_CALL_NOT_IMPLEMENTED
;
4911 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
4913 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
4917 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
4919 HeapFree(GetProcessHeap(), 0, ptr
);
4923 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
4928 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
4933 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)