2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/rpcserver.c
5 * PURPOSE: RPC server interface for the advapi32 calls
6 * COPYRIGHT: Copyright 2005-2006 Eric Kohl
7 * Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
8 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
11 /* INCLUDES ****************************************************************/
19 /* GLOBALS *****************************************************************/
21 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
22 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
24 typedef struct _SCMGR_HANDLE
31 typedef struct _MANAGER_HANDLE
34 WCHAR DatabaseName
[1];
35 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
38 typedef struct _SERVICE_HANDLE
41 PSERVICE ServiceEntry
;
42 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
45 #define SC_MANAGER_READ \
46 (STANDARD_RIGHTS_READ | \
47 SC_MANAGER_QUERY_LOCK_STATUS | \
48 SC_MANAGER_ENUMERATE_SERVICE)
50 #define SC_MANAGER_WRITE \
51 (STANDARD_RIGHTS_WRITE | \
52 SC_MANAGER_MODIFY_BOOT_CONFIG | \
53 SC_MANAGER_CREATE_SERVICE)
55 #define SC_MANAGER_EXECUTE \
56 (STANDARD_RIGHTS_EXECUTE | \
58 SC_MANAGER_ENUMERATE_SERVICE | \
59 SC_MANAGER_CONNECT | \
60 SC_MANAGER_CREATE_SERVICE)
63 #define SERVICE_READ \
64 (STANDARD_RIGHTS_READ | \
65 SERVICE_INTERROGATE | \
66 SERVICE_ENUMERATE_DEPENDENTS | \
67 SERVICE_QUERY_STATUS | \
70 #define SERVICE_WRITE \
71 (STANDARD_RIGHTS_WRITE | \
72 SERVICE_CHANGE_CONFIG)
74 #define SERVICE_EXECUTE \
75 (STANDARD_RIGHTS_EXECUTE | \
76 SERVICE_USER_DEFINED_CONTROL | \
77 SERVICE_PAUSE_CONTINUE | \
82 /* VARIABLES ***************************************************************/
84 static GENERIC_MAPPING
85 ScmManagerMapping
= {SC_MANAGER_READ
,
88 SC_MANAGER_ALL_ACCESS
};
90 static GENERIC_MAPPING
91 ScmServiceMapping
= {SERVICE_READ
,
94 SC_MANAGER_ALL_ACCESS
};
97 /* FUNCTIONS ***************************************************************/
100 ScmStartRpcServer(VOID
)
104 DPRINT("ScmStartRpcServer() called\n");
106 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
110 if (Status
!= RPC_S_OK
)
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
116 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
125 Status
= RpcServerListen(1, 20, TRUE
);
126 if (Status
!= RPC_S_OK
)
128 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
132 DPRINT("ScmStartRpcServer() done\n");
137 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
142 if (lpDatabaseName
== NULL
)
143 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
145 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
147 DPRINT("Database %S, does not exist\n",lpDatabaseName
);
148 return ERROR_DATABASE_DOES_NOT_EXIST
;
150 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
152 DPRINT("Invalid Database name %S.\n",lpDatabaseName
);
153 return ERROR_INVALID_NAME
;
156 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
158 sizeof(MANAGER_HANDLE
) + (wcslen(lpDatabaseName
) + 1) * sizeof(WCHAR
));
160 return ERROR_NOT_ENOUGH_MEMORY
;
162 Ptr
->Handle
.Tag
= MANAGER_TAG
;
164 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
166 *Handle
= (SC_HANDLE
)Ptr
;
168 return ERROR_SUCCESS
;
173 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
178 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
180 sizeof(SERVICE_HANDLE
));
182 return ERROR_NOT_ENOUGH_MEMORY
;
184 Ptr
->Handle
.Tag
= SERVICE_TAG
;
186 Ptr
->ServiceEntry
= lpServiceEntry
;
188 *Handle
= (SC_HANDLE
)Ptr
;
190 return ERROR_SUCCESS
;
194 static PMANAGER_HANDLE
195 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
197 PMANAGER_HANDLE pManager
= NULL
;
201 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
202 pManager
= (PMANAGER_HANDLE
)Handle
;
204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
206 DPRINT1("Exception: Invalid Service Manager handle!\n");
214 static PSERVICE_HANDLE
215 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
217 PSERVICE_HANDLE pService
= NULL
;
221 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
222 pService
= (PSERVICE_HANDLE
)Handle
;
224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
226 DPRINT1("Exception: Invalid Service handle!\n");
235 ScmCheckAccess(SC_HANDLE Handle
,
236 DWORD dwDesiredAccess
)
238 PMANAGER_HANDLE hMgr
;
240 hMgr
= (PMANAGER_HANDLE
)Handle
;
241 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
243 RtlMapGenericMask(&dwDesiredAccess
,
246 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
248 return ERROR_SUCCESS
;
250 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
252 RtlMapGenericMask(&dwDesiredAccess
,
255 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
257 return ERROR_SUCCESS
;
260 return ERROR_INVALID_HANDLE
;
265 ScmAssignNewTag(PSERVICE lpService
)
268 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
269 lpService
->dwTag
= 0;
270 return ERROR_SUCCESS
;
274 /* Internal recursive function */
275 /* Need to search for every dependency on every service */
277 Int_EnumDependentServicesW(HKEY hServicesKey
,
279 DWORD dwServiceState
,
280 PSERVICE
*lpServices
,
281 LPDWORD pcbBytesNeeded
,
282 LPDWORD lpServicesReturned
)
284 DWORD dwError
= ERROR_SUCCESS
;
285 WCHAR szNameBuf
[MAX_PATH
];
286 WCHAR szValueBuf
[MAX_PATH
];
287 WCHAR
*lpszNameBuf
= szNameBuf
;
288 WCHAR
*lpszValueBuf
= szValueBuf
;
292 PSERVICE lpCurrentService
;
293 HKEY hServiceEnumKey
;
294 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
295 DWORD dwDependServiceStrPtr
= 0;
296 DWORD dwRequiredSize
= 0;
298 /* Get the number of service keys */
299 dwError
= RegQueryInfoKeyW(hServicesKey
,
311 if (dwError
!= ERROR_SUCCESS
)
313 DPRINT("ERROR! Unable to get number of services keys.\n");
317 /* Iterate the service keys to see if another service depends on the this service */
318 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
321 dwError
= RegEnumKeyExW(hServicesKey
,
329 if (dwError
!= ERROR_SUCCESS
)
332 /* Open the Service key */
333 dwError
= RegOpenKeyExW(hServicesKey
,
338 if (dwError
!= ERROR_SUCCESS
)
343 /* Check for the DependOnService Value */
344 dwError
= RegQueryValueExW(hServiceEnumKey
,
348 (LPBYTE
)lpszValueBuf
,
351 /* FIXME: Handle load order. */
353 /* If the service found has a DependOnService value */
354 if (dwError
== ERROR_SUCCESS
)
356 dwDependServiceStrPtr
= 0;
358 /* Can be more than one Dependencies in the DependOnService string */
359 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
361 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
363 /* Get the current enumed service pointer */
364 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
366 /* Check for valid Service */
367 if (!lpCurrentService
)
369 /* This should never happen! */
370 DPRINT("This should not happen at this point, report to Developer\n");
371 return ERROR_NOT_FOUND
;
374 /* Determine state the service is in */
375 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
376 dwCurrentServiceState
= SERVICE_INACTIVE
;
378 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
379 if ((dwCurrentServiceState
== dwServiceState
) ||
380 (dwServiceState
== SERVICE_STATE_ALL
))
382 /* Calculate the required size */
383 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
384 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
385 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
387 /* Add the size for service name and display name pointers */
388 dwRequiredSize
+= (2 * sizeof(PVOID
));
390 /* increase the BytesNeeded size */
391 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
393 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
396 /* Recursive call to check for its dependencies */
397 Int_EnumDependentServicesW(hServicesKey
,
404 /* If the lpServices is valid set the service pointer */
406 lpServices
[*lpServicesReturned
] = lpCurrentService
;
408 *lpServicesReturned
= *lpServicesReturned
+ 1;
412 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
415 else if (*pcbBytesNeeded
)
417 dwError
= ERROR_SUCCESS
;
420 RegCloseKey(hServiceEnumKey
);
428 DWORD
RCloseServiceHandle(
429 LPSC_RPC_HANDLE hSCObject
)
431 PMANAGER_HANDLE hManager
;
432 PSERVICE_HANDLE hService
;
436 DWORD pcbBytesNeeded
= 0;
437 DWORD dwServicesReturned
= 0;
439 DPRINT("RCloseServiceHandle() called\n");
441 DPRINT("hSCObject = %p\n", *hSCObject
);
444 return ERROR_INVALID_HANDLE
;
446 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
447 hService
= ScmGetServiceFromHandle(*hSCObject
);
449 if (hManager
!= NULL
)
451 DPRINT("Found manager handle\n");
453 /* FIXME: add handle cleanup code */
455 HeapFree(GetProcessHeap(), 0, hManager
);
458 DPRINT("RCloseServiceHandle() done\n");
459 return ERROR_SUCCESS
;
461 else if (hService
!= NULL
)
463 DPRINT("Found service handle\n");
465 /* Get the pointer to the service record */
466 lpService
= hService
->ServiceEntry
;
468 /* FIXME: add handle cleanup code */
470 /* Free the handle */
471 HeapFree(GetProcessHeap(), 0, hService
);
474 ASSERT(lpService
->dwRefCount
> 0);
476 lpService
->dwRefCount
--;
477 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
478 lpService
->dwRefCount
);
480 if (lpService
->dwRefCount
== 0)
482 /* If this service has been marked for deletion */
483 if (lpService
->bDeleted
)
485 /* Open the Services Reg key */
486 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
487 L
"System\\CurrentControlSet\\Services",
489 KEY_SET_VALUE
| KEY_READ
,
491 if (dwError
!= ERROR_SUCCESS
)
493 DPRINT("Failed to open services key\n");
497 /* Call the internal function with NULL, just to get bytes we need */
498 Int_EnumDependentServicesW(hServicesKey
,
503 &dwServicesReturned
);
505 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
508 DPRINT("Deletion failed due to running dependencies.\n");
509 RegCloseKey(hServicesKey
);
510 return ERROR_SUCCESS
;
513 /* There are no references and no runnning dependencies,
514 it is now safe to delete the service */
516 /* Delete the Service Key */
517 dwError
= RegDeleteKeyW(hServicesKey
,
518 lpService
->lpServiceName
);
520 RegCloseKey(hServicesKey
);
522 if (dwError
!= ERROR_SUCCESS
)
524 DPRINT("Failed to Delete the Service Registry key\n");
528 /* Delete the Service */
529 ScmDeleteServiceRecord(lpService
);
533 DPRINT("RCloseServiceHandle() done\n");
534 return ERROR_SUCCESS
;
537 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
539 return ERROR_INVALID_HANDLE
;
544 DWORD
RControlService(
545 SC_RPC_HANDLE hService
,
547 LPSERVICE_STATUS lpServiceStatus
)
549 PSERVICE_HANDLE hSvc
;
551 ACCESS_MASK DesiredAccess
;
552 DWORD dwError
= ERROR_SUCCESS
;
553 DWORD pcbBytesNeeded
= 0;
554 DWORD dwServicesReturned
= 0;
555 DWORD dwControlsAccepted
;
556 HKEY hServicesKey
= NULL
;
558 DPRINT("RControlService() called\n");
561 return ERROR_SHUTDOWN_IN_PROGRESS
;
563 /* Check the service handle */
564 hSvc
= ScmGetServiceFromHandle(hService
);
567 DPRINT1("Invalid service handle!\n");
568 return ERROR_INVALID_HANDLE
;
572 /* Check the service entry point */
573 lpService
= hSvc
->ServiceEntry
;
574 if (lpService
== NULL
)
576 DPRINT1("lpService == NULL!\n");
577 return ERROR_INVALID_HANDLE
;
580 /* Check access rights */
583 case SERVICE_CONTROL_STOP
:
584 DesiredAccess
= SERVICE_STOP
;
587 case SERVICE_CONTROL_PAUSE
:
588 case SERVICE_CONTROL_CONTINUE
:
589 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
592 case SERVICE_INTERROGATE
:
593 DesiredAccess
= SERVICE_INTERROGATE
;
597 if (dwControl
>= 128 && dwControl
<= 255)
598 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
600 DesiredAccess
= SERVICE_QUERY_CONFIG
|
601 SERVICE_CHANGE_CONFIG
|
602 SERVICE_QUERY_STATUS
|
604 SERVICE_PAUSE_CONTINUE
;
608 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
610 return ERROR_ACCESS_DENIED
;
612 if (dwControl
== SERVICE_CONTROL_STOP
)
614 /* Check if the service has dependencies running as windows
615 doesn't stop a service that does */
617 /* Open the Services Reg key */
618 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
619 L
"System\\CurrentControlSet\\Services",
623 if (dwError
!= ERROR_SUCCESS
)
625 DPRINT("Failed to open services key\n");
629 /* Call the internal function with NULL, just to get bytes we need */
630 Int_EnumDependentServicesW(hServicesKey
,
635 &dwServicesReturned
);
637 RegCloseKey(hServicesKey
);
639 /* If pcbBytesNeeded is not zero then there are services running that
640 are dependent on this service */
641 if (pcbBytesNeeded
!= 0)
643 DPRINT("Service has running dependencies. Failed to stop service.\n");
644 return ERROR_DEPENDENT_SERVICES_RUNNING
;
648 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
650 /* Send control code to the driver */
651 dwError
= ScmControlDriver(lpService
,
657 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
659 /* Check if the control code is acceptable */
662 case SERVICE_CONTROL_STOP
:
663 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
664 return ERROR_INVALID_SERVICE_CONTROL
;
667 case SERVICE_CONTROL_PAUSE
:
668 case SERVICE_CONTROL_CONTINUE
:
669 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
670 return ERROR_INVALID_SERVICE_CONTROL
;
674 /* Send control code to the service */
675 dwError
= ScmControlService(lpService
,
678 /* Return service status information */
679 RtlCopyMemory(lpServiceStatus
,
681 sizeof(SERVICE_STATUS
));
684 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
685 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
687 if (dwError
== ERROR_SUCCESS
&&
688 dwControl
== SERVICE_CONTROL_STOP
&&
689 lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
)
691 lpService
->ProcessId
= 0; /* FIXME */
692 lpService
->ThreadId
= 0;
701 DWORD
RDeleteService(
702 SC_RPC_HANDLE hService
)
704 PSERVICE_HANDLE hSvc
;
708 DPRINT("RDeleteService() called\n");
711 return ERROR_SHUTDOWN_IN_PROGRESS
;
713 hSvc
= ScmGetServiceFromHandle(hService
);
716 DPRINT1("Invalid service handle!\n");
717 return ERROR_INVALID_HANDLE
;
720 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
722 return ERROR_ACCESS_DENIED
;
724 lpService
= hSvc
->ServiceEntry
;
725 if (lpService
== NULL
)
727 DPRINT("lpService == NULL!\n");
728 return ERROR_INVALID_HANDLE
;
731 /* FIXME: Acquire service database lock exclusively */
733 if (lpService
->bDeleted
)
735 DPRINT("The service has already been marked for delete!\n");
736 return ERROR_SERVICE_MARKED_FOR_DELETE
;
739 /* Mark service for delete */
740 lpService
->bDeleted
= TRUE
;
742 dwError
= ScmMarkServiceForDelete(lpService
);
744 /* FIXME: Release service database lock */
746 DPRINT("RDeleteService() done\n");
753 DWORD
RLockServiceDatabase(
754 SC_RPC_HANDLE hSCManager
,
755 LPSC_RPC_LOCK lpLock
)
757 PMANAGER_HANDLE hMgr
;
759 DPRINT("RLockServiceDatabase() called\n");
763 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
766 DPRINT1("Invalid service manager handle!\n");
767 return ERROR_INVALID_HANDLE
;
770 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
772 return ERROR_ACCESS_DENIED
;
774 // return ScmLockDatabase(0, hMgr->0xC, hLock);
776 /* FIXME: Lock the database */
777 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
779 return ERROR_SUCCESS
;
784 DWORD
RQueryServiceObjectSecurity(
785 SC_RPC_HANDLE hService
,
786 SECURITY_INFORMATION dwSecurityInformation
,
787 LPBYTE lpSecurityDescriptor
,
789 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
791 PSERVICE_HANDLE hSvc
;
793 ULONG DesiredAccess
= 0;
799 SECURITY_DESCRIPTOR ObjectDescriptor
;
801 DPRINT("RQueryServiceObjectSecurity() called\n");
803 hSvc
= ScmGetServiceFromHandle(hService
);
806 DPRINT1("Invalid service handle!\n");
807 return ERROR_INVALID_HANDLE
;
810 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
811 GROUP_SECURITY_INFORMATION
||
812 OWNER_SECURITY_INFORMATION
))
813 DesiredAccess
|= READ_CONTROL
;
815 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
816 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
818 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
821 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
822 return ERROR_ACCESS_DENIED
;
825 lpService
= hSvc
->ServiceEntry
;
826 if (lpService
== NULL
)
828 DPRINT("lpService == NULL!\n");
829 return ERROR_INVALID_HANDLE
;
832 /* FIXME: Lock the service list */
835 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
837 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
838 dwSecurityInformation
,
839 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
843 /* FIXME: Unlock the service list */
845 if (NT_SUCCESS(Status
))
847 *pcbBytesNeeded
= dwBytesNeeded
;
848 dwError
= STATUS_SUCCESS
;
850 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
852 *pcbBytesNeeded
= dwBytesNeeded
;
853 dwError
= ERROR_INSUFFICIENT_BUFFER
;
855 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
857 dwError
= ERROR_GEN_FAILURE
;
861 dwError
= RtlNtStatusToDosError(Status
);
869 DWORD
RSetServiceObjectSecurity(
870 SC_RPC_HANDLE hService
,
871 DWORD dwSecurityInformation
,
872 LPBYTE lpSecurityDescriptor
,
873 DWORD dwSecuityDescriptorSize
)
875 PSERVICE_HANDLE hSvc
;
877 ULONG DesiredAccess
= 0;
878 /* HANDLE hToken = NULL; */
880 /* NTSTATUS Status; */
883 DPRINT("RSetServiceObjectSecurity() called\n");
885 hSvc
= ScmGetServiceFromHandle(hService
);
888 DPRINT1("Invalid service handle!\n");
889 return ERROR_INVALID_HANDLE
;
892 if (dwSecurityInformation
== 0 ||
893 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
894 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
895 return ERROR_INVALID_PARAMETER
;
897 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
898 return ERROR_INVALID_PARAMETER
;
900 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
901 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
903 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
904 DesiredAccess
|= WRITE_DAC
;
906 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
907 DesiredAccess
|= WRITE_OWNER
;
909 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
910 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
911 return ERROR_INVALID_PARAMETER
;
913 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
914 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
915 return ERROR_INVALID_PARAMETER
;
917 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
920 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
921 return ERROR_ACCESS_DENIED
;
924 lpService
= hSvc
->ServiceEntry
;
925 if (lpService
== NULL
)
927 DPRINT("lpService == NULL!\n");
928 return ERROR_INVALID_HANDLE
;
931 if (lpService
->bDeleted
)
932 return ERROR_SERVICE_MARKED_FOR_DELETE
;
935 RpcImpersonateClient(NULL
);
937 Status
= NtOpenThreadToken(NtCurrentThread(),
941 if (!NT_SUCCESS(Status
))
942 return RtlNtStatusToDosError(Status
);
946 /* FIXME: Lock service database */
948 Status
= RtlSetSecurityObject(dwSecurityInformation
,
949 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
950 &lpService
->lpSecurityDescriptor
,
953 if (!NT_SUCCESS(Status
))
955 dwError
= RtlNtStatusToDosError(Status
);
960 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
961 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
963 if (dwError
!= ERROR_SUCCESS
)
967 dwError
= ERROR_SUCCESS
;
968 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
969 // lpService->lpSecurityDescriptor);
971 RegFlushKey(hServiceKey
);
972 RegCloseKey(hServiceKey
);
981 /* FIXME: Unlock service database */
983 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
990 DWORD
RQueryServiceStatus(
991 SC_RPC_HANDLE hService
,
992 LPSERVICE_STATUS lpServiceStatus
)
994 PSERVICE_HANDLE hSvc
;
997 DPRINT("RQueryServiceStatus() called\n");
1000 return ERROR_SHUTDOWN_IN_PROGRESS
;
1002 hSvc
= ScmGetServiceFromHandle(hService
);
1005 DPRINT1("Invalid service handle!\n");
1006 return ERROR_INVALID_HANDLE
;
1009 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1010 SERVICE_QUERY_STATUS
))
1012 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1013 return ERROR_ACCESS_DENIED
;
1016 lpService
= hSvc
->ServiceEntry
;
1017 if (lpService
== NULL
)
1019 DPRINT("lpService == NULL!\n");
1020 return ERROR_INVALID_HANDLE
;
1023 ScmLockDatabaseShared();
1025 /* Return service status information */
1026 RtlCopyMemory(lpServiceStatus
,
1028 sizeof(SERVICE_STATUS
));
1030 ScmUnlockDatabase();
1032 return ERROR_SUCCESS
;
1037 ScmIsValidServiceState(DWORD dwCurrentState
)
1039 switch (dwCurrentState
)
1041 case SERVICE_STOPPED
:
1042 case SERVICE_START_PENDING
:
1043 case SERVICE_STOP_PENDING
:
1044 case SERVICE_RUNNING
:
1045 case SERVICE_CONTINUE_PENDING
:
1046 case SERVICE_PAUSE_PENDING
:
1047 case SERVICE_PAUSED
:
1057 DWORD
RSetServiceStatus(
1058 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1059 LPSERVICE_STATUS lpServiceStatus
)
1063 DPRINT("RSetServiceStatus() called\n");
1064 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1065 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1066 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1067 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1068 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1069 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1070 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1071 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1073 if (hServiceStatus
== 0)
1075 DPRINT("hServiceStatus == NULL!\n");
1076 return ERROR_INVALID_HANDLE
;
1079 lpService
= (PSERVICE
)hServiceStatus
;
1080 if (lpService
== NULL
)
1082 DPRINT("lpService == NULL!\n");
1083 return ERROR_INVALID_HANDLE
;
1086 /* Check current state */
1087 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1089 DPRINT("Invalid service state!\n");
1090 return ERROR_INVALID_DATA
;
1093 /* Check service type */
1094 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1095 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1097 DPRINT("Invalid service type!\n");
1098 return ERROR_INVALID_DATA
;
1101 /* Check accepted controls */
1102 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1104 DPRINT("Invalid controls accepted!\n");
1105 return ERROR_INVALID_DATA
;
1108 ScmLockDatabaseExclusive();
1110 RtlCopyMemory(&lpService
->Status
,
1112 sizeof(SERVICE_STATUS
));
1114 ScmUnlockDatabase();
1116 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1117 DPRINT("RSetServiceStatus() done\n");
1119 return ERROR_SUCCESS
;
1124 DWORD
RUnlockServiceDatabase(
1128 return ERROR_SUCCESS
;
1133 DWORD
RNotifyBootConfigStatus(
1134 SVCCTL_HANDLEW lpMachineName
,
1135 DWORD BootAcceptable
)
1138 return ERROR_CALL_NOT_IMPLEMENTED
;
1143 DWORD
RI_ScSetServiceBitsW(
1144 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1145 DWORD dwServiceBits
,
1147 int bUpdateImmediately
,
1151 return ERROR_CALL_NOT_IMPLEMENTED
;
1156 DWORD
RChangeServiceConfigW(
1157 SC_RPC_HANDLE hService
,
1158 DWORD dwServiceType
,
1160 DWORD dwErrorControl
,
1161 LPWSTR lpBinaryPathName
,
1162 LPWSTR lpLoadOrderGroup
,
1164 LPBYTE lpDependencies
,
1166 LPWSTR lpServiceStartName
,
1169 LPWSTR lpDisplayName
)
1171 DWORD dwError
= ERROR_SUCCESS
;
1172 PSERVICE_HANDLE hSvc
;
1173 PSERVICE lpService
= NULL
;
1174 HKEY hServiceKey
= NULL
;
1175 LPWSTR lpDisplayNameW
= NULL
;
1177 DPRINT("RChangeServiceConfigW() called\n");
1178 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1179 DPRINT("dwStartType = %lu\n", dwStartType
);
1180 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1181 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1182 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1183 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1186 return ERROR_SHUTDOWN_IN_PROGRESS
;
1188 hSvc
= ScmGetServiceFromHandle(hService
);
1191 DPRINT1("Invalid service handle!\n");
1192 return ERROR_INVALID_HANDLE
;
1195 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1196 SERVICE_CHANGE_CONFIG
))
1198 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1199 return ERROR_ACCESS_DENIED
;
1202 lpService
= hSvc
->ServiceEntry
;
1203 if (lpService
== NULL
)
1205 DPRINT("lpService == NULL!\n");
1206 return ERROR_INVALID_HANDLE
;
1209 /* FIXME: Lock database exclusively */
1211 if (lpService
->bDeleted
)
1213 /* FIXME: Unlock database */
1214 DPRINT("The service has already been marked for delete!\n");
1215 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1218 /* Open the service key */
1219 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1222 if (dwError
!= ERROR_SUCCESS
)
1225 /* Write service data to the registry */
1226 /* Set the display name */
1227 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1229 RegSetValueExW(hServiceKey
,
1233 (LPBYTE
)lpDisplayName
,
1234 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1236 /* Update the display name */
1237 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1239 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1240 if (lpDisplayNameW
== NULL
)
1242 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1246 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1247 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1249 lpService
->lpDisplayName
= lpDisplayNameW
;
1252 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1254 /* Set the service type */
1255 dwError
= RegSetValueExW(hServiceKey
,
1259 (LPBYTE
)&dwServiceType
,
1261 if (dwError
!= ERROR_SUCCESS
)
1264 lpService
->Status
.dwServiceType
= dwServiceType
;
1267 if (dwStartType
!= SERVICE_NO_CHANGE
)
1269 /* Set the start value */
1270 dwError
= RegSetValueExW(hServiceKey
,
1274 (LPBYTE
)&dwStartType
,
1276 if (dwError
!= ERROR_SUCCESS
)
1279 lpService
->dwStartType
= dwStartType
;
1282 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1284 /* Set the error control value */
1285 dwError
= RegSetValueExW(hServiceKey
,
1289 (LPBYTE
)&dwErrorControl
,
1291 if (dwError
!= ERROR_SUCCESS
)
1294 lpService
->dwErrorControl
= dwErrorControl
;
1298 /* FIXME: set the new ImagePath value */
1300 /* Set the image path */
1301 if (dwServiceType
& SERVICE_WIN32
)
1303 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1305 dwError
= RegSetValueExW(hServiceKey
,
1309 (LPBYTE
)lpBinaryPathName
,
1310 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1311 if (dwError
!= ERROR_SUCCESS
)
1315 else if (dwServiceType
& SERVICE_DRIVER
)
1317 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1319 dwError
= RegSetValueExW(hServiceKey
,
1323 (LPBYTE
)lpImagePath
,
1324 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1325 if (dwError
!= ERROR_SUCCESS
)
1331 /* Set the group name */
1332 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1334 dwError
= RegSetValueExW(hServiceKey
,
1338 (LPBYTE
)lpLoadOrderGroup
,
1339 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1340 if (dwError
!= ERROR_SUCCESS
)
1343 dwError
= ScmSetServiceGroup(lpService
,
1345 if (dwError
!= ERROR_SUCCESS
)
1349 if (lpdwTagId
!= NULL
)
1351 dwError
= ScmAssignNewTag(lpService
);
1352 if (dwError
!= ERROR_SUCCESS
)
1355 dwError
= RegSetValueExW(hServiceKey
,
1359 (LPBYTE
)&lpService
->dwTag
,
1361 if (dwError
!= ERROR_SUCCESS
)
1364 *lpdwTagId
= lpService
->dwTag
;
1367 /* Write dependencies */
1368 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1370 dwError
= ScmWriteDependencies(hServiceKey
,
1371 (LPWSTR
)lpDependencies
,
1373 if (dwError
!= ERROR_SUCCESS
)
1377 if (lpPassword
!= NULL
)
1379 /* FIXME: Write password */
1382 /* FIXME: Unlock database */
1385 if (hServiceKey
!= NULL
)
1386 RegCloseKey(hServiceKey
);
1388 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1394 /* Create a path suitable for the bootloader out of the full path */
1396 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1398 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1401 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1402 OBJECT_ATTRIBUTES ObjectAttributes
;
1404 HANDLE SymbolicLinkHandle
;
1406 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1408 ServiceNameLen
= wcslen(CanonName
);
1410 /* First check, if it's already good */
1411 if (ServiceNameLen
> 12 &&
1412 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1414 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1415 if (*RelativeName
== NULL
)
1417 DPRINT("Error allocating memory for boot driver name!\n");
1418 return ERROR_NOT_ENOUGH_MEMORY
;
1422 wcscpy(*RelativeName
, CanonName
);
1424 DPRINT("Bootdriver name %S\n", *RelativeName
);
1425 return ERROR_SUCCESS
;
1428 /* If it has %SystemRoot% prefix, substitute it to \System*/
1429 if (ServiceNameLen
> 13 &&
1430 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1432 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1433 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1435 if (*RelativeName
== NULL
)
1437 DPRINT("Error allocating memory for boot driver name!\n");
1438 return ERROR_NOT_ENOUGH_MEMORY
;
1442 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1443 wcscat(*RelativeName
, CanonName
+ 13);
1445 DPRINT("Bootdriver name %S\n", *RelativeName
);
1446 return ERROR_SUCCESS
;
1449 /* Get buffer size needed for expanding env strings */
1450 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1452 if (BufferSize
<= 1)
1454 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1455 return ERROR_INVALID_ENVIRONMENT
;
1458 /* Allocate memory, since the size is known now */
1459 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1462 DPRINT("Error allocating memory for boot driver name!\n");
1463 return ERROR_NOT_ENOUGH_MEMORY
;
1467 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1470 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1471 LocalFree(Expanded
);
1472 return ERROR_NOT_ENOUGH_MEMORY
;
1475 /* Convert to NY-style path */
1476 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1478 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1479 return ERROR_INVALID_ENVIRONMENT
;
1482 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1484 /* No need to keep the dos-path anymore */
1485 LocalFree(Expanded
);
1487 /* Copy it to the allocated place */
1488 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1491 DPRINT("Error allocating memory for boot driver name!\n");
1492 return ERROR_NOT_ENOUGH_MEMORY
;
1495 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1496 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1497 Expanded
[ExpandedLen
] = 0;
1499 if (ServiceNameLen
> ExpandedLen
&&
1500 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1502 /* Only \SystemRoot\ is missing */
1503 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1504 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1505 if (*RelativeName
== NULL
)
1507 DPRINT("Error allocating memory for boot driver name!\n");
1508 LocalFree(Expanded
);
1509 return ERROR_NOT_ENOUGH_MEMORY
;
1512 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1513 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1515 RtlFreeUnicodeString(&NtPathName
);
1516 return ERROR_SUCCESS
;
1519 /* The most complex case starts here */
1520 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1521 InitializeObjectAttributes(&ObjectAttributes
,
1523 OBJ_CASE_INSENSITIVE
,
1527 /* Open this symlink */
1528 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1530 if (NT_SUCCESS(Status
))
1532 LinkTarget
.Length
= 0;
1533 LinkTarget
.MaximumLength
= 0;
1535 DPRINT("Opened symbolic link object\n");
1537 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1538 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1540 /* Check if required buffer size is sane */
1541 if (BufferSize
> 0xFFFD)
1543 DPRINT("Too large buffer required\n");
1546 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1547 LocalFree(Expanded
);
1548 return ERROR_NOT_ENOUGH_MEMORY
;
1551 /* Alloc the string */
1552 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1553 if (!LinkTarget
.Buffer
)
1555 DPRINT("Unable to alloc buffer\n");
1556 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1557 LocalFree(Expanded
);
1558 return ERROR_NOT_ENOUGH_MEMORY
;
1561 /* Do a real query now */
1562 LinkTarget
.Length
= BufferSize
;
1563 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1565 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1566 if (NT_SUCCESS(Status
))
1568 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1570 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1571 if ((ServiceNameLen
> ExpandedLen
) &&
1572 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1574 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1575 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1577 if (*RelativeName
== NULL
)
1579 DPRINT("Unable to alloc buffer\n");
1580 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1581 LocalFree(Expanded
);
1582 RtlFreeUnicodeString(&NtPathName
);
1583 return ERROR_NOT_ENOUGH_MEMORY
;
1586 /* Copy it over, substituting the first part
1588 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1589 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1592 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1593 LocalFree(Expanded
);
1594 RtlFreeUnicodeString(&NtPathName
);
1596 /* Return success */
1597 return ERROR_SUCCESS
;
1601 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1602 LocalFree(Expanded
);
1603 RtlFreeUnicodeString(&NtPathName
);
1604 return ERROR_INVALID_PARAMETER
;
1609 DPRINT("Error, Status = %08X\n", Status
);
1610 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1611 LocalFree(Expanded
);
1612 RtlFreeUnicodeString(&NtPathName
);
1613 return ERROR_INVALID_PARAMETER
;
1618 DPRINT("Error, Status = %08X\n", Status
);
1619 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1620 LocalFree(Expanded
);
1621 RtlFreeUnicodeString(&NtPathName
);
1622 return ERROR_INVALID_PARAMETER
;
1627 DPRINT("Error, Status = %08X\n", Status
);
1628 LocalFree(Expanded
);
1629 return ERROR_INVALID_PARAMETER
;
1633 *RelativeName
= NULL
;
1634 return ERROR_INVALID_PARAMETER
;
1638 ScmCanonDriverImagePath(DWORD dwStartType
,
1639 const wchar_t *lpServiceName
,
1640 wchar_t **lpCanonName
)
1642 DWORD ServiceNameLen
, Result
;
1643 UNICODE_STRING NtServiceName
;
1644 WCHAR
*RelativeName
;
1645 const WCHAR
*SourceName
= lpServiceName
;
1647 /* Calculate the length of the service's name */
1648 ServiceNameLen
= wcslen(lpServiceName
);
1650 /* 12 is wcslen(L"\\SystemRoot\\") */
1651 if (ServiceNameLen
> 12 &&
1652 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1654 /* SystemRoot prefix is already included */
1656 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1658 if (*lpCanonName
== NULL
)
1660 DPRINT("Error allocating memory for canonized service name!\n");
1661 return ERROR_NOT_ENOUGH_MEMORY
;
1664 /* If it's a boot-time driver, it must be systemroot relative */
1665 if (dwStartType
== SERVICE_BOOT_START
)
1669 wcscpy(*lpCanonName
, SourceName
);
1671 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1675 /* Check if it has %SystemRoot% (len=13) */
1676 if (ServiceNameLen
> 13 &&
1677 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1679 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1680 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1682 if (*lpCanonName
== NULL
)
1684 DPRINT("Error allocating memory for canonized service name!\n");
1685 return ERROR_NOT_ENOUGH_MEMORY
;
1688 /* If it's a boot-time driver, it must be systemroot relative */
1689 if (dwStartType
== SERVICE_BOOT_START
)
1690 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1692 wcscat(*lpCanonName
, lpServiceName
+ 13);
1694 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1698 /* Check if it's a relative path name */
1699 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1701 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1703 if (*lpCanonName
== NULL
)
1705 DPRINT("Error allocating memory for canonized service name!\n");
1706 return ERROR_NOT_ENOUGH_MEMORY
;
1709 /* Just copy it over without changing */
1710 wcscpy(*lpCanonName
, lpServiceName
);
1715 /* It seems to be a DOS path, convert it */
1716 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1718 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1719 return ERROR_INVALID_PARAMETER
;
1722 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1724 if (*lpCanonName
== NULL
)
1726 DPRINT("Error allocating memory for canonized service name!\n");
1727 RtlFreeUnicodeString(&NtServiceName
);
1728 return ERROR_NOT_ENOUGH_MEMORY
;
1731 /* Copy the string */
1732 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1734 /* The unicode string is not needed anymore */
1735 RtlFreeUnicodeString(&NtServiceName
);
1737 if (dwStartType
!= SERVICE_BOOT_START
)
1739 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1743 /* The service is boot-started, so must be relative */
1744 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1747 /* There is a problem, free name and return */
1748 LocalFree(*lpCanonName
);
1749 DPRINT("Error converting named!\n");
1753 ASSERT(RelativeName
);
1755 /* Copy that string */
1756 wcscpy(*lpCanonName
, RelativeName
+ 12);
1758 /* Free the allocated buffer */
1759 LocalFree(RelativeName
);
1761 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1769 DWORD
RCreateServiceW(
1770 SC_RPC_HANDLE hSCManager
,
1771 LPCWSTR lpServiceName
,
1772 LPCWSTR lpDisplayName
,
1773 DWORD dwDesiredAccess
,
1774 DWORD dwServiceType
,
1776 DWORD dwErrorControl
,
1777 LPCWSTR lpBinaryPathName
,
1778 LPCWSTR lpLoadOrderGroup
,
1780 LPBYTE lpDependencies
,
1782 LPCWSTR lpServiceStartName
,
1785 LPSC_RPC_HANDLE lpServiceHandle
)
1787 PMANAGER_HANDLE hManager
;
1788 DWORD dwError
= ERROR_SUCCESS
;
1789 PSERVICE lpService
= NULL
;
1790 SC_HANDLE hServiceHandle
= NULL
;
1791 LPWSTR lpImagePath
= NULL
;
1792 HKEY hServiceKey
= NULL
;
1793 LPWSTR lpObjectName
;
1795 DPRINT("RCreateServiceW() called\n");
1796 DPRINT("lpServiceName = %S\n", lpServiceName
);
1797 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1798 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1799 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1800 DPRINT("dwStartType = %lu\n", dwStartType
);
1801 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1802 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1803 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1806 return ERROR_SHUTDOWN_IN_PROGRESS
;
1808 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1809 if (hManager
== NULL
)
1811 DPRINT1("Invalid service manager handle!\n");
1812 return ERROR_INVALID_HANDLE
;
1815 /* Check access rights */
1816 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1817 SC_MANAGER_CREATE_SERVICE
))
1819 DPRINT("Insufficient access rights! 0x%lx\n",
1820 hManager
->Handle
.DesiredAccess
);
1821 return ERROR_ACCESS_DENIED
;
1824 if (wcslen(lpServiceName
) == 0)
1826 return ERROR_INVALID_NAME
;
1829 if (wcslen(lpBinaryPathName
) == 0)
1831 return ERROR_INVALID_PARAMETER
;
1834 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1835 (lpServiceStartName
))
1837 return ERROR_INVALID_PARAMETER
;
1840 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1841 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1842 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1844 return ERROR_INVALID_PARAMETER
;
1847 if (dwStartType
> SERVICE_DISABLED
)
1849 return ERROR_INVALID_PARAMETER
;
1852 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1855 /* check if it is marked for deletion */
1856 if (lpService
->bDeleted
)
1857 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1858 /* Return Error exist */
1859 return ERROR_SERVICE_EXISTS
;
1862 if (lpDisplayName
!= NULL
&&
1863 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1864 return ERROR_DUPLICATE_SERVICE_NAME
;
1866 if (dwServiceType
& SERVICE_DRIVER
)
1868 dwError
= ScmCanonDriverImagePath(dwStartType
,
1871 if (dwError
!= ERROR_SUCCESS
)
1876 if (dwStartType
== SERVICE_BOOT_START
||
1877 dwStartType
== SERVICE_SYSTEM_START
)
1879 return ERROR_INVALID_PARAMETER
;
1883 /* Allocate a new service entry */
1884 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1886 if (dwError
!= ERROR_SUCCESS
)
1889 /* Fill the new service entry */
1890 lpService
->Status
.dwServiceType
= dwServiceType
;
1891 lpService
->dwStartType
= dwStartType
;
1892 lpService
->dwErrorControl
= dwErrorControl
;
1894 /* Fill the display name */
1895 if (lpDisplayName
!= NULL
&&
1896 *lpDisplayName
!= 0 &&
1897 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1899 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1900 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1901 if (lpService
->lpDisplayName
== NULL
)
1903 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1906 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1909 /* Assign the service to a group */
1910 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1912 dwError
= ScmSetServiceGroup(lpService
,
1914 if (dwError
!= ERROR_SUCCESS
)
1918 /* Assign a new tag */
1919 if (lpdwTagId
!= NULL
)
1921 dwError
= ScmAssignNewTag(lpService
);
1922 if (dwError
!= ERROR_SUCCESS
)
1926 /* Write service data to the registry */
1927 /* Create the service key */
1928 dwError
= ScmCreateServiceKey(lpServiceName
,
1931 if (dwError
!= ERROR_SUCCESS
)
1934 /* Set the display name */
1935 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1937 RegSetValueExW(hServiceKey
,
1941 (LPBYTE
)lpDisplayName
,
1942 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1945 /* Set the service type */
1946 dwError
= RegSetValueExW(hServiceKey
,
1950 (LPBYTE
)&dwServiceType
,
1952 if (dwError
!= ERROR_SUCCESS
)
1955 /* Set the start value */
1956 dwError
= RegSetValueExW(hServiceKey
,
1960 (LPBYTE
)&dwStartType
,
1962 if (dwError
!= ERROR_SUCCESS
)
1965 /* Set the error control value */
1966 dwError
= RegSetValueExW(hServiceKey
,
1970 (LPBYTE
)&dwErrorControl
,
1972 if (dwError
!= ERROR_SUCCESS
)
1975 /* Set the image path */
1976 if (dwServiceType
& SERVICE_WIN32
)
1978 dwError
= RegSetValueExW(hServiceKey
,
1982 (LPBYTE
)lpBinaryPathName
,
1983 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1984 if (dwError
!= ERROR_SUCCESS
)
1987 else if (dwServiceType
& SERVICE_DRIVER
)
1989 dwError
= RegSetValueExW(hServiceKey
,
1993 (LPBYTE
)lpImagePath
,
1994 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1995 if (dwError
!= ERROR_SUCCESS
)
1999 /* Set the group name */
2000 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2002 dwError
= RegSetValueExW(hServiceKey
,
2006 (LPBYTE
)lpLoadOrderGroup
,
2007 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2008 if (dwError
!= ERROR_SUCCESS
)
2012 if (lpdwTagId
!= NULL
)
2014 dwError
= RegSetValueExW(hServiceKey
,
2018 (LPBYTE
)&lpService
->dwTag
,
2020 if (dwError
!= ERROR_SUCCESS
)
2024 /* Write dependencies */
2025 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2027 dwError
= ScmWriteDependencies(hServiceKey
,
2028 (LPWSTR
)lpDependencies
,
2030 if (dwError
!= ERROR_SUCCESS
)
2034 /* Write service start name */
2035 if (dwServiceType
& SERVICE_WIN32
)
2037 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2038 dwError
= RegSetValueExW(hServiceKey
,
2042 (LPBYTE
)lpObjectName
,
2043 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2044 if (dwError
!= ERROR_SUCCESS
)
2048 if (lpPassword
!= NULL
)
2050 /* FIXME: Write password */
2053 dwError
= ScmCreateServiceHandle(lpService
,
2055 if (dwError
!= ERROR_SUCCESS
)
2058 dwError
= ScmCheckAccess(hServiceHandle
,
2060 if (dwError
!= ERROR_SUCCESS
)
2063 lpService
->dwRefCount
= 1;
2064 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2067 if (hServiceKey
!= NULL
)
2068 RegCloseKey(hServiceKey
);
2070 if (dwError
== ERROR_SUCCESS
)
2072 DPRINT("hService %p\n", hServiceHandle
);
2073 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2075 if (lpdwTagId
!= NULL
)
2076 *lpdwTagId
= lpService
->dwTag
;
2080 /* Release the display name buffer */
2081 if (lpService
->lpServiceName
!= NULL
)
2082 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2086 /* Remove the service handle */
2087 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2090 if (lpService
!= NULL
)
2092 /* FIXME: remove the service entry */
2096 if (lpImagePath
!= NULL
)
2097 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2099 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2106 DWORD
REnumDependentServicesW(
2107 SC_RPC_HANDLE hService
,
2108 DWORD dwServiceState
,
2111 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2112 LPBOUNDED_DWORD_256K lpServicesReturned
)
2114 DWORD dwError
= ERROR_SUCCESS
;
2115 DWORD dwServicesReturned
= 0;
2116 DWORD dwServiceCount
;
2117 HKEY hServicesKey
= NULL
;
2118 PSERVICE_HANDLE hSvc
;
2119 PSERVICE lpService
= NULL
;
2120 PSERVICE
*lpServicesArray
= NULL
;
2121 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2124 *pcbBytesNeeded
= 0;
2125 *lpServicesReturned
= 0;
2127 DPRINT("REnumDependentServicesW() called\n");
2129 hSvc
= ScmGetServiceFromHandle(hService
);
2132 DPRINT1("Invalid service handle!\n");
2133 return ERROR_INVALID_HANDLE
;
2136 lpService
= hSvc
->ServiceEntry
;
2138 /* Check access rights */
2139 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2140 SC_MANAGER_ENUMERATE_SERVICE
))
2142 DPRINT("Insufficient access rights! 0x%lx\n",
2143 hSvc
->Handle
.DesiredAccess
);
2144 return ERROR_ACCESS_DENIED
;
2147 /* Open the Services Reg key */
2148 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2149 L
"System\\CurrentControlSet\\Services",
2153 if (dwError
!= ERROR_SUCCESS
)
2156 /* First determine the bytes needed and get the number of dependent services */
2157 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2162 &dwServicesReturned
);
2163 if (dwError
!= ERROR_SUCCESS
)
2166 /* If buffer size is less than the bytes needed or pointer is null */
2167 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2169 dwError
= ERROR_MORE_DATA
;
2173 /* Allocate memory for array of service pointers */
2174 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2176 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2177 if (!lpServicesArray
)
2179 DPRINT("Could not allocate a buffer!!\n");
2180 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2184 dwServicesReturned
= 0;
2185 *pcbBytesNeeded
= 0;
2187 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2192 &dwServicesReturned
);
2193 if (dwError
!= ERROR_SUCCESS
)
2198 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2199 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2201 /* Copy EnumDepenedentService to Buffer */
2202 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2204 lpService
= lpServicesArray
[dwServiceCount
];
2206 /* Copy status info */
2207 memcpy(&lpServicesPtr
->ServiceStatus
,
2209 sizeof(SERVICE_STATUS
));
2211 /* Copy display name */
2212 wcscpy(lpStr
, lpService
->lpDisplayName
);
2213 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2214 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2216 /* Copy service name */
2217 wcscpy(lpStr
, lpService
->lpServiceName
);
2218 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2219 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2224 *lpServicesReturned
= dwServicesReturned
;
2227 if (lpServicesArray
!= NULL
)
2228 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2230 RegCloseKey(hServicesKey
);
2232 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2239 DWORD
REnumServicesStatusW(
2240 SC_RPC_HANDLE hSCManager
,
2241 DWORD dwServiceType
,
2242 DWORD dwServiceState
,
2245 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2246 LPBOUNDED_DWORD_256K lpServicesReturned
,
2247 LPBOUNDED_DWORD_256K lpResumeHandle
)
2249 PMANAGER_HANDLE hManager
;
2251 DWORD dwError
= ERROR_SUCCESS
;
2252 PLIST_ENTRY ServiceEntry
;
2253 PSERVICE CurrentService
;
2255 DWORD dwRequiredSize
;
2256 DWORD dwServiceCount
;
2258 DWORD dwLastResumeCount
= 0;
2259 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2262 DPRINT("REnumServicesStatusW() called\n");
2265 return ERROR_SHUTDOWN_IN_PROGRESS
;
2267 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2268 if (hManager
== NULL
)
2270 DPRINT1("Invalid service manager handle!\n");
2271 return ERROR_INVALID_HANDLE
;
2275 *pcbBytesNeeded
= 0;
2276 *lpServicesReturned
= 0;
2278 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2280 DPRINT("Not a valid Service Type!\n");
2281 return ERROR_INVALID_PARAMETER
;
2284 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2286 DPRINT("Not a valid Service State!\n");
2287 return ERROR_INVALID_PARAMETER
;
2290 /* Check access rights */
2291 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2292 SC_MANAGER_ENUMERATE_SERVICE
))
2294 DPRINT("Insufficient access rights! 0x%lx\n",
2295 hManager
->Handle
.DesiredAccess
);
2296 return ERROR_ACCESS_DENIED
;
2300 dwLastResumeCount
= *lpResumeHandle
;
2302 /* FIXME: Lock the service list shared */
2304 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2305 if (lpService
== NULL
)
2307 dwError
= ERROR_SUCCESS
;
2314 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2315 ServiceEntry
!= &ServiceListHead
;
2316 ServiceEntry
= ServiceEntry
->Flink
)
2318 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2322 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2325 dwState
= SERVICE_ACTIVE
;
2326 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2327 dwState
= SERVICE_INACTIVE
;
2329 if ((dwState
& dwServiceState
) == 0)
2332 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2333 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2334 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2336 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2338 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2342 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2343 dwRequiredSize
+= dwSize
;
2345 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2348 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2349 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2352 ServiceEntry
!= &ServiceListHead
;
2353 ServiceEntry
= ServiceEntry
->Flink
)
2355 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2359 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2362 dwState
= SERVICE_ACTIVE
;
2363 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2364 dwState
= SERVICE_INACTIVE
;
2366 if ((dwState
& dwServiceState
) == 0)
2369 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2370 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2371 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2373 dwError
= ERROR_MORE_DATA
;
2376 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2379 *lpResumeHandle
= dwLastResumeCount
;
2381 *lpServicesReturned
= dwServiceCount
;
2382 *pcbBytesNeeded
= dwRequiredSize
;
2384 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2385 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2386 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2389 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2390 ServiceEntry
!= &ServiceListHead
;
2391 ServiceEntry
= ServiceEntry
->Flink
)
2393 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2397 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2400 dwState
= SERVICE_ACTIVE
;
2401 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2402 dwState
= SERVICE_INACTIVE
;
2404 if ((dwState
& dwServiceState
) == 0)
2407 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2408 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2409 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2411 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2414 /* Copy the service name */
2415 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2416 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2417 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2419 /* Copy the display name */
2420 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2421 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2422 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2424 /* Copy the status information */
2425 memcpy(&lpStatusPtr
->ServiceStatus
,
2426 &CurrentService
->Status
,
2427 sizeof(SERVICE_STATUS
));
2430 dwRequiredSize
+= dwSize
;
2435 *pcbBytesNeeded
= 0;
2436 if (lpResumeHandle
) *lpResumeHandle
= 0;
2440 /* FIXME: Unlock the service list */
2442 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2449 DWORD
ROpenSCManagerW(
2450 LPWSTR lpMachineName
,
2451 LPWSTR lpDatabaseName
,
2452 DWORD dwDesiredAccess
,
2453 LPSC_RPC_HANDLE lpScHandle
)
2458 DPRINT("ROpenSCManagerW() called\n");
2459 DPRINT("lpMachineName = %p\n", lpMachineName
);
2460 DPRINT("lpMachineName: %S\n", lpMachineName
);
2461 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2462 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2463 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2466 return ERROR_SHUTDOWN_IN_PROGRESS
;
2469 return ERROR_INVALID_PARAMETER
;
2471 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2473 if (dwError
!= ERROR_SUCCESS
)
2475 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2479 /* Check the desired access */
2480 dwError
= ScmCheckAccess(hHandle
,
2481 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2482 if (dwError
!= ERROR_SUCCESS
)
2484 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2485 HeapFree(GetProcessHeap(), 0, hHandle
);
2489 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2490 DPRINT("*hScm = %p\n", *lpScHandle
);
2492 DPRINT("ROpenSCManagerW() done\n");
2494 return ERROR_SUCCESS
;
2499 DWORD
ROpenServiceW(
2500 SC_RPC_HANDLE hSCManager
,
2501 LPWSTR lpServiceName
,
2502 DWORD dwDesiredAccess
,
2503 LPSC_RPC_HANDLE lpServiceHandle
)
2506 PMANAGER_HANDLE hManager
;
2510 DPRINT("ROpenServiceW() called\n");
2511 DPRINT("hSCManager = %p\n", hSCManager
);
2512 DPRINT("lpServiceName = %p\n", lpServiceName
);
2513 DPRINT("lpServiceName: %S\n", lpServiceName
);
2514 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2517 return ERROR_SHUTDOWN_IN_PROGRESS
;
2519 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2520 if (hManager
== NULL
)
2522 DPRINT1("Invalid service manager handle!\n");
2523 return ERROR_INVALID_HANDLE
;
2526 if (!lpServiceHandle
)
2527 return ERROR_INVALID_PARAMETER
;
2530 return ERROR_INVALID_ADDRESS
;
2532 /* FIXME: Lock the service list */
2534 /* Get service database entry */
2535 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2536 if (lpService
== NULL
)
2538 DPRINT("Could not find a service!\n");
2539 return ERROR_SERVICE_DOES_NOT_EXIST
;
2542 /* Create a service handle */
2543 dwError
= ScmCreateServiceHandle(lpService
,
2545 if (dwError
!= ERROR_SUCCESS
)
2547 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2551 /* Check the desired access */
2552 dwError
= ScmCheckAccess(hHandle
,
2554 if (dwError
!= ERROR_SUCCESS
)
2556 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2557 HeapFree(GetProcessHeap(), 0, hHandle
);
2561 lpService
->dwRefCount
++;
2562 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2564 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2565 DPRINT("*hService = %p\n", *lpServiceHandle
);
2567 DPRINT("ROpenServiceW() done\n");
2569 return ERROR_SUCCESS
;
2574 DWORD
RQueryServiceConfigW(
2575 SC_RPC_HANDLE hService
,
2576 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2578 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2580 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2581 DWORD dwError
= ERROR_SUCCESS
;
2582 PSERVICE_HANDLE hSvc
;
2583 PSERVICE lpService
= NULL
;
2584 HKEY hServiceKey
= NULL
;
2585 LPWSTR lpImagePath
= NULL
;
2586 LPWSTR lpServiceStartName
= NULL
;
2587 LPWSTR lpDependencies
= NULL
;
2588 DWORD dwDependenciesLength
= 0;
2589 DWORD dwRequiredSize
;
2590 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2591 WCHAR lpEmptyString
[] = {0,0};
2594 DPRINT("RQueryServiceConfigW() called\n");
2597 return ERROR_SHUTDOWN_IN_PROGRESS
;
2599 hSvc
= ScmGetServiceFromHandle(hService
);
2602 DPRINT1("Invalid service handle!\n");
2603 return ERROR_INVALID_HANDLE
;
2606 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2607 SERVICE_QUERY_CONFIG
))
2609 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2610 return ERROR_ACCESS_DENIED
;
2613 lpService
= hSvc
->ServiceEntry
;
2614 if (lpService
== NULL
)
2616 DPRINT("lpService == NULL!\n");
2617 return ERROR_INVALID_HANDLE
;
2620 /* FIXME: Lock the service database shared */
2622 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2625 if (dwError
!= ERROR_SUCCESS
)
2628 /* Read the image path */
2629 dwError
= ScmReadString(hServiceKey
,
2632 if (dwError
!= ERROR_SUCCESS
)
2635 /* Read the service start name */
2636 ScmReadString(hServiceKey
,
2638 &lpServiceStartName
);
2640 /* Read the dependencies */
2641 ScmReadDependencies(hServiceKey
,
2643 &dwDependenciesLength
);
2645 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2647 if (lpImagePath
!= NULL
)
2648 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2650 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2652 if (lpService
->lpGroup
!= NULL
)
2653 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2655 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2657 if (lpDependencies
!= NULL
)
2658 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2660 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2662 if (lpServiceStartName
!= NULL
)
2663 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2665 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2667 if (lpService
->lpDisplayName
!= NULL
)
2668 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2670 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2672 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2674 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2678 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2679 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2680 lpConfig
->dwStartType
= lpService
->dwStartType
;
2681 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2682 lpConfig
->dwTagId
= lpService
->dwTag
;
2684 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2686 /* Append the image path */
2687 if (lpImagePath
!= NULL
)
2689 wcscpy(lpStr
, lpImagePath
);
2693 wcscpy(lpStr
, lpEmptyString
);
2696 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2697 lpStr
+= (wcslen(lpStr
) + 1);
2699 /* Append the group name */
2700 if (lpService
->lpGroup
!= NULL
)
2702 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2706 wcscpy(lpStr
, lpEmptyString
);
2709 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2710 lpStr
+= (wcslen(lpStr
) + 1);
2712 /* Append Dependencies */
2713 if (lpDependencies
!= NULL
)
2717 dwDependenciesLength
* sizeof(WCHAR
));
2721 wcscpy(lpStr
, lpEmptyString
);
2724 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2725 if (lpDependencies
!= NULL
)
2726 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2728 lpStr
+= (wcslen(lpStr
) + 1);
2730 /* Append the service start name */
2731 if (lpServiceStartName
!= NULL
)
2733 wcscpy(lpStr
, lpServiceStartName
);
2737 wcscpy(lpStr
, lpEmptyString
);
2740 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2741 lpStr
+= (wcslen(lpStr
) + 1);
2743 /* Append the display name */
2744 if (lpService
->lpDisplayName
!= NULL
)
2746 wcscpy(lpStr
, lpService
->lpDisplayName
);
2750 wcscpy(lpStr
, lpEmptyString
);
2753 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2756 if (pcbBytesNeeded
!= NULL
)
2757 *pcbBytesNeeded
= dwRequiredSize
;
2760 if (lpImagePath
!= NULL
)
2761 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2763 if (lpServiceStartName
!= NULL
)
2764 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2766 if (lpDependencies
!= NULL
)
2767 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2769 if (hServiceKey
!= NULL
)
2770 RegCloseKey(hServiceKey
);
2772 /* FIXME: Unlock the service database */
2774 DPRINT("RQueryServiceConfigW() done\n");
2781 DWORD
RQueryServiceLockStatusW(
2782 SC_RPC_HANDLE hSCManager
,
2783 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2785 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2788 return ERROR_CALL_NOT_IMPLEMENTED
;
2793 DWORD
RStartServiceW(
2794 SC_RPC_HANDLE hService
,
2796 LPSTRING_PTRSW argv
)
2798 DWORD dwError
= ERROR_SUCCESS
;
2799 PSERVICE_HANDLE hSvc
;
2800 PSERVICE lpService
= NULL
;
2802 DPRINT("RStartServiceW() called\n");
2805 return ERROR_SHUTDOWN_IN_PROGRESS
;
2807 hSvc
= ScmGetServiceFromHandle(hService
);
2810 DPRINT1("Invalid service handle!\n");
2811 return ERROR_INVALID_HANDLE
;
2814 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2817 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2818 return ERROR_ACCESS_DENIED
;
2821 lpService
= hSvc
->ServiceEntry
;
2822 if (lpService
== NULL
)
2824 DPRINT("lpService == NULL!\n");
2825 return ERROR_INVALID_HANDLE
;
2828 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2829 return ERROR_SERVICE_DISABLED
;
2831 if (lpService
->bDeleted
)
2832 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2839 /* Start the service */
2840 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2847 DWORD
RGetServiceDisplayNameW(
2848 SC_RPC_HANDLE hSCManager
,
2849 LPCWSTR lpServiceName
,
2850 LPWSTR lpDisplayName
,
2853 // PMANAGER_HANDLE hManager;
2858 DPRINT("RGetServiceDisplayNameW() called\n");
2859 DPRINT("hSCManager = %p\n", hSCManager
);
2860 DPRINT("lpServiceName: %S\n", lpServiceName
);
2861 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2862 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2864 // hManager = (PMANAGER_HANDLE)hSCManager;
2865 // if (hManager->Handle.Tag != MANAGER_TAG)
2867 // DPRINT("Invalid manager handle!\n");
2868 // return ERROR_INVALID_HANDLE;
2871 /* Get service database entry */
2872 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2873 if (lpService
== NULL
)
2875 DPRINT("Could not find a service!\n");
2877 /* If the service could not be found and lpcchBuffer is less than 2, windows
2878 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2879 if (*lpcchBuffer
< 2)
2882 if (lpDisplayName
!= NULL
)
2884 *lpDisplayName
= '\0';
2888 return ERROR_SERVICE_DOES_NOT_EXIST
;
2891 if (!lpService
->lpDisplayName
)
2893 dwLength
= wcslen(lpService
->lpServiceName
);
2895 if (lpDisplayName
!= NULL
&&
2896 *lpcchBuffer
> dwLength
)
2898 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2903 dwLength
= wcslen(lpService
->lpDisplayName
);
2905 if (lpDisplayName
!= NULL
&&
2906 *lpcchBuffer
> dwLength
)
2908 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2912 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2914 *lpcchBuffer
= dwLength
;
2921 DWORD
RGetServiceKeyNameW(
2922 SC_RPC_HANDLE hSCManager
,
2923 LPCWSTR lpDisplayName
,
2924 LPWSTR lpServiceName
,
2927 // PMANAGER_HANDLE hManager;
2932 DPRINT("RGetServiceKeyNameW() called\n");
2933 DPRINT("hSCManager = %p\n", hSCManager
);
2934 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2935 DPRINT("lpServiceName: %p\n", lpServiceName
);
2936 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2938 // hManager = (PMANAGER_HANDLE)hSCManager;
2939 // if (hManager->Handle.Tag != MANAGER_TAG)
2941 // DPRINT("Invalid manager handle!\n");
2942 // return ERROR_INVALID_HANDLE;
2945 /* Get service database entry */
2946 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2947 if (lpService
== NULL
)
2949 DPRINT("Could not find a service!\n");
2951 /* If the service could not be found and lpcchBuffer is less than 2, windows
2952 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2953 if (*lpcchBuffer
< 2)
2956 if (lpServiceName
!= NULL
)
2958 *lpServiceName
= '\0';
2962 return ERROR_SERVICE_DOES_NOT_EXIST
;
2965 dwLength
= wcslen(lpService
->lpServiceName
);
2967 if (lpServiceName
!= NULL
&&
2968 *lpcchBuffer
> dwLength
)
2970 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2971 *lpcchBuffer
= dwLength
;
2972 return ERROR_SUCCESS
;
2975 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2977 *lpcchBuffer
= dwLength
;
2984 DWORD
RI_ScSetServiceBitsA(
2985 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
2986 DWORD dwServiceBits
,
2988 int bUpdateImmediately
,
2992 return ERROR_CALL_NOT_IMPLEMENTED
;
2997 DWORD
RChangeServiceConfigA(
2998 SC_RPC_HANDLE hService
,
2999 DWORD dwServiceType
,
3001 DWORD dwErrorControl
,
3002 LPSTR lpBinaryPathName
,
3003 LPSTR lpLoadOrderGroup
,
3005 LPSTR lpDependencies
,
3007 LPSTR lpServiceStartName
,
3010 LPSTR lpDisplayName
)
3012 DWORD dwError
= ERROR_SUCCESS
;
3013 PSERVICE_HANDLE hSvc
;
3014 PSERVICE lpService
= NULL
;
3015 HKEY hServiceKey
= NULL
;
3016 LPWSTR lpDisplayNameW
= NULL
;
3017 // LPWSTR lpBinaryPathNameW = NULL;
3018 LPWSTR lpLoadOrderGroupW
= NULL
;
3019 LPWSTR lpDependenciesW
= NULL
;
3020 // LPWSTR lpPasswordW = NULL;
3022 DPRINT("RChangeServiceConfigA() called\n");
3023 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3024 DPRINT("dwStartType = %lu\n", dwStartType
);
3025 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3026 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3027 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3028 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3031 return ERROR_SHUTDOWN_IN_PROGRESS
;
3033 hSvc
= ScmGetServiceFromHandle(hService
);
3036 DPRINT1("Invalid service handle!\n");
3037 return ERROR_INVALID_HANDLE
;
3040 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3041 SERVICE_CHANGE_CONFIG
))
3043 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3044 return ERROR_ACCESS_DENIED
;
3047 lpService
= hSvc
->ServiceEntry
;
3048 if (lpService
== NULL
)
3050 DPRINT("lpService == NULL!\n");
3051 return ERROR_INVALID_HANDLE
;
3054 /* FIXME: Lock database exclusively */
3056 if (lpService
->bDeleted
)
3058 /* FIXME: Unlock database */
3059 DPRINT("The service has already been marked for delete!\n");
3060 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3063 /* Open the service key */
3064 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3067 if (dwError
!= ERROR_SUCCESS
)
3070 /* Write service data to the registry */
3072 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3074 /* Set the display name */
3075 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3077 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3078 if (lpDisplayNameW
== NULL
)
3080 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3084 MultiByteToWideChar(CP_ACP
,
3089 strlen(lpDisplayName
) + 1);
3091 RegSetValueExW(hServiceKey
,
3095 (LPBYTE
)lpDisplayNameW
,
3096 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3098 /* Update lpService->lpDisplayName */
3099 if (lpService
->lpDisplayName
)
3100 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3102 lpService
->lpDisplayName
= lpDisplayNameW
;
3105 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3107 /* Set the service type */
3108 dwError
= RegSetValueExW(hServiceKey
,
3112 (LPBYTE
)&dwServiceType
,
3114 if (dwError
!= ERROR_SUCCESS
)
3117 lpService
->Status
.dwServiceType
= dwServiceType
;
3120 if (dwStartType
!= SERVICE_NO_CHANGE
)
3122 /* Set the start value */
3123 dwError
= RegSetValueExW(hServiceKey
,
3127 (LPBYTE
)&dwStartType
,
3129 if (dwError
!= ERROR_SUCCESS
)
3132 lpService
->dwStartType
= dwStartType
;
3135 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3137 /* Set the error control value */
3138 dwError
= RegSetValueExW(hServiceKey
,
3142 (LPBYTE
)&dwErrorControl
,
3144 if (dwError
!= ERROR_SUCCESS
)
3147 lpService
->dwErrorControl
= dwErrorControl
;
3151 /* FIXME: set the new ImagePath value */
3153 /* Set the image path */
3154 if (dwServiceType
& SERVICE_WIN32
)
3156 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3158 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3159 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3160 dwError
= RegSetValueExW(hServiceKey
,
3164 (LPBYTE
)lpBinaryPathNameW
,
3165 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3166 if (dwError
!= ERROR_SUCCESS
)
3170 else if (dwServiceType
& SERVICE_DRIVER
)
3172 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3174 dwError
= RegSetValueExW(hServiceKey
,
3178 (LPBYTE
)lpImagePath
,
3179 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3180 if (dwError
!= ERROR_SUCCESS
)
3186 /* Set the group name */
3187 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3189 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3191 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3192 if (lpLoadOrderGroupW
== NULL
)
3194 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3198 MultiByteToWideChar(CP_ACP
,
3203 strlen(lpLoadOrderGroup
) + 1);
3205 dwError
= RegSetValueExW(hServiceKey
,
3209 (LPBYTE
)lpLoadOrderGroupW
,
3210 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3211 if (dwError
!= ERROR_SUCCESS
)
3213 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3217 dwError
= ScmSetServiceGroup(lpService
,
3220 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3222 if (dwError
!= ERROR_SUCCESS
)
3226 if (lpdwTagId
!= NULL
)
3228 dwError
= ScmAssignNewTag(lpService
);
3229 if (dwError
!= ERROR_SUCCESS
)
3232 dwError
= RegSetValueExW(hServiceKey
,
3236 (LPBYTE
)&lpService
->dwTag
,
3238 if (dwError
!= ERROR_SUCCESS
)
3241 *lpdwTagId
= lpService
->dwTag
;
3244 /* Write dependencies */
3245 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3247 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3249 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3250 if (lpDependenciesW
== NULL
)
3252 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3256 MultiByteToWideChar(CP_ACP
,
3261 strlen(lpDependencies
) + 1);
3263 dwError
= ScmWriteDependencies(hServiceKey
,
3264 (LPWSTR
)lpDependenciesW
,
3267 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3270 if (lpPassword
!= NULL
)
3272 /* FIXME: Write password */
3275 /* FIXME: Unlock database */
3278 if (hServiceKey
!= NULL
)
3279 RegCloseKey(hServiceKey
);
3281 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3288 DWORD
RCreateServiceA(
3289 SC_RPC_HANDLE hSCManager
,
3290 LPSTR lpServiceName
,
3291 LPSTR lpDisplayName
,
3292 DWORD dwDesiredAccess
,
3293 DWORD dwServiceType
,
3295 DWORD dwErrorControl
,
3296 LPSTR lpBinaryPathName
,
3297 LPSTR lpLoadOrderGroup
,
3299 LPBYTE lpDependencies
,
3301 LPSTR lpServiceStartName
,
3304 LPSC_RPC_HANDLE lpServiceHandle
)
3306 DWORD dwError
= ERROR_SUCCESS
;
3307 LPWSTR lpServiceNameW
= NULL
;
3308 LPWSTR lpDisplayNameW
= NULL
;
3309 LPWSTR lpBinaryPathNameW
= NULL
;
3310 LPWSTR lpLoadOrderGroupW
= NULL
;
3311 LPWSTR lpDependenciesW
= NULL
;
3312 LPWSTR lpServiceStartNameW
= NULL
;
3313 DWORD dwDependenciesLength
= 0;
3320 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3321 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3322 if (!lpServiceNameW
)
3324 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3327 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3332 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3333 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3334 if (!lpDisplayNameW
)
3336 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3339 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3342 if (lpBinaryPathName
)
3344 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3345 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3346 if (!lpBinaryPathNameW
)
3348 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3351 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3354 if (lpLoadOrderGroup
)
3356 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3357 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3358 if (!lpLoadOrderGroupW
)
3360 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3363 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3368 lpStr
= (LPSTR
)lpDependencies
;
3371 dwLength
= strlen(lpStr
) + 1;
3372 dwDependenciesLength
+= dwLength
;
3373 lpStr
= lpStr
+ dwLength
;
3375 dwDependenciesLength
++;
3377 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3378 if (!lpDependenciesW
)
3380 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3383 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3386 if (lpServiceStartName
)
3388 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3389 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3390 if (!lpServiceStartNameW
)
3392 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3395 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3398 dwError
= RCreateServiceW(hSCManager
,
3408 (LPBYTE
)lpDependenciesW
,
3409 dwDependenciesLength
,
3410 lpServiceStartNameW
,
3416 if (lpServiceNameW
!=NULL
)
3417 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3419 if (lpDisplayNameW
!= NULL
)
3420 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3422 if (lpBinaryPathNameW
!= NULL
)
3423 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3425 if (lpLoadOrderGroupW
!= NULL
)
3426 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3428 if (lpDependenciesW
!= NULL
)
3429 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3431 if (lpServiceStartNameW
!= NULL
)
3432 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3439 DWORD
REnumDependentServicesA(
3440 SC_RPC_HANDLE hService
,
3441 DWORD dwServiceState
,
3444 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3445 LPBOUNDED_DWORD_256K lpServicesReturned
)
3447 DWORD dwError
= ERROR_SUCCESS
;
3448 DWORD dwServicesReturned
= 0;
3449 DWORD dwServiceCount
;
3450 HKEY hServicesKey
= NULL
;
3451 PSERVICE_HANDLE hSvc
;
3452 PSERVICE lpService
= NULL
;
3453 PSERVICE
*lpServicesArray
= NULL
;
3454 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3457 *pcbBytesNeeded
= 0;
3458 *lpServicesReturned
= 0;
3460 DPRINT("REnumDependentServicesA() called\n");
3462 hSvc
= ScmGetServiceFromHandle(hService
);
3465 DPRINT1("Invalid service handle!\n");
3466 return ERROR_INVALID_HANDLE
;
3469 lpService
= hSvc
->ServiceEntry
;
3471 /* Check access rights */
3472 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3473 SC_MANAGER_ENUMERATE_SERVICE
))
3475 DPRINT("Insufficient access rights! 0x%lx\n",
3476 hSvc
->Handle
.DesiredAccess
);
3477 return ERROR_ACCESS_DENIED
;
3480 /* Open the Services Reg key */
3481 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3482 L
"System\\CurrentControlSet\\Services",
3487 if (dwError
!= ERROR_SUCCESS
)
3490 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3491 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3492 are the same for both. Verified in WINXP. */
3494 /* First determine the bytes needed and get the number of dependent services*/
3495 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3500 &dwServicesReturned
);
3501 if (dwError
!= ERROR_SUCCESS
)
3504 /* If buffer size is less than the bytes needed or pointer is null*/
3505 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3507 dwError
= ERROR_MORE_DATA
;
3511 /* Allocate memory for array of service pointers */
3512 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3514 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3515 if (!lpServicesArray
)
3517 DPRINT("Could not allocate a buffer!!\n");
3518 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3522 dwServicesReturned
= 0;
3523 *pcbBytesNeeded
= 0;
3525 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3530 &dwServicesReturned
);
3531 if (dwError
!= ERROR_SUCCESS
)
3536 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3537 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3539 /* Copy EnumDepenedentService to Buffer */
3540 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3542 lpService
= lpServicesArray
[dwServiceCount
];
3544 /* Copy the status info */
3545 memcpy(&lpServicesPtr
->ServiceStatus
,
3547 sizeof(SERVICE_STATUS
));
3549 /* Copy display name */
3550 WideCharToMultiByte(CP_ACP
,
3552 lpService
->lpDisplayName
,
3555 wcslen(lpService
->lpDisplayName
),
3558 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3559 lpStr
+= strlen(lpStr
) + 1;
3561 /* Copy service name */
3562 WideCharToMultiByte(CP_ACP
,
3564 lpService
->lpServiceName
,
3567 wcslen(lpService
->lpServiceName
),
3570 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3571 lpStr
+= strlen(lpStr
) + 1;
3576 *lpServicesReturned
= dwServicesReturned
;
3579 if (lpServicesArray
)
3580 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3582 RegCloseKey(hServicesKey
);
3584 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3591 DWORD
REnumServicesStatusA(
3592 SC_RPC_HANDLE hSCManager
,
3593 DWORD dwServiceType
,
3594 DWORD dwServiceState
,
3597 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3598 LPBOUNDED_DWORD_256K lpServicesReturned
,
3599 LPBOUNDED_DWORD_256K lpResumeHandle
)
3601 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3602 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3603 LPWSTR lpStringPtrW
;
3606 DWORD dwServiceCount
;
3608 DPRINT("REnumServicesStatusA() called\n");
3610 if ((dwBufSize
> 0) && (lpBuffer
))
3612 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3615 DPRINT("Failed to allocate buffer!\n");
3616 return ERROR_NOT_ENOUGH_MEMORY
;
3620 dwError
= REnumServicesStatusW(hSCManager
,
3623 (LPBYTE
)lpStatusPtrW
,
3629 /* if no services were returned then we are Done */
3630 if (*lpServicesReturned
== 0)
3633 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3634 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3635 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3636 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3637 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3639 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3641 /* Copy the service name */
3642 WideCharToMultiByte(CP_ACP
,
3647 wcslen(lpStringPtrW
),
3651 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3652 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3653 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3655 /* Copy the display name */
3656 WideCharToMultiByte(CP_ACP
,
3661 wcslen(lpStringPtrW
),
3665 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3666 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3667 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3669 /* Copy the status information */
3670 memcpy(&lpStatusPtrA
->ServiceStatus
,
3671 &lpStatusPtrW
->ServiceStatus
,
3672 sizeof(SERVICE_STATUS
));
3679 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3681 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3688 DWORD
ROpenSCManagerA(
3689 LPSTR lpMachineName
,
3690 LPSTR lpDatabaseName
,
3691 DWORD dwDesiredAccess
,
3692 LPSC_RPC_HANDLE lpScHandle
)
3694 UNICODE_STRING MachineName
;
3695 UNICODE_STRING DatabaseName
;
3698 DPRINT("ROpenSCManagerA() called\n");
3701 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3705 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3708 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3709 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3714 RtlFreeUnicodeString(&MachineName
);
3717 RtlFreeUnicodeString(&DatabaseName
);
3724 DWORD
ROpenServiceA(
3725 SC_RPC_HANDLE hSCManager
,
3726 LPSTR lpServiceName
,
3727 DWORD dwDesiredAccess
,
3728 LPSC_RPC_HANDLE lpServiceHandle
)
3730 UNICODE_STRING ServiceName
;
3733 DPRINT("ROpenServiceA() called\n");
3736 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3739 dwError
= ROpenServiceW(hSCManager
,
3740 lpServiceName
? ServiceName
.Buffer
: NULL
,
3745 RtlFreeUnicodeString(&ServiceName
);
3752 DWORD
RQueryServiceConfigA(
3753 SC_RPC_HANDLE hService
,
3754 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3756 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3758 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3759 DWORD dwError
= ERROR_SUCCESS
;
3760 PSERVICE_HANDLE hSvc
;
3761 PSERVICE lpService
= NULL
;
3762 HKEY hServiceKey
= NULL
;
3763 LPWSTR lpImagePath
= NULL
;
3764 LPWSTR lpServiceStartName
= NULL
;
3765 LPWSTR lpDependencies
= NULL
;
3766 DWORD dwDependenciesLength
= 0;
3767 DWORD dwRequiredSize
;
3768 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3769 CHAR lpEmptyString
[]={0,0};
3772 DPRINT("RQueryServiceConfigA() called\n");
3775 return ERROR_SHUTDOWN_IN_PROGRESS
;
3777 hSvc
= ScmGetServiceFromHandle(hService
);
3780 DPRINT1("Invalid service handle!\n");
3781 return ERROR_INVALID_HANDLE
;
3784 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3785 SERVICE_QUERY_CONFIG
))
3787 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3788 return ERROR_ACCESS_DENIED
;
3791 lpService
= hSvc
->ServiceEntry
;
3792 if (lpService
== NULL
)
3794 DPRINT("lpService == NULL!\n");
3795 return ERROR_INVALID_HANDLE
;
3798 /* FIXME: Lock the service database shared */
3800 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3803 if (dwError
!= ERROR_SUCCESS
)
3806 /* Read the image path */
3807 dwError
= ScmReadString(hServiceKey
,
3810 if (dwError
!= ERROR_SUCCESS
)
3813 /* Read the service start name */
3814 ScmReadString(hServiceKey
,
3816 &lpServiceStartName
);
3818 /* Read the dependencies */
3819 ScmReadDependencies(hServiceKey
,
3821 &dwDependenciesLength
);
3823 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3825 if (lpImagePath
!= NULL
)
3826 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3828 dwRequiredSize
+= 2;
3830 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3831 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3833 dwRequiredSize
+= 2;
3835 /* Add Dependencies length */
3836 if (lpDependencies
!= NULL
)
3837 dwRequiredSize
+= dwDependenciesLength
;
3839 dwRequiredSize
+= 2;
3841 if (lpServiceStartName
!= NULL
)
3842 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3844 dwRequiredSize
+= 2;
3846 if (lpService
->lpDisplayName
!= NULL
)
3847 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3849 dwRequiredSize
+= 2;
3851 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3853 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3857 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3858 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3859 lpConfig
->dwStartType
= lpService
->dwStartType
;
3860 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3861 lpConfig
->dwTagId
= lpService
->dwTag
;
3863 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3865 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3870 WideCharToMultiByte(CP_ACP
,
3875 wcslen(lpImagePath
) + 1,
3881 strcpy(lpStr
, lpEmptyString
);
3884 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3885 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3887 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3889 WideCharToMultiByte(CP_ACP
,
3891 lpService
->lpGroup
->lpGroupName
,
3894 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3900 strcpy(lpStr
, lpEmptyString
);
3903 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3904 lpStr
+= (strlen(lpStr
) + 1);
3906 /* Append Dependencies */
3909 WideCharToMultiByte(CP_ACP
,
3912 dwDependenciesLength
,
3914 dwDependenciesLength
,
3920 strcpy(lpStr
, lpEmptyString
);
3923 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3925 lpStr
+= dwDependenciesLength
;
3927 lpStr
+= (strlen(lpStr
) + 1);
3929 if (lpServiceStartName
)
3931 WideCharToMultiByte(CP_ACP
,
3936 wcslen(lpServiceStartName
) + 1,
3942 strcpy(lpStr
, lpEmptyString
);
3945 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3946 lpStr
+= (strlen(lpStr
) + 1);
3948 if (lpService
->lpDisplayName
)
3950 WideCharToMultiByte(CP_ACP
,
3952 lpService
->lpDisplayName
,
3955 wcslen(lpService
->lpDisplayName
) + 1,
3961 strcpy(lpStr
, lpEmptyString
);
3964 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3967 if (pcbBytesNeeded
!= NULL
)
3968 *pcbBytesNeeded
= dwRequiredSize
;
3971 if (lpImagePath
!= NULL
)
3972 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3974 if (lpServiceStartName
!= NULL
)
3975 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3977 if (lpDependencies
!= NULL
)
3978 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3980 if (hServiceKey
!= NULL
)
3981 RegCloseKey(hServiceKey
);
3983 /* FIXME: Unlock the service database */
3985 DPRINT("RQueryServiceConfigA() done\n");
3992 DWORD
RQueryServiceLockStatusA(
3993 SC_RPC_HANDLE hSCManager
,
3994 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3996 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3999 return ERROR_CALL_NOT_IMPLEMENTED
;
4004 DWORD
RStartServiceA(
4005 SC_RPC_HANDLE hService
,
4007 LPSTRING_PTRSA argv
)
4009 DWORD dwError
= ERROR_SUCCESS
;
4010 PSERVICE_HANDLE hSvc
;
4011 PSERVICE lpService
= NULL
;
4013 DPRINT("RStartServiceA() called\n");
4016 return ERROR_SHUTDOWN_IN_PROGRESS
;
4018 hSvc
= ScmGetServiceFromHandle(hService
);
4021 DPRINT1("Invalid service handle!\n");
4022 return ERROR_INVALID_HANDLE
;
4025 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4028 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4029 return ERROR_ACCESS_DENIED
;
4032 lpService
= hSvc
->ServiceEntry
;
4033 if (lpService
== NULL
)
4035 DPRINT("lpService == NULL!\n");
4036 return ERROR_INVALID_HANDLE
;
4039 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4040 return ERROR_SERVICE_DISABLED
;
4042 if (lpService
->bDeleted
)
4043 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4045 /* FIXME: Convert argument vector to Unicode */
4047 /* Start the service */
4048 dwError
= ScmStartService(lpService
, 0, NULL
);
4050 /* FIXME: Free argument vector */
4057 DWORD
RGetServiceDisplayNameA(
4058 SC_RPC_HANDLE hSCManager
,
4059 LPCSTR lpServiceName
,
4060 LPSTR lpDisplayName
,
4061 LPBOUNDED_DWORD_4K lpcchBuffer
)
4063 // PMANAGER_HANDLE hManager;
4064 PSERVICE lpService
= NULL
;
4067 LPWSTR lpServiceNameW
;
4069 DPRINT("RGetServiceDisplayNameA() called\n");
4070 DPRINT("hSCManager = %p\n", hSCManager
);
4071 DPRINT("lpServiceName: %s\n", lpServiceName
);
4072 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4073 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4075 // hManager = (PMANAGER_HANDLE)hSCManager;
4076 // if (hManager->Handle.Tag != MANAGER_TAG)
4078 // DPRINT("Invalid manager handle!\n");
4079 // return ERROR_INVALID_HANDLE;
4082 if (lpServiceName
!= NULL
)
4084 dwLength
= strlen(lpServiceName
) + 1;
4085 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4087 dwLength
* sizeof(WCHAR
));
4088 if (!lpServiceNameW
)
4089 return ERROR_NOT_ENOUGH_MEMORY
;
4091 MultiByteToWideChar(CP_ACP
,
4098 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4100 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4103 if (lpService
== NULL
)
4105 DPRINT("Could not find a service!\n");
4107 /* If the service could not be found and lpcchBuffer is 0, windows
4108 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4109 if (*lpcchBuffer
== 0)
4112 if (lpDisplayName
!= NULL
)
4114 *lpDisplayName
= '\0';
4117 return ERROR_SERVICE_DOES_NOT_EXIST
;
4120 if (!lpService
->lpDisplayName
)
4122 dwLength
= wcslen(lpService
->lpServiceName
);
4123 if (lpDisplayName
!= NULL
&&
4124 *lpcchBuffer
> dwLength
)
4126 WideCharToMultiByte(CP_ACP
,
4128 lpService
->lpServiceName
,
4129 wcslen(lpService
->lpServiceName
),
4134 return ERROR_SUCCESS
;
4139 dwLength
= wcslen(lpService
->lpDisplayName
);
4140 if (lpDisplayName
!= NULL
&&
4141 *lpcchBuffer
> dwLength
)
4143 WideCharToMultiByte(CP_ACP
,
4145 lpService
->lpDisplayName
,
4146 wcslen(lpService
->lpDisplayName
),
4151 return ERROR_SUCCESS
;
4155 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4157 *lpcchBuffer
= dwLength
* 2;
4164 DWORD
RGetServiceKeyNameA(
4165 SC_RPC_HANDLE hSCManager
,
4166 LPCSTR lpDisplayName
,
4167 LPSTR lpServiceName
,
4168 LPBOUNDED_DWORD_4K lpcchBuffer
)
4173 LPWSTR lpDisplayNameW
;
4175 DPRINT("RGetServiceKeyNameA() called\n");
4176 DPRINT("hSCManager = %p\n", hSCManager
);
4177 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4178 DPRINT("lpServiceName: %p\n", lpServiceName
);
4179 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4181 dwLength
= strlen(lpDisplayName
) + 1;
4182 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4184 dwLength
* sizeof(WCHAR
));
4185 if (!lpDisplayNameW
)
4186 return ERROR_NOT_ENOUGH_MEMORY
;
4188 MultiByteToWideChar(CP_ACP
,
4195 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4197 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4199 if (lpService
== NULL
)
4201 DPRINT("Could not find the service!\n");
4203 /* If the service could not be found and lpcchBuffer is 0,
4204 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4205 if (*lpcchBuffer
== 0)
4208 if (lpServiceName
!= NULL
)
4210 *lpServiceName
= '\0';
4214 return ERROR_SERVICE_DOES_NOT_EXIST
;
4217 dwLength
= wcslen(lpService
->lpServiceName
);
4218 if (lpServiceName
!= NULL
&&
4219 *lpcchBuffer
> dwLength
)
4221 WideCharToMultiByte(CP_ACP
,
4223 lpService
->lpServiceName
,
4224 wcslen(lpService
->lpServiceName
),
4229 return ERROR_SUCCESS
;
4232 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4234 *lpcchBuffer
= dwLength
* 2;
4241 DWORD
RI_ScGetCurrentGroupStateW(
4242 SC_RPC_HANDLE hSCManager
,
4243 LPWSTR lpLoadOrderGroup
,
4247 return ERROR_CALL_NOT_IMPLEMENTED
;
4252 DWORD
REnumServiceGroupW(
4253 SC_RPC_HANDLE hSCManager
,
4254 DWORD dwServiceType
,
4255 DWORD dwServiceState
,
4258 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4259 LPBOUNDED_DWORD_256K lpServicesReturned
,
4260 LPBOUNDED_DWORD_256K lpResumeIndex
,
4261 LPCWSTR pszGroupName
)
4264 return ERROR_CALL_NOT_IMPLEMENTED
;
4269 // WARNING: This function is untested
4272 DWORD
RChangeServiceConfig2A(
4273 SC_RPC_HANDLE hService
,
4274 SC_RPC_CONFIG_INFOA Info
)
4276 SC_RPC_CONFIG_INFOW InfoW
;
4277 DWORD dwRet
, dwLength
;
4280 DPRINT("RChangeServiceConfig2A() called\n");
4281 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4283 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4285 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4287 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4288 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4290 lpServiceDescriptonA
= Info
.psd
;
4292 ///if (lpServiceDescriptonA &&
4293 ///lpServiceDescriptonA->lpDescription)
4295 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4297 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4299 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4300 if (!lpServiceDescriptonW
)
4302 return ERROR_NOT_ENOUGH_MEMORY
;
4305 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4307 MultiByteToWideChar(CP_ACP
,
4311 lpServiceDescriptonW
->lpDescription
,
4314 ptr
= lpServiceDescriptonW
;
4315 InfoW
.psd
= lpServiceDescriptonW
;
4318 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4320 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4321 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4322 DWORD dwRebootLen
= 0;
4323 DWORD dwCommandLen
= 0;
4325 lpServiceFailureActionsA
= Info
.psfa
;
4327 if (lpServiceFailureActionsA
)
4329 if (lpServiceFailureActionsA
->lpRebootMsg
)
4331 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4333 if (lpServiceFailureActionsA
->lpCommand
)
4335 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4337 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4339 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4342 if (!lpServiceFailureActionsW
)
4344 return ERROR_NOT_ENOUGH_MEMORY
;
4347 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4348 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4349 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4351 if (lpServiceFailureActionsA
->lpRebootMsg
)
4353 MultiByteToWideChar(CP_ACP
,
4355 lpServiceFailureActionsA
->lpRebootMsg
,
4357 lpServiceFailureActionsW
->lpRebootMsg
,
4361 if (lpServiceFailureActionsA
->lpCommand
)
4363 MultiByteToWideChar(CP_ACP
,
4365 lpServiceFailureActionsA
->lpCommand
,
4367 lpServiceFailureActionsW
->lpCommand
,
4371 ptr
= lpServiceFailureActionsW
;
4375 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4377 HeapFree(GetProcessHeap(), 0, ptr
);
4384 DWORD
RChangeServiceConfig2W(
4385 SC_RPC_HANDLE hService
,
4386 SC_RPC_CONFIG_INFOW Info
)
4388 DWORD dwError
= ERROR_SUCCESS
;
4389 PSERVICE_HANDLE hSvc
;
4390 PSERVICE lpService
= NULL
;
4391 HKEY hServiceKey
= NULL
;
4393 DPRINT("RChangeServiceConfig2W() called\n");
4394 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4397 return ERROR_SHUTDOWN_IN_PROGRESS
;
4399 hSvc
= ScmGetServiceFromHandle(hService
);
4402 DPRINT1("Invalid service handle!\n");
4403 return ERROR_INVALID_HANDLE
;
4406 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4407 SERVICE_CHANGE_CONFIG
))
4409 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4410 return ERROR_ACCESS_DENIED
;
4413 lpService
= hSvc
->ServiceEntry
;
4414 if (lpService
== NULL
)
4416 DPRINT("lpService == NULL!\n");
4417 return ERROR_INVALID_HANDLE
;
4420 /* FIXME: Lock database exclusively */
4422 if (lpService
->bDeleted
)
4424 /* FIXME: Unlock database */
4425 DPRINT("The service has already been marked for delete!\n");
4426 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4429 /* Open the service key */
4430 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4433 if (dwError
!= ERROR_SUCCESS
)
4436 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4438 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4440 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4441 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4443 if (lpServiceDescription
!= NULL
&&
4444 lpServiceDescription
->lpDescription
!= NULL
)
4446 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4447 RegSetValueExW(hServiceKey
,
4451 (LPBYTE
)lpServiceDescription
->lpDescription
,
4452 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4454 if (dwError
!= ERROR_SUCCESS
)
4458 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4461 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4466 /* FIXME: Unlock database */
4467 if (hServiceKey
!= NULL
)
4468 RegCloseKey(hServiceKey
);
4470 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4477 DWORD
RQueryServiceConfig2A(
4478 SC_RPC_HANDLE hService
,
4482 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4484 DWORD dwError
= ERROR_SUCCESS
;
4485 PSERVICE_HANDLE hSvc
;
4486 PSERVICE lpService
= NULL
;
4487 HKEY hServiceKey
= NULL
;
4488 LPWSTR lpDescriptionW
= NULL
;
4489 LPSTR lpDescription
= NULL
;
4491 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4492 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4495 return ERROR_INVALID_ADDRESS
;
4498 return ERROR_SHUTDOWN_IN_PROGRESS
;
4500 hSvc
= ScmGetServiceFromHandle(hService
);
4503 DPRINT1("Invalid service handle!\n");
4504 return ERROR_INVALID_HANDLE
;
4507 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4508 SERVICE_QUERY_CONFIG
))
4510 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4511 return ERROR_ACCESS_DENIED
;
4514 lpService
= hSvc
->ServiceEntry
;
4515 if (lpService
== NULL
)
4517 DPRINT("lpService == NULL!\n");
4518 return ERROR_INVALID_HANDLE
;
4521 /* FIXME: Lock the service database shared */
4523 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4526 if (dwError
!= ERROR_SUCCESS
)
4529 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4531 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4534 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4536 dwError
= ScmReadString(hServiceKey
,
4539 if (dwError
== ERROR_SUCCESS
)
4541 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4544 if (cbBufSize
>= *pcbBytesNeeded
)
4547 if (dwError
== ERROR_SUCCESS
)
4549 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4551 WideCharToMultiByte(CP_ACP
,
4556 wcslen(lpDescriptionW
),
4559 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4563 lpServiceDescription
->lpDescription
= NULL
;
4569 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4573 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4576 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4581 if (lpDescription
!= NULL
)
4582 HeapFree(GetProcessHeap(), 0, lpDescription
);
4584 if (hServiceKey
!= NULL
)
4585 RegCloseKey(hServiceKey
);
4587 /* FIXME: Unlock database */
4589 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4596 DWORD
RQueryServiceConfig2W(
4597 SC_RPC_HANDLE hService
,
4601 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4603 DWORD dwError
= ERROR_SUCCESS
;
4604 PSERVICE_HANDLE hSvc
;
4605 PSERVICE lpService
= NULL
;
4606 HKEY hServiceKey
= NULL
;
4607 DWORD dwRequiredSize
;
4608 LPWSTR lpDescription
= NULL
;
4609 LPWSTR lpFailureCommand
= NULL
;
4610 LPWSTR lpRebootMessage
= NULL
;
4612 DPRINT("RQueryServiceConfig2W() called\n");
4615 return ERROR_INVALID_ADDRESS
;
4618 return ERROR_SHUTDOWN_IN_PROGRESS
;
4620 hSvc
= ScmGetServiceFromHandle(hService
);
4623 DPRINT1("Invalid service handle!\n");
4624 return ERROR_INVALID_HANDLE
;
4627 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4628 SERVICE_QUERY_CONFIG
))
4630 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4631 return ERROR_ACCESS_DENIED
;
4634 lpService
= hSvc
->ServiceEntry
;
4635 if (lpService
== NULL
)
4637 DPRINT("lpService == NULL!\n");
4638 return ERROR_INVALID_HANDLE
;
4641 /* FIXME: Lock the service database shared */
4643 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4646 if (dwError
!= ERROR_SUCCESS
)
4649 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4651 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4654 dwError
= ScmReadString(hServiceKey
,
4657 if (dwError
!= ERROR_SUCCESS
)
4660 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4662 if (cbBufSize
< dwRequiredSize
)
4664 *pcbBytesNeeded
= dwRequiredSize
;
4665 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4669 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4670 wcscpy(lpStr
, lpDescription
);
4671 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4673 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4676 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4680 dwError
= ScmReadString(hServiceKey
,
4684 dwError
= ScmReadString(hServiceKey
,
4688 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4690 if (lpFailureCommand
)
4691 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4693 if (lpRebootMessage
)
4694 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4696 if (cbBufSize
< dwRequiredSize
)
4698 *pcbBytesNeeded
= dwRequiredSize
;
4699 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4703 lpFailureActions
->cActions
= 0;
4704 lpFailureActions
->dwResetPeriod
= 0;
4705 lpFailureActions
->lpCommand
= NULL
;
4706 lpFailureActions
->lpRebootMsg
= NULL
;
4707 lpFailureActions
->lpsaActions
= NULL
;
4709 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4710 if (lpRebootMessage
)
4712 wcscpy(lpStr
, lpRebootMessage
);
4713 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4714 lpStr
+= wcslen(lpRebootMessage
) + 1;
4717 if (lpFailureCommand
)
4719 wcscpy(lpStr
, lpFailureCommand
);
4720 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4721 lpStr
+= wcslen(lpRebootMessage
) + 1;
4723 dwError
= STATUS_SUCCESS
;
4728 if (lpDescription
!= NULL
)
4729 HeapFree(GetProcessHeap(), 0, lpDescription
);
4731 if (lpRebootMessage
!= NULL
)
4732 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4734 if (lpFailureCommand
!= NULL
)
4735 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4737 if (hServiceKey
!= NULL
)
4738 RegCloseKey(hServiceKey
);
4740 /* FIXME: Unlock database */
4742 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4749 DWORD
RQueryServiceStatusEx(
4750 SC_RPC_HANDLE hService
,
4751 SC_STATUS_TYPE InfoLevel
,
4754 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4756 LPSERVICE_STATUS_PROCESS lpStatus
;
4757 PSERVICE_HANDLE hSvc
;
4760 DPRINT("RQueryServiceStatusEx() called\n");
4763 return ERROR_SHUTDOWN_IN_PROGRESS
;
4765 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4766 return ERROR_INVALID_LEVEL
;
4768 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4770 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4771 return ERROR_INSUFFICIENT_BUFFER
;
4773 hSvc
= ScmGetServiceFromHandle(hService
);
4776 DPRINT1("Invalid service handle!\n");
4777 return ERROR_INVALID_HANDLE
;
4780 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4781 SERVICE_QUERY_STATUS
))
4783 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4784 return ERROR_ACCESS_DENIED
;
4787 lpService
= hSvc
->ServiceEntry
;
4788 if (lpService
== NULL
)
4790 DPRINT("lpService == NULL!\n");
4791 return ERROR_INVALID_HANDLE
;
4794 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4796 /* Return service status information */
4797 RtlCopyMemory(lpStatus
,
4799 sizeof(SERVICE_STATUS
));
4801 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4802 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4804 return ERROR_SUCCESS
;
4809 DWORD
REnumServicesStatusExA(
4810 SC_RPC_HANDLE hSCManager
,
4811 SC_ENUM_TYPE InfoLevel
,
4812 DWORD dwServiceType
,
4813 DWORD dwServiceState
,
4816 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4817 LPBOUNDED_DWORD_256K lpServicesReturned
,
4818 LPBOUNDED_DWORD_256K lpResumeIndex
,
4819 LPCSTR pszGroupName
)
4821 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4822 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4823 LPWSTR lpStringPtrW
;
4825 LPWSTR pszGroupNameW
= NULL
;
4827 DWORD dwServiceCount
;
4829 DPRINT("REnumServicesStatusExA() called\n");
4833 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4836 DPRINT("Failed to allocate buffer!\n");
4837 return ERROR_NOT_ENOUGH_MEMORY
;
4840 MultiByteToWideChar(CP_ACP
,
4845 strlen(pszGroupName
) + 1);
4848 if ((cbBufSize
> 0) && (lpBuffer
))
4850 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4853 DPRINT("Failed to allocate buffer!\n");
4854 return ERROR_NOT_ENOUGH_MEMORY
;
4858 dwError
= REnumServicesStatusExW(hSCManager
,
4862 (LPBYTE
)lpStatusPtrW
,
4869 /* if no services were returned then we are Done */
4870 if (*lpServicesReturned
== 0)
4873 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4874 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4875 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4876 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4877 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4879 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4881 /* Copy the service name */
4882 WideCharToMultiByte(CP_ACP
,
4887 wcslen(lpStringPtrW
),
4891 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4892 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4893 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4895 /* Copy the display name */
4896 WideCharToMultiByte(CP_ACP
,
4901 wcslen(lpStringPtrW
),
4905 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4906 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4907 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4909 /* Copy the status information */
4910 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4911 &lpStatusPtrW
->ServiceStatusProcess
,
4912 sizeof(SERVICE_STATUS
));
4914 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4915 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4921 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4924 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4926 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4933 DWORD
REnumServicesStatusExW(
4934 SC_RPC_HANDLE hSCManager
,
4935 SC_ENUM_TYPE InfoLevel
,
4936 DWORD dwServiceType
,
4937 DWORD dwServiceState
,
4940 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4941 LPBOUNDED_DWORD_256K lpServicesReturned
,
4942 LPBOUNDED_DWORD_256K lpResumeIndex
,
4943 LPCWSTR pszGroupName
)
4945 PMANAGER_HANDLE hManager
;
4947 DWORD dwError
= ERROR_SUCCESS
;
4948 PLIST_ENTRY ServiceEntry
;
4949 PSERVICE CurrentService
;
4951 DWORD dwRequiredSize
;
4952 DWORD dwServiceCount
;
4954 DWORD dwLastResumeCount
= 0;
4955 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4958 DPRINT("REnumServicesStatusExW() called\n");
4961 return ERROR_SHUTDOWN_IN_PROGRESS
;
4963 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4964 return ERROR_INVALID_LEVEL
;
4966 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
4967 if (hManager
== NULL
)
4969 DPRINT1("Invalid service manager handle!\n");
4970 return ERROR_INVALID_HANDLE
;
4973 *pcbBytesNeeded
= 0;
4974 *lpServicesReturned
= 0;
4976 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4978 DPRINT("Not a valid Service Type!\n");
4979 return ERROR_INVALID_PARAMETER
;
4982 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4984 DPRINT("Not a valid Service State!\n");
4985 return ERROR_INVALID_PARAMETER
;
4988 /* Check access rights */
4989 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4990 SC_MANAGER_ENUMERATE_SERVICE
))
4992 DPRINT("Insufficient access rights! 0x%lx\n",
4993 hManager
->Handle
.DesiredAccess
);
4994 return ERROR_ACCESS_DENIED
;
4997 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4999 /* Lock the service list shared */
5001 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5002 if (lpService
== NULL
)
5004 dwError
= ERROR_SUCCESS
;
5011 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5012 ServiceEntry
!= &ServiceListHead
;
5013 ServiceEntry
= ServiceEntry
->Flink
)
5015 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5019 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5022 dwState
= SERVICE_ACTIVE
;
5023 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5024 dwState
= SERVICE_INACTIVE
;
5026 if ((dwState
& dwServiceState
) == 0)
5031 if (*pszGroupName
== 0)
5033 if (CurrentService
->lpGroup
!= NULL
)
5038 if ((CurrentService
->lpGroup
== NULL
) ||
5039 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5044 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5045 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5046 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5048 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5050 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5051 dwRequiredSize
+= dwSize
;
5053 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5057 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5063 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5064 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5067 ServiceEntry
!= &ServiceListHead
;
5068 ServiceEntry
= ServiceEntry
->Flink
)
5070 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5074 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5077 dwState
= SERVICE_ACTIVE
;
5078 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5079 dwState
= SERVICE_INACTIVE
;
5081 if ((dwState
& dwServiceState
) == 0)
5086 if (*pszGroupName
== 0)
5088 if (CurrentService
->lpGroup
!= NULL
)
5093 if ((CurrentService
->lpGroup
== NULL
) ||
5094 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5099 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5100 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5101 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5103 dwError
= ERROR_MORE_DATA
;
5106 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5109 *lpResumeIndex
= dwLastResumeCount
;
5111 *lpServicesReturned
= dwServiceCount
;
5112 *pcbBytesNeeded
= dwRequiredSize
;
5114 /* If there was no services that matched */
5115 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5117 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5121 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5122 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5123 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5126 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5127 ServiceEntry
!= &ServiceListHead
;
5128 ServiceEntry
= ServiceEntry
->Flink
)
5130 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5134 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5137 dwState
= SERVICE_ACTIVE
;
5138 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5139 dwState
= SERVICE_INACTIVE
;
5141 if ((dwState
& dwServiceState
) == 0)
5146 if (*pszGroupName
== 0)
5148 if (CurrentService
->lpGroup
!= NULL
)
5153 if ((CurrentService
->lpGroup
== NULL
) ||
5154 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5159 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5160 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5161 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5163 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5165 /* Copy the service name */
5167 CurrentService
->lpServiceName
);
5168 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5169 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5171 /* Copy the display name */
5173 CurrentService
->lpDisplayName
);
5174 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5175 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5177 /* Copy the status information */
5178 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5179 &CurrentService
->Status
,
5180 sizeof(SERVICE_STATUS
));
5181 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
5182 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5185 dwRequiredSize
+= dwSize
;
5195 *pcbBytesNeeded
= 0;
5201 /* Unlock the service list */
5203 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5210 DWORD
RSendTSMessage(
5211 handle_t BindingHandle
) /* FIXME */
5214 return ERROR_CALL_NOT_IMPLEMENTED
;
5219 DWORD
RCreateServiceWOW64A(
5220 handle_t BindingHandle
,
5221 LPSTR lpServiceName
,
5222 LPSTR lpDisplayName
,
5223 DWORD dwDesiredAccess
,
5224 DWORD dwServiceType
,
5226 DWORD dwErrorControl
,
5227 LPSTR lpBinaryPathName
,
5228 LPSTR lpLoadOrderGroup
,
5230 LPBYTE lpDependencies
,
5232 LPSTR lpServiceStartName
,
5235 LPSC_RPC_HANDLE lpServiceHandle
)
5238 return ERROR_CALL_NOT_IMPLEMENTED
;
5243 DWORD
RCreateServiceWOW64W(
5244 handle_t BindingHandle
,
5245 LPWSTR lpServiceName
,
5246 LPWSTR lpDisplayName
,
5247 DWORD dwDesiredAccess
,
5248 DWORD dwServiceType
,
5250 DWORD dwErrorControl
,
5251 LPWSTR lpBinaryPathName
,
5252 LPWSTR lpLoadOrderGroup
,
5254 LPBYTE lpDependencies
,
5256 LPWSTR lpServiceStartName
,
5259 LPSC_RPC_HANDLE lpServiceHandle
)
5262 return ERROR_CALL_NOT_IMPLEMENTED
;
5267 DWORD
RQueryServiceTagInfo(
5268 handle_t BindingHandle
) /* FIXME */
5271 return ERROR_CALL_NOT_IMPLEMENTED
;
5276 DWORD
RNotifyServiceStatusChange(
5277 SC_RPC_HANDLE hService
,
5278 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5279 GUID
*pClientProcessGuid
,
5280 GUID
*pSCMProcessGuid
,
5281 PBOOL pfCreateRemoteQueue
,
5282 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5285 return ERROR_CALL_NOT_IMPLEMENTED
;
5290 DWORD
RGetNotifyResults(
5291 SC_NOTIFY_RPC_HANDLE hNotify
,
5292 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5295 return ERROR_CALL_NOT_IMPLEMENTED
;
5300 DWORD
RCloseNotifyHandle(
5301 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5305 return ERROR_CALL_NOT_IMPLEMENTED
;
5310 DWORD
RControlServiceExA(
5311 SC_RPC_HANDLE hService
,
5316 return ERROR_CALL_NOT_IMPLEMENTED
;
5321 DWORD
RControlServiceExW(
5322 SC_RPC_HANDLE hService
,
5327 return ERROR_CALL_NOT_IMPLEMENTED
;
5332 DWORD
RSendPnPMessage(
5333 handle_t BindingHandle
) /* FIXME */
5336 return ERROR_CALL_NOT_IMPLEMENTED
;
5341 DWORD
RValidatePnPService(
5342 handle_t BindingHandle
) /* FIXME */
5345 return ERROR_CALL_NOT_IMPLEMENTED
;
5350 DWORD
ROpenServiceStatusHandle(
5351 handle_t BindingHandle
) /* FIXME */
5354 return ERROR_CALL_NOT_IMPLEMENTED
;
5360 handle_t BindingHandle
) /* FIXME */
5363 return ERROR_CALL_NOT_IMPLEMENTED
;
5367 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5369 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5373 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5375 HeapFree(GetProcessHeap(), 0, ptr
);
5379 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5384 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5389 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)