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>
12 /* INCLUDES ****************************************************************/
20 /* GLOBALS *****************************************************************/
22 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
23 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
25 typedef struct _SCMGR_HANDLE
33 typedef struct _MANAGER_HANDLE
37 /* FIXME: Insert more data here */
39 WCHAR DatabaseName
[1];
40 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
43 typedef struct _SERVICE_HANDLE
48 PSERVICE ServiceEntry
;
50 /* FIXME: Insert more data here */
52 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
55 #define SC_MANAGER_READ \
56 (STANDARD_RIGHTS_READ | \
57 SC_MANAGER_QUERY_LOCK_STATUS | \
58 SC_MANAGER_ENUMERATE_SERVICE)
60 #define SC_MANAGER_WRITE \
61 (STANDARD_RIGHTS_WRITE | \
62 SC_MANAGER_MODIFY_BOOT_CONFIG | \
63 SC_MANAGER_CREATE_SERVICE)
65 #define SC_MANAGER_EXECUTE \
66 (STANDARD_RIGHTS_EXECUTE | \
68 SC_MANAGER_ENUMERATE_SERVICE | \
69 SC_MANAGER_CONNECT | \
70 SC_MANAGER_CREATE_SERVICE)
73 #define SERVICE_READ \
74 (STANDARD_RIGHTS_READ | \
75 SERVICE_INTERROGATE | \
76 SERVICE_ENUMERATE_DEPENDENTS | \
77 SERVICE_QUERY_STATUS | \
80 #define SERVICE_WRITE \
81 (STANDARD_RIGHTS_WRITE | \
82 SERVICE_CHANGE_CONFIG)
84 #define SERVICE_EXECUTE \
85 (STANDARD_RIGHTS_EXECUTE | \
86 SERVICE_USER_DEFINED_CONTROL | \
87 SERVICE_PAUSE_CONTINUE | \
92 /* VARIABLES ***************************************************************/
94 static GENERIC_MAPPING
95 ScmManagerMapping
= {SC_MANAGER_READ
,
98 SC_MANAGER_ALL_ACCESS
};
100 static GENERIC_MAPPING
101 ScmServiceMapping
= {SERVICE_READ
,
104 SC_MANAGER_ALL_ACCESS
};
107 /* FUNCTIONS ***************************************************************/
110 ScmStartRpcServer(VOID
)
114 DPRINT("ScmStartRpcServer() called\n");
116 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
120 if (Status
!= RPC_S_OK
)
122 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
126 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
129 if (Status
!= RPC_S_OK
)
131 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
135 Status
= RpcServerListen(1, 20, TRUE
);
136 if (Status
!= RPC_S_OK
)
138 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
142 DPRINT("ScmStartRpcServer() done\n");
147 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
152 if (lpDatabaseName
== NULL
)
153 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
155 if (wcsicmp(lpDatabaseName
,SERVICES_FAILED_DATABASEW
)==0)
157 DPRINT1("Database %S, does not exist\n",lpDatabaseName
);
158 return ERROR_DATABASE_DOES_NOT_EXIST
;
160 else if (wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
162 DPRINT1("Invalid Database name %S.\n",lpDatabaseName
);
163 return ERROR_INVALID_NAME
;
166 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
168 sizeof(MANAGER_HANDLE
) + wcslen(lpDatabaseName
) * sizeof(WCHAR
));
170 return ERROR_NOT_ENOUGH_MEMORY
;
172 Ptr
->Handle
.Tag
= MANAGER_TAG
;
173 Ptr
->Handle
.RefCount
= 1;
175 /* FIXME: initialize more data here */
177 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
179 *Handle
= (SC_HANDLE
)Ptr
;
181 return ERROR_SUCCESS
;
186 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
191 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
193 sizeof(SERVICE_HANDLE
));
195 return ERROR_NOT_ENOUGH_MEMORY
;
197 Ptr
->Handle
.Tag
= SERVICE_TAG
;
198 Ptr
->Handle
.RefCount
= 1;
200 /* FIXME: initialize more data here */
201 Ptr
->ServiceEntry
= lpServiceEntry
;
203 *Handle
= (SC_HANDLE
)Ptr
;
205 return ERROR_SUCCESS
;
210 ScmCheckAccess(SC_HANDLE Handle
,
211 DWORD dwDesiredAccess
)
213 PMANAGER_HANDLE hMgr
;
215 hMgr
= (PMANAGER_HANDLE
)Handle
;
216 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
218 RtlMapGenericMask(&dwDesiredAccess
,
221 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
223 return ERROR_SUCCESS
;
225 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
227 RtlMapGenericMask(&dwDesiredAccess
,
230 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
232 return ERROR_SUCCESS
;
235 return ERROR_INVALID_HANDLE
;
240 ScmAssignNewTag(PSERVICE lpService
)
243 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
244 lpService
->dwTag
= 0;
245 return ERROR_SUCCESS
;
249 /* Internal recursive function */
250 /* Need to search for every dependency on every service */
252 Int_EnumDependentServicesW(HKEY hServicesKey
,
254 DWORD dwServiceState
,
255 PSERVICE
*lpServices
,
256 LPDWORD pcbBytesNeeded
,
257 LPDWORD lpServicesReturned
)
259 DWORD dwError
= ERROR_SUCCESS
;
260 WCHAR szNameBuf
[MAX_PATH
];
261 WCHAR szValueBuf
[MAX_PATH
];
262 WCHAR
*lpszNameBuf
= szNameBuf
;
263 WCHAR
*lpszValueBuf
= szValueBuf
;
267 PSERVICE lpCurrentService
;
268 HKEY hServiceEnumKey
;
269 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
270 DWORD dwDependServiceStrPtr
= 0;
271 DWORD dwRequiredSize
= 0;
273 /* Get the number of service keys */
274 dwError
= RegQueryInfoKeyW(hServicesKey
,
286 if (dwError
!= ERROR_SUCCESS
)
288 DPRINT1("ERROR! Unable to get number of services keys.\n");
292 /* Iterate the service keys to see if another service depends on the this service */
293 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
296 dwError
= RegEnumKeyExW(hServicesKey
,
304 if (dwError
!= ERROR_SUCCESS
)
307 /* Open the Service key */
308 dwError
= RegOpenKeyExW(hServicesKey
,
313 if (dwError
!= ERROR_SUCCESS
)
318 /* Check for the DependOnService Value */
319 dwError
= RegQueryValueExW(hServiceEnumKey
,
323 (LPBYTE
)lpszValueBuf
,
326 /* FIXME: Handle load order. */
328 /* If the service found has a DependOnService value */
329 if (dwError
== ERROR_SUCCESS
)
331 dwDependServiceStrPtr
= 0;
333 /* Can be more than one Dependencies in the DependOnService string */
334 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
336 if (wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
338 /* Get the current enumed service pointer */
339 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
341 /* Check for valid Service */
342 if (!lpCurrentService
)
344 /* This should never happen! */
345 DPRINT1("This should not happen at this point, report to Developer\n");
346 return ERROR_NOT_FOUND
;
349 /* Determine state the service is in */
350 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
351 dwCurrentServiceState
= SERVICE_INACTIVE
;
353 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
354 if ((dwCurrentServiceState
== dwServiceState
) ||
355 (dwServiceState
== SERVICE_STATE_ALL
))
357 /* Calculate the required size */
358 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
359 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
360 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
362 /* Add the size for service name and display name pointers */
363 dwRequiredSize
+= (2 * sizeof(PVOID
));
365 /* increase the BytesNeeded size */
366 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
368 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
371 /* Recursive call to check for its dependencies */
372 Int_EnumDependentServicesW(hServicesKey
,
379 /* If the lpServices is valid set the service pointer */
381 lpServices
[*lpServicesReturned
] = lpCurrentService
;
383 *lpServicesReturned
= *lpServicesReturned
+ 1;
387 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
390 else if (*pcbBytesNeeded
)
392 dwError
= ERROR_SUCCESS
;
395 RegCloseKey(hServiceEnumKey
);
403 DWORD
RCloseServiceHandle(
404 handle_t BindingHandle
,
405 LPSC_RPC_HANDLE hSCObject
)
407 PMANAGER_HANDLE hManager
;
409 DPRINT("RCloseServiceHandle() called\n");
411 DPRINT("hSCObject = %p\n", *hSCObject
);
414 return ERROR_INVALID_HANDLE
;
416 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
417 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
419 DPRINT("Found manager handle\n");
421 hManager
->Handle
.RefCount
--;
422 if (hManager
->Handle
.RefCount
== 0)
424 /* FIXME: add cleanup code */
426 HeapFree(GetProcessHeap(), 0, hManager
);
429 DPRINT("RCloseServiceHandle() done\n");
430 return ERROR_SUCCESS
;
432 else if (hManager
->Handle
.Tag
== SERVICE_TAG
)
434 DPRINT("Found service handle\n");
436 hManager
->Handle
.RefCount
--;
437 if (hManager
->Handle
.RefCount
== 0)
439 /* FIXME: add cleanup code */
441 HeapFree(GetProcessHeap(), 0, hManager
);
444 DPRINT("RCloseServiceHandle() done\n");
445 return ERROR_SUCCESS
;
448 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
450 return ERROR_INVALID_HANDLE
;
455 DWORD
RControlService(
456 handle_t BindingHandle
,
457 SC_RPC_HANDLE hService
,
459 LPSERVICE_STATUS lpServiceStatus
)
461 PSERVICE_HANDLE hSvc
;
463 ACCESS_MASK DesiredAccess
;
464 DWORD dwError
= ERROR_SUCCESS
;
466 DPRINT("RControlService() called\n");
469 return ERROR_SHUTDOWN_IN_PROGRESS
;
471 /* Check the service handle */
472 hSvc
= (PSERVICE_HANDLE
)hService
;
473 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
475 DPRINT1("Invalid handle tag!\n");
476 return ERROR_INVALID_HANDLE
;
479 /* Check access rights */
482 case SERVICE_CONTROL_STOP
:
483 DesiredAccess
= SERVICE_STOP
;
486 case SERVICE_CONTROL_PAUSE
:
487 case SERVICE_CONTROL_CONTINUE
:
488 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
491 case SERVICE_INTERROGATE
:
492 DesiredAccess
= SERVICE_INTERROGATE
;
496 if (dwControl
>= 128 && dwControl
<= 255)
497 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
499 DesiredAccess
= SERVICE_QUERY_CONFIG
|
500 SERVICE_CHANGE_CONFIG
|
501 SERVICE_QUERY_STATUS
|
503 SERVICE_PAUSE_CONTINUE
;
507 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
509 return ERROR_ACCESS_DENIED
;
511 /* Check the service entry point */
512 lpService
= hSvc
->ServiceEntry
;
513 if (lpService
== NULL
)
515 DPRINT1("lpService == NULL!\n");
516 return ERROR_INVALID_HANDLE
;
519 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
521 /* Send control code to the driver */
522 dwError
= ScmControlDriver(lpService
,
528 /* Send control code to the service */
529 dwError
= ScmControlService(lpService
,
534 /* Return service status information */
535 RtlCopyMemory(lpServiceStatus
,
537 sizeof(SERVICE_STATUS
));
544 DWORD
RDeleteService(
545 handle_t BindingHandle
,
546 SC_RPC_HANDLE hService
)
548 PSERVICE_HANDLE hSvc
;
552 DPRINT("RDeleteService() called\n");
555 return ERROR_SHUTDOWN_IN_PROGRESS
;
557 hSvc
= (PSERVICE_HANDLE
)hService
;
558 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
559 return ERROR_INVALID_HANDLE
;
561 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
563 return ERROR_ACCESS_DENIED
;
565 lpService
= hSvc
->ServiceEntry
;
566 if (lpService
== NULL
)
568 DPRINT1("lpService == NULL!\n");
569 return ERROR_INVALID_HANDLE
;
572 /* FIXME: Acquire service database lock exclusively */
574 if (lpService
->bDeleted
)
576 DPRINT1("The service has already been marked for delete!\n");
577 return ERROR_SERVICE_MARKED_FOR_DELETE
;
580 /* Mark service for delete */
581 lpService
->bDeleted
= TRUE
;
583 dwError
= ScmMarkServiceForDelete(lpService
);
585 /* FIXME: Release service database lock */
587 DPRINT("RDeleteService() done\n");
594 DWORD
RLockServiceDatabase(
595 handle_t BindingHandle
,
596 SC_RPC_HANDLE hSCManager
,
597 LPSC_RPC_LOCK lpLock
)
599 PMANAGER_HANDLE hMgr
;
601 DPRINT("RLockServiceDatabase() called\n");
605 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
606 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
607 return ERROR_INVALID_HANDLE
;
609 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
611 return ERROR_ACCESS_DENIED
;
613 // return ScmLockDatabase(0, hMgr->0xC, hLock);
615 /* FIXME: Lock the database */
616 *lpLock
= (void *)0x12345678; /* Dummy! */
618 return ERROR_SUCCESS
;
623 DWORD
RQueryServiceObjectSecurity(
624 handle_t BindingHandle
,
625 SC_RPC_HANDLE hService
,
626 SECURITY_INFORMATION dwSecurityInformation
,
627 LPBYTE lpSecurityDescriptor
,
629 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
632 PSERVICE_HANDLE hSvc
;
634 ULONG DesiredAccess
= 0;
639 DPRINT("RQueryServiceObjectSecurity() called\n");
641 hSvc
= (PSERVICE_HANDLE
)hService
;
642 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
644 DPRINT1("Invalid handle tag!\n");
645 return ERROR_INVALID_HANDLE
;
648 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
649 GROUP_SECURITY_INFORMATION
||
650 OWNER_SECURITY_INFORMATION
))
651 DesiredAccess
|= READ_CONTROL
;
653 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
654 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
656 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
659 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
660 return ERROR_ACCESS_DENIED
;
663 lpService
= hSvc
->ServiceEntry
;
664 if (lpService
== NULL
)
666 DPRINT1("lpService == NULL!\n");
667 return ERROR_INVALID_HANDLE
;
670 /* FIXME: Lock the service list */
672 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
673 dwSecurityInformation
,
674 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
675 dwSecuityDescriptorSize
,
678 /* FIXME: Unlock the service list */
680 if (NT_SUCCESS(Status
))
682 *pcbBytesNeeded
= dwBytesNeeded
;
683 dwError
= STATUS_SUCCESS
;
685 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
687 *pcbBytesNeeded
= dwBytesNeeded
;
688 dwError
= ERROR_INSUFFICIENT_BUFFER
;
690 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
692 dwError
= ERROR_GEN_FAILURE
;
696 dwError
= RtlNtStatusToDosError(Status
);
702 return ERROR_CALL_NOT_IMPLEMENTED
;
707 DWORD
RSetServiceObjectSecurity(
708 handle_t BindingHandle
,
709 SC_RPC_HANDLE hService
,
710 DWORD dwSecurityInformation
,
711 LPBYTE lpSecurityDescriptor
,
712 DWORD dwSecuityDescriptorSize
)
714 PSERVICE_HANDLE hSvc
;
716 ULONG DesiredAccess
= 0;
717 HANDLE hToken
= NULL
;
722 DPRINT1("RSetServiceObjectSecurity() called\n");
724 hSvc
= (PSERVICE_HANDLE
)hService
;
725 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
727 DPRINT1("Invalid handle tag!\n");
728 return ERROR_INVALID_HANDLE
;
731 if (dwSecurityInformation
== 0 ||
732 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
733 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
734 return ERROR_INVALID_PARAMETER
;
736 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
737 return ERROR_INVALID_PARAMETER
;
739 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
740 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
742 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
743 DesiredAccess
|= WRITE_DAC
;
745 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
746 DesiredAccess
|= WRITE_OWNER
;
748 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
749 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
750 return ERROR_INVALID_PARAMETER
;
752 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
753 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
754 return ERROR_INVALID_PARAMETER
;
756 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
759 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
760 return ERROR_ACCESS_DENIED
;
763 lpService
= hSvc
->ServiceEntry
;
764 if (lpService
== NULL
)
766 DPRINT1("lpService == NULL!\n");
767 return ERROR_INVALID_HANDLE
;
770 if (lpService
->bDeleted
)
771 return ERROR_SERVICE_MARKED_FOR_DELETE
;
773 RpcImpersonateClient(NULL
);
775 Status
= NtOpenThreadToken(NtCurrentThread(),
779 if (!NT_SUCCESS(Status
))
780 return RtlNtStatusToDosError(Status
);
784 /* FIXME: Lock service database */
787 Status
= RtlSetSecurityObject(dwSecurityInformation
,
788 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
789 &lpService
->lpSecurityDescriptor
,
792 if (!NT_SUCCESS(Status
))
794 dwError
= RtlNtStatusToDosError(Status
);
799 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
800 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
802 if (dwError
!= ERROR_SUCCESS
)
806 dwError
= ERROR_SUCCESS
;
807 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
808 // lpService->lpSecurityDescriptor);
810 RegFlushKey(hServiceKey
);
811 RegCloseKey(hServiceKey
);
818 /* FIXME: Unlock service database */
820 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
827 DWORD
RQueryServiceStatus(
828 handle_t BindingHandle
,
829 SC_RPC_HANDLE hService
,
830 LPSERVICE_STATUS lpServiceStatus
)
832 PSERVICE_HANDLE hSvc
;
835 DPRINT("RQueryServiceStatus() called\n");
838 return ERROR_SHUTDOWN_IN_PROGRESS
;
840 hSvc
= (PSERVICE_HANDLE
)hService
;
841 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
843 DPRINT1("Invalid handle tag!\n");
844 return ERROR_INVALID_HANDLE
;
847 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
848 SERVICE_QUERY_STATUS
))
850 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
851 return ERROR_ACCESS_DENIED
;
854 lpService
= hSvc
->ServiceEntry
;
855 if (lpService
== NULL
)
857 DPRINT1("lpService == NULL!\n");
858 return ERROR_INVALID_HANDLE
;
861 /* Return service status information */
862 RtlCopyMemory(lpServiceStatus
,
864 sizeof(SERVICE_STATUS
));
866 return ERROR_SUCCESS
;
871 DWORD
RSetServiceStatus(
872 handle_t BindingHandle
,
873 SC_RPC_HANDLE hServiceStatus
,
874 LPSERVICE_STATUS lpServiceStatus
)
878 DPRINT("RSetServiceStatus() called\n");
881 return ERROR_SHUTDOWN_IN_PROGRESS
;
883 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
884 if (lpService
== NULL
)
886 DPRINT1("lpService == NULL!\n");
887 return ERROR_INVALID_HANDLE
;
890 RtlCopyMemory(&lpService
->Status
,
892 sizeof(SERVICE_STATUS
));
894 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
895 DPRINT("RSetServiceStatus() done\n");
897 return ERROR_SUCCESS
;
902 DWORD
RUnlockServiceDatabase(
903 handle_t BindingHandle
,
907 return ERROR_SUCCESS
;
912 DWORD
RNotifyBootConfigStatus(
913 handle_t BindingHandle
,
914 SVCCTL_HANDLEW lpMachineName
,
915 DWORD BootAcceptable
)
918 return ERROR_CALL_NOT_IMPLEMENTED
;
923 DWORD
RSetServiceBitsW(
924 handle_t BindingHandle
,
925 SC_RPC_HANDLE hServiceStatus
,
928 int bUpdateImmediately
,
932 return ERROR_CALL_NOT_IMPLEMENTED
;
937 DWORD
RChangeServiceConfigW(
938 handle_t BindingHandle
,
939 SC_RPC_HANDLE hService
,
942 DWORD dwErrorControl
,
943 LPWSTR lpBinaryPathName
,
944 LPWSTR lpLoadOrderGroup
,
946 LPBYTE lpDependencies
,
948 LPWSTR lpServiceStartName
,
951 LPWSTR lpDisplayName
)
953 DWORD dwError
= ERROR_SUCCESS
;
954 PSERVICE_HANDLE hSvc
;
955 PSERVICE lpService
= NULL
;
956 HKEY hServiceKey
= NULL
;
957 LPWSTR lpDisplayNameW
= NULL
;
959 DPRINT("RChangeServiceConfigW() called\n");
960 DPRINT("dwServiceType = %lu\n", dwServiceType
);
961 DPRINT("dwStartType = %lu\n", dwStartType
);
962 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
963 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
964 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
965 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
968 return ERROR_SHUTDOWN_IN_PROGRESS
;
970 hSvc
= (PSERVICE_HANDLE
)hService
;
971 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
973 DPRINT1("Invalid handle tag!\n");
974 return ERROR_INVALID_HANDLE
;
977 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
978 SERVICE_CHANGE_CONFIG
))
980 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
981 return ERROR_ACCESS_DENIED
;
984 lpService
= hSvc
->ServiceEntry
;
985 if (lpService
== NULL
)
987 DPRINT1("lpService == NULL!\n");
988 return ERROR_INVALID_HANDLE
;
991 /* FIXME: Lock database exclusively */
993 if (lpService
->bDeleted
)
995 /* FIXME: Unlock database */
996 DPRINT1("The service has already been marked for delete!\n");
997 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1000 /* Open the service key */
1001 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1004 if (dwError
!= ERROR_SUCCESS
)
1007 /* Write service data to the registry */
1008 /* Set the display name */
1009 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1011 RegSetValueExW(hServiceKey
,
1015 (LPBYTE
)lpDisplayName
,
1016 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1018 /* Update the display name */
1019 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1021 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1022 if (lpDisplayNameW
== NULL
)
1024 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1028 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1029 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1031 lpService
->lpDisplayName
= lpDisplayNameW
;
1034 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1036 /* Set the service type */
1037 dwError
= RegSetValueExW(hServiceKey
,
1041 (LPBYTE
)&dwServiceType
,
1043 if (dwError
!= ERROR_SUCCESS
)
1046 lpService
->Status
.dwServiceType
= dwServiceType
;
1049 if (dwStartType
!= SERVICE_NO_CHANGE
)
1051 /* Set the start value */
1052 dwError
= RegSetValueExW(hServiceKey
,
1056 (LPBYTE
)&dwStartType
,
1058 if (dwError
!= ERROR_SUCCESS
)
1061 lpService
->dwStartType
= dwStartType
;
1064 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1066 /* Set the error control value */
1067 dwError
= RegSetValueExW(hServiceKey
,
1071 (LPBYTE
)&dwErrorControl
,
1073 if (dwError
!= ERROR_SUCCESS
)
1076 lpService
->dwErrorControl
= dwErrorControl
;
1080 /* FIXME: set the new ImagePath value */
1082 /* Set the image path */
1083 if (dwServiceType
& SERVICE_WIN32
)
1085 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1087 dwError
= RegSetValueExW(hServiceKey
,
1091 (LPBYTE
)lpBinaryPathName
,
1092 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1093 if (dwError
!= ERROR_SUCCESS
)
1097 else if (dwServiceType
& SERVICE_DRIVER
)
1099 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1101 dwError
= RegSetValueExW(hServiceKey
,
1105 (LPBYTE
)lpImagePath
,
1106 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1107 if (dwError
!= ERROR_SUCCESS
)
1113 /* Set the group name */
1114 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1116 dwError
= RegSetValueExW(hServiceKey
,
1120 (LPBYTE
)lpLoadOrderGroup
,
1121 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1122 if (dwError
!= ERROR_SUCCESS
)
1124 /* FIXME: update lpService->lpServiceGroup */
1127 if (lpdwTagId
!= NULL
)
1129 dwError
= ScmAssignNewTag(lpService
);
1130 if (dwError
!= ERROR_SUCCESS
)
1133 dwError
= RegSetValueExW(hServiceKey
,
1137 (LPBYTE
)&lpService
->dwTag
,
1139 if (dwError
!= ERROR_SUCCESS
)
1142 *lpdwTagId
= lpService
->dwTag
;
1145 /* Write dependencies */
1146 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1148 dwError
= ScmWriteDependencies(hServiceKey
,
1149 (LPWSTR
)lpDependencies
,
1151 if (dwError
!= ERROR_SUCCESS
)
1155 if (lpPassword
!= NULL
)
1157 /* FIXME: Write password */
1160 /* FIXME: Unlock database */
1163 if (hServiceKey
!= NULL
)
1164 RegCloseKey(hServiceKey
);
1166 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1171 /* Create a path suitable for the bootloader out of the full path */
1173 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1175 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1178 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1179 OBJECT_ATTRIBUTES ObjectAttributes
;
1181 HANDLE SymbolicLinkHandle
;
1183 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1185 ServiceNameLen
= wcslen(CanonName
);
1186 /* First check, if it's already good */
1187 if (ServiceNameLen
> 12 &&
1188 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1190 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1192 if (*RelativeName
== NULL
)
1194 DPRINT1("Error allocating memory for boot driver name!\n");
1195 return ERROR_NOT_ENOUGH_MEMORY
;
1199 wcscpy(*RelativeName
, CanonName
);
1201 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1202 return ERROR_SUCCESS
;
1205 /* If it has %SystemRoot% prefix, substitute it to \System*/
1206 if (ServiceNameLen
> 13 &&
1207 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1209 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1210 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1212 if (*RelativeName
== NULL
)
1214 DPRINT1("Error allocating memory for boot driver name!\n");
1215 return ERROR_NOT_ENOUGH_MEMORY
;
1219 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1220 wcscat(*RelativeName
, CanonName
+ 13);
1222 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1223 return ERROR_SUCCESS
;
1226 /* Get buffer size needed for expanding env strings */
1227 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1229 if (BufferSize
<= 1)
1231 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1232 return ERROR_INVALID_ENVIRONMENT
;
1235 /* Allocate memory, since the size is known now */
1236 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1239 DPRINT1("Error allocating memory for boot driver name!\n");
1240 return ERROR_NOT_ENOUGH_MEMORY
;
1244 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1247 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1248 LocalFree(Expanded
);
1249 return ERROR_NOT_ENOUGH_MEMORY
;
1252 /* Convert to NY-style path */
1253 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1255 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1256 return ERROR_INVALID_ENVIRONMENT
;
1259 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1261 /* No need to keep the dos-path anymore */
1262 LocalFree(Expanded
);
1264 /* Copy it to the allocated place */
1265 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1268 DPRINT1("Error allocating memory for boot driver name!\n");
1269 return ERROR_NOT_ENOUGH_MEMORY
;
1272 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1273 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1274 Expanded
[ExpandedLen
] = 0;
1276 if (ServiceNameLen
> ExpandedLen
&&
1277 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1279 /* Only \SystemRoot\ is missing */
1280 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1281 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1283 if (*RelativeName
== NULL
)
1285 DPRINT1("Error allocating memory for boot driver name!\n");
1286 LocalFree(Expanded
);
1287 return ERROR_NOT_ENOUGH_MEMORY
;
1290 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1291 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1293 RtlFreeUnicodeString(&NtPathName
);
1294 return ERROR_SUCCESS
;
1297 /* The most complex case starts here */
1298 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1299 InitializeObjectAttributes(&ObjectAttributes
,
1301 OBJ_CASE_INSENSITIVE
,
1305 /* Open this symlink */
1306 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1308 if (NT_SUCCESS(Status
))
1310 LinkTarget
.Length
= 0;
1311 LinkTarget
.MaximumLength
= 0;
1313 DPRINT("Opened symbolic link object\n");
1315 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1316 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1318 /* Check if required buffer size is sane */
1319 if (BufferSize
> 0xFFFD)
1321 DPRINT1("Too large buffer required\n");
1324 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1325 LocalFree(Expanded
);
1326 return ERROR_NOT_ENOUGH_MEMORY
;
1329 /* Alloc the string */
1330 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1331 if (!LinkTarget
.Buffer
)
1333 DPRINT1("Unable to alloc buffer\n");
1334 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1335 LocalFree(Expanded
);
1336 return ERROR_NOT_ENOUGH_MEMORY
;
1339 /* Do a real query now */
1340 LinkTarget
.Length
= BufferSize
;
1341 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1343 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1344 if (NT_SUCCESS(Status
))
1346 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1348 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1349 if ((ServiceNameLen
> ExpandedLen
) &&
1350 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1352 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1353 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1355 if (*RelativeName
== NULL
)
1357 DPRINT1("Unable to alloc buffer\n");
1358 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1359 LocalFree(Expanded
);
1360 RtlFreeUnicodeString(&NtPathName
);
1361 return ERROR_NOT_ENOUGH_MEMORY
;
1364 /* Copy it over, substituting the first part
1366 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1367 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1370 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1371 LocalFree(Expanded
);
1372 RtlFreeUnicodeString(&NtPathName
);
1374 /* Return success */
1375 return ERROR_SUCCESS
;
1379 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1380 LocalFree(Expanded
);
1381 RtlFreeUnicodeString(&NtPathName
);
1382 return ERROR_INVALID_PARAMETER
;
1387 DPRINT1("Error, Status = %08X\n", Status
);
1388 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1389 LocalFree(Expanded
);
1390 RtlFreeUnicodeString(&NtPathName
);
1391 return ERROR_INVALID_PARAMETER
;
1396 DPRINT1("Error, Status = %08X\n", Status
);
1397 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1398 LocalFree(Expanded
);
1399 RtlFreeUnicodeString(&NtPathName
);
1400 return ERROR_INVALID_PARAMETER
;
1405 DPRINT1("Error, Status = %08X\n", Status
);
1406 LocalFree(Expanded
);
1407 return ERROR_INVALID_PARAMETER
;
1411 *RelativeName
= NULL
;
1412 return ERROR_INVALID_PARAMETER
;
1416 ScmCanonDriverImagePath(DWORD dwStartType
,
1417 wchar_t *lpServiceName
,
1418 wchar_t **lpCanonName
)
1420 DWORD ServiceNameLen
, Result
;
1421 UNICODE_STRING NtServiceName
;
1422 WCHAR
*RelativeName
;
1423 WCHAR
*SourceName
= lpServiceName
;
1425 /* Calculate the length of the service's name */
1426 ServiceNameLen
= wcslen(lpServiceName
);
1428 /* 12 is wcslen(L"\\SystemRoot\\") */
1429 if (ServiceNameLen
> 12 &&
1430 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1432 /* SystemRoot prefix is already included */
1434 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1436 if (*lpCanonName
== NULL
)
1438 DPRINT1("Error allocating memory for canonized service name!\n");
1439 return ERROR_NOT_ENOUGH_MEMORY
;
1442 /* If it's a boot-time driver, it must be systemroot relative */
1443 if (dwStartType
== SERVICE_BOOT_START
)
1447 wcscpy(*lpCanonName
, SourceName
);
1449 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1453 /* Check if it has %SystemRoot% (len=13) */
1454 if (ServiceNameLen
> 13 &&
1455 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1457 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1458 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1460 if (*lpCanonName
== NULL
)
1462 DPRINT1("Error allocating memory for canonized service name!\n");
1463 return ERROR_NOT_ENOUGH_MEMORY
;
1466 /* If it's a boot-time driver, it must be systemroot relative */
1467 if (dwStartType
== SERVICE_BOOT_START
)
1468 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1470 wcscat(*lpCanonName
, lpServiceName
+ 13);
1472 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1476 /* Check if it's a relative path name */
1477 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1479 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1481 if (*lpCanonName
== NULL
)
1483 DPRINT1("Error allocating memory for canonized service name!\n");
1484 return ERROR_NOT_ENOUGH_MEMORY
;
1487 /* Just copy it over without changing */
1488 wcscpy(*lpCanonName
, lpServiceName
);
1493 /* It seems to be a DOS path, convert it */
1494 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1496 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1497 return ERROR_INVALID_PARAMETER
;
1500 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1502 if (*lpCanonName
== NULL
)
1504 DPRINT1("Error allocating memory for canonized service name!\n");
1505 RtlFreeUnicodeString(&NtServiceName
);
1506 return ERROR_NOT_ENOUGH_MEMORY
;
1509 /* Copy the string */
1510 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1512 /* The unicode string is not needed anymore */
1513 RtlFreeUnicodeString(&NtServiceName
);
1515 if (dwStartType
!= SERVICE_BOOT_START
)
1517 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1521 /* The service is boot-started, so must be relative */
1522 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1525 /* There is a problem, free name and return */
1526 LocalFree(*lpCanonName
);
1527 DPRINT1("Error converting named!\n");
1531 ASSERT(RelativeName
);
1533 /* Copy that string */
1534 wcscpy(*lpCanonName
, RelativeName
+ 12);
1536 /* Free the allocated buffer */
1537 LocalFree(RelativeName
);
1539 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1547 DWORD
RCreateServiceW(
1548 handle_t BindingHandle
,
1549 SC_RPC_HANDLE hSCManager
,
1550 LPWSTR lpServiceName
,
1551 LPWSTR lpDisplayName
,
1552 DWORD dwDesiredAccess
,
1553 DWORD dwServiceType
,
1555 DWORD dwErrorControl
,
1556 LPWSTR lpBinaryPathName
,
1557 LPWSTR lpLoadOrderGroup
,
1559 LPBYTE lpDependencies
,
1561 LPWSTR lpServiceStartName
,
1564 LPSC_RPC_HANDLE lpServiceHandle
)
1566 PMANAGER_HANDLE hManager
;
1567 DWORD dwError
= ERROR_SUCCESS
;
1568 PSERVICE lpService
= NULL
;
1569 SC_HANDLE hServiceHandle
= NULL
;
1570 LPWSTR lpImagePath
= NULL
;
1571 HKEY hServiceKey
= NULL
;
1573 DPRINT("RCreateServiceW() called\n");
1574 DPRINT("lpServiceName = %S\n", lpServiceName
);
1575 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1576 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1577 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1578 DPRINT("dwStartType = %lu\n", dwStartType
);
1579 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1580 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1581 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1584 return ERROR_SHUTDOWN_IN_PROGRESS
;
1586 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1587 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1589 DPRINT1("Invalid manager handle!\n");
1590 return ERROR_INVALID_HANDLE
;
1593 /* Check access rights */
1594 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1595 SC_MANAGER_CREATE_SERVICE
))
1597 DPRINT1("Insufficient access rights! 0x%lx\n",
1598 hManager
->Handle
.DesiredAccess
);
1599 return ERROR_ACCESS_DENIED
;
1602 if (wcslen(lpServiceName
) == 0)
1604 return ERROR_INVALID_NAME
;
1607 if (wcslen(lpBinaryPathName
) == 0)
1609 return ERROR_INVALID_PARAMETER
;
1612 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1613 (lpServiceStartName
))
1615 return ERROR_INVALID_PARAMETER
;
1618 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1619 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1620 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1622 return ERROR_INVALID_PARAMETER
;
1625 if (dwStartType
> SERVICE_DISABLED
)
1627 return ERROR_INVALID_PARAMETER
;
1630 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1633 /* check if it is marked for deletion */
1634 if (lpService
->bDeleted
)
1635 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1636 /* Return Error exist */
1637 return ERROR_SERVICE_EXISTS
;
1640 if (lpDisplayName
!= NULL
&&
1641 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1642 return ERROR_DUPLICATE_SERVICE_NAME
;
1644 if (dwServiceType
& SERVICE_DRIVER
)
1646 dwError
= ScmCanonDriverImagePath(dwStartType
,
1650 if (dwError
!= ERROR_SUCCESS
)
1655 if (dwStartType
== SERVICE_BOOT_START
||
1656 dwStartType
== SERVICE_SYSTEM_START
)
1658 return ERROR_INVALID_PARAMETER
;
1662 /* Allocate a new service entry */
1663 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1665 if (dwError
!= ERROR_SUCCESS
)
1668 /* Fill the new service entry */
1669 lpService
->Status
.dwServiceType
= dwServiceType
;
1670 lpService
->dwStartType
= dwStartType
;
1671 lpService
->dwErrorControl
= dwErrorControl
;
1673 /* Fill the display name */
1674 if (lpDisplayName
!= NULL
&&
1675 *lpDisplayName
!= 0 &&
1676 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1678 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1679 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1680 if (lpService
->lpDisplayName
== NULL
)
1682 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1685 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1688 /* Assign the service to a group */
1689 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1691 dwError
= ScmSetServiceGroup(lpService
,
1693 if (dwError
!= ERROR_SUCCESS
)
1697 /* Assign a new tag */
1698 if (lpdwTagId
!= NULL
)
1700 dwError
= ScmAssignNewTag(lpService
);
1701 if (dwError
!= ERROR_SUCCESS
)
1705 /* Write service data to the registry */
1706 /* Create the service key */
1707 dwError
= ScmCreateServiceKey(lpServiceName
,
1710 if (dwError
!= ERROR_SUCCESS
)
1713 /* Set the display name */
1714 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1716 RegSetValueExW(hServiceKey
,
1720 (LPBYTE
)lpDisplayName
,
1721 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1724 /* Set the service type */
1725 dwError
= RegSetValueExW(hServiceKey
,
1729 (LPBYTE
)&dwServiceType
,
1731 if (dwError
!= ERROR_SUCCESS
)
1734 /* Set the start value */
1735 dwError
= RegSetValueExW(hServiceKey
,
1739 (LPBYTE
)&dwStartType
,
1741 if (dwError
!= ERROR_SUCCESS
)
1744 /* Set the error control value */
1745 dwError
= RegSetValueExW(hServiceKey
,
1749 (LPBYTE
)&dwErrorControl
,
1751 if (dwError
!= ERROR_SUCCESS
)
1754 /* Set the image path */
1755 if (dwServiceType
& SERVICE_WIN32
)
1757 dwError
= RegSetValueExW(hServiceKey
,
1761 (LPBYTE
)lpBinaryPathName
,
1762 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1763 if (dwError
!= ERROR_SUCCESS
)
1766 else if (dwServiceType
& SERVICE_DRIVER
)
1768 dwError
= RegSetValueExW(hServiceKey
,
1772 (LPBYTE
)lpImagePath
,
1773 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1774 if (dwError
!= ERROR_SUCCESS
)
1778 /* Set the group name */
1779 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1781 dwError
= RegSetValueExW(hServiceKey
,
1785 (LPBYTE
)lpLoadOrderGroup
,
1786 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1787 if (dwError
!= ERROR_SUCCESS
)
1791 if (lpdwTagId
!= NULL
)
1793 dwError
= RegSetValueExW(hServiceKey
,
1797 (LPBYTE
)&lpService
->dwTag
,
1799 if (dwError
!= ERROR_SUCCESS
)
1803 /* Write dependencies */
1804 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1806 dwError
= ScmWriteDependencies(hServiceKey
,
1807 (LPWSTR
)lpDependencies
,
1809 if (dwError
!= ERROR_SUCCESS
)
1813 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1814 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1816 dwError
= RegSetValueExW(hServiceKey
,
1820 (LPBYTE
)L
"LocalSystem",
1822 if (dwError
!= ERROR_SUCCESS
)
1826 if (lpPassword
!= NULL
)
1828 /* FIXME: Write password */
1831 dwError
= ScmCreateServiceHandle(lpService
,
1833 if (dwError
!= ERROR_SUCCESS
)
1836 dwError
= ScmCheckAccess(hServiceHandle
,
1838 if (dwError
!= ERROR_SUCCESS
)
1842 if (hServiceKey
!= NULL
)
1843 RegCloseKey(hServiceKey
);
1845 if (dwError
== ERROR_SUCCESS
)
1847 DPRINT("hService %p\n", hServiceHandle
);
1848 *lpServiceHandle
= (unsigned long)hServiceHandle
; /* FIXME: 64 bit portability */
1850 if (lpdwTagId
!= NULL
)
1851 *lpdwTagId
= lpService
->dwTag
;
1855 /* Release the display name buffer */
1856 if (lpService
->lpServiceName
!= NULL
)
1857 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1861 /* Remove the service handle */
1862 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1865 if (lpService
!= NULL
)
1867 /* FIXME: remove the service entry */
1871 if (lpImagePath
!= NULL
)
1872 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1874 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
1881 DWORD
REnumDependentServicesW(
1882 handle_t BindingHandle
,
1883 SC_RPC_HANDLE hService
,
1884 DWORD dwServiceState
,
1887 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
1888 LPBOUNDED_DWORD_256K lpServicesReturned
)
1890 DWORD dwError
= ERROR_SUCCESS
;
1891 DWORD dwServicesReturned
= 0;
1892 DWORD dwServiceCount
;
1893 HKEY hServicesKey
= NULL
;
1894 LPSC_RPC_HANDLE hSCObject
;
1895 PSERVICE_HANDLE hSvc
;
1896 PSERVICE lpService
= NULL
;
1897 PSERVICE
*lpServicesArray
= NULL
;
1898 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
1901 *pcbBytesNeeded
= 0;
1902 *lpServicesReturned
= 0;
1904 DPRINT("REnumDependentServicesW() called\n");
1906 hSCObject
= &hService
;
1907 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
1908 lpService
= hSvc
->ServiceEntry
;
1910 /* Check access rights */
1911 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1912 SC_MANAGER_ENUMERATE_SERVICE
))
1914 DPRINT1("Insufficient access rights! 0x%lx\n",
1915 hSvc
->Handle
.DesiredAccess
);
1916 return ERROR_ACCESS_DENIED
;
1919 /* Open the Services Reg key */
1920 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1921 L
"System\\CurrentControlSet\\Services",
1925 if (dwError
!= ERROR_SUCCESS
)
1928 /* First determine the bytes needed and get the number of dependent services */
1929 dwError
= Int_EnumDependentServicesW(hServicesKey
,
1934 &dwServicesReturned
);
1935 if (dwError
!= ERROR_SUCCESS
)
1938 /* If buffer size is less than the bytes needed or pointer is null */
1939 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
1941 dwError
= ERROR_MORE_DATA
;
1945 /* Allocate memory for array of service pointers */
1946 lpServicesArray
= HeapAlloc(GetProcessHeap(),
1948 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
1949 if (!lpServicesArray
)
1951 DPRINT1("Could not allocate a buffer!!\n");
1952 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1956 dwServicesReturned
= 0;
1957 *pcbBytesNeeded
= 0;
1959 dwError
= Int_EnumDependentServicesW(hServicesKey
,
1964 &dwServicesReturned
);
1965 if (dwError
!= ERROR_SUCCESS
)
1970 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
1971 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
1973 /* Copy EnumDepenedentService to Buffer */
1974 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
1976 lpService
= lpServicesArray
[dwServiceCount
];
1978 /* Copy status info */
1979 memcpy(&lpServicesPtr
->ServiceStatus
,
1981 sizeof(SERVICE_STATUS
));
1983 /* Copy display name */
1984 wcscpy(lpStr
, lpService
->lpDisplayName
);
1985 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
1986 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
1988 /* Copy service name */
1989 wcscpy(lpStr
, lpService
->lpServiceName
);
1990 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
1991 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
1996 *lpServicesReturned
= dwServicesReturned
;
1999 if (lpServicesArray
!= NULL
)
2000 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2002 RegCloseKey(hServicesKey
);
2004 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2011 DWORD
REnumServicesStatusW(
2012 handle_t BindingHandle
,
2013 SC_RPC_HANDLE hSCManager
,
2014 DWORD dwServiceType
,
2015 DWORD dwServiceState
,
2018 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2019 LPBOUNDED_DWORD_256K lpServicesReturned
,
2020 LPBOUNDED_DWORD_256K lpResumeHandle
)
2022 PMANAGER_HANDLE hManager
;
2024 DWORD dwError
= ERROR_SUCCESS
;
2025 PLIST_ENTRY ServiceEntry
;
2026 PSERVICE CurrentService
;
2028 DWORD dwRequiredSize
;
2029 DWORD dwServiceCount
;
2031 DWORD dwLastResumeCount
;
2032 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2035 DPRINT("REnumServicesStatusW() called\n");
2038 return ERROR_SHUTDOWN_IN_PROGRESS
;
2040 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2041 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2043 DPRINT1("Invalid manager handle!\n");
2044 return ERROR_INVALID_HANDLE
;
2047 /* Check access rights */
2048 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2049 SC_MANAGER_ENUMERATE_SERVICE
))
2051 DPRINT1("Insufficient access rights! 0x%lx\n",
2052 hManager
->Handle
.DesiredAccess
);
2053 return ERROR_ACCESS_DENIED
;
2056 *pcbBytesNeeded
= 0;
2057 *lpServicesReturned
= 0;
2059 dwLastResumeCount
= *lpResumeHandle
;
2061 /* FIXME: Lock the service list shared */
2063 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2064 if (lpService
== NULL
)
2066 dwError
= ERROR_SUCCESS
;
2073 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2074 ServiceEntry
!= &ServiceListHead
;
2075 ServiceEntry
= ServiceEntry
->Flink
)
2077 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2081 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2084 dwState
= SERVICE_ACTIVE
;
2085 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2086 dwState
= SERVICE_INACTIVE
;
2088 if ((dwState
& dwServiceState
) == 0)
2091 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2092 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2093 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2095 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2097 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2101 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2102 dwRequiredSize
+= dwSize
;
2104 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2107 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2108 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2111 ServiceEntry
!= &ServiceListHead
;
2112 ServiceEntry
= ServiceEntry
->Flink
)
2114 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2118 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2121 dwState
= SERVICE_ACTIVE
;
2122 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2123 dwState
= SERVICE_INACTIVE
;
2125 if ((dwState
& dwServiceState
) == 0)
2128 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2129 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2130 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2132 dwError
= ERROR_MORE_DATA
;
2135 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2137 *lpResumeHandle
= dwLastResumeCount
;
2138 *lpServicesReturned
= dwServiceCount
;
2139 *pcbBytesNeeded
= dwRequiredSize
;
2141 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2142 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2143 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2146 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2147 ServiceEntry
!= &ServiceListHead
;
2148 ServiceEntry
= ServiceEntry
->Flink
)
2150 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2154 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2157 dwState
= SERVICE_ACTIVE
;
2158 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2159 dwState
= SERVICE_INACTIVE
;
2161 if ((dwState
& dwServiceState
) == 0)
2164 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2165 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2166 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2168 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2171 /* Copy the service name */
2172 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2173 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2174 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2176 /* Copy the display name */
2177 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2178 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2179 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2181 /* Copy the status information */
2182 memcpy(&lpStatusPtr
->ServiceStatus
,
2183 &CurrentService
->Status
,
2184 sizeof(SERVICE_STATUS
));
2187 dwRequiredSize
+= dwSize
;
2191 /* FIXME: Unlock the service list */
2193 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2200 DWORD
ROpenSCManagerW(
2201 handle_t BindingHandle
,
2202 LPWSTR lpMachineName
,
2203 LPWSTR lpDatabaseName
,
2204 DWORD dwDesiredAccess
,
2205 LPSC_RPC_HANDLE lpScHandle
)
2210 DPRINT("ROpenSCManagerW() called\n");
2211 DPRINT("lpMachineName = %p\n", lpMachineName
);
2212 DPRINT("lpMachineName: %S\n", lpMachineName
);
2213 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2214 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2215 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2218 return ERROR_SHUTDOWN_IN_PROGRESS
;
2221 return ERROR_INVALID_PARAMETER
;
2223 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2225 if (dwError
!= ERROR_SUCCESS
)
2227 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2231 /* Check the desired access */
2232 dwError
= ScmCheckAccess(hHandle
,
2233 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2234 if (dwError
!= ERROR_SUCCESS
)
2236 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2237 HeapFree(GetProcessHeap(), 0, hHandle
);
2241 *lpScHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
2242 DPRINT("*hScm = %p\n", *lpScHandle
);
2244 DPRINT("ROpenSCManagerW() done\n");
2246 return ERROR_SUCCESS
;
2251 DWORD
ROpenServiceW(
2252 handle_t BindingHandle
,
2253 SC_RPC_HANDLE hSCManager
,
2254 LPWSTR lpServiceName
,
2255 DWORD dwDesiredAccess
,
2256 LPSC_RPC_HANDLE lpServiceHandle
)
2259 PMANAGER_HANDLE hManager
;
2263 DPRINT("ROpenServiceW() called\n");
2264 DPRINT("hSCManager = %p\n", hSCManager
);
2265 DPRINT("lpServiceName = %p\n", lpServiceName
);
2266 DPRINT("lpServiceName: %S\n", lpServiceName
);
2267 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2270 return ERROR_SHUTDOWN_IN_PROGRESS
;
2272 if (!lpServiceHandle
)
2273 return ERROR_INVALID_PARAMETER
;
2276 return ERROR_INVALID_ADDRESS
;
2278 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2279 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2281 DPRINT1("Invalid manager handle!\n");
2282 return ERROR_INVALID_HANDLE
;
2285 /* FIXME: Lock the service list */
2287 /* Get service database entry */
2288 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2289 if (lpService
== NULL
)
2291 DPRINT("Could not find a service!\n");
2292 return ERROR_SERVICE_DOES_NOT_EXIST
;
2295 /* Create a service handle */
2296 dwError
= ScmCreateServiceHandle(lpService
,
2298 if (dwError
!= ERROR_SUCCESS
)
2300 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2304 /* Check the desired access */
2305 dwError
= ScmCheckAccess(hHandle
,
2307 if (dwError
!= ERROR_SUCCESS
)
2309 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2310 HeapFree(GetProcessHeap(), 0, hHandle
);
2314 *lpServiceHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
2315 DPRINT("*hService = %p\n", *lpServiceHandle
);
2317 DPRINT("ROpenServiceW() done\n");
2319 return ERROR_SUCCESS
;
2324 DWORD
RQueryServiceConfigW(
2325 handle_t BindingHandle
,
2326 SC_RPC_HANDLE hService
,
2327 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2329 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2331 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2332 DWORD dwError
= ERROR_SUCCESS
;
2333 PSERVICE_HANDLE hSvc
;
2334 PSERVICE lpService
= NULL
;
2335 HKEY hServiceKey
= NULL
;
2336 LPWSTR lpImagePath
= NULL
;
2337 LPWSTR lpServiceStartName
= NULL
;
2338 DWORD dwRequiredSize
;
2339 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2340 WCHAR lpEmptyString
[] = {0,0};
2343 DPRINT("RQueryServiceConfigW() called\n");
2346 return ERROR_SHUTDOWN_IN_PROGRESS
;
2348 hSvc
= (PSERVICE_HANDLE
)hService
;
2349 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2351 DPRINT1("Invalid handle tag!\n");
2352 return ERROR_INVALID_HANDLE
;
2355 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2356 SERVICE_QUERY_CONFIG
))
2358 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2359 return ERROR_ACCESS_DENIED
;
2362 lpService
= hSvc
->ServiceEntry
;
2363 if (lpService
== NULL
)
2365 DPRINT1("lpService == NULL!\n");
2366 return ERROR_INVALID_HANDLE
;
2369 /* FIXME: Lock the service database shared */
2371 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2374 if (dwError
!= ERROR_SUCCESS
)
2377 dwError
= ScmReadString(hServiceKey
,
2380 if (dwError
!= ERROR_SUCCESS
)
2383 ScmReadString(hServiceKey
,
2385 &lpServiceStartName
);
2387 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2389 if (lpImagePath
!= NULL
)
2390 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2392 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2394 if (lpService
->lpGroup
!= NULL
)
2395 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2397 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2399 /* FIXME: Add Dependencies length*/
2401 if (lpServiceStartName
!= NULL
)
2402 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2404 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2406 if (lpService
->lpDisplayName
!= NULL
)
2407 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2409 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2411 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2413 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2417 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2418 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2419 lpConfig
->dwStartType
= lpService
->dwStartType
;
2420 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2421 lpConfig
->dwTagId
= lpService
->dwTag
;
2423 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2425 if (lpImagePath
!= NULL
)
2427 wcscpy(lpStr
, lpImagePath
);
2431 wcscpy(lpStr
, lpEmptyString
);
2434 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2435 lpStr
+= (wcslen(lpStr
) + 1);
2437 if (lpService
->lpGroup
!= NULL
)
2439 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2443 wcscpy(lpStr
, lpEmptyString
);
2446 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2447 lpStr
+= (wcslen(lpStr
) + 1);
2449 /* FIXME: Append Dependencies */
2450 wcscpy(lpStr
, lpEmptyString
);
2452 lpStr
+= (wcslen(lpStr
) + 1);
2453 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2455 if (lpServiceStartName
!= NULL
)
2457 wcscpy(lpStr
, lpServiceStartName
);
2461 wcscpy(lpStr
, lpEmptyString
);
2464 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2465 lpStr
+= (wcslen(lpStr
) + 1);
2467 if (lpService
->lpDisplayName
!= NULL
)
2469 wcscpy(lpStr
, lpService
->lpDisplayName
);
2473 wcscpy(lpStr
, lpEmptyString
);
2476 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2479 if (pcbBytesNeeded
!= NULL
)
2480 *pcbBytesNeeded
= dwRequiredSize
;
2483 if (lpImagePath
!= NULL
)
2484 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2486 if (lpServiceStartName
!= NULL
)
2487 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2489 if (hServiceKey
!= NULL
)
2490 RegCloseKey(hServiceKey
);
2492 /* FIXME: Unlock the service database */
2494 DPRINT("RQueryServiceConfigW() done\n");
2501 DWORD
RQueryServiceLockStatusW(
2502 handle_t BindingHandle
,
2503 SC_RPC_HANDLE hSCManager
,
2504 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2506 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2509 return ERROR_CALL_NOT_IMPLEMENTED
;
2514 DWORD
RStartServiceW(
2515 handle_t BindingHandle
,
2516 SC_RPC_HANDLE hService
,
2518 LPSTRING_PTRSW argv
)
2520 DWORD dwError
= ERROR_SUCCESS
;
2521 PSERVICE_HANDLE hSvc
;
2522 PSERVICE lpService
= NULL
;
2524 DPRINT("RStartServiceW() called\n");
2527 return ERROR_SHUTDOWN_IN_PROGRESS
;
2529 hSvc
= (PSERVICE_HANDLE
)hService
;
2530 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2532 DPRINT1("Invalid handle tag!\n");
2533 return ERROR_INVALID_HANDLE
;
2536 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2539 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2540 return ERROR_ACCESS_DENIED
;
2543 lpService
= hSvc
->ServiceEntry
;
2544 if (lpService
== NULL
)
2546 DPRINT1("lpService == NULL!\n");
2547 return ERROR_INVALID_HANDLE
;
2550 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2551 return ERROR_SERVICE_DISABLED
;
2553 if (lpService
->bDeleted
)
2554 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2561 /* Start the service */
2562 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2569 DWORD
RGetServiceDisplayNameW(
2570 handle_t BindingHandle
,
2571 SC_RPC_HANDLE hSCManager
,
2572 LPWSTR lpServiceName
,
2573 LPWSTR lpDisplayName
,
2576 // PMANAGER_HANDLE hManager;
2581 DPRINT("RGetServiceDisplayNameW() called\n");
2582 DPRINT("hSCManager = %p\n", hSCManager
);
2583 DPRINT("lpServiceName: %S\n", lpServiceName
);
2584 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2585 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2587 // hManager = (PMANAGER_HANDLE)hSCManager;
2588 // if (hManager->Handle.Tag != MANAGER_TAG)
2590 // DPRINT1("Invalid manager handle!\n");
2591 // return ERROR_INVALID_HANDLE;
2594 /* Get service database entry */
2595 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2596 if (lpService
== NULL
)
2598 DPRINT1("Could not find a service!\n");
2600 /* If the service could not be found and lpcchBuffer is 0, windows
2601 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2602 if (*lpcchBuffer
== 0)
2605 *lpDisplayName
= '\0';
2608 return ERROR_SERVICE_DOES_NOT_EXIST
;
2611 if (!lpService
->lpDisplayName
)
2613 dwLength
= wcslen(lpService
->lpServiceName
);
2615 if (lpServiceName
!= NULL
&&
2616 *lpcchBuffer
> dwLength
)
2618 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2623 dwLength
= wcslen(lpService
->lpDisplayName
);
2625 if (lpDisplayName
!= NULL
&&
2626 *lpcchBuffer
> dwLength
)
2628 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2632 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2634 *lpcchBuffer
= dwLength
;
2641 DWORD
RGetServiceKeyNameW(
2642 handle_t BindingHandle
,
2643 SC_RPC_HANDLE hSCManager
,
2644 LPWSTR lpDisplayName
,
2645 LPWSTR lpServiceName
,
2648 // PMANAGER_HANDLE hManager;
2653 DPRINT("RGetServiceKeyNameW() called\n");
2654 DPRINT("hSCManager = %p\n", hSCManager
);
2655 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2656 DPRINT("lpServiceName: %p\n", lpServiceName
);
2657 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2659 // hManager = (PMANAGER_HANDLE)hSCManager;
2660 // if (hManager->Handle.Tag != MANAGER_TAG)
2662 // DPRINT1("Invalid manager handle!\n");
2663 // return ERROR_INVALID_HANDLE;
2666 /* Get service database entry */
2667 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2668 if (lpService
== NULL
)
2670 DPRINT1("Could not find a service!\n");
2672 /* If the service could not be found and lpcchBuffer is 0, windows
2673 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2674 if (*lpcchBuffer
== 0)
2677 *lpServiceName
= '\0';
2680 return ERROR_SERVICE_DOES_NOT_EXIST
;
2683 dwLength
= wcslen(lpService
->lpServiceName
);
2685 if (lpServiceName
!= NULL
&&
2686 *lpcchBuffer
> dwLength
)
2688 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2689 *lpcchBuffer
= dwLength
;
2690 return ERROR_SUCCESS
;
2693 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2695 *lpcchBuffer
= dwLength
* 2;
2702 DWORD
RSetServiceBitsA(
2703 handle_t BindingHandle
,
2704 SC_RPC_HANDLE hServiceStatus
,
2705 DWORD dwServiceBits
,
2707 int bUpdateImmediately
,
2711 return ERROR_CALL_NOT_IMPLEMENTED
;
2716 DWORD
RChangeServiceConfigA(
2717 handle_t BindingHandle
,
2718 SC_RPC_HANDLE hService
,
2719 DWORD dwServiceType
,
2721 DWORD dwErrorControl
,
2722 LPSTR lpBinaryPathName
,
2723 LPSTR lpLoadOrderGroup
,
2725 LPSTR lpDependencies
,
2727 LPSTR lpServiceStartName
,
2730 LPSTR lpDisplayName
)
2732 DWORD dwError
= ERROR_SUCCESS
;
2733 PSERVICE_HANDLE hSvc
;
2734 PSERVICE lpService
= NULL
;
2735 HKEY hServiceKey
= NULL
;
2736 LPWSTR lpDisplayNameW
= NULL
;
2737 // LPWSTR lpBinaryPathNameW = NULL;
2738 LPWSTR lpLoadOrderGroupW
= NULL
;
2739 LPWSTR lpDependenciesW
= NULL
;
2740 // LPWSTR lpPasswordW = NULL;
2742 DPRINT("RChangeServiceConfigA() called\n");
2743 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2744 DPRINT("dwStartType = %lu\n", dwStartType
);
2745 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2746 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2747 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2748 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2751 return ERROR_SHUTDOWN_IN_PROGRESS
;
2753 hSvc
= (PSERVICE_HANDLE
)hService
;
2754 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2756 DPRINT1("Invalid handle tag!\n");
2757 return ERROR_INVALID_HANDLE
;
2760 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2761 SERVICE_CHANGE_CONFIG
))
2763 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2764 return ERROR_ACCESS_DENIED
;
2767 lpService
= hSvc
->ServiceEntry
;
2768 if (lpService
== NULL
)
2770 DPRINT1("lpService == NULL!\n");
2771 return ERROR_INVALID_HANDLE
;
2774 /* FIXME: Lock database exclusively */
2776 if (lpService
->bDeleted
)
2778 /* FIXME: Unlock database */
2779 DPRINT1("The service has already been marked for delete!\n");
2780 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2783 /* Open the service key */
2784 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2787 if (dwError
!= ERROR_SUCCESS
)
2790 /* Write service data to the registry */
2792 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2794 /* Set the display name */
2795 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2797 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2798 if (lpDisplayNameW
== NULL
)
2800 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2804 MultiByteToWideChar(CP_ACP
,
2809 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2811 RegSetValueExW(hServiceKey
,
2815 (LPBYTE
)lpDisplayNameW
,
2816 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2818 /* Update lpService->lpDisplayName */
2819 if (lpService
->lpDisplayName
)
2820 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2822 lpService
->lpDisplayName
= lpDisplayNameW
;
2825 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2827 /* Set the service type */
2828 dwError
= RegSetValueExW(hServiceKey
,
2832 (LPBYTE
)&dwServiceType
,
2834 if (dwError
!= ERROR_SUCCESS
)
2837 lpService
->Status
.dwServiceType
= dwServiceType
;
2840 if (dwStartType
!= SERVICE_NO_CHANGE
)
2842 /* Set the start value */
2843 dwError
= RegSetValueExW(hServiceKey
,
2847 (LPBYTE
)&dwStartType
,
2849 if (dwError
!= ERROR_SUCCESS
)
2852 lpService
->dwStartType
= dwStartType
;
2855 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
2857 /* Set the error control value */
2858 dwError
= RegSetValueExW(hServiceKey
,
2862 (LPBYTE
)&dwErrorControl
,
2864 if (dwError
!= ERROR_SUCCESS
)
2867 lpService
->dwErrorControl
= dwErrorControl
;
2871 /* FIXME: set the new ImagePath value */
2873 /* Set the image path */
2874 if (dwServiceType
& SERVICE_WIN32
)
2876 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2878 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
2879 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, (wcslen(lpBinaryPathNameW
)+1) * sizeof(WCHAR
));
2880 dwError
= RegSetValueExW(hServiceKey
,
2884 (LPBYTE
)lpBinaryPathNameW
,
2885 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
2886 if (dwError
!= ERROR_SUCCESS
)
2890 else if (dwServiceType
& SERVICE_DRIVER
)
2892 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
2894 dwError
= RegSetValueExW(hServiceKey
,
2898 (LPBYTE
)lpImagePath
,
2899 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
2900 if (dwError
!= ERROR_SUCCESS
)
2906 /* Set the group name */
2907 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2909 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
2911 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
2912 if (lpLoadOrderGroupW
== NULL
)
2914 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2918 MultiByteToWideChar(CP_ACP
,
2923 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
2925 dwError
= RegSetValueExW(hServiceKey
,
2929 (LPBYTE
)lpLoadOrderGroupW
,
2930 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
2931 if (dwError
!= ERROR_SUCCESS
)
2934 /* FIXME: Update lpService->lpServiceGroup */
2936 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
2939 if (lpdwTagId
!= NULL
)
2941 dwError
= ScmAssignNewTag(lpService
);
2942 if (dwError
!= ERROR_SUCCESS
)
2945 dwError
= RegSetValueExW(hServiceKey
,
2949 (LPBYTE
)&lpService
->dwTag
,
2951 if (dwError
!= ERROR_SUCCESS
)
2954 *lpdwTagId
= lpService
->dwTag
;
2957 /* Write dependencies */
2958 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2960 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
2962 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
2963 if (lpDependenciesW
== NULL
)
2965 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2969 MultiByteToWideChar(CP_ACP
,
2974 (wcslen(lpDependenciesW
)+1) * sizeof(WCHAR
));
2976 dwError
= ScmWriteDependencies(hServiceKey
,
2977 (LPWSTR
)lpDependenciesW
,
2980 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
2983 if (lpPassword
!= NULL
)
2985 /* FIXME: Write password */
2988 /* FIXME: Unlock database */
2991 if (hServiceKey
!= NULL
)
2992 RegCloseKey(hServiceKey
);
2994 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3001 DWORD
RCreateServiceA(
3002 handle_t BindingHandle
,
3003 SC_RPC_HANDLE hSCManager
,
3004 LPSTR lpServiceName
,
3005 LPSTR lpDisplayName
,
3006 DWORD dwDesiredAccess
,
3007 DWORD dwServiceType
,
3009 DWORD dwErrorControl
,
3010 LPSTR lpBinaryPathName
,
3011 LPSTR lpLoadOrderGroup
,
3013 LPBYTE lpDependencies
,
3015 LPSTR lpServiceStartName
,
3018 LPSC_RPC_HANDLE lpServiceHandle
)
3021 return ERROR_CALL_NOT_IMPLEMENTED
;
3026 DWORD
REnumDependentServicesA(
3027 handle_t BindingHandle
,
3028 SC_RPC_HANDLE hService
,
3029 DWORD dwServiceState
,
3032 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3033 LPBOUNDED_DWORD_256K lpServicesReturned
)
3035 DWORD dwError
= ERROR_SUCCESS
;
3036 DWORD dwServicesReturned
= 0;
3037 DWORD dwServiceCount
;
3038 HKEY hServicesKey
= NULL
;
3039 LPSC_RPC_HANDLE hSCObject
;
3040 PSERVICE_HANDLE hSvc
;
3041 PSERVICE lpService
= NULL
;
3042 PSERVICE
*lpServicesArray
= NULL
;
3043 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3046 *pcbBytesNeeded
= 0;
3047 *lpServicesReturned
= 0;
3049 DPRINT("REnumDependentServicesA() called\n");
3051 hSCObject
= &hService
;
3052 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3053 lpService
= hSvc
->ServiceEntry
;
3055 /* Check access rights */
3056 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3057 SC_MANAGER_ENUMERATE_SERVICE
))
3059 DPRINT1("Insufficient access rights! 0x%lx\n",
3060 hSvc
->Handle
.DesiredAccess
);
3061 return ERROR_ACCESS_DENIED
;
3064 /* Open the Services Reg key */
3065 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3066 L
"System\\CurrentControlSet\\Services",
3071 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3073 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3074 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3075 are the same for both. Verified in WINXP. */
3077 /* First determine the bytes needed and get the number of dependent services*/
3078 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3083 &dwServicesReturned
);
3084 if (dwError
!= ERROR_SUCCESS
)
3087 /* If buffer size is less than the bytes needed or pointer is null*/
3088 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3090 dwError
= ERROR_MORE_DATA
;
3094 /* Allocate memory for array of service pointers */
3095 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3097 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3098 if (!lpServicesArray
)
3100 DPRINT1("Could not allocate a buffer!!\n");
3101 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3105 dwServicesReturned
= 0;
3106 *pcbBytesNeeded
= 0;
3108 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3113 &dwServicesReturned
);
3114 if (dwError
!= ERROR_SUCCESS
)
3119 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3120 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3122 /* Copy EnumDepenedentService to Buffer */
3123 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3125 lpService
= lpServicesArray
[dwServiceCount
];
3127 /* Copy the status info */
3128 memcpy(&lpServicesPtr
->ServiceStatus
,
3130 sizeof(SERVICE_STATUS
));
3132 /* Copy display name */
3133 WideCharToMultiByte(CP_ACP
,
3135 lpService
->lpDisplayName
,
3138 wcslen(lpService
->lpDisplayName
),
3141 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3142 lpStr
+= strlen(lpStr
) + 1;
3144 /* Copy service name */
3145 WideCharToMultiByte(CP_ACP
,
3147 lpService
->lpServiceName
,
3150 wcslen(lpService
->lpServiceName
),
3153 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3154 lpStr
+= strlen(lpStr
) + 1;
3159 *lpServicesReturned
= dwServicesReturned
;
3162 if (lpServicesArray
)
3163 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3165 RegCloseKey(hServicesKey
);
3167 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3174 DWORD
REnumServicesStatusA(
3175 handle_t BindingHandle
,
3176 SC_RPC_HANDLE hSCManager
,
3177 DWORD dwServiceType
,
3178 DWORD dwServiceState
,
3181 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3182 LPBOUNDED_DWORD_256K lpServicesReturned
,
3183 LPBOUNDED_DWORD_256K lpResumeHandle
)
3186 return ERROR_CALL_NOT_IMPLEMENTED
;
3191 DWORD
ROpenSCManagerA(
3192 handle_t BindingHandle
,
3193 LPSTR lpMachineName
,
3194 LPSTR lpDatabaseName
,
3195 DWORD dwDesiredAccess
,
3196 LPSC_RPC_HANDLE lpScHandle
)
3198 UNICODE_STRING MachineName
;
3199 UNICODE_STRING DatabaseName
;
3202 DPRINT("ROpenSCManagerA() called\n");
3205 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3209 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3212 dwError
= ROpenSCManagerW(BindingHandle
,
3213 lpMachineName
? MachineName
.Buffer
: NULL
,
3214 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3219 RtlFreeUnicodeString(&MachineName
);
3222 RtlFreeUnicodeString(&DatabaseName
);
3229 DWORD
ROpenServiceA(
3230 handle_t BindingHandle
,
3231 SC_RPC_HANDLE hSCManager
,
3232 LPSTR lpServiceName
,
3233 DWORD dwDesiredAccess
,
3234 LPSC_RPC_HANDLE lpServiceHandle
)
3236 UNICODE_STRING ServiceName
;
3239 DPRINT("ROpenServiceA() called\n");
3242 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3245 dwError
= ROpenServiceW(BindingHandle
,
3252 RtlFreeUnicodeString(&ServiceName
);
3259 DWORD
RQueryServiceConfigA(
3260 handle_t BindingHandle
,
3261 SC_RPC_HANDLE hService
,
3262 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3264 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3266 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3267 DWORD dwError
= ERROR_SUCCESS
;
3268 PSERVICE_HANDLE hSvc
;
3269 PSERVICE lpService
= NULL
;
3270 HKEY hServiceKey
= NULL
;
3271 LPWSTR lpImagePath
= NULL
;
3272 LPWSTR lpServiceStartName
= NULL
;
3273 DWORD dwRequiredSize
;
3274 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3275 CHAR lpEmptyString
[]={0,0};
3278 DPRINT("RQueryServiceConfigA() called\n");
3281 return ERROR_SHUTDOWN_IN_PROGRESS
;
3283 hSvc
= (PSERVICE_HANDLE
)hService
;
3284 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3286 DPRINT1("Invalid handle tag!\n");
3287 return ERROR_INVALID_HANDLE
;
3290 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3291 SERVICE_QUERY_CONFIG
))
3293 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3294 return ERROR_ACCESS_DENIED
;
3297 lpService
= hSvc
->ServiceEntry
;
3298 if (lpService
== NULL
)
3300 DPRINT1("lpService == NULL!\n");
3301 return ERROR_INVALID_HANDLE
;
3304 /* FIXME: Lock the service database shared */
3306 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3309 if (dwError
!= ERROR_SUCCESS
)
3312 dwError
= ScmReadString(hServiceKey
,
3315 if (dwError
!= ERROR_SUCCESS
)
3318 ScmReadString(hServiceKey
,
3320 &lpServiceStartName
);
3322 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3324 if (lpImagePath
!= NULL
)
3325 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3327 dwRequiredSize
+= 2;
3329 if (lpService
->lpGroup
!= NULL
)
3330 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3332 dwRequiredSize
+= 2;
3334 /* FIXME: Add Dependencies length*/
3335 dwRequiredSize
+= 2;
3337 if (lpServiceStartName
!= NULL
)
3338 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3340 dwRequiredSize
+= 2;
3342 if (lpService
->lpDisplayName
!= NULL
)
3343 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3345 dwRequiredSize
+= 2;
3347 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3349 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3353 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3354 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3355 lpConfig
->dwStartType
= lpService
->dwStartType
;
3356 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3357 lpConfig
->dwTagId
= lpService
->dwTag
;
3359 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3361 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3366 WideCharToMultiByte(CP_ACP
,
3371 wcslen(lpImagePath
),
3377 strcpy(lpStr
, lpEmptyString
);
3380 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3381 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3383 if (lpService
->lpGroup
)
3385 WideCharToMultiByte(CP_ACP
,
3387 lpService
->lpGroup
->lpGroupName
,
3390 wcslen(lpService
->lpGroup
->lpGroupName
),
3396 strcpy(lpStr
, lpEmptyString
);
3399 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3400 lpStr
+= (strlen(lpStr
) + 1);
3402 /* FIXME: Append Dependencies */
3403 strcpy(lpStr
, lpEmptyString
);
3405 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3406 lpStr
+= (strlen(lpStr
) + 1);
3408 if (lpServiceStartName
)
3410 WideCharToMultiByte(CP_ACP
,
3415 wcslen(lpServiceStartName
),
3421 strcpy(lpStr
, lpEmptyString
);
3424 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3425 lpStr
+= (strlen(lpStr
) + 1);
3427 if (lpService
->lpDisplayName
)
3429 WideCharToMultiByte(CP_ACP
,
3431 lpService
->lpDisplayName
,
3434 wcslen(lpService
->lpDisplayName
),
3440 strcpy(lpStr
, lpEmptyString
);
3443 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3446 if (pcbBytesNeeded
!= NULL
)
3447 *pcbBytesNeeded
= dwRequiredSize
;
3450 if (lpImagePath
!= NULL
)
3451 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3453 if (lpServiceStartName
!= NULL
)
3454 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3456 if (hServiceKey
!= NULL
)
3457 RegCloseKey(hServiceKey
);
3459 /* FIXME: Unlock the service database */
3461 DPRINT("RQueryServiceConfigA() done\n");
3468 DWORD
RQueryServiceLockStatusA(
3469 handle_t BindingHandle
,
3470 SC_RPC_HANDLE hSCManager
,
3471 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3473 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3476 return ERROR_CALL_NOT_IMPLEMENTED
;
3481 DWORD
RStartServiceA(
3482 handle_t BindingHandle
,
3483 SC_RPC_HANDLE hService
,
3485 LPSTRING_PTRSA argv
)
3487 DWORD dwError
= ERROR_SUCCESS
;
3488 PSERVICE_HANDLE hSvc
;
3489 PSERVICE lpService
= NULL
;
3491 DPRINT1("RStartServiceA() called\n");
3494 return ERROR_SHUTDOWN_IN_PROGRESS
;
3496 hSvc
= (PSERVICE_HANDLE
)hService
;
3497 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3499 DPRINT1("Invalid handle tag!\n");
3500 return ERROR_INVALID_HANDLE
;
3503 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3506 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3507 return ERROR_ACCESS_DENIED
;
3510 lpService
= hSvc
->ServiceEntry
;
3511 if (lpService
== NULL
)
3513 DPRINT1("lpService == NULL!\n");
3514 return ERROR_INVALID_HANDLE
;
3517 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3518 return ERROR_SERVICE_DISABLED
;
3520 if (lpService
->bDeleted
)
3521 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3523 /* FIXME: Convert argument vector to Unicode */
3525 /* Start the service */
3526 dwError
= ScmStartService(lpService
, 0, NULL
);
3528 /* FIXME: Free argument vector */
3535 DWORD
RGetServiceDisplayNameA(
3536 handle_t BindingHandle
,
3537 SC_RPC_HANDLE hSCManager
,
3538 LPSTR lpServiceName
,
3539 LPSTR lpDisplayName
,
3540 LPBOUNDED_DWORD_4K lpcchBuffer
)
3542 // PMANAGER_HANDLE hManager;
3546 LPWSTR lpServiceNameW
;
3548 DPRINT("RGetServiceDisplayNameA() called\n");
3549 DPRINT("hSCManager = %p\n", hSCManager
);
3550 DPRINT("lpServiceName: %s\n", lpServiceName
);
3551 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3552 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3554 // hManager = (PMANAGER_HANDLE)hSCManager;
3555 // if (hManager->Handle.Tag != MANAGER_TAG)
3557 // DPRINT1("Invalid manager handle!\n");
3558 // return ERROR_INVALID_HANDLE;
3561 dwLength
= strlen(lpServiceName
) + 1;
3562 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3564 dwLength
* sizeof(WCHAR
));
3565 if (!lpServiceNameW
)
3566 return ERROR_NOT_ENOUGH_MEMORY
;
3568 MultiByteToWideChar(CP_ACP
,
3571 strlen(lpServiceName
),
3575 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3577 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3579 if (lpService
== NULL
)
3581 DPRINT1("Could not find a service!\n");
3583 /* If the service could not be found and lpcchBuffer is 0, windows
3584 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3585 if (*lpcchBuffer
== 0)
3588 *lpDisplayName
= '\0';
3590 return ERROR_SERVICE_DOES_NOT_EXIST
;
3593 if (!lpService
->lpDisplayName
)
3595 dwLength
= wcslen(lpService
->lpServiceName
);
3596 if (lpServiceName
!= NULL
&&
3597 *lpcchBuffer
> dwLength
)
3599 WideCharToMultiByte(CP_ACP
,
3601 lpService
->lpServiceName
,
3602 wcslen(lpService
->lpServiceName
),
3607 return ERROR_SUCCESS
;
3612 dwLength
= wcslen(lpService
->lpDisplayName
);
3613 if (lpDisplayName
!= NULL
&&
3614 *lpcchBuffer
> dwLength
)
3616 WideCharToMultiByte(CP_ACP
,
3618 lpService
->lpDisplayName
,
3619 wcslen(lpService
->lpDisplayName
),
3624 return ERROR_SUCCESS
;
3628 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3630 *lpcchBuffer
= dwLength
* 2;
3637 DWORD
RGetServiceKeyNameA(
3638 handle_t BindingHandle
,
3639 SC_RPC_HANDLE hSCManager
,
3640 LPSTR lpDisplayName
,
3641 LPSTR lpServiceName
,
3642 LPBOUNDED_DWORD_4K lpcchBuffer
)
3647 LPWSTR lpDisplayNameW
;
3649 DPRINT("RGetServiceKeyNameA() called\n");
3650 DPRINT("hSCManager = %p\n", hSCManager
);
3651 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3652 DPRINT("lpServiceName: %p\n", lpServiceName
);
3653 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3655 dwLength
= strlen(lpDisplayName
) + 1;
3656 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3658 dwLength
* sizeof(WCHAR
));
3659 if (!lpDisplayNameW
)
3660 return ERROR_NOT_ENOUGH_MEMORY
;
3662 MultiByteToWideChar(CP_ACP
,
3665 strlen(lpDisplayName
),
3669 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
3671 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3673 if (lpService
== NULL
)
3675 DPRINT1("Could not find the service!\n");
3677 /* If the service could not be found and lpcchBuffer is 0,
3678 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
3679 if (*lpcchBuffer
== 0)
3682 *lpServiceName
= '\0';
3685 return ERROR_SERVICE_DOES_NOT_EXIST
;
3688 dwLength
= wcslen(lpService
->lpServiceName
);
3689 if (lpService
!= NULL
&&
3690 *lpcchBuffer
> dwLength
)
3692 WideCharToMultiByte(CP_ACP
,
3694 lpService
->lpServiceName
,
3695 wcslen(lpService
->lpServiceName
),
3700 return ERROR_SUCCESS
;
3703 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3705 *lpcchBuffer
= dwLength
* 2;
3712 DWORD
RGetCurrentGroupStateW(
3713 handle_t BindingHandle
)
3716 return ERROR_CALL_NOT_IMPLEMENTED
;
3721 DWORD
REnumServiceGroupW(
3722 handle_t BindingHandle
,
3723 SC_RPC_HANDLE hSCManager
,
3724 DWORD dwServiceType
,
3725 DWORD dwServiceState
,
3728 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3729 LPBOUNDED_DWORD_256K lpServicesReturned
,
3730 LPBOUNDED_DWORD_256K lpResumeIndex
,
3731 LPCWSTR pszGroupName
)
3734 return ERROR_CALL_NOT_IMPLEMENTED
;
3739 DWORD
RChangeServiceConfig2A(
3740 handle_t BindingHandle
,
3741 SC_RPC_HANDLE hService
,
3742 SC_RPC_CONFIG_INFOA Info
)
3745 return ERROR_CALL_NOT_IMPLEMENTED
;
3750 DWORD
RChangeServiceConfig2W(
3751 handle_t BindingHandle
,
3752 SC_RPC_HANDLE hService
,
3753 SC_RPC_CONFIG_INFOW Info
)
3755 DWORD dwError
= ERROR_SUCCESS
;
3756 PSERVICE_HANDLE hSvc
;
3757 PSERVICE lpService
= NULL
;
3758 HKEY hServiceKey
= NULL
;
3760 DPRINT("RChangeServiceConfig2W() called\n");
3761 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
3764 return ERROR_SHUTDOWN_IN_PROGRESS
;
3766 hSvc
= (PSERVICE_HANDLE
)hService
;
3767 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3769 DPRINT1("Invalid handle tag!\n");
3770 return ERROR_INVALID_HANDLE
;
3773 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3774 SERVICE_CHANGE_CONFIG
))
3776 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3777 return ERROR_ACCESS_DENIED
;
3780 lpService
= hSvc
->ServiceEntry
;
3781 if (lpService
== NULL
)
3783 DPRINT1("lpService == NULL!\n");
3784 return ERROR_INVALID_HANDLE
;
3787 /* FIXME: Lock database exclusively */
3789 if (lpService
->bDeleted
)
3791 /* FIXME: Unlock database */
3792 DPRINT1("The service has already been marked for delete!\n");
3793 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3796 /* Open the service key */
3797 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3800 if (dwError
!= ERROR_SUCCESS
)
3803 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
3805 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
3807 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
3808 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
3810 if (lpServiceDescription
!= NULL
&&
3811 lpServiceDescription
->lpDescription
!= NULL
)
3813 RegSetValueExW(hServiceKey
,
3817 (LPBYTE
)lpServiceDescription
->lpDescription
,
3818 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
3820 if (dwError
!= ERROR_SUCCESS
)
3824 else if (Info
.dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
3827 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
3832 /* FIXME: Unlock database */
3833 if (hServiceKey
!= NULL
)
3834 RegCloseKey(hServiceKey
);
3836 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
3843 DWORD
RQueryServiceConfig2A(
3844 handle_t BindingHandle
,
3845 SC_RPC_HANDLE hService
,
3849 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3851 DWORD dwError
= ERROR_SUCCESS
;
3852 PSERVICE_HANDLE hSvc
;
3853 PSERVICE lpService
= NULL
;
3854 HKEY hServiceKey
= NULL
;
3855 DWORD dwRequiredSize
;
3856 LPWSTR lpDescriptionW
= NULL
;
3857 LPSTR lpDescription
= NULL
;
3859 DPRINT("RQueryServiceConfig2W() called\n");
3862 return ERROR_INVALID_ADDRESS
;
3865 return ERROR_SHUTDOWN_IN_PROGRESS
;
3867 hSvc
= (PSERVICE_HANDLE
)hService
;
3868 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3870 DPRINT1("Invalid handle tag!\n");
3871 return ERROR_INVALID_HANDLE
;
3874 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3875 SERVICE_QUERY_CONFIG
))
3877 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3878 return ERROR_ACCESS_DENIED
;
3881 lpService
= hSvc
->ServiceEntry
;
3882 if (lpService
== NULL
)
3884 DPRINT1("lpService == NULL!\n");
3885 return ERROR_INVALID_HANDLE
;
3888 /* FIXME: Lock the service database shared */
3890 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3893 if (dwError
!= ERROR_SUCCESS
)
3896 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
3898 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
3901 dwError
= ScmReadString(hServiceKey
,
3904 if (dwError
!= ERROR_SUCCESS
)
3907 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONA
) + ((wcslen(lpDescriptionW
) + 1));
3909 if (cbBufSize
< dwRequiredSize
)
3911 *pcbBytesNeeded
= dwRequiredSize
;
3912 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3916 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
3918 WideCharToMultiByte(CP_ACP
,
3923 wcslen(lpDescriptionW
),
3926 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
3928 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
3931 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
3936 if (lpDescription
!= NULL
)
3937 HeapFree(GetProcessHeap(), 0, lpDescription
);
3939 if (hServiceKey
!= NULL
)
3940 RegCloseKey(hServiceKey
);
3942 /* FIXME: Unlock database */
3944 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
3951 DWORD
RQueryServiceConfig2W(
3952 handle_t BindingHandle
,
3953 SC_RPC_HANDLE hService
,
3957 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3959 DWORD dwError
= ERROR_SUCCESS
;
3960 PSERVICE_HANDLE hSvc
;
3961 PSERVICE lpService
= NULL
;
3962 HKEY hServiceKey
= NULL
;
3963 DWORD dwRequiredSize
;
3964 LPWSTR lpDescription
= NULL
;
3966 DPRINT("RQueryServiceConfig2W() called\n");
3969 return ERROR_INVALID_ADDRESS
;
3972 return ERROR_SHUTDOWN_IN_PROGRESS
;
3974 hSvc
= (PSERVICE_HANDLE
)hService
;
3975 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3977 DPRINT1("Invalid handle tag!\n");
3978 return ERROR_INVALID_HANDLE
;
3981 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3982 SERVICE_QUERY_CONFIG
))
3984 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3985 return ERROR_ACCESS_DENIED
;
3988 lpService
= hSvc
->ServiceEntry
;
3989 if (lpService
== NULL
)
3991 DPRINT1("lpService == NULL!\n");
3992 return ERROR_INVALID_HANDLE
;
3995 /* FIXME: Lock the service database shared */
3997 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4000 if (dwError
!= ERROR_SUCCESS
)
4003 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4005 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4008 dwError
= ScmReadString(hServiceKey
,
4011 if (dwError
!= ERROR_SUCCESS
)
4014 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4016 if (cbBufSize
< dwRequiredSize
)
4018 *pcbBytesNeeded
= dwRequiredSize
;
4019 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4023 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4024 wcscpy(lpStr
, lpDescription
);
4025 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4027 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4030 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4035 if (lpDescription
!= NULL
)
4036 HeapFree(GetProcessHeap(), 0, lpDescription
);
4038 if (hServiceKey
!= NULL
)
4039 RegCloseKey(hServiceKey
);
4041 /* FIXME: Unlock database */
4043 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4050 DWORD
RQueryServiceStatusEx(
4051 handle_t BindingHandle
,
4052 SC_RPC_HANDLE hService
,
4053 SC_STATUS_TYPE InfoLevel
,
4056 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4058 LPSERVICE_STATUS_PROCESS lpStatus
;
4059 PSERVICE_HANDLE hSvc
;
4062 DPRINT("RQueryServiceStatusEx() called\n");
4065 return ERROR_SHUTDOWN_IN_PROGRESS
;
4067 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4068 return ERROR_INVALID_LEVEL
;
4070 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4072 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4073 return ERROR_INSUFFICIENT_BUFFER
;
4075 hSvc
= (PSERVICE_HANDLE
)hService
;
4076 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4078 DPRINT1("Invalid handle tag!\n");
4079 return ERROR_INVALID_HANDLE
;
4082 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4083 SERVICE_QUERY_STATUS
))
4085 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4086 return ERROR_ACCESS_DENIED
;
4089 lpService
= hSvc
->ServiceEntry
;
4090 if (lpService
== NULL
)
4092 DPRINT1("lpService == NULL!\n");
4093 return ERROR_INVALID_HANDLE
;
4096 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4098 /* Return service status information */
4099 RtlCopyMemory(lpStatus
,
4101 sizeof(SERVICE_STATUS
));
4103 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4104 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4106 return ERROR_SUCCESS
;
4111 DWORD
REnumServicesStatusExA(
4112 handle_t BindingHandle
,
4113 SC_RPC_HANDLE hSCManager
,
4114 SC_ENUM_TYPE InfoLevel
,
4115 DWORD dwServiceType
,
4116 DWORD dwServiceState
,
4119 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4120 LPBOUNDED_DWORD_256K lpServicesReturned
,
4121 LPBOUNDED_DWORD_256K lpResumeIndex
,
4122 LPCSTR pszGroupName
)
4125 *pcbBytesNeeded
= 0;
4126 *lpServicesReturned
= 0;
4127 return ERROR_CALL_NOT_IMPLEMENTED
;
4132 DWORD
REnumServicesStatusExW(
4133 handle_t BindingHandle
,
4134 SC_RPC_HANDLE hSCManager
,
4135 SC_ENUM_TYPE InfoLevel
,
4136 DWORD dwServiceType
,
4137 DWORD dwServiceState
,
4140 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4141 LPBOUNDED_DWORD_256K lpServicesReturned
,
4142 LPBOUNDED_DWORD_256K lpResumeIndex
,
4143 LPCWSTR pszGroupName
)
4145 PMANAGER_HANDLE hManager
;
4147 DWORD dwError
= ERROR_SUCCESS
;
4148 PLIST_ENTRY ServiceEntry
;
4149 PSERVICE CurrentService
;
4151 DWORD dwRequiredSize
;
4152 DWORD dwServiceCount
;
4154 DWORD dwLastResumeCount
;
4155 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4158 DPRINT("REnumServicesStatusExW() called\n");
4161 return ERROR_SHUTDOWN_IN_PROGRESS
;
4163 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4164 return ERROR_INVALID_LEVEL
;
4166 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4167 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4169 DPRINT1("Invalid manager handle!\n");
4170 return ERROR_INVALID_HANDLE
;
4173 /* Check access rights */
4174 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4175 SC_MANAGER_ENUMERATE_SERVICE
))
4177 DPRINT1("Insufficient access rights! 0x%lx\n",
4178 hManager
->Handle
.DesiredAccess
);
4179 return ERROR_ACCESS_DENIED
;
4182 *pcbBytesNeeded
= 0;
4183 *lpServicesReturned
= 0;
4185 dwLastResumeCount
= *lpResumeIndex
;
4187 /* Lock the service list shared */
4189 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4190 if (lpService
== NULL
)
4192 dwError
= ERROR_SUCCESS
;
4199 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4200 ServiceEntry
!= &ServiceListHead
;
4201 ServiceEntry
= ServiceEntry
->Flink
)
4203 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4207 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4210 dwState
= SERVICE_ACTIVE
;
4211 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4212 dwState
= SERVICE_INACTIVE
;
4214 if ((dwState
& dwServiceState
) == 0)
4219 if (*pszGroupName
== 0)
4221 if (CurrentService
->lpGroup
!= NULL
)
4226 if ((CurrentService
->lpGroup
== NULL
) ||
4227 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4232 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4233 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4234 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4236 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4238 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4239 dwRequiredSize
+= dwSize
;
4241 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4245 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4251 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4252 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4255 ServiceEntry
!= &ServiceListHead
;
4256 ServiceEntry
= ServiceEntry
->Flink
)
4258 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4262 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4265 dwState
= SERVICE_ACTIVE
;
4266 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4267 dwState
= SERVICE_INACTIVE
;
4269 if ((dwState
& dwServiceState
) == 0)
4274 if (*pszGroupName
== 0)
4276 if (CurrentService
->lpGroup
!= NULL
)
4281 if ((CurrentService
->lpGroup
== NULL
) ||
4282 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4287 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4288 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4289 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4291 dwError
= ERROR_MORE_DATA
;
4294 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4296 *lpResumeIndex
= dwLastResumeCount
;
4297 *lpServicesReturned
= dwServiceCount
;
4298 *pcbBytesNeeded
= dwRequiredSize
;
4300 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
4301 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4302 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4305 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4306 ServiceEntry
!= &ServiceListHead
;
4307 ServiceEntry
= ServiceEntry
->Flink
)
4309 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4313 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4316 dwState
= SERVICE_ACTIVE
;
4317 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4318 dwState
= SERVICE_INACTIVE
;
4320 if ((dwState
& dwServiceState
) == 0)
4325 if (*pszGroupName
== 0)
4327 if (CurrentService
->lpGroup
!= NULL
)
4332 if ((CurrentService
->lpGroup
== NULL
) ||
4333 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4338 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4339 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4340 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4342 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4344 /* Copy the service name */
4346 CurrentService
->lpServiceName
);
4347 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4348 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4350 /* Copy the display name */
4352 CurrentService
->lpDisplayName
);
4353 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4354 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4356 /* Copy the status information */
4357 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
4358 &CurrentService
->Status
,
4359 sizeof(SERVICE_STATUS
));
4360 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
4361 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4364 dwRequiredSize
+= dwSize
;
4374 /* Unlock the service list */
4376 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
4383 DWORD
RSendTSMessage(
4384 handle_t BindingHandle
)
4387 return ERROR_CALL_NOT_IMPLEMENTED
;
4392 DWORD
RCreateServiceWOW64A(
4393 handle_t BindingHandle
,
4394 LPSTR lpServiceName
,
4395 LPSTR lpDisplayName
,
4396 DWORD dwDesiredAccess
,
4397 DWORD dwServiceType
,
4399 DWORD dwErrorControl
,
4400 LPSTR lpBinaryPathName
,
4401 LPSTR lpLoadOrderGroup
,
4403 LPBYTE lpDependencies
,
4405 LPSTR lpServiceStartName
,
4408 LPSC_RPC_HANDLE lpServiceHandle
)
4411 return ERROR_CALL_NOT_IMPLEMENTED
;
4416 DWORD
RCreateServiceWOW64W(
4417 handle_t BindingHandle
,
4418 LPWSTR lpServiceName
,
4419 LPWSTR lpDisplayName
,
4420 DWORD dwDesiredAccess
,
4421 DWORD dwServiceType
,
4423 DWORD dwErrorControl
,
4424 LPWSTR lpBinaryPathName
,
4425 LPWSTR lpLoadOrderGroup
,
4427 LPBYTE lpDependencies
,
4429 LPWSTR lpServiceStartName
,
4432 LPSC_RPC_HANDLE lpServiceHandle
)
4435 return ERROR_CALL_NOT_IMPLEMENTED
;
4440 DWORD
RQueryServiceTagInfo(
4441 handle_t BindingHandle
)
4444 return ERROR_CALL_NOT_IMPLEMENTED
;
4449 DWORD
RNotifyServiceStatusChange(
4450 handle_t BindingHandle
,
4451 SC_RPC_HANDLE hService
,
4452 SC_RPC_NOTIFY_PARAMS NotifyParams
,
4453 GUID
*pClientProcessGuid
,
4454 GUID
*pSCMProcessGuid
,
4455 PBOOL pfCreateRemoteQueue
,
4456 LPSC_NOTIFY_RPC_HANDLE phNotify
)
4459 return ERROR_CALL_NOT_IMPLEMENTED
;
4464 DWORD
RGetNotifyResults(
4465 handle_t BindingHandle
,
4466 SC_NOTIFY_RPC_HANDLE hNotify
,
4467 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
4470 return ERROR_CALL_NOT_IMPLEMENTED
;
4475 DWORD
RCloseNotifyHandle(
4476 handle_t BindingHandle
,
4477 LPSC_NOTIFY_RPC_HANDLE phNotify
,
4481 return ERROR_CALL_NOT_IMPLEMENTED
;
4486 DWORD
RControlServiceExA(
4487 handle_t BindingHandle
,
4488 SC_RPC_HANDLE hService
,
4493 return ERROR_CALL_NOT_IMPLEMENTED
;
4498 DWORD
RControlServiceExW(
4499 handle_t BindingHandle
,
4500 SC_RPC_HANDLE hService
,
4505 return ERROR_CALL_NOT_IMPLEMENTED
;
4510 DWORD
RSendPnPMessage(
4511 handle_t BindingHandle
)
4514 return ERROR_CALL_NOT_IMPLEMENTED
;
4519 DWORD
RValidatePnPService(
4520 handle_t BindingHandle
)
4523 return ERROR_CALL_NOT_IMPLEMENTED
;
4528 DWORD
ROpenServiceStatusHandle(
4529 handle_t BindingHandle
)
4532 return ERROR_CALL_NOT_IMPLEMENTED
;
4538 handle_t BindingHandle
)
4541 return ERROR_CALL_NOT_IMPLEMENTED
;
4545 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
4547 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
4551 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
4553 HeapFree(GetProcessHeap(), 0, ptr
);
4557 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
4562 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
4567 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)