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
= RegDeleteKeyW(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
)
741 PSERVICE_HANDLE hSvc
;
743 ULONG DesiredAccess
= 0;
748 DPRINT("RQueryServiceObjectSecurity() called\n");
750 hSvc
= (PSERVICE_HANDLE
)hService
;
751 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
753 DPRINT1("Invalid handle tag!\n");
754 return ERROR_INVALID_HANDLE
;
757 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
758 GROUP_SECURITY_INFORMATION
||
759 OWNER_SECURITY_INFORMATION
))
760 DesiredAccess
|= READ_CONTROL
;
762 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
763 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
765 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
768 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
769 return ERROR_ACCESS_DENIED
;
772 lpService
= hSvc
->ServiceEntry
;
773 if (lpService
== NULL
)
775 DPRINT1("lpService == NULL!\n");
776 return ERROR_INVALID_HANDLE
;
779 /* FIXME: Lock the service list */
781 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
782 dwSecurityInformation
,
783 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
787 /* FIXME: Unlock the service list */
789 if (NT_SUCCESS(Status
))
791 *pcbBytesNeeded
= dwBytesNeeded
;
792 dwError
= STATUS_SUCCESS
;
794 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
796 *pcbBytesNeeded
= dwBytesNeeded
;
797 dwError
= ERROR_INSUFFICIENT_BUFFER
;
799 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
801 dwError
= ERROR_GEN_FAILURE
;
805 dwError
= RtlNtStatusToDosError(Status
);
813 DWORD
RSetServiceObjectSecurity(
814 SC_RPC_HANDLE hService
,
815 DWORD dwSecurityInformation
,
816 LPBYTE lpSecurityDescriptor
,
817 DWORD dwSecuityDescriptorSize
)
819 PSERVICE_HANDLE hSvc
;
821 ULONG DesiredAccess
= 0;
822 HANDLE hToken
= NULL
;
827 DPRINT1("RSetServiceObjectSecurity() called\n");
829 hSvc
= (PSERVICE_HANDLE
)hService
;
830 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
832 DPRINT1("Invalid handle tag!\n");
833 return ERROR_INVALID_HANDLE
;
836 if (dwSecurityInformation
== 0 ||
837 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
838 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
839 return ERROR_INVALID_PARAMETER
;
841 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
842 return ERROR_INVALID_PARAMETER
;
844 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
845 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
847 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
848 DesiredAccess
|= WRITE_DAC
;
850 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
851 DesiredAccess
|= WRITE_OWNER
;
853 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
854 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
855 return ERROR_INVALID_PARAMETER
;
857 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
858 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
859 return ERROR_INVALID_PARAMETER
;
861 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
864 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
865 return ERROR_ACCESS_DENIED
;
868 lpService
= hSvc
->ServiceEntry
;
869 if (lpService
== NULL
)
871 DPRINT1("lpService == NULL!\n");
872 return ERROR_INVALID_HANDLE
;
875 if (lpService
->bDeleted
)
876 return ERROR_SERVICE_MARKED_FOR_DELETE
;
878 RpcImpersonateClient(NULL
);
880 Status
= NtOpenThreadToken(NtCurrentThread(),
884 if (!NT_SUCCESS(Status
))
885 return RtlNtStatusToDosError(Status
);
889 /* FIXME: Lock service database */
892 Status
= RtlSetSecurityObject(dwSecurityInformation
,
893 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
894 &lpService
->lpSecurityDescriptor
,
897 if (!NT_SUCCESS(Status
))
899 dwError
= RtlNtStatusToDosError(Status
);
904 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
905 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
907 if (dwError
!= ERROR_SUCCESS
)
911 dwError
= ERROR_SUCCESS
;
912 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
913 // lpService->lpSecurityDescriptor);
915 RegFlushKey(hServiceKey
);
916 RegCloseKey(hServiceKey
);
923 /* FIXME: Unlock service database */
925 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
932 DWORD
RQueryServiceStatus(
933 SC_RPC_HANDLE hService
,
934 LPSERVICE_STATUS lpServiceStatus
)
936 PSERVICE_HANDLE hSvc
;
939 DPRINT("RQueryServiceStatus() called\n");
942 return ERROR_SHUTDOWN_IN_PROGRESS
;
944 hSvc
= (PSERVICE_HANDLE
)hService
;
945 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
947 DPRINT1("Invalid handle tag!\n");
948 return ERROR_INVALID_HANDLE
;
951 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
952 SERVICE_QUERY_STATUS
))
954 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
955 return ERROR_ACCESS_DENIED
;
958 lpService
= hSvc
->ServiceEntry
;
959 if (lpService
== NULL
)
961 DPRINT1("lpService == NULL!\n");
962 return ERROR_INVALID_HANDLE
;
965 /* Return service status information */
966 RtlCopyMemory(lpServiceStatus
,
968 sizeof(SERVICE_STATUS
));
970 return ERROR_SUCCESS
;
975 ScmIsValidServiceState(DWORD dwCurrentState
)
977 switch (dwCurrentState
)
979 case SERVICE_STOPPED
:
980 case SERVICE_START_PENDING
:
981 case SERVICE_STOP_PENDING
:
982 case SERVICE_RUNNING
:
983 case SERVICE_CONTINUE_PENDING
:
984 case SERVICE_PAUSE_PENDING
:
995 DWORD
RSetServiceStatus(
996 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
997 LPSERVICE_STATUS lpServiceStatus
)
1001 DPRINT("RSetServiceStatus() called\n");
1002 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1003 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1004 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1005 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1006 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1007 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1008 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1009 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1011 if (hServiceStatus
== 0)
1013 DPRINT1("hServiceStatus == NULL!\n");
1014 return ERROR_INVALID_HANDLE
;
1017 lpService
= ScmGetServiceEntryByClientHandle((HANDLE
)hServiceStatus
);
1018 if (lpService
== NULL
)
1020 DPRINT1("lpService == NULL!\n");
1021 return ERROR_INVALID_HANDLE
;
1024 /* Check current state */
1025 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1027 DPRINT1("Invalid service state!\n");
1028 return ERROR_INVALID_DATA
;
1031 /* Check service type */
1032 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1033 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1035 DPRINT1("Invalid service type!\n");
1036 return ERROR_INVALID_DATA
;
1039 /* Check accepted controls */
1040 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1042 DPRINT1("Invalid controls accepted!\n");
1043 return ERROR_INVALID_DATA
;
1047 RtlCopyMemory(&lpService
->Status
,
1049 sizeof(SERVICE_STATUS
));
1051 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1052 DPRINT("RSetServiceStatus() done\n");
1054 return ERROR_SUCCESS
;
1059 DWORD
RUnlockServiceDatabase(
1063 return ERROR_SUCCESS
;
1068 DWORD
RNotifyBootConfigStatus(
1069 SVCCTL_HANDLEW lpMachineName
,
1070 DWORD BootAcceptable
)
1073 return ERROR_CALL_NOT_IMPLEMENTED
;
1078 DWORD
RI_ScSetServiceBitsW(
1079 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1080 DWORD dwServiceBits
,
1082 int bUpdateImmediately
,
1086 return ERROR_CALL_NOT_IMPLEMENTED
;
1091 DWORD
RChangeServiceConfigW(
1092 SC_RPC_HANDLE hService
,
1093 DWORD dwServiceType
,
1095 DWORD dwErrorControl
,
1096 LPWSTR lpBinaryPathName
,
1097 LPWSTR lpLoadOrderGroup
,
1099 LPBYTE lpDependencies
,
1101 LPWSTR lpServiceStartName
,
1104 LPWSTR lpDisplayName
)
1106 DWORD dwError
= ERROR_SUCCESS
;
1107 PSERVICE_HANDLE hSvc
;
1108 PSERVICE lpService
= NULL
;
1109 HKEY hServiceKey
= NULL
;
1110 LPWSTR lpDisplayNameW
= NULL
;
1112 DPRINT("RChangeServiceConfigW() called\n");
1113 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1114 DPRINT("dwStartType = %lu\n", dwStartType
);
1115 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1116 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1117 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1118 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1121 return ERROR_SHUTDOWN_IN_PROGRESS
;
1123 hSvc
= (PSERVICE_HANDLE
)hService
;
1124 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1126 DPRINT1("Invalid handle tag!\n");
1127 return ERROR_INVALID_HANDLE
;
1130 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1131 SERVICE_CHANGE_CONFIG
))
1133 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1134 return ERROR_ACCESS_DENIED
;
1137 lpService
= hSvc
->ServiceEntry
;
1138 if (lpService
== NULL
)
1140 DPRINT1("lpService == NULL!\n");
1141 return ERROR_INVALID_HANDLE
;
1144 /* FIXME: Lock database exclusively */
1146 if (lpService
->bDeleted
)
1148 /* FIXME: Unlock database */
1149 DPRINT1("The service has already been marked for delete!\n");
1150 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1153 /* Open the service key */
1154 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1157 if (dwError
!= ERROR_SUCCESS
)
1160 /* Write service data to the registry */
1161 /* Set the display name */
1162 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1164 RegSetValueExW(hServiceKey
,
1168 (LPBYTE
)lpDisplayName
,
1169 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1171 /* Update the display name */
1172 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1174 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1175 if (lpDisplayNameW
== NULL
)
1177 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1181 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1182 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1184 lpService
->lpDisplayName
= lpDisplayNameW
;
1187 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1189 /* Set the service type */
1190 dwError
= RegSetValueExW(hServiceKey
,
1194 (LPBYTE
)&dwServiceType
,
1196 if (dwError
!= ERROR_SUCCESS
)
1199 lpService
->Status
.dwServiceType
= dwServiceType
;
1202 if (dwStartType
!= SERVICE_NO_CHANGE
)
1204 /* Set the start value */
1205 dwError
= RegSetValueExW(hServiceKey
,
1209 (LPBYTE
)&dwStartType
,
1211 if (dwError
!= ERROR_SUCCESS
)
1214 lpService
->dwStartType
= dwStartType
;
1217 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1219 /* Set the error control value */
1220 dwError
= RegSetValueExW(hServiceKey
,
1224 (LPBYTE
)&dwErrorControl
,
1226 if (dwError
!= ERROR_SUCCESS
)
1229 lpService
->dwErrorControl
= dwErrorControl
;
1233 /* FIXME: set the new ImagePath value */
1235 /* Set the image path */
1236 if (dwServiceType
& SERVICE_WIN32
)
1238 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1240 dwError
= RegSetValueExW(hServiceKey
,
1244 (LPBYTE
)lpBinaryPathName
,
1245 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1246 if (dwError
!= ERROR_SUCCESS
)
1250 else if (dwServiceType
& SERVICE_DRIVER
)
1252 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1254 dwError
= RegSetValueExW(hServiceKey
,
1258 (LPBYTE
)lpImagePath
,
1259 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1260 if (dwError
!= ERROR_SUCCESS
)
1266 /* Set the group name */
1267 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1269 dwError
= RegSetValueExW(hServiceKey
,
1273 (LPBYTE
)lpLoadOrderGroup
,
1274 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1275 if (dwError
!= ERROR_SUCCESS
)
1277 /* FIXME: Update lpService->lpServiceGroup */
1280 if (lpdwTagId
!= NULL
)
1282 dwError
= ScmAssignNewTag(lpService
);
1283 if (dwError
!= ERROR_SUCCESS
)
1286 dwError
= RegSetValueExW(hServiceKey
,
1290 (LPBYTE
)&lpService
->dwTag
,
1292 if (dwError
!= ERROR_SUCCESS
)
1295 *lpdwTagId
= lpService
->dwTag
;
1298 /* Write dependencies */
1299 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1301 dwError
= ScmWriteDependencies(hServiceKey
,
1302 (LPWSTR
)lpDependencies
,
1304 if (dwError
!= ERROR_SUCCESS
)
1308 if (lpPassword
!= NULL
)
1310 /* FIXME: Write password */
1313 /* FIXME: Unlock database */
1316 if (hServiceKey
!= NULL
)
1317 RegCloseKey(hServiceKey
);
1319 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1325 /* Create a path suitable for the bootloader out of the full path */
1327 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1329 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1332 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1333 OBJECT_ATTRIBUTES ObjectAttributes
;
1335 HANDLE SymbolicLinkHandle
;
1337 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1339 ServiceNameLen
= wcslen(CanonName
);
1341 /* First check, if it's already good */
1342 if (ServiceNameLen
> 12 &&
1343 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1345 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1346 if (*RelativeName
== NULL
)
1348 DPRINT1("Error allocating memory for boot driver name!\n");
1349 return ERROR_NOT_ENOUGH_MEMORY
;
1353 wcscpy(*RelativeName
, CanonName
);
1355 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1356 return ERROR_SUCCESS
;
1359 /* If it has %SystemRoot% prefix, substitute it to \System*/
1360 if (ServiceNameLen
> 13 &&
1361 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1363 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1364 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1366 if (*RelativeName
== NULL
)
1368 DPRINT1("Error allocating memory for boot driver name!\n");
1369 return ERROR_NOT_ENOUGH_MEMORY
;
1373 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1374 wcscat(*RelativeName
, CanonName
+ 13);
1376 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1377 return ERROR_SUCCESS
;
1380 /* Get buffer size needed for expanding env strings */
1381 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1383 if (BufferSize
<= 1)
1385 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1386 return ERROR_INVALID_ENVIRONMENT
;
1389 /* Allocate memory, since the size is known now */
1390 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1393 DPRINT1("Error allocating memory for boot driver name!\n");
1394 return ERROR_NOT_ENOUGH_MEMORY
;
1398 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1401 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1402 LocalFree(Expanded
);
1403 return ERROR_NOT_ENOUGH_MEMORY
;
1406 /* Convert to NY-style path */
1407 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1409 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1410 return ERROR_INVALID_ENVIRONMENT
;
1413 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1415 /* No need to keep the dos-path anymore */
1416 LocalFree(Expanded
);
1418 /* Copy it to the allocated place */
1419 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1422 DPRINT1("Error allocating memory for boot driver name!\n");
1423 return ERROR_NOT_ENOUGH_MEMORY
;
1426 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1427 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1428 Expanded
[ExpandedLen
] = 0;
1430 if (ServiceNameLen
> ExpandedLen
&&
1431 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1433 /* Only \SystemRoot\ is missing */
1434 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1435 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1436 if (*RelativeName
== NULL
)
1438 DPRINT1("Error allocating memory for boot driver name!\n");
1439 LocalFree(Expanded
);
1440 return ERROR_NOT_ENOUGH_MEMORY
;
1443 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1444 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1446 RtlFreeUnicodeString(&NtPathName
);
1447 return ERROR_SUCCESS
;
1450 /* The most complex case starts here */
1451 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1452 InitializeObjectAttributes(&ObjectAttributes
,
1454 OBJ_CASE_INSENSITIVE
,
1458 /* Open this symlink */
1459 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1461 if (NT_SUCCESS(Status
))
1463 LinkTarget
.Length
= 0;
1464 LinkTarget
.MaximumLength
= 0;
1466 DPRINT("Opened symbolic link object\n");
1468 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1469 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1471 /* Check if required buffer size is sane */
1472 if (BufferSize
> 0xFFFD)
1474 DPRINT1("Too large buffer required\n");
1477 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1478 LocalFree(Expanded
);
1479 return ERROR_NOT_ENOUGH_MEMORY
;
1482 /* Alloc the string */
1483 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1484 if (!LinkTarget
.Buffer
)
1486 DPRINT1("Unable to alloc buffer\n");
1487 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1488 LocalFree(Expanded
);
1489 return ERROR_NOT_ENOUGH_MEMORY
;
1492 /* Do a real query now */
1493 LinkTarget
.Length
= BufferSize
;
1494 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1496 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1497 if (NT_SUCCESS(Status
))
1499 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1501 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1502 if ((ServiceNameLen
> ExpandedLen
) &&
1503 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1505 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1506 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1508 if (*RelativeName
== NULL
)
1510 DPRINT1("Unable to alloc buffer\n");
1511 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1512 LocalFree(Expanded
);
1513 RtlFreeUnicodeString(&NtPathName
);
1514 return ERROR_NOT_ENOUGH_MEMORY
;
1517 /* Copy it over, substituting the first part
1519 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1520 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1523 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1524 LocalFree(Expanded
);
1525 RtlFreeUnicodeString(&NtPathName
);
1527 /* Return success */
1528 return ERROR_SUCCESS
;
1532 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1533 LocalFree(Expanded
);
1534 RtlFreeUnicodeString(&NtPathName
);
1535 return ERROR_INVALID_PARAMETER
;
1540 DPRINT1("Error, Status = %08X\n", Status
);
1541 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1542 LocalFree(Expanded
);
1543 RtlFreeUnicodeString(&NtPathName
);
1544 return ERROR_INVALID_PARAMETER
;
1549 DPRINT1("Error, Status = %08X\n", Status
);
1550 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1551 LocalFree(Expanded
);
1552 RtlFreeUnicodeString(&NtPathName
);
1553 return ERROR_INVALID_PARAMETER
;
1558 DPRINT1("Error, Status = %08X\n", Status
);
1559 LocalFree(Expanded
);
1560 return ERROR_INVALID_PARAMETER
;
1564 *RelativeName
= NULL
;
1565 return ERROR_INVALID_PARAMETER
;
1569 ScmCanonDriverImagePath(DWORD dwStartType
,
1570 const wchar_t *lpServiceName
,
1571 wchar_t **lpCanonName
)
1573 DWORD ServiceNameLen
, Result
;
1574 UNICODE_STRING NtServiceName
;
1575 WCHAR
*RelativeName
;
1576 const WCHAR
*SourceName
= lpServiceName
;
1578 /* Calculate the length of the service's name */
1579 ServiceNameLen
= wcslen(lpServiceName
);
1581 /* 12 is wcslen(L"\\SystemRoot\\") */
1582 if (ServiceNameLen
> 12 &&
1583 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1585 /* SystemRoot prefix is already included */
1587 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1589 if (*lpCanonName
== NULL
)
1591 DPRINT1("Error allocating memory for canonized service name!\n");
1592 return ERROR_NOT_ENOUGH_MEMORY
;
1595 /* If it's a boot-time driver, it must be systemroot relative */
1596 if (dwStartType
== SERVICE_BOOT_START
)
1600 wcscpy(*lpCanonName
, SourceName
);
1602 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1606 /* Check if it has %SystemRoot% (len=13) */
1607 if (ServiceNameLen
> 13 &&
1608 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1610 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1611 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1613 if (*lpCanonName
== NULL
)
1615 DPRINT1("Error allocating memory for canonized service name!\n");
1616 return ERROR_NOT_ENOUGH_MEMORY
;
1619 /* If it's a boot-time driver, it must be systemroot relative */
1620 if (dwStartType
== SERVICE_BOOT_START
)
1621 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1623 wcscat(*lpCanonName
, lpServiceName
+ 13);
1625 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1629 /* Check if it's a relative path name */
1630 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1632 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1634 if (*lpCanonName
== NULL
)
1636 DPRINT1("Error allocating memory for canonized service name!\n");
1637 return ERROR_NOT_ENOUGH_MEMORY
;
1640 /* Just copy it over without changing */
1641 wcscpy(*lpCanonName
, lpServiceName
);
1646 /* It seems to be a DOS path, convert it */
1647 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1649 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1650 return ERROR_INVALID_PARAMETER
;
1653 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1655 if (*lpCanonName
== NULL
)
1657 DPRINT1("Error allocating memory for canonized service name!\n");
1658 RtlFreeUnicodeString(&NtServiceName
);
1659 return ERROR_NOT_ENOUGH_MEMORY
;
1662 /* Copy the string */
1663 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1665 /* The unicode string is not needed anymore */
1666 RtlFreeUnicodeString(&NtServiceName
);
1668 if (dwStartType
!= SERVICE_BOOT_START
)
1670 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1674 /* The service is boot-started, so must be relative */
1675 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1678 /* There is a problem, free name and return */
1679 LocalFree(*lpCanonName
);
1680 DPRINT1("Error converting named!\n");
1684 ASSERT(RelativeName
);
1686 /* Copy that string */
1687 wcscpy(*lpCanonName
, RelativeName
+ 12);
1689 /* Free the allocated buffer */
1690 LocalFree(RelativeName
);
1692 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1700 DWORD
RCreateServiceW(
1701 SC_RPC_HANDLE hSCManager
,
1702 LPCWSTR lpServiceName
,
1703 LPCWSTR lpDisplayName
,
1704 DWORD dwDesiredAccess
,
1705 DWORD dwServiceType
,
1707 DWORD dwErrorControl
,
1708 LPCWSTR lpBinaryPathName
,
1709 LPCWSTR lpLoadOrderGroup
,
1711 LPBYTE lpDependencies
,
1713 LPCWSTR lpServiceStartName
,
1716 LPSC_RPC_HANDLE lpServiceHandle
)
1718 PMANAGER_HANDLE hManager
;
1719 DWORD dwError
= ERROR_SUCCESS
;
1720 PSERVICE lpService
= NULL
;
1721 SC_HANDLE hServiceHandle
= NULL
;
1722 LPWSTR lpImagePath
= NULL
;
1723 HKEY hServiceKey
= NULL
;
1725 DPRINT("RCreateServiceW() called\n");
1726 DPRINT("lpServiceName = %S\n", lpServiceName
);
1727 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1728 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1729 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1730 DPRINT("dwStartType = %lu\n", dwStartType
);
1731 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1732 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1733 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1736 return ERROR_SHUTDOWN_IN_PROGRESS
;
1738 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1739 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1741 DPRINT1("Invalid manager handle!\n");
1742 return ERROR_INVALID_HANDLE
;
1745 /* Check access rights */
1746 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1747 SC_MANAGER_CREATE_SERVICE
))
1749 DPRINT1("Insufficient access rights! 0x%lx\n",
1750 hManager
->Handle
.DesiredAccess
);
1751 return ERROR_ACCESS_DENIED
;
1754 if (wcslen(lpServiceName
) == 0)
1756 return ERROR_INVALID_NAME
;
1759 if (wcslen(lpBinaryPathName
) == 0)
1761 return ERROR_INVALID_PARAMETER
;
1764 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1765 (lpServiceStartName
))
1767 return ERROR_INVALID_PARAMETER
;
1770 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1771 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1772 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1774 return ERROR_INVALID_PARAMETER
;
1777 if (dwStartType
> SERVICE_DISABLED
)
1779 return ERROR_INVALID_PARAMETER
;
1782 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1785 /* check if it is marked for deletion */
1786 if (lpService
->bDeleted
)
1787 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1788 /* Return Error exist */
1789 return ERROR_SERVICE_EXISTS
;
1792 if (lpDisplayName
!= NULL
&&
1793 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1794 return ERROR_DUPLICATE_SERVICE_NAME
;
1796 if (dwServiceType
& SERVICE_DRIVER
)
1798 dwError
= ScmCanonDriverImagePath(dwStartType
,
1801 if (dwError
!= ERROR_SUCCESS
)
1806 if (dwStartType
== SERVICE_BOOT_START
||
1807 dwStartType
== SERVICE_SYSTEM_START
)
1809 return ERROR_INVALID_PARAMETER
;
1813 /* Allocate a new service entry */
1814 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1816 if (dwError
!= ERROR_SUCCESS
)
1819 /* Fill the new service entry */
1820 lpService
->Status
.dwServiceType
= dwServiceType
;
1821 lpService
->dwStartType
= dwStartType
;
1822 lpService
->dwErrorControl
= dwErrorControl
;
1824 /* Fill the display name */
1825 if (lpDisplayName
!= NULL
&&
1826 *lpDisplayName
!= 0 &&
1827 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1829 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1830 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1831 if (lpService
->lpDisplayName
== NULL
)
1833 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1836 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1839 /* Assign the service to a group */
1840 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1842 dwError
= ScmSetServiceGroup(lpService
,
1844 if (dwError
!= ERROR_SUCCESS
)
1848 /* Assign a new tag */
1849 if (lpdwTagId
!= NULL
)
1851 dwError
= ScmAssignNewTag(lpService
);
1852 if (dwError
!= ERROR_SUCCESS
)
1856 /* Write service data to the registry */
1857 /* Create the service key */
1858 dwError
= ScmCreateServiceKey(lpServiceName
,
1861 if (dwError
!= ERROR_SUCCESS
)
1864 /* Set the display name */
1865 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1867 RegSetValueExW(hServiceKey
,
1871 (LPBYTE
)lpDisplayName
,
1872 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1875 /* Set the service type */
1876 dwError
= RegSetValueExW(hServiceKey
,
1880 (LPBYTE
)&dwServiceType
,
1882 if (dwError
!= ERROR_SUCCESS
)
1885 /* Set the start value */
1886 dwError
= RegSetValueExW(hServiceKey
,
1890 (LPBYTE
)&dwStartType
,
1892 if (dwError
!= ERROR_SUCCESS
)
1895 /* Set the error control value */
1896 dwError
= RegSetValueExW(hServiceKey
,
1900 (LPBYTE
)&dwErrorControl
,
1902 if (dwError
!= ERROR_SUCCESS
)
1905 /* Set the image path */
1906 if (dwServiceType
& SERVICE_WIN32
)
1908 dwError
= RegSetValueExW(hServiceKey
,
1912 (LPBYTE
)lpBinaryPathName
,
1913 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1914 if (dwError
!= ERROR_SUCCESS
)
1917 else if (dwServiceType
& SERVICE_DRIVER
)
1919 dwError
= RegSetValueExW(hServiceKey
,
1923 (LPBYTE
)lpImagePath
,
1924 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1925 if (dwError
!= ERROR_SUCCESS
)
1929 /* Set the group name */
1930 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1932 dwError
= RegSetValueExW(hServiceKey
,
1936 (LPBYTE
)lpLoadOrderGroup
,
1937 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1938 if (dwError
!= ERROR_SUCCESS
)
1942 if (lpdwTagId
!= NULL
)
1944 dwError
= RegSetValueExW(hServiceKey
,
1948 (LPBYTE
)&lpService
->dwTag
,
1950 if (dwError
!= ERROR_SUCCESS
)
1954 /* Write dependencies */
1955 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1957 dwError
= ScmWriteDependencies(hServiceKey
,
1958 (LPWSTR
)lpDependencies
,
1960 if (dwError
!= ERROR_SUCCESS
)
1964 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1965 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1967 dwError
= RegSetValueExW(hServiceKey
,
1971 (LPBYTE
)L
"LocalSystem",
1973 if (dwError
!= ERROR_SUCCESS
)
1977 if (lpPassword
!= NULL
)
1979 /* FIXME: Write password */
1982 dwError
= ScmCreateServiceHandle(lpService
,
1984 if (dwError
!= ERROR_SUCCESS
)
1987 dwError
= ScmCheckAccess(hServiceHandle
,
1989 if (dwError
!= ERROR_SUCCESS
)
1992 lpService
->dwRefCount
= 1;
1993 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
1996 if (hServiceKey
!= NULL
)
1997 RegCloseKey(hServiceKey
);
1999 if (dwError
== ERROR_SUCCESS
)
2001 DPRINT("hService %p\n", hServiceHandle
);
2002 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2004 if (lpdwTagId
!= NULL
)
2005 *lpdwTagId
= lpService
->dwTag
;
2009 /* Release the display name buffer */
2010 if (lpService
->lpServiceName
!= NULL
)
2011 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2015 /* Remove the service handle */
2016 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2019 if (lpService
!= NULL
)
2021 /* FIXME: remove the service entry */
2025 if (lpImagePath
!= NULL
)
2026 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2028 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2035 DWORD
REnumDependentServicesW(
2036 SC_RPC_HANDLE hService
,
2037 DWORD dwServiceState
,
2040 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2041 LPBOUNDED_DWORD_256K lpServicesReturned
)
2043 DWORD dwError
= ERROR_SUCCESS
;
2044 DWORD dwServicesReturned
= 0;
2045 DWORD dwServiceCount
;
2046 HKEY hServicesKey
= NULL
;
2047 LPSC_RPC_HANDLE hSCObject
;
2048 PSERVICE_HANDLE hSvc
;
2049 PSERVICE lpService
= NULL
;
2050 PSERVICE
*lpServicesArray
= NULL
;
2051 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2054 *pcbBytesNeeded
= 0;
2055 *lpServicesReturned
= 0;
2057 DPRINT("REnumDependentServicesW() called\n");
2059 hSCObject
= &hService
;
2060 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2061 lpService
= hSvc
->ServiceEntry
;
2063 /* Check access rights */
2064 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2065 SC_MANAGER_ENUMERATE_SERVICE
))
2067 DPRINT1("Insufficient access rights! 0x%lx\n",
2068 hSvc
->Handle
.DesiredAccess
);
2069 return ERROR_ACCESS_DENIED
;
2072 /* Open the Services Reg key */
2073 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2074 L
"System\\CurrentControlSet\\Services",
2078 if (dwError
!= ERROR_SUCCESS
)
2081 /* First determine the bytes needed and get the number of dependent services */
2082 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2087 &dwServicesReturned
);
2088 if (dwError
!= ERROR_SUCCESS
)
2091 /* If buffer size is less than the bytes needed or pointer is null */
2092 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2094 dwError
= ERROR_MORE_DATA
;
2098 /* Allocate memory for array of service pointers */
2099 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2101 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2102 if (!lpServicesArray
)
2104 DPRINT1("Could not allocate a buffer!!\n");
2105 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2109 dwServicesReturned
= 0;
2110 *pcbBytesNeeded
= 0;
2112 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2117 &dwServicesReturned
);
2118 if (dwError
!= ERROR_SUCCESS
)
2123 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2124 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2126 /* Copy EnumDepenedentService to Buffer */
2127 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2129 lpService
= lpServicesArray
[dwServiceCount
];
2131 /* Copy status info */
2132 memcpy(&lpServicesPtr
->ServiceStatus
,
2134 sizeof(SERVICE_STATUS
));
2136 /* Copy display name */
2137 wcscpy(lpStr
, lpService
->lpDisplayName
);
2138 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2139 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2141 /* Copy service name */
2142 wcscpy(lpStr
, lpService
->lpServiceName
);
2143 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2144 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2149 *lpServicesReturned
= dwServicesReturned
;
2152 if (lpServicesArray
!= NULL
)
2153 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2155 RegCloseKey(hServicesKey
);
2157 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2164 DWORD
REnumServicesStatusW(
2165 SC_RPC_HANDLE hSCManager
,
2166 DWORD dwServiceType
,
2167 DWORD dwServiceState
,
2170 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2171 LPBOUNDED_DWORD_256K lpServicesReturned
,
2172 LPBOUNDED_DWORD_256K lpResumeHandle
)
2174 PMANAGER_HANDLE hManager
;
2176 DWORD dwError
= ERROR_SUCCESS
;
2177 PLIST_ENTRY ServiceEntry
;
2178 PSERVICE CurrentService
;
2180 DWORD dwRequiredSize
;
2181 DWORD dwServiceCount
;
2183 DWORD dwLastResumeCount
= 0;
2184 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2187 DPRINT("REnumServicesStatusW() called\n");
2190 return ERROR_SHUTDOWN_IN_PROGRESS
;
2192 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2193 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2195 DPRINT1("Invalid manager handle!\n");
2196 return ERROR_INVALID_HANDLE
;
2199 *pcbBytesNeeded
= 0;
2200 *lpServicesReturned
= 0;
2202 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2204 DPRINT("Not a valid Service Type!\n");
2205 return ERROR_INVALID_PARAMETER
;
2208 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2210 DPRINT("Not a valid Service State!\n");
2211 return ERROR_INVALID_PARAMETER
;
2214 /* Check access rights */
2215 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2216 SC_MANAGER_ENUMERATE_SERVICE
))
2218 DPRINT1("Insufficient access rights! 0x%lx\n",
2219 hManager
->Handle
.DesiredAccess
);
2220 return ERROR_ACCESS_DENIED
;
2223 if (lpResumeHandle
) dwLastResumeCount
= *lpResumeHandle
;
2225 /* FIXME: Lock the service list shared */
2227 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2228 if (lpService
== NULL
)
2230 dwError
= ERROR_SUCCESS
;
2237 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2238 ServiceEntry
!= &ServiceListHead
;
2239 ServiceEntry
= ServiceEntry
->Flink
)
2241 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2245 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2248 dwState
= SERVICE_ACTIVE
;
2249 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2250 dwState
= SERVICE_INACTIVE
;
2252 if ((dwState
& dwServiceState
) == 0)
2255 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2256 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2257 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2259 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2261 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2265 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2266 dwRequiredSize
+= dwSize
;
2268 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2271 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2272 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2275 ServiceEntry
!= &ServiceListHead
;
2276 ServiceEntry
= ServiceEntry
->Flink
)
2278 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2282 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2285 dwState
= SERVICE_ACTIVE
;
2286 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2287 dwState
= SERVICE_INACTIVE
;
2289 if ((dwState
& dwServiceState
) == 0)
2292 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2293 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2294 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2296 dwError
= ERROR_MORE_DATA
;
2299 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2301 if (lpResumeHandle
) *lpResumeHandle
= dwLastResumeCount
;
2302 *lpServicesReturned
= dwServiceCount
;
2303 *pcbBytesNeeded
= dwRequiredSize
;
2305 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2306 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2307 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2310 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2311 ServiceEntry
!= &ServiceListHead
;
2312 ServiceEntry
= ServiceEntry
->Flink
)
2314 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2318 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2321 dwState
= SERVICE_ACTIVE
;
2322 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2323 dwState
= SERVICE_INACTIVE
;
2325 if ((dwState
& dwServiceState
) == 0)
2328 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2329 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2330 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2332 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2335 /* Copy the service name */
2336 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2337 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2338 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2340 /* Copy the display name */
2341 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2342 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2343 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2345 /* Copy the status information */
2346 memcpy(&lpStatusPtr
->ServiceStatus
,
2347 &CurrentService
->Status
,
2348 sizeof(SERVICE_STATUS
));
2351 dwRequiredSize
+= dwSize
;
2356 *pcbBytesNeeded
= 0;
2357 if (lpResumeHandle
) *lpResumeHandle
= 0;
2361 /* FIXME: Unlock the service list */
2363 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2370 DWORD
ROpenSCManagerW(
2371 LPWSTR lpMachineName
,
2372 LPWSTR lpDatabaseName
,
2373 DWORD dwDesiredAccess
,
2374 LPSC_RPC_HANDLE lpScHandle
)
2379 DPRINT("ROpenSCManagerW() called\n");
2380 DPRINT("lpMachineName = %p\n", lpMachineName
);
2381 DPRINT("lpMachineName: %S\n", lpMachineName
);
2382 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2383 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2384 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2387 return ERROR_SHUTDOWN_IN_PROGRESS
;
2390 return ERROR_INVALID_PARAMETER
;
2392 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2394 if (dwError
!= ERROR_SUCCESS
)
2396 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2400 /* Check the desired access */
2401 dwError
= ScmCheckAccess(hHandle
,
2402 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2403 if (dwError
!= ERROR_SUCCESS
)
2405 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2406 HeapFree(GetProcessHeap(), 0, hHandle
);
2410 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2411 DPRINT("*hScm = %p\n", *lpScHandle
);
2413 DPRINT("ROpenSCManagerW() done\n");
2415 return ERROR_SUCCESS
;
2420 DWORD
ROpenServiceW(
2421 SC_RPC_HANDLE hSCManager
,
2422 LPWSTR lpServiceName
,
2423 DWORD dwDesiredAccess
,
2424 LPSC_RPC_HANDLE lpServiceHandle
)
2427 PMANAGER_HANDLE hManager
;
2431 DPRINT("ROpenServiceW() called\n");
2432 DPRINT("hSCManager = %p\n", hSCManager
);
2433 DPRINT("lpServiceName = %p\n", lpServiceName
);
2434 DPRINT("lpServiceName: %S\n", lpServiceName
);
2435 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2438 return ERROR_SHUTDOWN_IN_PROGRESS
;
2440 if (!lpServiceHandle
)
2441 return ERROR_INVALID_PARAMETER
;
2444 return ERROR_INVALID_ADDRESS
;
2446 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2447 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2449 DPRINT1("Invalid manager handle!\n");
2450 return ERROR_INVALID_HANDLE
;
2453 /* FIXME: Lock the service list */
2455 /* Get service database entry */
2456 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2457 if (lpService
== NULL
)
2459 DPRINT("Could not find a service!\n");
2460 return ERROR_SERVICE_DOES_NOT_EXIST
;
2463 /* Create a service handle */
2464 dwError
= ScmCreateServiceHandle(lpService
,
2466 if (dwError
!= ERROR_SUCCESS
)
2468 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2472 /* Check the desired access */
2473 dwError
= ScmCheckAccess(hHandle
,
2475 if (dwError
!= ERROR_SUCCESS
)
2477 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2478 HeapFree(GetProcessHeap(), 0, hHandle
);
2482 lpService
->dwRefCount
++;
2483 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2485 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2486 DPRINT("*hService = %p\n", *lpServiceHandle
);
2488 DPRINT("ROpenServiceW() done\n");
2490 return ERROR_SUCCESS
;
2495 DWORD
RQueryServiceConfigW(
2496 SC_RPC_HANDLE hService
,
2497 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2499 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2501 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2502 DWORD dwError
= ERROR_SUCCESS
;
2503 PSERVICE_HANDLE hSvc
;
2504 PSERVICE lpService
= NULL
;
2505 HKEY hServiceKey
= NULL
;
2506 LPWSTR lpImagePath
= NULL
;
2507 LPWSTR lpServiceStartName
= NULL
;
2508 DWORD dwRequiredSize
;
2509 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2510 WCHAR lpEmptyString
[] = {0,0};
2513 DPRINT("RQueryServiceConfigW() called\n");
2516 return ERROR_SHUTDOWN_IN_PROGRESS
;
2518 hSvc
= (PSERVICE_HANDLE
)hService
;
2519 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2521 DPRINT1("Invalid handle tag!\n");
2522 return ERROR_INVALID_HANDLE
;
2525 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2526 SERVICE_QUERY_CONFIG
))
2528 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2529 return ERROR_ACCESS_DENIED
;
2532 lpService
= hSvc
->ServiceEntry
;
2533 if (lpService
== NULL
)
2535 DPRINT1("lpService == NULL!\n");
2536 return ERROR_INVALID_HANDLE
;
2539 /* FIXME: Lock the service database shared */
2541 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2544 if (dwError
!= ERROR_SUCCESS
)
2547 dwError
= ScmReadString(hServiceKey
,
2550 if (dwError
!= ERROR_SUCCESS
)
2553 ScmReadString(hServiceKey
,
2555 &lpServiceStartName
);
2557 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2559 if (lpImagePath
!= NULL
)
2560 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2562 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2564 if (lpService
->lpGroup
!= NULL
)
2565 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2567 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2569 /* FIXME: Add Dependencies length*/
2571 if (lpServiceStartName
!= NULL
)
2572 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2574 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2576 if (lpService
->lpDisplayName
!= NULL
)
2577 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2579 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2581 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2583 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2587 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2588 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2589 lpConfig
->dwStartType
= lpService
->dwStartType
;
2590 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2591 lpConfig
->dwTagId
= lpService
->dwTag
;
2593 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2595 if (lpImagePath
!= NULL
)
2597 wcscpy(lpStr
, lpImagePath
);
2601 wcscpy(lpStr
, lpEmptyString
);
2604 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2605 lpStr
+= (wcslen(lpStr
) + 1);
2607 if (lpService
->lpGroup
!= NULL
)
2609 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2613 wcscpy(lpStr
, lpEmptyString
);
2616 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2617 lpStr
+= (wcslen(lpStr
) + 1);
2619 /* FIXME: Append Dependencies */
2620 wcscpy(lpStr
, lpEmptyString
);
2622 lpStr
+= (wcslen(lpStr
) + 1);
2623 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2625 if (lpServiceStartName
!= NULL
)
2627 wcscpy(lpStr
, lpServiceStartName
);
2631 wcscpy(lpStr
, lpEmptyString
);
2634 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2635 lpStr
+= (wcslen(lpStr
) + 1);
2637 if (lpService
->lpDisplayName
!= NULL
)
2639 wcscpy(lpStr
, lpService
->lpDisplayName
);
2643 wcscpy(lpStr
, lpEmptyString
);
2646 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2649 if (pcbBytesNeeded
!= NULL
)
2650 *pcbBytesNeeded
= dwRequiredSize
;
2653 if (lpImagePath
!= NULL
)
2654 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2656 if (lpServiceStartName
!= NULL
)
2657 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2659 if (hServiceKey
!= NULL
)
2660 RegCloseKey(hServiceKey
);
2662 /* FIXME: Unlock the service database */
2664 DPRINT("RQueryServiceConfigW() done\n");
2671 DWORD
RQueryServiceLockStatusW(
2672 SC_RPC_HANDLE hSCManager
,
2673 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2675 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2678 return ERROR_CALL_NOT_IMPLEMENTED
;
2683 DWORD
RStartServiceW(
2684 SC_RPC_HANDLE hService
,
2686 LPSTRING_PTRSW argv
)
2688 DWORD dwError
= ERROR_SUCCESS
;
2689 PSERVICE_HANDLE hSvc
;
2690 PSERVICE lpService
= NULL
;
2692 DPRINT("RStartServiceW() called\n");
2695 return ERROR_SHUTDOWN_IN_PROGRESS
;
2697 hSvc
= (PSERVICE_HANDLE
)hService
;
2698 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2700 DPRINT1("Invalid handle tag!\n");
2701 return ERROR_INVALID_HANDLE
;
2704 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2707 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2708 return ERROR_ACCESS_DENIED
;
2711 lpService
= hSvc
->ServiceEntry
;
2712 if (lpService
== NULL
)
2714 DPRINT1("lpService == NULL!\n");
2715 return ERROR_INVALID_HANDLE
;
2718 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2719 return ERROR_SERVICE_DISABLED
;
2721 if (lpService
->bDeleted
)
2722 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2729 /* Start the service */
2730 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2737 DWORD
RGetServiceDisplayNameW(
2738 SC_RPC_HANDLE hSCManager
,
2739 LPCWSTR lpServiceName
,
2740 LPWSTR lpDisplayName
,
2743 // PMANAGER_HANDLE hManager;
2748 DPRINT("RGetServiceDisplayNameW() called\n");
2749 DPRINT("hSCManager = %p\n", hSCManager
);
2750 DPRINT("lpServiceName: %S\n", lpServiceName
);
2751 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2752 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2754 // hManager = (PMANAGER_HANDLE)hSCManager;
2755 // if (hManager->Handle.Tag != MANAGER_TAG)
2757 // DPRINT1("Invalid manager handle!\n");
2758 // return ERROR_INVALID_HANDLE;
2761 /* Get service database entry */
2762 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2763 if (lpService
== NULL
)
2765 DPRINT1("Could not find a service!\n");
2767 /* If the service could not be found and lpcchBuffer is 0, windows
2768 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2769 if (*lpcchBuffer
== 0)
2772 if (lpDisplayName
!= NULL
)
2774 *lpDisplayName
= '\0';
2778 return ERROR_SERVICE_DOES_NOT_EXIST
;
2781 if (!lpService
->lpDisplayName
)
2783 dwLength
= wcslen(lpService
->lpServiceName
);
2785 if (lpDisplayName
!= NULL
&&
2786 *lpcchBuffer
> dwLength
)
2788 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2793 dwLength
= wcslen(lpService
->lpDisplayName
);
2795 if (lpDisplayName
!= NULL
&&
2796 *lpcchBuffer
> dwLength
)
2798 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2802 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2804 *lpcchBuffer
= dwLength
;
2811 DWORD
RGetServiceKeyNameW(
2812 SC_RPC_HANDLE hSCManager
,
2813 LPCWSTR lpDisplayName
,
2814 LPWSTR lpServiceName
,
2817 // PMANAGER_HANDLE hManager;
2822 DPRINT("RGetServiceKeyNameW() called\n");
2823 DPRINT("hSCManager = %p\n", hSCManager
);
2824 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2825 DPRINT("lpServiceName: %p\n", lpServiceName
);
2826 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2828 // hManager = (PMANAGER_HANDLE)hSCManager;
2829 // if (hManager->Handle.Tag != MANAGER_TAG)
2831 // DPRINT1("Invalid manager handle!\n");
2832 // return ERROR_INVALID_HANDLE;
2835 /* Get service database entry */
2836 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2837 if (lpService
== NULL
)
2839 DPRINT1("Could not find a service!\n");
2841 /* If the service could not be found and lpcchBuffer is 0, windows
2842 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2843 if (*lpcchBuffer
== 0)
2846 if (lpServiceName
!= NULL
)
2848 *lpServiceName
= '\0';
2852 return ERROR_SERVICE_DOES_NOT_EXIST
;
2855 dwLength
= wcslen(lpService
->lpServiceName
);
2857 if (lpServiceName
!= NULL
&&
2858 *lpcchBuffer
> dwLength
)
2860 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2861 *lpcchBuffer
= dwLength
;
2862 return ERROR_SUCCESS
;
2865 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2867 *lpcchBuffer
= dwLength
* 2;
2874 DWORD
RI_ScSetServiceBitsA(
2875 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
2876 DWORD dwServiceBits
,
2878 int bUpdateImmediately
,
2882 return ERROR_CALL_NOT_IMPLEMENTED
;
2887 DWORD
RChangeServiceConfigA(
2888 SC_RPC_HANDLE hService
,
2889 DWORD dwServiceType
,
2891 DWORD dwErrorControl
,
2892 LPSTR lpBinaryPathName
,
2893 LPSTR lpLoadOrderGroup
,
2895 LPSTR lpDependencies
,
2897 LPSTR lpServiceStartName
,
2900 LPSTR lpDisplayName
)
2902 DWORD dwError
= ERROR_SUCCESS
;
2903 PSERVICE_HANDLE hSvc
;
2904 PSERVICE lpService
= NULL
;
2905 HKEY hServiceKey
= NULL
;
2906 LPWSTR lpDisplayNameW
= NULL
;
2907 // LPWSTR lpBinaryPathNameW = NULL;
2908 LPWSTR lpLoadOrderGroupW
= NULL
;
2909 LPWSTR lpDependenciesW
= NULL
;
2910 // LPWSTR lpPasswordW = NULL;
2912 DPRINT("RChangeServiceConfigA() called\n");
2913 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2914 DPRINT("dwStartType = %lu\n", dwStartType
);
2915 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2916 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2917 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2918 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2921 return ERROR_SHUTDOWN_IN_PROGRESS
;
2923 hSvc
= (PSERVICE_HANDLE
)hService
;
2924 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2926 DPRINT1("Invalid handle tag!\n");
2927 return ERROR_INVALID_HANDLE
;
2930 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2931 SERVICE_CHANGE_CONFIG
))
2933 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2934 return ERROR_ACCESS_DENIED
;
2937 lpService
= hSvc
->ServiceEntry
;
2938 if (lpService
== NULL
)
2940 DPRINT1("lpService == NULL!\n");
2941 return ERROR_INVALID_HANDLE
;
2944 /* FIXME: Lock database exclusively */
2946 if (lpService
->bDeleted
)
2948 /* FIXME: Unlock database */
2949 DPRINT1("The service has already been marked for delete!\n");
2950 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2953 /* Open the service key */
2954 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2957 if (dwError
!= ERROR_SUCCESS
)
2960 /* Write service data to the registry */
2962 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2964 /* Set the display name */
2965 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2967 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2968 if (lpDisplayNameW
== NULL
)
2970 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2974 MultiByteToWideChar(CP_ACP
,
2979 wcslen(lpDisplayNameW
) + 1);
2981 RegSetValueExW(hServiceKey
,
2985 (LPBYTE
)lpDisplayNameW
,
2986 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2988 /* Update lpService->lpDisplayName */
2989 if (lpService
->lpDisplayName
)
2990 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2992 lpService
->lpDisplayName
= lpDisplayNameW
;
2995 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2997 /* Set the service type */
2998 dwError
= RegSetValueExW(hServiceKey
,
3002 (LPBYTE
)&dwServiceType
,
3004 if (dwError
!= ERROR_SUCCESS
)
3007 lpService
->Status
.dwServiceType
= dwServiceType
;
3010 if (dwStartType
!= SERVICE_NO_CHANGE
)
3012 /* Set the start value */
3013 dwError
= RegSetValueExW(hServiceKey
,
3017 (LPBYTE
)&dwStartType
,
3019 if (dwError
!= ERROR_SUCCESS
)
3022 lpService
->dwStartType
= dwStartType
;
3025 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3027 /* Set the error control value */
3028 dwError
= RegSetValueExW(hServiceKey
,
3032 (LPBYTE
)&dwErrorControl
,
3034 if (dwError
!= ERROR_SUCCESS
)
3037 lpService
->dwErrorControl
= dwErrorControl
;
3041 /* FIXME: set the new ImagePath value */
3043 /* Set the image path */
3044 if (dwServiceType
& SERVICE_WIN32
)
3046 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3048 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3049 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3050 dwError
= RegSetValueExW(hServiceKey
,
3054 (LPBYTE
)lpBinaryPathNameW
,
3055 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3056 if (dwError
!= ERROR_SUCCESS
)
3060 else if (dwServiceType
& SERVICE_DRIVER
)
3062 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3064 dwError
= RegSetValueExW(hServiceKey
,
3068 (LPBYTE
)lpImagePath
,
3069 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3070 if (dwError
!= ERROR_SUCCESS
)
3076 /* Set the group name */
3077 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3079 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3081 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3082 if (lpLoadOrderGroupW
== NULL
)
3084 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3088 MultiByteToWideChar(CP_ACP
,
3093 wcslen(lpLoadOrderGroupW
) + 1);
3095 dwError
= RegSetValueExW(hServiceKey
,
3099 (LPBYTE
)lpLoadOrderGroupW
,
3100 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3101 if (dwError
!= ERROR_SUCCESS
)
3104 /* FIXME: Update lpService->lpServiceGroup */
3106 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3109 if (lpdwTagId
!= NULL
)
3111 dwError
= ScmAssignNewTag(lpService
);
3112 if (dwError
!= ERROR_SUCCESS
)
3115 dwError
= RegSetValueExW(hServiceKey
,
3119 (LPBYTE
)&lpService
->dwTag
,
3121 if (dwError
!= ERROR_SUCCESS
)
3124 *lpdwTagId
= lpService
->dwTag
;
3127 /* Write dependencies */
3128 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3130 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3132 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3133 if (lpDependenciesW
== NULL
)
3135 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3139 MultiByteToWideChar(CP_ACP
,
3144 wcslen(lpDependenciesW
)+1);
3146 dwError
= ScmWriteDependencies(hServiceKey
,
3147 (LPWSTR
)lpDependenciesW
,
3150 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3153 if (lpPassword
!= NULL
)
3155 /* FIXME: Write password */
3158 /* FIXME: Unlock database */
3161 if (hServiceKey
!= NULL
)
3162 RegCloseKey(hServiceKey
);
3164 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3171 DWORD
RCreateServiceA(
3172 SC_RPC_HANDLE hSCManager
,
3173 LPSTR lpServiceName
,
3174 LPSTR lpDisplayName
,
3175 DWORD dwDesiredAccess
,
3176 DWORD dwServiceType
,
3178 DWORD dwErrorControl
,
3179 LPSTR lpBinaryPathName
,
3180 LPSTR lpLoadOrderGroup
,
3182 LPBYTE lpDependencies
,
3184 LPSTR lpServiceStartName
,
3187 LPSC_RPC_HANDLE lpServiceHandle
)
3190 return ERROR_CALL_NOT_IMPLEMENTED
;
3195 DWORD
REnumDependentServicesA(
3196 SC_RPC_HANDLE hService
,
3197 DWORD dwServiceState
,
3200 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3201 LPBOUNDED_DWORD_256K lpServicesReturned
)
3203 DWORD dwError
= ERROR_SUCCESS
;
3204 DWORD dwServicesReturned
= 0;
3205 DWORD dwServiceCount
;
3206 HKEY hServicesKey
= NULL
;
3207 LPSC_RPC_HANDLE hSCObject
;
3208 PSERVICE_HANDLE hSvc
;
3209 PSERVICE lpService
= NULL
;
3210 PSERVICE
*lpServicesArray
= NULL
;
3211 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3214 *pcbBytesNeeded
= 0;
3215 *lpServicesReturned
= 0;
3217 DPRINT("REnumDependentServicesA() called\n");
3219 hSCObject
= &hService
;
3220 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3221 lpService
= hSvc
->ServiceEntry
;
3223 /* Check access rights */
3224 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3225 SC_MANAGER_ENUMERATE_SERVICE
))
3227 DPRINT1("Insufficient access rights! 0x%lx\n",
3228 hSvc
->Handle
.DesiredAccess
);
3229 return ERROR_ACCESS_DENIED
;
3232 /* Open the Services Reg key */
3233 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3234 L
"System\\CurrentControlSet\\Services",
3239 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3241 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3242 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3243 are the same for both. Verified in WINXP. */
3245 /* First determine the bytes needed and get the number of dependent services*/
3246 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3251 &dwServicesReturned
);
3252 if (dwError
!= ERROR_SUCCESS
)
3255 /* If buffer size is less than the bytes needed or pointer is null*/
3256 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3258 dwError
= ERROR_MORE_DATA
;
3262 /* Allocate memory for array of service pointers */
3263 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3265 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3266 if (!lpServicesArray
)
3268 DPRINT1("Could not allocate a buffer!!\n");
3269 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3273 dwServicesReturned
= 0;
3274 *pcbBytesNeeded
= 0;
3276 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3281 &dwServicesReturned
);
3282 if (dwError
!= ERROR_SUCCESS
)
3287 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3288 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3290 /* Copy EnumDepenedentService to Buffer */
3291 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3293 lpService
= lpServicesArray
[dwServiceCount
];
3295 /* Copy the status info */
3296 memcpy(&lpServicesPtr
->ServiceStatus
,
3298 sizeof(SERVICE_STATUS
));
3300 /* Copy display name */
3301 WideCharToMultiByte(CP_ACP
,
3303 lpService
->lpDisplayName
,
3306 wcslen(lpService
->lpDisplayName
),
3309 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3310 lpStr
+= strlen(lpStr
) + 1;
3312 /* Copy service name */
3313 WideCharToMultiByte(CP_ACP
,
3315 lpService
->lpServiceName
,
3318 wcslen(lpService
->lpServiceName
),
3321 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3322 lpStr
+= strlen(lpStr
) + 1;
3327 *lpServicesReturned
= dwServicesReturned
;
3330 if (lpServicesArray
)
3331 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3333 RegCloseKey(hServicesKey
);
3335 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3342 DWORD
REnumServicesStatusA(
3343 SC_RPC_HANDLE hSCManager
,
3344 DWORD dwServiceType
,
3345 DWORD dwServiceState
,
3348 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3349 LPBOUNDED_DWORD_256K lpServicesReturned
,
3350 LPBOUNDED_DWORD_256K lpResumeHandle
)
3352 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3353 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3354 LPWSTR lpStringPtrW
;
3357 DWORD dwServiceCount
;
3359 DPRINT("REnumServicesStatusA() called\n");
3361 if ((dwBufSize
> 0) && (lpBuffer
))
3363 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3366 DPRINT1("Failed to allocate buffer!\n");
3367 return ERROR_NOT_ENOUGH_MEMORY
;
3371 dwError
= REnumServicesStatusW(//BindingHandle,
3375 (LPBYTE
)lpStatusPtrW
,
3381 /* if no services were returned then we are Done */
3382 if (*lpServicesReturned
== 0) goto Done
;
3384 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3385 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3386 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3387 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3388 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3390 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3392 /* Copy the service name */
3393 WideCharToMultiByte(CP_ACP
,
3398 wcslen(lpStringPtrW
),
3402 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3403 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3404 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3406 /* Copy the display name */
3407 WideCharToMultiByte(CP_ACP
,
3412 wcslen(lpStringPtrW
),
3416 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3417 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3418 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3420 /* Copy the status information */
3421 memcpy(&lpStatusPtrA
->ServiceStatus
,
3422 &lpStatusPtrW
->ServiceStatus
,
3423 sizeof(SERVICE_STATUS
));
3429 if (lpStatusPtrW
) HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3431 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3438 DWORD
ROpenSCManagerA(
3439 LPSTR lpMachineName
,
3440 LPSTR lpDatabaseName
,
3441 DWORD dwDesiredAccess
,
3442 LPSC_RPC_HANDLE lpScHandle
)
3444 UNICODE_STRING MachineName
;
3445 UNICODE_STRING DatabaseName
;
3448 DPRINT("ROpenSCManagerA() called\n");
3451 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3455 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3458 dwError
= ROpenSCManagerW(//BindingHandle,
3459 lpMachineName
? MachineName
.Buffer
: NULL
,
3460 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3465 RtlFreeUnicodeString(&MachineName
);
3468 RtlFreeUnicodeString(&DatabaseName
);
3475 DWORD
ROpenServiceA(
3476 SC_RPC_HANDLE hSCManager
,
3477 LPSTR lpServiceName
,
3478 DWORD dwDesiredAccess
,
3479 LPSC_RPC_HANDLE lpServiceHandle
)
3481 UNICODE_STRING ServiceName
;
3484 DPRINT("ROpenServiceA() called\n");
3487 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3490 dwError
= ROpenServiceW(//BindingHandle,
3492 lpServiceName
? ServiceName
.Buffer
: NULL
,
3497 RtlFreeUnicodeString(&ServiceName
);
3504 DWORD
RQueryServiceConfigA(
3505 SC_RPC_HANDLE hService
,
3506 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3508 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3510 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3511 DWORD dwError
= ERROR_SUCCESS
;
3512 PSERVICE_HANDLE hSvc
;
3513 PSERVICE lpService
= NULL
;
3514 HKEY hServiceKey
= NULL
;
3515 LPWSTR lpImagePath
= NULL
;
3516 LPWSTR lpServiceStartName
= NULL
;
3517 DWORD dwRequiredSize
;
3518 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3519 CHAR lpEmptyString
[]={0,0};
3522 DPRINT("RQueryServiceConfigA() called\n");
3525 return ERROR_SHUTDOWN_IN_PROGRESS
;
3527 hSvc
= (PSERVICE_HANDLE
)hService
;
3528 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3530 DPRINT1("Invalid handle tag!\n");
3531 return ERROR_INVALID_HANDLE
;
3534 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3535 SERVICE_QUERY_CONFIG
))
3537 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3538 return ERROR_ACCESS_DENIED
;
3541 lpService
= hSvc
->ServiceEntry
;
3542 if (lpService
== NULL
)
3544 DPRINT1("lpService == NULL!\n");
3545 return ERROR_INVALID_HANDLE
;
3548 /* FIXME: Lock the service database shared */
3550 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3553 if (dwError
!= ERROR_SUCCESS
)
3556 dwError
= ScmReadString(hServiceKey
,
3559 if (dwError
!= ERROR_SUCCESS
)
3562 ScmReadString(hServiceKey
,
3564 &lpServiceStartName
);
3566 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3568 if (lpImagePath
!= NULL
)
3569 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3571 dwRequiredSize
+= 2;
3573 if (lpService
->lpGroup
!= NULL
)
3574 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3576 dwRequiredSize
+= 2;
3578 /* FIXME: Add Dependencies length*/
3579 dwRequiredSize
+= 2;
3581 if (lpServiceStartName
!= NULL
)
3582 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3584 dwRequiredSize
+= 2;
3586 if (lpService
->lpDisplayName
!= NULL
)
3587 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3589 dwRequiredSize
+= 2;
3591 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3593 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3597 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3598 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3599 lpConfig
->dwStartType
= lpService
->dwStartType
;
3600 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3601 lpConfig
->dwTagId
= lpService
->dwTag
;
3603 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3605 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3610 WideCharToMultiByte(CP_ACP
,
3615 wcslen(lpImagePath
),
3621 strcpy(lpStr
, lpEmptyString
);
3624 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3625 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3627 if (lpService
->lpGroup
)
3629 WideCharToMultiByte(CP_ACP
,
3631 lpService
->lpGroup
->lpGroupName
,
3634 wcslen(lpService
->lpGroup
->lpGroupName
),
3640 strcpy(lpStr
, lpEmptyString
);
3643 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3644 lpStr
+= (strlen(lpStr
) + 1);
3646 /* FIXME: Append Dependencies */
3647 strcpy(lpStr
, lpEmptyString
);
3649 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3650 lpStr
+= (strlen(lpStr
) + 1);
3652 if (lpServiceStartName
)
3654 WideCharToMultiByte(CP_ACP
,
3659 wcslen(lpServiceStartName
),
3665 strcpy(lpStr
, lpEmptyString
);
3668 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3669 lpStr
+= (strlen(lpStr
) + 1);
3671 if (lpService
->lpDisplayName
)
3673 WideCharToMultiByte(CP_ACP
,
3675 lpService
->lpDisplayName
,
3678 wcslen(lpService
->lpDisplayName
),
3684 strcpy(lpStr
, lpEmptyString
);
3687 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3690 if (pcbBytesNeeded
!= NULL
)
3691 *pcbBytesNeeded
= dwRequiredSize
;
3694 if (lpImagePath
!= NULL
)
3695 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3697 if (lpServiceStartName
!= NULL
)
3698 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3700 if (hServiceKey
!= NULL
)
3701 RegCloseKey(hServiceKey
);
3703 /* FIXME: Unlock the service database */
3705 DPRINT("RQueryServiceConfigA() done\n");
3712 DWORD
RQueryServiceLockStatusA(
3713 SC_RPC_HANDLE hSCManager
,
3714 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3716 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3719 return ERROR_CALL_NOT_IMPLEMENTED
;
3724 DWORD
RStartServiceA(
3725 SC_RPC_HANDLE hService
,
3727 LPSTRING_PTRSA argv
)
3729 DWORD dwError
= ERROR_SUCCESS
;
3730 PSERVICE_HANDLE hSvc
;
3731 PSERVICE lpService
= NULL
;
3733 DPRINT1("RStartServiceA() called\n");
3736 return ERROR_SHUTDOWN_IN_PROGRESS
;
3738 hSvc
= (PSERVICE_HANDLE
)hService
;
3739 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3741 DPRINT1("Invalid handle tag!\n");
3742 return ERROR_INVALID_HANDLE
;
3745 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3748 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3749 return ERROR_ACCESS_DENIED
;
3752 lpService
= hSvc
->ServiceEntry
;
3753 if (lpService
== NULL
)
3755 DPRINT1("lpService == NULL!\n");
3756 return ERROR_INVALID_HANDLE
;
3759 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3760 return ERROR_SERVICE_DISABLED
;
3762 if (lpService
->bDeleted
)
3763 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3765 /* FIXME: Convert argument vector to Unicode */
3767 /* Start the service */
3768 dwError
= ScmStartService(lpService
, 0, NULL
);
3770 /* FIXME: Free argument vector */
3777 DWORD
RGetServiceDisplayNameA(
3778 SC_RPC_HANDLE hSCManager
,
3779 LPCSTR lpServiceName
,
3780 LPSTR lpDisplayName
,
3781 LPBOUNDED_DWORD_4K lpcchBuffer
)
3783 // PMANAGER_HANDLE hManager;
3784 PSERVICE lpService
= NULL
;
3787 LPWSTR lpServiceNameW
;
3789 DPRINT("RGetServiceDisplayNameA() called\n");
3790 DPRINT("hSCManager = %p\n", hSCManager
);
3791 DPRINT("lpServiceName: %s\n", lpServiceName
);
3792 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3793 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3795 // hManager = (PMANAGER_HANDLE)hSCManager;
3796 // if (hManager->Handle.Tag != MANAGER_TAG)
3798 // DPRINT1("Invalid manager handle!\n");
3799 // return ERROR_INVALID_HANDLE;
3802 if (lpServiceName
!= NULL
)
3804 dwLength
= strlen(lpServiceName
) + 1;
3805 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3807 dwLength
* sizeof(WCHAR
));
3808 if (!lpServiceNameW
)
3809 return ERROR_NOT_ENOUGH_MEMORY
;
3811 MultiByteToWideChar(CP_ACP
,
3818 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3820 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3823 if (lpService
== NULL
)
3825 DPRINT1("Could not find a service!\n");
3827 /* If the service could not be found and lpcchBuffer is 0, windows
3828 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3829 if (*lpcchBuffer
== 0)
3832 if (lpDisplayName
!= NULL
)
3834 *lpDisplayName
= '\0';
3837 return ERROR_SERVICE_DOES_NOT_EXIST
;
3840 if (!lpService
->lpDisplayName
)
3842 dwLength
= wcslen(lpService
->lpServiceName
);
3843 if (lpDisplayName
!= NULL
&&
3844 *lpcchBuffer
> dwLength
)
3846 WideCharToMultiByte(CP_ACP
,
3848 lpService
->lpServiceName
,
3849 wcslen(lpService
->lpServiceName
),
3854 return ERROR_SUCCESS
;
3859 dwLength
= wcslen(lpService
->lpDisplayName
);
3860 if (lpDisplayName
!= NULL
&&
3861 *lpcchBuffer
> dwLength
)
3863 WideCharToMultiByte(CP_ACP
,
3865 lpService
->lpDisplayName
,
3866 wcslen(lpService
->lpDisplayName
),
3871 return ERROR_SUCCESS
;
3875 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3877 *lpcchBuffer
= dwLength
* 2;
3884 DWORD
RGetServiceKeyNameA(
3885 SC_RPC_HANDLE hSCManager
,
3886 LPCSTR lpDisplayName
,
3887 LPSTR lpServiceName
,
3888 LPBOUNDED_DWORD_4K lpcchBuffer
)
3893 LPWSTR lpDisplayNameW
;
3895 DPRINT("RGetServiceKeyNameA() called\n");
3896 DPRINT("hSCManager = %p\n", hSCManager
);
3897 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3898 DPRINT("lpServiceName: %p\n", lpServiceName
);
3899 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3901 dwLength
= strlen(lpDisplayName
) + 1;
3902 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3904 dwLength
* sizeof(WCHAR
));
3905 if (!lpDisplayNameW
)
3906 return ERROR_NOT_ENOUGH_MEMORY
;
3908 MultiByteToWideChar(CP_ACP
,
3915 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
3917 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3919 if (lpService
== NULL
)
3921 DPRINT1("Could not find the service!\n");
3923 /* If the service could not be found and lpcchBuffer is 0,
3924 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
3925 if (*lpcchBuffer
== 0)
3928 if (lpServiceName
!= NULL
)
3930 *lpServiceName
= '\0';
3934 return ERROR_SERVICE_DOES_NOT_EXIST
;
3937 dwLength
= wcslen(lpService
->lpServiceName
);
3938 if (lpServiceName
!= NULL
&&
3939 *lpcchBuffer
> dwLength
)
3941 WideCharToMultiByte(CP_ACP
,
3943 lpService
->lpServiceName
,
3944 wcslen(lpService
->lpServiceName
),
3949 return ERROR_SUCCESS
;
3952 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3954 *lpcchBuffer
= dwLength
* 2;
3961 DWORD
RI_ScGetCurrentGroupStateW(
3962 SC_RPC_HANDLE hSCManager
,
3963 LPWSTR lpLoadOrderGroup
,
3967 return ERROR_CALL_NOT_IMPLEMENTED
;
3972 DWORD
REnumServiceGroupW(
3973 SC_RPC_HANDLE hSCManager
,
3974 DWORD dwServiceType
,
3975 DWORD dwServiceState
,
3978 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3979 LPBOUNDED_DWORD_256K lpServicesReturned
,
3980 LPBOUNDED_DWORD_256K lpResumeIndex
,
3981 LPCWSTR pszGroupName
)
3984 return ERROR_CALL_NOT_IMPLEMENTED
;
3989 DWORD
RChangeServiceConfig2A(
3990 SC_RPC_HANDLE hService
,
3991 SC_RPC_CONFIG_INFOA Info
)
3994 return ERROR_CALL_NOT_IMPLEMENTED
;
3999 DWORD
RChangeServiceConfig2W(
4000 SC_RPC_HANDLE hService
,
4001 SC_RPC_CONFIG_INFOW Info
)
4003 DWORD dwError
= ERROR_SUCCESS
;
4004 PSERVICE_HANDLE hSvc
;
4005 PSERVICE lpService
= NULL
;
4006 HKEY hServiceKey
= NULL
;
4008 DPRINT("RChangeServiceConfig2W() called\n");
4009 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4012 return ERROR_SHUTDOWN_IN_PROGRESS
;
4014 hSvc
= (PSERVICE_HANDLE
)hService
;
4015 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4017 DPRINT1("Invalid handle tag!\n");
4018 return ERROR_INVALID_HANDLE
;
4021 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4022 SERVICE_CHANGE_CONFIG
))
4024 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4025 return ERROR_ACCESS_DENIED
;
4028 lpService
= hSvc
->ServiceEntry
;
4029 if (lpService
== NULL
)
4031 DPRINT1("lpService == NULL!\n");
4032 return ERROR_INVALID_HANDLE
;
4035 /* FIXME: Lock database exclusively */
4037 if (lpService
->bDeleted
)
4039 /* FIXME: Unlock database */
4040 DPRINT1("The service has already been marked for delete!\n");
4041 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4044 /* Open the service key */
4045 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4048 if (dwError
!= ERROR_SUCCESS
)
4051 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4053 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4055 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
4056 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4058 if (lpServiceDescription
!= NULL
&&
4059 lpServiceDescription
->lpDescription
!= NULL
)
4061 RegSetValueExW(hServiceKey
,
4065 (LPBYTE
)lpServiceDescription
->lpDescription
,
4066 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4068 if (dwError
!= ERROR_SUCCESS
)
4072 else if (Info
.dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4075 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4080 /* FIXME: Unlock database */
4081 if (hServiceKey
!= NULL
)
4082 RegCloseKey(hServiceKey
);
4084 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4091 DWORD
RQueryServiceConfig2A(
4092 SC_RPC_HANDLE hService
,
4096 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4098 DWORD dwError
= ERROR_SUCCESS
;
4099 PSERVICE_HANDLE hSvc
;
4100 PSERVICE lpService
= NULL
;
4101 HKEY hServiceKey
= NULL
;
4102 DWORD dwRequiredSize
;
4103 LPWSTR lpDescriptionW
= NULL
;
4104 LPSTR lpDescription
= NULL
;
4106 DPRINT("RQueryServiceConfig2W() called\n");
4109 return ERROR_INVALID_ADDRESS
;
4112 return ERROR_SHUTDOWN_IN_PROGRESS
;
4114 hSvc
= (PSERVICE_HANDLE
)hService
;
4115 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4117 DPRINT1("Invalid handle tag!\n");
4118 return ERROR_INVALID_HANDLE
;
4121 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4122 SERVICE_QUERY_CONFIG
))
4124 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4125 return ERROR_ACCESS_DENIED
;
4128 lpService
= hSvc
->ServiceEntry
;
4129 if (lpService
== NULL
)
4131 DPRINT1("lpService == NULL!\n");
4132 return ERROR_INVALID_HANDLE
;
4135 /* FIXME: Lock the service database shared */
4137 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4140 if (dwError
!= ERROR_SUCCESS
)
4143 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4145 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4148 dwError
= ScmReadString(hServiceKey
,
4151 if (dwError
!= ERROR_SUCCESS
)
4154 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONA
) + ((wcslen(lpDescriptionW
) + 1));
4156 if (cbBufSize
< dwRequiredSize
)
4158 *pcbBytesNeeded
= dwRequiredSize
;
4159 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4163 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4165 WideCharToMultiByte(CP_ACP
,
4170 wcslen(lpDescriptionW
),
4173 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4175 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4178 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4183 if (lpDescription
!= NULL
)
4184 HeapFree(GetProcessHeap(), 0, lpDescription
);
4186 if (hServiceKey
!= NULL
)
4187 RegCloseKey(hServiceKey
);
4189 /* FIXME: Unlock database */
4191 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4198 DWORD
RQueryServiceConfig2W(
4199 SC_RPC_HANDLE hService
,
4203 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4205 DWORD dwError
= ERROR_SUCCESS
;
4206 PSERVICE_HANDLE hSvc
;
4207 PSERVICE lpService
= NULL
;
4208 HKEY hServiceKey
= NULL
;
4209 DWORD dwRequiredSize
;
4210 LPWSTR lpDescription
= NULL
;
4212 DPRINT("RQueryServiceConfig2W() called\n");
4215 return ERROR_INVALID_ADDRESS
;
4218 return ERROR_SHUTDOWN_IN_PROGRESS
;
4220 hSvc
= (PSERVICE_HANDLE
)hService
;
4221 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4223 DPRINT1("Invalid handle tag!\n");
4224 return ERROR_INVALID_HANDLE
;
4227 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4228 SERVICE_QUERY_CONFIG
))
4230 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4231 return ERROR_ACCESS_DENIED
;
4234 lpService
= hSvc
->ServiceEntry
;
4235 if (lpService
== NULL
)
4237 DPRINT1("lpService == NULL!\n");
4238 return ERROR_INVALID_HANDLE
;
4241 /* FIXME: Lock the service database shared */
4243 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4246 if (dwError
!= ERROR_SUCCESS
)
4249 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4251 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4254 dwError
= ScmReadString(hServiceKey
,
4257 if (dwError
!= ERROR_SUCCESS
)
4260 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4262 if (cbBufSize
< dwRequiredSize
)
4264 *pcbBytesNeeded
= dwRequiredSize
;
4265 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4269 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4270 wcscpy(lpStr
, lpDescription
);
4271 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4273 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4276 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4281 if (lpDescription
!= NULL
)
4282 HeapFree(GetProcessHeap(), 0, lpDescription
);
4284 if (hServiceKey
!= NULL
)
4285 RegCloseKey(hServiceKey
);
4287 /* FIXME: Unlock database */
4289 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4296 DWORD
RQueryServiceStatusEx(
4297 SC_RPC_HANDLE hService
,
4298 SC_STATUS_TYPE InfoLevel
,
4301 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4303 LPSERVICE_STATUS_PROCESS lpStatus
;
4304 PSERVICE_HANDLE hSvc
;
4307 DPRINT("RQueryServiceStatusEx() called\n");
4310 return ERROR_SHUTDOWN_IN_PROGRESS
;
4312 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4313 return ERROR_INVALID_LEVEL
;
4315 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4317 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4318 return ERROR_INSUFFICIENT_BUFFER
;
4320 hSvc
= (PSERVICE_HANDLE
)hService
;
4321 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4323 DPRINT1("Invalid handle tag!\n");
4324 return ERROR_INVALID_HANDLE
;
4327 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4328 SERVICE_QUERY_STATUS
))
4330 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4331 return ERROR_ACCESS_DENIED
;
4334 lpService
= hSvc
->ServiceEntry
;
4335 if (lpService
== NULL
)
4337 DPRINT1("lpService == NULL!\n");
4338 return ERROR_INVALID_HANDLE
;
4341 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4343 /* Return service status information */
4344 RtlCopyMemory(lpStatus
,
4346 sizeof(SERVICE_STATUS
));
4348 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4349 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4351 return ERROR_SUCCESS
;
4356 DWORD
REnumServicesStatusExA(
4357 SC_RPC_HANDLE hSCManager
,
4358 SC_ENUM_TYPE InfoLevel
,
4359 DWORD dwServiceType
,
4360 DWORD dwServiceState
,
4363 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4364 LPBOUNDED_DWORD_256K lpServicesReturned
,
4365 LPBOUNDED_DWORD_256K lpResumeIndex
,
4366 LPCSTR pszGroupName
)
4368 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4369 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4370 LPWSTR lpStringPtrW
;
4372 LPWSTR pszGroupNameW
= NULL
;
4374 DWORD dwServiceCount
;
4376 DPRINT("REnumServicesStatusExA() called\n");
4380 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4383 DPRINT1("Failed to allocate buffer!\n");
4384 return ERROR_NOT_ENOUGH_MEMORY
;
4386 MultiByteToWideChar(CP_ACP
,
4391 strlen(pszGroupName
) + 1);
4394 if ((cbBufSize
> 0) && (lpBuffer
))
4396 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4399 DPRINT1("Failed to allocate buffer!\n");
4400 return ERROR_NOT_ENOUGH_MEMORY
;
4404 dwError
= REnumServicesStatusExW(hSCManager
,
4408 (LPBYTE
)lpStatusPtrW
,
4415 /* if no services were returned then we are Done */
4416 if (*lpServicesReturned
== 0) goto Done
;
4418 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4419 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4420 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4421 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4422 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4424 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4426 /* Copy the service name */
4427 WideCharToMultiByte(CP_ACP
,
4432 wcslen(lpStringPtrW
),
4436 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4437 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4438 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4440 /* Copy the display name */
4441 WideCharToMultiByte(CP_ACP
,
4446 wcslen(lpStringPtrW
),
4450 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4451 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4452 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4454 /* Copy the status information */
4455 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4456 &lpStatusPtrW
->ServiceStatusProcess
,
4457 sizeof(SERVICE_STATUS
));
4459 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4460 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4465 if (pszGroupNameW
) HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4467 if (lpStatusPtrW
) HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4469 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4476 DWORD
REnumServicesStatusExW(
4477 SC_RPC_HANDLE hSCManager
,
4478 SC_ENUM_TYPE InfoLevel
,
4479 DWORD dwServiceType
,
4480 DWORD dwServiceState
,
4483 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4484 LPBOUNDED_DWORD_256K lpServicesReturned
,
4485 LPBOUNDED_DWORD_256K lpResumeIndex
,
4486 LPCWSTR pszGroupName
)
4488 PMANAGER_HANDLE hManager
;
4490 DWORD dwError
= ERROR_SUCCESS
;
4491 PLIST_ENTRY ServiceEntry
;
4492 PSERVICE CurrentService
;
4494 DWORD dwRequiredSize
;
4495 DWORD dwServiceCount
;
4497 DWORD dwLastResumeCount
= 0;
4498 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4501 DPRINT("REnumServicesStatusExW() called\n");
4504 return ERROR_SHUTDOWN_IN_PROGRESS
;
4506 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4507 return ERROR_INVALID_LEVEL
;
4509 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4510 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4512 DPRINT1("Invalid manager handle!\n");
4513 return ERROR_INVALID_HANDLE
;
4516 *pcbBytesNeeded
= 0;
4517 *lpServicesReturned
= 0;
4519 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4521 DPRINT1("Not a valid Service Type!\n");
4522 return ERROR_INVALID_PARAMETER
;
4525 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4527 DPRINT1("Not a valid Service State!\n");
4528 return ERROR_INVALID_PARAMETER
;
4531 /* Check access rights */
4532 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4533 SC_MANAGER_ENUMERATE_SERVICE
))
4535 DPRINT1("Insufficient access rights! 0x%lx\n",
4536 hManager
->Handle
.DesiredAccess
);
4537 return ERROR_ACCESS_DENIED
;
4540 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4542 /* Lock the service list shared */
4544 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4545 if (lpService
== NULL
)
4547 dwError
= ERROR_SUCCESS
;
4554 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4555 ServiceEntry
!= &ServiceListHead
;
4556 ServiceEntry
= ServiceEntry
->Flink
)
4558 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4562 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4565 dwState
= SERVICE_ACTIVE
;
4566 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4567 dwState
= SERVICE_INACTIVE
;
4569 if ((dwState
& dwServiceState
) == 0)
4574 if (*pszGroupName
== 0)
4576 if (CurrentService
->lpGroup
!= NULL
)
4581 if ((CurrentService
->lpGroup
== NULL
) ||
4582 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4587 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4588 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4589 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4591 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4593 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4594 dwRequiredSize
+= dwSize
;
4596 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4600 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4606 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4607 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4610 ServiceEntry
!= &ServiceListHead
;
4611 ServiceEntry
= ServiceEntry
->Flink
)
4613 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4617 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4620 dwState
= SERVICE_ACTIVE
;
4621 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4622 dwState
= SERVICE_INACTIVE
;
4624 if ((dwState
& dwServiceState
) == 0)
4629 if (*pszGroupName
== 0)
4631 if (CurrentService
->lpGroup
!= NULL
)
4636 if ((CurrentService
->lpGroup
== NULL
) ||
4637 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4642 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4643 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4644 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4646 dwError
= ERROR_MORE_DATA
;
4649 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4651 if (lpResumeIndex
) *lpResumeIndex
= dwLastResumeCount
;
4652 *lpServicesReturned
= dwServiceCount
;
4653 *pcbBytesNeeded
= dwRequiredSize
;
4655 /* If there was no services that matched */
4656 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
4658 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
4662 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
4663 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4664 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4667 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4668 ServiceEntry
!= &ServiceListHead
;
4669 ServiceEntry
= ServiceEntry
->Flink
)
4671 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4675 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4678 dwState
= SERVICE_ACTIVE
;
4679 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4680 dwState
= SERVICE_INACTIVE
;
4682 if ((dwState
& dwServiceState
) == 0)
4687 if (*pszGroupName
== 0)
4689 if (CurrentService
->lpGroup
!= NULL
)
4694 if ((CurrentService
->lpGroup
== NULL
) ||
4695 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4700 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4701 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4702 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4704 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4706 /* Copy the service name */
4708 CurrentService
->lpServiceName
);
4709 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4710 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4712 /* Copy the display name */
4714 CurrentService
->lpDisplayName
);
4715 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4716 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4718 /* Copy the status information */
4719 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
4720 &CurrentService
->Status
,
4721 sizeof(SERVICE_STATUS
));
4722 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
4723 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4726 dwRequiredSize
+= dwSize
;
4736 *pcbBytesNeeded
= 0;
4737 if (lpResumeIndex
) *lpResumeIndex
= 0;
4741 /* Unlock the service list */
4743 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
4750 DWORD
RSendTSMessage(
4751 handle_t BindingHandle
) /* FIXME */
4754 return ERROR_CALL_NOT_IMPLEMENTED
;
4759 DWORD
RCreateServiceWOW64A(
4760 handle_t BindingHandle
,
4761 LPSTR lpServiceName
,
4762 LPSTR lpDisplayName
,
4763 DWORD dwDesiredAccess
,
4764 DWORD dwServiceType
,
4766 DWORD dwErrorControl
,
4767 LPSTR lpBinaryPathName
,
4768 LPSTR lpLoadOrderGroup
,
4770 LPBYTE lpDependencies
,
4772 LPSTR lpServiceStartName
,
4775 LPSC_RPC_HANDLE lpServiceHandle
)
4778 return ERROR_CALL_NOT_IMPLEMENTED
;
4783 DWORD
RCreateServiceWOW64W(
4784 handle_t BindingHandle
,
4785 LPWSTR lpServiceName
,
4786 LPWSTR lpDisplayName
,
4787 DWORD dwDesiredAccess
,
4788 DWORD dwServiceType
,
4790 DWORD dwErrorControl
,
4791 LPWSTR lpBinaryPathName
,
4792 LPWSTR lpLoadOrderGroup
,
4794 LPBYTE lpDependencies
,
4796 LPWSTR lpServiceStartName
,
4799 LPSC_RPC_HANDLE lpServiceHandle
)
4802 return ERROR_CALL_NOT_IMPLEMENTED
;
4807 DWORD
RQueryServiceTagInfo(
4808 handle_t BindingHandle
) /* FIXME */
4811 return ERROR_CALL_NOT_IMPLEMENTED
;
4816 DWORD
RNotifyServiceStatusChange(
4817 SC_RPC_HANDLE hService
,
4818 SC_RPC_NOTIFY_PARAMS NotifyParams
,
4819 GUID
*pClientProcessGuid
,
4820 GUID
*pSCMProcessGuid
,
4821 PBOOL pfCreateRemoteQueue
,
4822 LPSC_NOTIFY_RPC_HANDLE phNotify
)
4825 return ERROR_CALL_NOT_IMPLEMENTED
;
4830 DWORD
RGetNotifyResults(
4831 SC_NOTIFY_RPC_HANDLE hNotify
,
4832 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
4835 return ERROR_CALL_NOT_IMPLEMENTED
;
4840 DWORD
RCloseNotifyHandle(
4841 LPSC_NOTIFY_RPC_HANDLE phNotify
,
4845 return ERROR_CALL_NOT_IMPLEMENTED
;
4850 DWORD
RControlServiceExA(
4851 SC_RPC_HANDLE hService
,
4856 return ERROR_CALL_NOT_IMPLEMENTED
;
4861 DWORD
RControlServiceExW(
4862 SC_RPC_HANDLE hService
,
4867 return ERROR_CALL_NOT_IMPLEMENTED
;
4872 DWORD
RSendPnPMessage(
4873 handle_t BindingHandle
) /* FIXME */
4876 return ERROR_CALL_NOT_IMPLEMENTED
;
4881 DWORD
RValidatePnPService(
4882 handle_t BindingHandle
) /* FIXME */
4885 return ERROR_CALL_NOT_IMPLEMENTED
;
4890 DWORD
ROpenServiceStatusHandle(
4891 handle_t BindingHandle
) /* FIXME */
4894 return ERROR_CALL_NOT_IMPLEMENTED
;
4900 handle_t BindingHandle
) /* FIXME */
4903 return ERROR_CALL_NOT_IMPLEMENTED
;
4907 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
4909 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
4913 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
4915 HeapFree(GetProcessHeap(), 0, ptr
);
4919 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
4924 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
4929 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)