2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/rpcserver.c
5 * PURPOSE: RPC server interface for the advapi32 calls
6 * COPYRIGHT: Copyright 2005-2006 Eric Kohl
7 * Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
8 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
12 /* INCLUDES ****************************************************************/
20 /* GLOBALS *****************************************************************/
22 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
23 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
25 typedef struct _SCMGR_HANDLE
33 typedef struct _MANAGER_HANDLE
37 /* FIXME: Insert more data here */
39 WCHAR DatabaseName
[1];
40 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
43 typedef struct _SERVICE_HANDLE
48 PSERVICE ServiceEntry
;
50 /* FIXME: Insert more data here */
52 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
55 #define SC_MANAGER_READ \
56 (STANDARD_RIGHTS_READ | \
57 SC_MANAGER_QUERY_LOCK_STATUS | \
58 SC_MANAGER_ENUMERATE_SERVICE)
60 #define SC_MANAGER_WRITE \
61 (STANDARD_RIGHTS_WRITE | \
62 SC_MANAGER_MODIFY_BOOT_CONFIG | \
63 SC_MANAGER_CREATE_SERVICE)
65 #define SC_MANAGER_EXECUTE \
66 (STANDARD_RIGHTS_EXECUTE | \
68 SC_MANAGER_ENUMERATE_SERVICE | \
69 SC_MANAGER_CONNECT | \
70 SC_MANAGER_CREATE_SERVICE)
73 #define SERVICE_READ \
74 (STANDARD_RIGHTS_READ | \
75 SERVICE_INTERROGATE | \
76 SERVICE_ENUMERATE_DEPENDENTS | \
77 SERVICE_QUERY_STATUS | \
80 #define SERVICE_WRITE \
81 (STANDARD_RIGHTS_WRITE | \
82 SERVICE_CHANGE_CONFIG)
84 #define SERVICE_EXECUTE \
85 (STANDARD_RIGHTS_EXECUTE | \
86 SERVICE_USER_DEFINED_CONTROL | \
87 SERVICE_PAUSE_CONTINUE | \
92 /* VARIABLES ***************************************************************/
94 static GENERIC_MAPPING
95 ScmManagerMapping
= {SC_MANAGER_READ
,
98 SC_MANAGER_ALL_ACCESS
};
100 static GENERIC_MAPPING
101 ScmServiceMapping
= {SERVICE_READ
,
104 SC_MANAGER_ALL_ACCESS
};
107 /* FUNCTIONS ***************************************************************/
110 ScmStartRpcServer(VOID
)
114 DPRINT("ScmStartRpcServer() called\n");
116 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
120 if (Status
!= RPC_S_OK
)
122 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
126 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
129 if (Status
!= RPC_S_OK
)
131 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
135 Status
= RpcServerListen(1, 20, TRUE
);
136 if (Status
!= RPC_S_OK
)
138 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
142 DPRINT("ScmStartRpcServer() done\n");
147 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
152 if (lpDatabaseName
== NULL
)
153 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
155 if (wcsicmp(lpDatabaseName
,SERVICES_FAILED_DATABASEW
)==0)
157 DPRINT1("Database %S, does not exist\n",lpDatabaseName
);
158 return ERROR_DATABASE_DOES_NOT_EXIST
;
160 else if (wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
162 DPRINT1("Invalid Database name %S.\n",lpDatabaseName
);
163 return ERROR_INVALID_NAME
;
166 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
168 sizeof(MANAGER_HANDLE
) + wcslen(lpDatabaseName
) * sizeof(WCHAR
));
170 return ERROR_NOT_ENOUGH_MEMORY
;
172 Ptr
->Handle
.Tag
= MANAGER_TAG
;
173 Ptr
->Handle
.RefCount
= 1;
175 /* FIXME: initialize more data here */
177 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
179 *Handle
= (SC_HANDLE
)Ptr
;
181 return ERROR_SUCCESS
;
186 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
191 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
193 sizeof(SERVICE_HANDLE
));
195 return ERROR_NOT_ENOUGH_MEMORY
;
197 Ptr
->Handle
.Tag
= SERVICE_TAG
;
198 Ptr
->Handle
.RefCount
= 1;
200 /* FIXME: initialize more data here */
201 Ptr
->ServiceEntry
= lpServiceEntry
;
203 *Handle
= (SC_HANDLE
)Ptr
;
205 return ERROR_SUCCESS
;
210 ScmCheckAccess(SC_HANDLE Handle
,
211 DWORD dwDesiredAccess
)
213 PMANAGER_HANDLE hMgr
;
215 hMgr
= (PMANAGER_HANDLE
)Handle
;
216 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
218 RtlMapGenericMask(&dwDesiredAccess
,
221 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
223 return ERROR_SUCCESS
;
225 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
227 RtlMapGenericMask(&dwDesiredAccess
,
230 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
232 return ERROR_SUCCESS
;
235 return ERROR_INVALID_HANDLE
;
240 ScmAssignNewTag(PSERVICE lpService
)
243 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
244 lpService
->dwTag
= 0;
245 return ERROR_SUCCESS
;
250 DWORD
RCloseServiceHandle(
251 handle_t BindingHandle
,
252 LPSC_RPC_HANDLE hSCObject
)
254 PMANAGER_HANDLE hManager
;
256 DPRINT("RCloseServiceHandle() called\n");
258 DPRINT("hSCObject = %p\n", *hSCObject
);
261 return ERROR_INVALID_HANDLE
;
263 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
264 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
266 DPRINT("Found manager handle\n");
268 hManager
->Handle
.RefCount
--;
269 if (hManager
->Handle
.RefCount
== 0)
271 /* FIXME: add cleanup code */
273 HeapFree(GetProcessHeap(), 0, hManager
);
276 DPRINT("RCloseServiceHandle() done\n");
277 return ERROR_SUCCESS
;
279 else if (hManager
->Handle
.Tag
== SERVICE_TAG
)
281 DPRINT("Found service handle\n");
283 hManager
->Handle
.RefCount
--;
284 if (hManager
->Handle
.RefCount
== 0)
286 /* FIXME: add cleanup code */
288 HeapFree(GetProcessHeap(), 0, hManager
);
291 DPRINT("RCloseServiceHandle() done\n");
292 return ERROR_SUCCESS
;
295 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
297 return ERROR_INVALID_HANDLE
;
302 DWORD
RControlService(
303 handle_t BindingHandle
,
304 SC_RPC_HANDLE hService
,
306 LPSERVICE_STATUS lpServiceStatus
)
308 PSERVICE_HANDLE hSvc
;
310 ACCESS_MASK DesiredAccess
;
311 DWORD dwError
= ERROR_SUCCESS
;
313 DPRINT("RControlService() called\n");
316 return ERROR_SHUTDOWN_IN_PROGRESS
;
318 /* Check the service handle */
319 hSvc
= (PSERVICE_HANDLE
)hService
;
320 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
322 DPRINT1("Invalid handle tag!\n");
323 return ERROR_INVALID_HANDLE
;
326 /* Check access rights */
329 case SERVICE_CONTROL_STOP
:
330 DesiredAccess
= SERVICE_STOP
;
333 case SERVICE_CONTROL_PAUSE
:
334 case SERVICE_CONTROL_CONTINUE
:
335 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
338 case SERVICE_INTERROGATE
:
339 DesiredAccess
= SERVICE_INTERROGATE
;
343 if (dwControl
>= 128 && dwControl
<= 255)
344 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
346 DesiredAccess
= SERVICE_QUERY_CONFIG
|
347 SERVICE_CHANGE_CONFIG
|
348 SERVICE_QUERY_STATUS
|
350 SERVICE_PAUSE_CONTINUE
;
354 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
356 return ERROR_ACCESS_DENIED
;
358 /* Check the service entry point */
359 lpService
= hSvc
->ServiceEntry
;
360 if (lpService
== NULL
)
362 DPRINT1("lpService == NULL!\n");
363 return ERROR_INVALID_HANDLE
;
366 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
368 /* Send control code to the driver */
369 dwError
= ScmControlDriver(lpService
,
375 /* Send control code to the service */
376 dwError
= ScmControlService(lpService
,
381 /* Return service status information */
382 RtlCopyMemory(lpServiceStatus
,
384 sizeof(SERVICE_STATUS
));
391 DWORD
RDeleteService(
392 handle_t BindingHandle
,
393 SC_RPC_HANDLE hService
)
395 PSERVICE_HANDLE hSvc
;
399 DPRINT("RDeleteService() called\n");
402 return ERROR_SHUTDOWN_IN_PROGRESS
;
404 hSvc
= (PSERVICE_HANDLE
)hService
;
405 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
406 return ERROR_INVALID_HANDLE
;
408 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
410 return ERROR_ACCESS_DENIED
;
412 lpService
= hSvc
->ServiceEntry
;
413 if (lpService
== NULL
)
415 DPRINT1("lpService == NULL!\n");
416 return ERROR_INVALID_HANDLE
;
419 /* FIXME: Acquire service database lock exclusively */
421 if (lpService
->bDeleted
)
423 DPRINT1("The service has already been marked for delete!\n");
424 return ERROR_SERVICE_MARKED_FOR_DELETE
;
427 /* Mark service for delete */
428 lpService
->bDeleted
= TRUE
;
430 dwError
= ScmMarkServiceForDelete(lpService
);
432 /* FIXME: Release service database lock */
434 DPRINT("RDeleteService() done\n");
441 DWORD
RLockServiceDatabase(
442 handle_t BindingHandle
,
443 SC_RPC_HANDLE hSCManager
,
444 LPSC_RPC_LOCK lpLock
)
446 PMANAGER_HANDLE hMgr
;
448 DPRINT("RLockServiceDatabase() called\n");
452 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
453 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
454 return ERROR_INVALID_HANDLE
;
456 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
458 return ERROR_ACCESS_DENIED
;
460 // return ScmLockDatabase(0, hMgr->0xC, hLock);
462 /* FIXME: Lock the database */
463 *lpLock
= (void *)0x12345678; /* Dummy! */
465 return ERROR_SUCCESS
;
470 DWORD
RQueryServiceObjectSecurity(
471 handle_t BindingHandle
,
472 SC_RPC_HANDLE hService
,
473 SECURITY_INFORMATION dwSecurityInformation
,
474 LPBYTE lpSecurityDescriptor
,
476 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
479 PSERVICE_HANDLE hSvc
;
481 ULONG DesiredAccess
= 0;
486 DPRINT("RQueryServiceObjectSecurity() called\n");
488 hSvc
= (PSERVICE_HANDLE
)hService
;
489 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
491 DPRINT1("Invalid handle tag!\n");
492 return ERROR_INVALID_HANDLE
;
495 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
496 GROUP_SECURITY_INFORMATION
||
497 OWNER_SECURITY_INFORMATION
))
498 DesiredAccess
|= READ_CONTROL
;
500 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
501 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
503 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
506 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
507 return ERROR_ACCESS_DENIED
;
510 lpService
= hSvc
->ServiceEntry
;
511 if (lpService
== NULL
)
513 DPRINT1("lpService == NULL!\n");
514 return ERROR_INVALID_HANDLE
;
517 /* FIXME: Lock the service list */
519 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
520 dwSecurityInformation
,
521 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
522 dwSecuityDescriptorSize
,
525 /* FIXME: Unlock the service list */
527 if (NT_SUCCESS(Status
))
529 *pcbBytesNeeded
= dwBytesNeeded
;
530 dwError
= STATUS_SUCCESS
;
532 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
534 *pcbBytesNeeded
= dwBytesNeeded
;
535 dwError
= ERROR_INSUFFICIENT_BUFFER
;
537 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
539 dwError
= ERROR_GEN_FAILURE
;
543 dwError
= RtlNtStatusToDosError(Status
);
549 return ERROR_CALL_NOT_IMPLEMENTED
;
554 DWORD
RSetServiceObjectSecurity(
555 handle_t BindingHandle
,
556 SC_RPC_HANDLE hService
,
557 DWORD dwSecurityInformation
,
558 LPBYTE lpSecurityDescriptor
,
559 DWORD dwSecuityDescriptorSize
)
561 PSERVICE_HANDLE hSvc
;
563 ULONG DesiredAccess
= 0;
564 HANDLE hToken
= NULL
;
569 DPRINT1("RSetServiceObjectSecurity() called\n");
571 hSvc
= (PSERVICE_HANDLE
)hService
;
572 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
574 DPRINT1("Invalid handle tag!\n");
575 return ERROR_INVALID_HANDLE
;
578 if (dwSecurityInformation
== 0 ||
579 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
580 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
581 return ERROR_INVALID_PARAMETER
;
583 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
584 return ERROR_INVALID_PARAMETER
;
586 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
587 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
589 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
590 DesiredAccess
|= WRITE_DAC
;
592 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
593 DesiredAccess
|= WRITE_OWNER
;
595 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
596 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
597 return ERROR_INVALID_PARAMETER
;
599 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
600 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
601 return ERROR_INVALID_PARAMETER
;
603 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
606 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
607 return ERROR_ACCESS_DENIED
;
610 lpService
= hSvc
->ServiceEntry
;
611 if (lpService
== NULL
)
613 DPRINT1("lpService == NULL!\n");
614 return ERROR_INVALID_HANDLE
;
617 if (lpService
->bDeleted
)
618 return ERROR_SERVICE_MARKED_FOR_DELETE
;
620 RpcImpersonateClient(NULL
);
622 Status
= NtOpenThreadToken(NtCurrentThread(),
626 if (!NT_SUCCESS(Status
))
627 return RtlNtStatusToDosError(Status
);
631 /* FIXME: Lock service database */
634 Status
= RtlSetSecurityObject(dwSecurityInformation
,
635 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
636 &lpService
->lpSecurityDescriptor
,
639 if (!NT_SUCCESS(Status
))
641 dwError
= RtlNtStatusToDosError(Status
);
646 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
647 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
649 if (dwError
!= ERROR_SUCCESS
)
653 dwError
= ERROR_SUCCESS
;
654 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
655 // lpService->lpSecurityDescriptor);
657 RegFlushKey(hServiceKey
);
658 RegCloseKey(hServiceKey
);
665 /* FIXME: Unlock service database */
667 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
674 DWORD
RQueryServiceStatus(
675 handle_t BindingHandle
,
676 SC_RPC_HANDLE hService
,
677 LPSERVICE_STATUS lpServiceStatus
)
679 PSERVICE_HANDLE hSvc
;
682 DPRINT("RQueryServiceStatus() called\n");
685 return ERROR_SHUTDOWN_IN_PROGRESS
;
687 hSvc
= (PSERVICE_HANDLE
)hService
;
688 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
690 DPRINT1("Invalid handle tag!\n");
691 return ERROR_INVALID_HANDLE
;
694 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
695 SERVICE_QUERY_STATUS
))
697 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
698 return ERROR_ACCESS_DENIED
;
701 lpService
= hSvc
->ServiceEntry
;
702 if (lpService
== NULL
)
704 DPRINT1("lpService == NULL!\n");
705 return ERROR_INVALID_HANDLE
;
708 /* Return service status information */
709 RtlCopyMemory(lpServiceStatus
,
711 sizeof(SERVICE_STATUS
));
713 return ERROR_SUCCESS
;
718 DWORD
RSetServiceStatus(
719 handle_t BindingHandle
,
720 SC_RPC_HANDLE hServiceStatus
,
721 LPSERVICE_STATUS lpServiceStatus
)
725 DPRINT("RSetServiceStatus() called\n");
728 return ERROR_SHUTDOWN_IN_PROGRESS
;
730 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
731 if (lpService
== NULL
)
733 DPRINT1("lpService == NULL!\n");
734 return ERROR_INVALID_HANDLE
;
737 RtlCopyMemory(&lpService
->Status
,
739 sizeof(SERVICE_STATUS
));
741 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
742 DPRINT("RSetServiceStatus() done\n");
744 return ERROR_SUCCESS
;
749 DWORD
RUnlockServiceDatabase(
750 handle_t BindingHandle
,
754 return ERROR_SUCCESS
;
759 DWORD
RNotifyBootConfigStatus(
760 handle_t BindingHandle
,
761 SVCCTL_HANDLEW lpMachineName
,
762 DWORD BootAcceptable
)
765 return ERROR_CALL_NOT_IMPLEMENTED
;
770 DWORD
RSetServiceBitsW(
771 handle_t BindingHandle
,
772 SC_RPC_HANDLE hServiceStatus
,
775 int bUpdateImmediately
,
779 return ERROR_CALL_NOT_IMPLEMENTED
;
784 DWORD
RChangeServiceConfigW(
785 handle_t BindingHandle
,
786 SC_RPC_HANDLE hService
,
789 DWORD dwErrorControl
,
790 LPWSTR lpBinaryPathName
,
791 LPWSTR lpLoadOrderGroup
,
793 LPBYTE lpDependencies
,
795 LPWSTR lpServiceStartName
,
798 LPWSTR lpDisplayName
)
800 DWORD dwError
= ERROR_SUCCESS
;
801 PSERVICE_HANDLE hSvc
;
802 PSERVICE lpService
= NULL
;
803 HKEY hServiceKey
= NULL
;
804 LPWSTR lpDisplayNameW
= NULL
;
806 DPRINT("RChangeServiceConfigW() called\n");
807 DPRINT("dwServiceType = %lu\n", dwServiceType
);
808 DPRINT("dwStartType = %lu\n", dwStartType
);
809 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
810 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
811 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
812 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
815 return ERROR_SHUTDOWN_IN_PROGRESS
;
817 hSvc
= (PSERVICE_HANDLE
)hService
;
818 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
820 DPRINT1("Invalid handle tag!\n");
821 return ERROR_INVALID_HANDLE
;
824 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
825 SERVICE_CHANGE_CONFIG
))
827 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
828 return ERROR_ACCESS_DENIED
;
831 lpService
= hSvc
->ServiceEntry
;
832 if (lpService
== NULL
)
834 DPRINT1("lpService == NULL!\n");
835 return ERROR_INVALID_HANDLE
;
838 /* FIXME: Lock database exclusively */
840 if (lpService
->bDeleted
)
842 /* FIXME: Unlock database */
843 DPRINT1("The service has already been marked for delete!\n");
844 return ERROR_SERVICE_MARKED_FOR_DELETE
;
847 /* Open the service key */
848 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
851 if (dwError
!= ERROR_SUCCESS
)
854 /* Write service data to the registry */
855 /* Set the display name */
856 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
858 RegSetValueExW(hServiceKey
,
862 (LPBYTE
)lpDisplayName
,
863 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
865 /* Update the display name */
866 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
868 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
869 if (lpDisplayNameW
== NULL
)
871 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
875 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
876 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
878 lpService
->lpDisplayName
= lpDisplayNameW
;
881 if (dwServiceType
!= SERVICE_NO_CHANGE
)
883 /* Set the service type */
884 dwError
= RegSetValueExW(hServiceKey
,
888 (LPBYTE
)&dwServiceType
,
890 if (dwError
!= ERROR_SUCCESS
)
893 lpService
->Status
.dwServiceType
= dwServiceType
;
896 if (dwStartType
!= SERVICE_NO_CHANGE
)
898 /* Set the start value */
899 dwError
= RegSetValueExW(hServiceKey
,
903 (LPBYTE
)&dwStartType
,
905 if (dwError
!= ERROR_SUCCESS
)
908 lpService
->dwStartType
= dwStartType
;
911 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
913 /* Set the error control value */
914 dwError
= RegSetValueExW(hServiceKey
,
918 (LPBYTE
)&dwErrorControl
,
920 if (dwError
!= ERROR_SUCCESS
)
923 lpService
->dwErrorControl
= dwErrorControl
;
927 /* FIXME: set the new ImagePath value */
929 /* Set the image path */
930 if (dwServiceType
& SERVICE_WIN32
)
932 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
934 dwError
= RegSetValueExW(hServiceKey
,
938 (LPBYTE
)lpBinaryPathName
,
939 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
940 if (dwError
!= ERROR_SUCCESS
)
944 else if (dwServiceType
& SERVICE_DRIVER
)
946 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
948 dwError
= RegSetValueExW(hServiceKey
,
953 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
954 if (dwError
!= ERROR_SUCCESS
)
960 /* Set the group name */
961 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
963 dwError
= RegSetValueExW(hServiceKey
,
967 (LPBYTE
)lpLoadOrderGroup
,
968 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
969 if (dwError
!= ERROR_SUCCESS
)
971 /* FIXME: update lpService->lpServiceGroup */
974 if (lpdwTagId
!= NULL
)
976 dwError
= ScmAssignNewTag(lpService
);
977 if (dwError
!= ERROR_SUCCESS
)
980 dwError
= RegSetValueExW(hServiceKey
,
984 (LPBYTE
)&lpService
->dwTag
,
986 if (dwError
!= ERROR_SUCCESS
)
989 *lpdwTagId
= lpService
->dwTag
;
992 /* Write dependencies */
993 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
995 dwError
= ScmWriteDependencies(hServiceKey
,
996 (LPWSTR
)lpDependencies
,
998 if (dwError
!= ERROR_SUCCESS
)
1002 if (lpPassword
!= NULL
)
1004 /* FIXME: Write password */
1007 /* FIXME: Unlock database */
1010 if (hServiceKey
!= NULL
)
1011 RegCloseKey(hServiceKey
);
1013 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1018 /* Create a path suitable for the bootloader out of the full path */
1020 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1022 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1025 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1026 OBJECT_ATTRIBUTES ObjectAttributes
;
1028 HANDLE SymbolicLinkHandle
;
1030 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1032 ServiceNameLen
= wcslen(CanonName
);
1033 /* First check, if it's already good */
1034 if (ServiceNameLen
> 12 &&
1035 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1037 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1039 if (*RelativeName
== NULL
)
1041 DPRINT1("Error allocating memory for boot driver name!\n");
1042 return ERROR_NOT_ENOUGH_MEMORY
;
1046 wcscpy(*RelativeName
, CanonName
);
1048 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1049 return ERROR_SUCCESS
;
1052 /* If it has %SystemRoot% prefix, substitute it to \System*/
1053 if (ServiceNameLen
> 13 &&
1054 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1056 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1057 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1059 if (*RelativeName
== NULL
)
1061 DPRINT1("Error allocating memory for boot driver name!\n");
1062 return ERROR_NOT_ENOUGH_MEMORY
;
1066 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1067 wcscat(*RelativeName
, CanonName
+ 13);
1069 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1070 return ERROR_SUCCESS
;
1073 /* Get buffer size needed for expanding env strings */
1074 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1076 if (BufferSize
<= 1)
1078 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1079 return ERROR_INVALID_ENVIRONMENT
;
1082 /* Allocate memory, since the size is known now */
1083 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1086 DPRINT1("Error allocating memory for boot driver name!\n");
1087 return ERROR_NOT_ENOUGH_MEMORY
;
1091 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1094 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1095 LocalFree(Expanded
);
1096 return ERROR_NOT_ENOUGH_MEMORY
;
1099 /* Convert to NY-style path */
1100 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1102 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1103 return ERROR_INVALID_ENVIRONMENT
;
1106 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1108 /* No need to keep the dos-path anymore */
1109 LocalFree(Expanded
);
1111 /* Copy it to the allocated place */
1112 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1115 DPRINT1("Error allocating memory for boot driver name!\n");
1116 return ERROR_NOT_ENOUGH_MEMORY
;
1119 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1120 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1121 Expanded
[ExpandedLen
] = 0;
1123 if (ServiceNameLen
> ExpandedLen
&&
1124 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1126 /* Only \SystemRoot\ is missing */
1127 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1128 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1130 if (*RelativeName
== NULL
)
1132 DPRINT1("Error allocating memory for boot driver name!\n");
1133 LocalFree(Expanded
);
1134 return ERROR_NOT_ENOUGH_MEMORY
;
1137 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1138 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1140 RtlFreeUnicodeString(&NtPathName
);
1141 return ERROR_SUCCESS
;
1144 /* The most complex case starts here */
1145 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1146 InitializeObjectAttributes(&ObjectAttributes
,
1148 OBJ_CASE_INSENSITIVE
,
1152 /* Open this symlink */
1153 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1155 if (NT_SUCCESS(Status
))
1157 LinkTarget
.Length
= 0;
1158 LinkTarget
.MaximumLength
= 0;
1160 DPRINT("Opened symbolic link object\n");
1162 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1163 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1165 /* Check if required buffer size is sane */
1166 if (BufferSize
> 0xFFFD)
1168 DPRINT1("Too large buffer required\n");
1171 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1172 LocalFree(Expanded
);
1173 return ERROR_NOT_ENOUGH_MEMORY
;
1176 /* Alloc the string */
1177 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1178 if (!LinkTarget
.Buffer
)
1180 DPRINT1("Unable to alloc buffer\n");
1181 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1182 LocalFree(Expanded
);
1183 return ERROR_NOT_ENOUGH_MEMORY
;
1186 /* Do a real query now */
1187 LinkTarget
.Length
= BufferSize
;
1188 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1190 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1191 if (NT_SUCCESS(Status
))
1193 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1195 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1196 if ((ServiceNameLen
> ExpandedLen
) &&
1197 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1199 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1200 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1202 if (*RelativeName
== NULL
)
1204 DPRINT1("Unable to alloc buffer\n");
1205 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1206 LocalFree(Expanded
);
1207 RtlFreeUnicodeString(&NtPathName
);
1208 return ERROR_NOT_ENOUGH_MEMORY
;
1211 /* Copy it over, substituting the first part
1213 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1214 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1217 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1218 LocalFree(Expanded
);
1219 RtlFreeUnicodeString(&NtPathName
);
1221 /* Return success */
1222 return ERROR_SUCCESS
;
1226 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1227 LocalFree(Expanded
);
1228 RtlFreeUnicodeString(&NtPathName
);
1229 return ERROR_INVALID_PARAMETER
;
1234 DPRINT1("Error, Status = %08X\n", Status
);
1235 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1236 LocalFree(Expanded
);
1237 RtlFreeUnicodeString(&NtPathName
);
1238 return ERROR_INVALID_PARAMETER
;
1243 DPRINT1("Error, Status = %08X\n", Status
);
1244 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1245 LocalFree(Expanded
);
1246 RtlFreeUnicodeString(&NtPathName
);
1247 return ERROR_INVALID_PARAMETER
;
1252 DPRINT1("Error, Status = %08X\n", Status
);
1253 LocalFree(Expanded
);
1254 return ERROR_INVALID_PARAMETER
;
1258 *RelativeName
= NULL
;
1259 return ERROR_INVALID_PARAMETER
;
1263 ScmCanonDriverImagePath(DWORD dwStartType
,
1264 wchar_t *lpServiceName
,
1265 wchar_t **lpCanonName
)
1267 DWORD ServiceNameLen
, Result
;
1268 UNICODE_STRING NtServiceName
;
1269 WCHAR
*RelativeName
;
1270 WCHAR
*SourceName
= lpServiceName
;
1272 /* Calculate the length of the service's name */
1273 ServiceNameLen
= wcslen(lpServiceName
);
1275 /* 12 is wcslen(L"\\SystemRoot\\") */
1276 if (ServiceNameLen
> 12 &&
1277 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1279 /* SystemRoot prefix is already included */
1281 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1283 if (*lpCanonName
== NULL
)
1285 DPRINT1("Error allocating memory for canonized service name!\n");
1286 return ERROR_NOT_ENOUGH_MEMORY
;
1289 /* If it's a boot-time driver, it must be systemroot relative */
1290 if (dwStartType
== SERVICE_BOOT_START
)
1294 wcscpy(*lpCanonName
, SourceName
);
1296 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1300 /* Check if it has %SystemRoot% (len=13) */
1301 if (ServiceNameLen
> 13 &&
1302 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1304 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1305 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1307 if (*lpCanonName
== NULL
)
1309 DPRINT1("Error allocating memory for canonized service name!\n");
1310 return ERROR_NOT_ENOUGH_MEMORY
;
1313 /* If it's a boot-time driver, it must be systemroot relative */
1314 if (dwStartType
== SERVICE_BOOT_START
)
1315 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1317 wcscat(*lpCanonName
, lpServiceName
+ 13);
1319 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1323 /* Check if it's a relative path name */
1324 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1326 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1328 if (*lpCanonName
== NULL
)
1330 DPRINT1("Error allocating memory for canonized service name!\n");
1331 return ERROR_NOT_ENOUGH_MEMORY
;
1334 /* Just copy it over without changing */
1335 wcscpy(*lpCanonName
, lpServiceName
);
1340 /* It seems to be a DOS path, convert it */
1341 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1343 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1344 return ERROR_INVALID_PARAMETER
;
1347 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1349 if (*lpCanonName
== NULL
)
1351 DPRINT1("Error allocating memory for canonized service name!\n");
1352 RtlFreeUnicodeString(&NtServiceName
);
1353 return ERROR_NOT_ENOUGH_MEMORY
;
1356 /* Copy the string */
1357 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1359 /* The unicode string is not needed anymore */
1360 RtlFreeUnicodeString(&NtServiceName
);
1362 if (dwStartType
!= SERVICE_BOOT_START
)
1364 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1368 /* The service is boot-started, so must be relative */
1369 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1372 /* There is a problem, free name and return */
1373 LocalFree(*lpCanonName
);
1374 DPRINT1("Error converting named!\n");
1378 ASSERT(RelativeName
);
1380 /* Copy that string */
1381 wcscpy(*lpCanonName
, RelativeName
+ 12);
1383 /* Free the allocated buffer */
1384 LocalFree(RelativeName
);
1386 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1394 DWORD
RCreateServiceW(
1395 handle_t BindingHandle
,
1396 SC_RPC_HANDLE hSCManager
,
1397 LPWSTR lpServiceName
,
1398 LPWSTR lpDisplayName
,
1399 DWORD dwDesiredAccess
,
1400 DWORD dwServiceType
,
1402 DWORD dwErrorControl
,
1403 LPWSTR lpBinaryPathName
,
1404 LPWSTR lpLoadOrderGroup
,
1406 LPBYTE lpDependencies
,
1408 LPWSTR lpServiceStartName
,
1411 LPSC_RPC_HANDLE lpServiceHandle
)
1413 PMANAGER_HANDLE hManager
;
1414 DWORD dwError
= ERROR_SUCCESS
;
1415 PSERVICE lpService
= NULL
;
1416 SC_HANDLE hServiceHandle
= NULL
;
1417 LPWSTR lpImagePath
= NULL
;
1418 HKEY hServiceKey
= NULL
;
1420 DPRINT("RCreateServiceW() called\n");
1421 DPRINT("lpServiceName = %S\n", lpServiceName
);
1422 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1423 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1424 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1425 DPRINT("dwStartType = %lu\n", dwStartType
);
1426 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1427 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1428 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1431 return ERROR_SHUTDOWN_IN_PROGRESS
;
1433 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1434 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1436 DPRINT1("Invalid manager handle!\n");
1437 return ERROR_INVALID_HANDLE
;
1440 /* Check access rights */
1441 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1442 SC_MANAGER_CREATE_SERVICE
))
1444 DPRINT1("Insufficient access rights! 0x%lx\n",
1445 hManager
->Handle
.DesiredAccess
);
1446 return ERROR_ACCESS_DENIED
;
1449 /* Fail if the service already exists! */
1450 if (ScmGetServiceEntryByName(lpServiceName
) != NULL
)
1451 return ERROR_SERVICE_EXISTS
;
1453 if (dwServiceType
& SERVICE_DRIVER
)
1455 dwError
= ScmCanonDriverImagePath(dwStartType
,
1459 if (dwError
!= ERROR_SUCCESS
)
1463 /* Allocate a new service entry */
1464 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1466 if (dwError
!= ERROR_SUCCESS
)
1469 /* Fill the new service entry */
1470 lpService
->Status
.dwServiceType
= dwServiceType
;
1471 lpService
->dwStartType
= dwStartType
;
1472 lpService
->dwErrorControl
= dwErrorControl
;
1474 /* Fill the display name */
1475 if (lpDisplayName
!= NULL
&&
1476 *lpDisplayName
!= 0 &&
1477 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1479 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1480 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1481 if (lpService
->lpDisplayName
== NULL
)
1483 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1486 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1489 /* Assign the service to a group */
1490 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1492 dwError
= ScmSetServiceGroup(lpService
,
1494 if (dwError
!= ERROR_SUCCESS
)
1498 /* Assign a new tag */
1499 if (lpdwTagId
!= NULL
)
1501 dwError
= ScmAssignNewTag(lpService
);
1502 if (dwError
!= ERROR_SUCCESS
)
1506 /* Write service data to the registry */
1507 /* Create the service key */
1508 dwError
= ScmCreateServiceKey(lpServiceName
,
1511 if (dwError
!= ERROR_SUCCESS
)
1514 /* Set the display name */
1515 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1517 RegSetValueExW(hServiceKey
,
1521 (LPBYTE
)lpDisplayName
,
1522 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1525 /* Set the service type */
1526 dwError
= RegSetValueExW(hServiceKey
,
1530 (LPBYTE
)&dwServiceType
,
1532 if (dwError
!= ERROR_SUCCESS
)
1535 /* Set the start value */
1536 dwError
= RegSetValueExW(hServiceKey
,
1540 (LPBYTE
)&dwStartType
,
1542 if (dwError
!= ERROR_SUCCESS
)
1545 /* Set the error control value */
1546 dwError
= RegSetValueExW(hServiceKey
,
1550 (LPBYTE
)&dwErrorControl
,
1552 if (dwError
!= ERROR_SUCCESS
)
1555 /* Set the image path */
1556 if (dwServiceType
& SERVICE_WIN32
)
1558 dwError
= RegSetValueExW(hServiceKey
,
1562 (LPBYTE
)lpBinaryPathName
,
1563 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1564 if (dwError
!= ERROR_SUCCESS
)
1567 else if (dwServiceType
& SERVICE_DRIVER
)
1569 dwError
= RegSetValueExW(hServiceKey
,
1573 (LPBYTE
)lpImagePath
,
1574 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1575 if (dwError
!= ERROR_SUCCESS
)
1579 /* Set the group name */
1580 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1582 dwError
= RegSetValueExW(hServiceKey
,
1586 (LPBYTE
)lpLoadOrderGroup
,
1587 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1588 if (dwError
!= ERROR_SUCCESS
)
1592 if (lpdwTagId
!= NULL
)
1594 dwError
= RegSetValueExW(hServiceKey
,
1598 (LPBYTE
)&lpService
->dwTag
,
1600 if (dwError
!= ERROR_SUCCESS
)
1604 /* Write dependencies */
1605 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1607 dwError
= ScmWriteDependencies(hServiceKey
,
1608 (LPWSTR
)lpDependencies
,
1610 if (dwError
!= ERROR_SUCCESS
)
1614 if (lpPassword
!= NULL
)
1616 /* FIXME: Write password */
1619 dwError
= ScmCreateServiceHandle(lpService
,
1621 if (dwError
!= ERROR_SUCCESS
)
1624 dwError
= ScmCheckAccess(hServiceHandle
,
1626 if (dwError
!= ERROR_SUCCESS
)
1630 if (hServiceKey
!= NULL
)
1631 RegCloseKey(hServiceKey
);
1633 if (dwError
== ERROR_SUCCESS
)
1635 DPRINT("hService %p\n", hServiceHandle
);
1636 *lpServiceHandle
= (unsigned long)hServiceHandle
; /* FIXME: 64 bit portability */
1638 if (lpdwTagId
!= NULL
)
1639 *lpdwTagId
= lpService
->dwTag
;
1643 /* Release the display name buffer */
1644 if (lpService
->lpServiceName
!= NULL
)
1645 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1649 /* Remove the service handle */
1650 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1653 if (lpService
!= NULL
)
1655 /* FIXME: remove the service entry */
1659 if (lpImagePath
!= NULL
)
1660 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1662 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
1669 DWORD
REnumDependentServicesW(
1670 handle_t BindingHandle
,
1671 SC_RPC_HANDLE hService
,
1672 DWORD dwServiceState
,
1675 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
1676 LPBOUNDED_DWORD_256K lpServicesReturned
)
1678 DWORD dwError
= ERROR_SUCCESS
;
1681 *pcbBytesNeeded
= 0;
1682 *lpServicesReturned
= 0;
1684 DPRINT1("REnumDependentServicesW() done (Error %lu)\n", dwError
);
1691 DWORD
REnumServicesStatusW(
1692 handle_t BindingHandle
,
1693 SC_RPC_HANDLE hSCManager
,
1694 DWORD dwServiceType
,
1695 DWORD dwServiceState
,
1698 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
1699 LPBOUNDED_DWORD_256K lpServicesReturned
,
1700 LPBOUNDED_DWORD_256K lpResumeHandle
)
1702 PMANAGER_HANDLE hManager
;
1704 DWORD dwError
= ERROR_SUCCESS
;
1705 PLIST_ENTRY ServiceEntry
;
1706 PSERVICE CurrentService
;
1708 DWORD dwRequiredSize
;
1709 DWORD dwServiceCount
;
1711 DWORD dwLastResumeCount
;
1712 LPENUM_SERVICE_STATUSW lpStatusPtr
;
1715 DPRINT("REnumServicesStatusW() called\n");
1718 return ERROR_SHUTDOWN_IN_PROGRESS
;
1720 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1721 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1723 DPRINT1("Invalid manager handle!\n");
1724 return ERROR_INVALID_HANDLE
;
1727 /* Check access rights */
1728 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1729 SC_MANAGER_ENUMERATE_SERVICE
))
1731 DPRINT1("Insufficient access rights! 0x%lx\n",
1732 hManager
->Handle
.DesiredAccess
);
1733 return ERROR_ACCESS_DENIED
;
1736 *pcbBytesNeeded
= 0;
1737 *lpServicesReturned
= 0;
1739 dwLastResumeCount
= *lpResumeHandle
;
1741 /* FIXME: Lock the service list shared */
1743 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
1744 if (lpService
== NULL
)
1746 dwError
= ERROR_SUCCESS
;
1753 for (ServiceEntry
= &lpService
->ServiceListEntry
;
1754 ServiceEntry
!= &ServiceListHead
;
1755 ServiceEntry
= ServiceEntry
->Flink
)
1757 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1761 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1764 dwState
= SERVICE_ACTIVE
;
1765 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1766 dwState
= SERVICE_INACTIVE
;
1768 if ((dwState
& dwServiceState
) == 0)
1771 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
1772 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1773 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1775 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
1777 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
1778 dwRequiredSize
+= dwSize
;
1780 dwLastResumeCount
= CurrentService
->dwResumeCount
;
1784 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
1790 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
1791 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
1794 ServiceEntry
!= &ServiceListHead
;
1795 ServiceEntry
= ServiceEntry
->Flink
)
1797 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1801 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1804 dwState
= SERVICE_ACTIVE
;
1805 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1806 dwState
= SERVICE_INACTIVE
;
1808 if ((dwState
& dwServiceState
) == 0)
1811 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
1812 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1813 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
1815 dwError
= ERROR_MORE_DATA
;
1818 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
1820 *lpResumeHandle
= dwLastResumeCount
;
1821 *lpServicesReturned
= dwServiceCount
;
1822 *pcbBytesNeeded
= dwRequiredSize
;
1824 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
1825 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
1826 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
1829 for (ServiceEntry
= &lpService
->ServiceListEntry
;
1830 ServiceEntry
!= &ServiceListHead
;
1831 ServiceEntry
= ServiceEntry
->Flink
)
1833 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1837 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1840 dwState
= SERVICE_ACTIVE
;
1841 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1842 dwState
= SERVICE_INACTIVE
;
1844 if ((dwState
& dwServiceState
) == 0)
1847 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
1848 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1849 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1851 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
1853 /* Copy the service name */
1855 CurrentService
->lpServiceName
);
1856 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
1857 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
1859 /* Copy the display name */
1861 CurrentService
->lpDisplayName
);
1862 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
1863 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
1865 /* Copy the status information */
1866 memcpy(&lpStatusPtr
->ServiceStatus
,
1867 &CurrentService
->Status
,
1868 sizeof(SERVICE_STATUS
));
1871 dwRequiredSize
+= dwSize
;
1881 /* FIXME: Unlock the service list */
1883 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
1890 DWORD
ROpenSCManagerW(
1891 handle_t BindingHandle
,
1892 LPWSTR lpMachineName
,
1893 LPWSTR lpDatabaseName
,
1894 DWORD dwDesiredAccess
,
1895 LPSC_RPC_HANDLE lpScHandle
)
1900 DPRINT("ROpenSCManagerW() called\n");
1901 DPRINT("lpMachineName = %p\n", lpMachineName
);
1902 DPRINT("lpMachineName: %S\n", lpMachineName
);
1903 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
1904 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
1905 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
1908 return ERROR_SHUTDOWN_IN_PROGRESS
;
1911 return ERROR_INVALID_PARAMETER
;
1913 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
1915 if (dwError
!= ERROR_SUCCESS
)
1917 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
1921 /* Check the desired access */
1922 dwError
= ScmCheckAccess(hHandle
,
1923 dwDesiredAccess
| SC_MANAGER_CONNECT
);
1924 if (dwError
!= ERROR_SUCCESS
)
1926 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1927 HeapFree(GetProcessHeap(), 0, hHandle
);
1931 *lpScHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
1932 DPRINT("*hScm = %p\n", *lpScHandle
);
1934 DPRINT("ROpenSCManagerW() done\n");
1936 return ERROR_SUCCESS
;
1941 DWORD
ROpenServiceW(
1942 handle_t BindingHandle
,
1943 SC_RPC_HANDLE hSCManager
,
1944 LPWSTR lpServiceName
,
1945 DWORD dwDesiredAccess
,
1946 LPSC_RPC_HANDLE lpServiceHandle
)
1949 PMANAGER_HANDLE hManager
;
1953 DPRINT("ROpenServiceW() called\n");
1954 DPRINT("hSCManager = %p\n", hSCManager
);
1955 DPRINT("lpServiceName = %p\n", lpServiceName
);
1956 DPRINT("lpServiceName: %S\n", lpServiceName
);
1957 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
1960 return ERROR_SHUTDOWN_IN_PROGRESS
;
1962 if (!lpServiceHandle
)
1963 return ERROR_INVALID_PARAMETER
;
1966 return ERROR_INVALID_ADDRESS
;
1968 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1969 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1971 DPRINT1("Invalid manager handle!\n");
1972 return ERROR_INVALID_HANDLE
;
1975 /* FIXME: Lock the service list */
1977 /* Get service database entry */
1978 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1979 if (lpService
== NULL
)
1981 DPRINT("Could not find a service!\n");
1982 return ERROR_SERVICE_DOES_NOT_EXIST
;
1985 /* Create a service handle */
1986 dwError
= ScmCreateServiceHandle(lpService
,
1988 if (dwError
!= ERROR_SUCCESS
)
1990 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
1994 /* Check the desired access */
1995 dwError
= ScmCheckAccess(hHandle
,
1997 if (dwError
!= ERROR_SUCCESS
)
1999 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2000 HeapFree(GetProcessHeap(), 0, hHandle
);
2004 *lpServiceHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
2005 DPRINT("*hService = %p\n", *lpServiceHandle
);
2007 DPRINT("ROpenServiceW() done\n");
2009 return ERROR_SUCCESS
;
2014 DWORD
RQueryServiceConfigW(
2015 handle_t BindingHandle
,
2016 SC_RPC_HANDLE hService
,
2017 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2019 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2021 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2022 DWORD dwError
= ERROR_SUCCESS
;
2023 PSERVICE_HANDLE hSvc
;
2024 PSERVICE lpService
= NULL
;
2025 HKEY hServiceKey
= NULL
;
2026 LPWSTR lpImagePath
= NULL
;
2027 LPWSTR lpServiceStartName
= NULL
;
2028 DWORD dwRequiredSize
;
2029 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2030 WCHAR lpEmptyString
[] = {0,0};
2033 DPRINT("RQueryServiceConfigW() called\n");
2036 return ERROR_SHUTDOWN_IN_PROGRESS
;
2038 hSvc
= (PSERVICE_HANDLE
)hService
;
2039 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2041 DPRINT1("Invalid handle tag!\n");
2042 return ERROR_INVALID_HANDLE
;
2045 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2046 SERVICE_QUERY_CONFIG
))
2048 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2049 return ERROR_ACCESS_DENIED
;
2052 lpService
= hSvc
->ServiceEntry
;
2053 if (lpService
== NULL
)
2055 DPRINT1("lpService == NULL!\n");
2056 return ERROR_INVALID_HANDLE
;
2059 /* FIXME: Lock the service database shared */
2061 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2064 if (dwError
!= ERROR_SUCCESS
)
2067 dwError
= ScmReadString(hServiceKey
,
2070 if (dwError
!= ERROR_SUCCESS
)
2073 ScmReadString(hServiceKey
,
2075 &lpServiceStartName
);
2077 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2079 if (lpImagePath
!= NULL
)
2080 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2082 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2084 if (lpService
->lpGroup
!= NULL
)
2085 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2087 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2089 /* FIXME: Add Dependencies length*/
2091 if (lpServiceStartName
!= NULL
)
2092 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2094 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2096 if (lpService
->lpDisplayName
!= NULL
)
2097 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2099 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2101 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2103 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2107 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2108 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2109 lpConfig
->dwStartType
= lpService
->dwStartType
;
2110 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2111 lpConfig
->dwTagId
= lpService
->dwTag
;
2113 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2115 if (lpImagePath
!= NULL
)
2117 wcscpy(lpStr
, lpImagePath
);
2121 wcscpy(lpStr
, lpEmptyString
);
2124 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2125 lpStr
+= (wcslen(lpStr
) + 1);
2127 if (lpService
->lpGroup
!= NULL
)
2129 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2133 wcscpy(lpStr
, lpEmptyString
);
2136 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2137 lpStr
+= (wcslen(lpStr
) + 1);
2139 /* FIXME: Append Dependencies */
2140 wcscpy(lpStr
, lpEmptyString
);
2142 lpStr
+= (wcslen(lpStr
) + 1);
2143 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2145 if (lpServiceStartName
!= NULL
)
2147 wcscpy(lpStr
, lpServiceStartName
);
2151 wcscpy(lpStr
, lpEmptyString
);
2154 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2155 lpStr
+= (wcslen(lpStr
) + 1);
2157 if (lpService
->lpDisplayName
!= NULL
)
2159 wcscpy(lpStr
, lpService
->lpDisplayName
);
2163 wcscpy(lpStr
, lpEmptyString
);
2166 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2169 if (pcbBytesNeeded
!= NULL
)
2170 *pcbBytesNeeded
= dwRequiredSize
;
2173 if (lpImagePath
!= NULL
)
2174 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2176 if (lpServiceStartName
!= NULL
)
2177 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2179 if (hServiceKey
!= NULL
)
2180 RegCloseKey(hServiceKey
);
2182 /* FIXME: Unlock the service database */
2184 DPRINT("RQueryServiceConfigW() done\n");
2191 DWORD
RQueryServiceLockStatusW(
2192 handle_t BindingHandle
,
2193 SC_RPC_HANDLE hSCManager
,
2194 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2196 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2199 return ERROR_CALL_NOT_IMPLEMENTED
;
2204 DWORD
RStartServiceW(
2205 handle_t BindingHandle
,
2206 SC_RPC_HANDLE hService
,
2208 LPSTRING_PTRSW argv
)
2210 DWORD dwError
= ERROR_SUCCESS
;
2211 PSERVICE_HANDLE hSvc
;
2212 PSERVICE lpService
= NULL
;
2214 DPRINT("RStartServiceW() called\n");
2217 return ERROR_SHUTDOWN_IN_PROGRESS
;
2219 hSvc
= (PSERVICE_HANDLE
)hService
;
2220 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2222 DPRINT1("Invalid handle tag!\n");
2223 return ERROR_INVALID_HANDLE
;
2226 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2229 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2230 return ERROR_ACCESS_DENIED
;
2233 lpService
= hSvc
->ServiceEntry
;
2234 if (lpService
== NULL
)
2236 DPRINT1("lpService == NULL!\n");
2237 return ERROR_INVALID_HANDLE
;
2240 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2241 return ERROR_SERVICE_DISABLED
;
2243 if (lpService
->bDeleted
)
2244 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2251 /* Start the service */
2252 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2259 DWORD
RGetServiceDisplayNameW(
2260 handle_t BindingHandle
,
2261 SC_RPC_HANDLE hSCManager
,
2262 LPWSTR lpServiceName
,
2263 LPWSTR lpDisplayName
,
2266 // PMANAGER_HANDLE hManager;
2271 DPRINT("RGetServiceDisplayNameW() called\n");
2272 DPRINT("hSCManager = %p\n", hSCManager
);
2273 DPRINT("lpServiceName: %S\n", lpServiceName
);
2274 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2275 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2277 // hManager = (PMANAGER_HANDLE)hSCManager;
2278 // if (hManager->Handle.Tag != MANAGER_TAG)
2280 // DPRINT1("Invalid manager handle!\n");
2281 // return ERROR_INVALID_HANDLE;
2284 /* Get service database entry */
2285 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2286 if (lpService
== NULL
)
2288 DPRINT1("Could not find a service!\n");
2290 /* If the service could not be found and lpcchBuffer is 0, windows
2291 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2292 if (*lpcchBuffer
== 0)
2295 *lpDisplayName
= '\0';
2298 return ERROR_SERVICE_DOES_NOT_EXIST
;
2301 if (!lpService
->lpDisplayName
)
2303 dwLength
= wcslen(lpService
->lpServiceName
);
2305 if (lpServiceName
!= NULL
&&
2306 *lpcchBuffer
> dwLength
)
2308 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2313 dwLength
= wcslen(lpService
->lpDisplayName
);
2315 if (lpDisplayName
!= NULL
&&
2316 *lpcchBuffer
> dwLength
)
2318 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2322 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2324 *lpcchBuffer
= dwLength
;
2331 DWORD
RGetServiceKeyNameW(
2332 handle_t BindingHandle
,
2333 SC_RPC_HANDLE hSCManager
,
2334 LPWSTR lpDisplayName
,
2335 LPWSTR lpServiceName
,
2338 // PMANAGER_HANDLE hManager;
2343 DPRINT("RGetServiceKeyNameW() called\n");
2344 DPRINT("hSCManager = %p\n", hSCManager
);
2345 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2346 DPRINT("lpServiceName: %p\n", lpServiceName
);
2347 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2349 // hManager = (PMANAGER_HANDLE)hSCManager;
2350 // if (hManager->Handle.Tag != MANAGER_TAG)
2352 // DPRINT1("Invalid manager handle!\n");
2353 // return ERROR_INVALID_HANDLE;
2356 /* Get service database entry */
2357 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2358 if (lpService
== NULL
)
2360 DPRINT1("Could not find a service!\n");
2362 /* If the service could not be found and lpcchBuffer is 0, windows
2363 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2364 if (*lpcchBuffer
== 0)
2367 *lpServiceName
= '\0';
2370 return ERROR_SERVICE_DOES_NOT_EXIST
;
2373 dwLength
= wcslen(lpService
->lpServiceName
);
2375 if (lpServiceName
!= NULL
&&
2376 *lpcchBuffer
> dwLength
)
2378 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2379 *lpcchBuffer
= dwLength
;
2380 return ERROR_SUCCESS
;
2383 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2385 *lpcchBuffer
= dwLength
* 2;
2392 DWORD
RSetServiceBitsA(
2393 handle_t BindingHandle
,
2394 SC_RPC_HANDLE hServiceStatus
,
2395 DWORD dwServiceBits
,
2397 int bUpdateImmediately
,
2401 return ERROR_CALL_NOT_IMPLEMENTED
;
2406 DWORD
RChangeServiceConfigA(
2407 handle_t BindingHandle
,
2408 SC_RPC_HANDLE hService
,
2409 DWORD dwServiceType
,
2411 DWORD dwErrorControl
,
2412 LPSTR lpBinaryPathName
,
2413 LPSTR lpLoadOrderGroup
,
2415 LPSTR lpDependencies
,
2417 LPSTR lpServiceStartName
,
2420 LPSTR lpDisplayName
)
2422 DWORD dwError
= ERROR_SUCCESS
;
2423 PSERVICE_HANDLE hSvc
;
2424 PSERVICE lpService
= NULL
;
2425 HKEY hServiceKey
= NULL
;
2426 LPWSTR lpDisplayNameW
= NULL
;
2427 // LPWSTR lpBinaryPathNameW = NULL;
2428 LPWSTR lpLoadOrderGroupW
= NULL
;
2429 LPWSTR lpDependenciesW
= NULL
;
2430 // LPWSTR lpPasswordW = NULL;
2432 DPRINT("RChangeServiceConfigA() called\n");
2433 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2434 DPRINT("dwStartType = %lu\n", dwStartType
);
2435 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2436 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2437 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2438 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2441 return ERROR_SHUTDOWN_IN_PROGRESS
;
2443 hSvc
= (PSERVICE_HANDLE
)hService
;
2444 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2446 DPRINT1("Invalid handle tag!\n");
2447 return ERROR_INVALID_HANDLE
;
2450 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2451 SERVICE_CHANGE_CONFIG
))
2453 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2454 return ERROR_ACCESS_DENIED
;
2457 lpService
= hSvc
->ServiceEntry
;
2458 if (lpService
== NULL
)
2460 DPRINT1("lpService == NULL!\n");
2461 return ERROR_INVALID_HANDLE
;
2464 /* FIXME: Lock database exclusively */
2466 if (lpService
->bDeleted
)
2468 /* FIXME: Unlock database */
2469 DPRINT1("The service has already been marked for delete!\n");
2470 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2473 /* Open the service key */
2474 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2477 if (dwError
!= ERROR_SUCCESS
)
2480 /* Write service data to the registry */
2482 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2484 /* Set the display name */
2485 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2487 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2488 if (lpDisplayNameW
== NULL
)
2490 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2494 MultiByteToWideChar(CP_ACP
,
2499 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2501 RegSetValueExW(hServiceKey
,
2505 (LPBYTE
)lpDisplayNameW
,
2506 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2508 /* Update lpService->lpDisplayName */
2509 if (lpService
->lpDisplayName
)
2510 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2512 lpService
->lpDisplayName
= lpDisplayNameW
;
2515 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2517 /* Set the service type */
2518 dwError
= RegSetValueExW(hServiceKey
,
2522 (LPBYTE
)&dwServiceType
,
2524 if (dwError
!= ERROR_SUCCESS
)
2527 lpService
->Status
.dwServiceType
= dwServiceType
;
2530 if (dwStartType
!= SERVICE_NO_CHANGE
)
2532 /* Set the start value */
2533 dwError
= RegSetValueExW(hServiceKey
,
2537 (LPBYTE
)&dwStartType
,
2539 if (dwError
!= ERROR_SUCCESS
)
2542 lpService
->dwStartType
= dwStartType
;
2545 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
2547 /* Set the error control value */
2548 dwError
= RegSetValueExW(hServiceKey
,
2552 (LPBYTE
)&dwErrorControl
,
2554 if (dwError
!= ERROR_SUCCESS
)
2557 lpService
->dwErrorControl
= dwErrorControl
;
2561 /* FIXME: set the new ImagePath value */
2563 /* Set the image path */
2564 if (dwServiceType
& SERVICE_WIN32
)
2566 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2568 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
2569 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, (wcslen(lpBinaryPathNameW
)+1) * sizeof(WCHAR
));
2570 dwError
= RegSetValueExW(hServiceKey
,
2574 (LPBYTE
)lpBinaryPathNameW
,
2575 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
2576 if (dwError
!= ERROR_SUCCESS
)
2580 else if (dwServiceType
& SERVICE_DRIVER
)
2582 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
2584 dwError
= RegSetValueExW(hServiceKey
,
2588 (LPBYTE
)lpImagePath
,
2589 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
2590 if (dwError
!= ERROR_SUCCESS
)
2596 /* Set the group name */
2597 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2599 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
2601 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
2602 if (lpLoadOrderGroupW
== NULL
)
2604 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2608 MultiByteToWideChar(CP_ACP
,
2613 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
2615 dwError
= RegSetValueExW(hServiceKey
,
2619 (LPBYTE
)lpLoadOrderGroupW
,
2620 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
2621 if (dwError
!= ERROR_SUCCESS
)
2624 /* FIXME: Update lpService->lpServiceGroup */
2626 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
2629 if (lpdwTagId
!= NULL
)
2631 dwError
= ScmAssignNewTag(lpService
);
2632 if (dwError
!= ERROR_SUCCESS
)
2635 dwError
= RegSetValueExW(hServiceKey
,
2639 (LPBYTE
)&lpService
->dwTag
,
2641 if (dwError
!= ERROR_SUCCESS
)
2644 *lpdwTagId
= lpService
->dwTag
;
2647 /* Write dependencies */
2648 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2650 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
2652 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
2653 if (lpDependenciesW
== NULL
)
2655 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2659 MultiByteToWideChar(CP_ACP
,
2664 (wcslen(lpDependenciesW
)+1) * sizeof(WCHAR
));
2666 dwError
= ScmWriteDependencies(hServiceKey
,
2667 (LPWSTR
)lpDependenciesW
,
2670 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
2673 if (lpPassword
!= NULL
)
2675 /* FIXME: Write password */
2678 /* FIXME: Unlock database */
2681 if (hServiceKey
!= NULL
)
2682 RegCloseKey(hServiceKey
);
2684 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
2691 DWORD
RCreateServiceA(
2692 handle_t BindingHandle
,
2693 SC_RPC_HANDLE hSCManager
,
2694 LPSTR lpServiceName
,
2695 LPSTR lpDisplayName
,
2696 DWORD dwDesiredAccess
,
2697 DWORD dwServiceType
,
2699 DWORD dwErrorControl
,
2700 LPSTR lpBinaryPathName
,
2701 LPSTR lpLoadOrderGroup
,
2703 LPBYTE lpDependencies
,
2705 LPSTR lpServiceStartName
,
2708 LPSC_RPC_HANDLE lpServiceHandle
)
2711 return ERROR_CALL_NOT_IMPLEMENTED
;
2716 DWORD
REnumDependentServicesA(
2717 handle_t BindingHandle
,
2718 SC_RPC_HANDLE hService
,
2719 DWORD dwServiceState
,
2722 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2723 LPBOUNDED_DWORD_256K lpServicesReturned
)
2726 *pcbBytesNeeded
= 0;
2727 *lpServicesReturned
= 0;
2728 return ERROR_CALL_NOT_IMPLEMENTED
;
2733 DWORD
REnumServicesStatusA(
2734 handle_t BindingHandle
,
2735 SC_RPC_HANDLE hSCManager
,
2736 DWORD dwServiceType
,
2737 DWORD dwServiceState
,
2740 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2741 LPBOUNDED_DWORD_256K lpServicesReturned
,
2742 LPBOUNDED_DWORD_256K lpResumeHandle
)
2745 return ERROR_CALL_NOT_IMPLEMENTED
;
2750 DWORD
ROpenSCManagerA(
2751 handle_t BindingHandle
,
2752 LPSTR lpMachineName
,
2753 LPSTR lpDatabaseName
,
2754 DWORD dwDesiredAccess
,
2755 LPSC_RPC_HANDLE lpScHandle
)
2757 UNICODE_STRING MachineName
;
2758 UNICODE_STRING DatabaseName
;
2761 DPRINT("ROpenSCManagerA() called\n");
2764 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
2768 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
2771 dwError
= ROpenSCManagerW(BindingHandle
,
2772 lpMachineName
? MachineName
.Buffer
: NULL
,
2773 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
2778 RtlFreeUnicodeString(&MachineName
);
2781 RtlFreeUnicodeString(&DatabaseName
);
2788 DWORD
ROpenServiceA(
2789 handle_t BindingHandle
,
2790 SC_RPC_HANDLE hSCManager
,
2791 LPSTR lpServiceName
,
2792 DWORD dwDesiredAccess
,
2793 LPSC_RPC_HANDLE lpServiceHandle
)
2795 UNICODE_STRING ServiceName
;
2798 DPRINT("ROpenServiceA() called\n");
2801 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
2804 dwError
= ROpenServiceW(BindingHandle
,
2811 RtlFreeUnicodeString(&ServiceName
);
2818 DWORD
RQueryServiceConfigA(
2819 handle_t BindingHandle
,
2820 SC_RPC_HANDLE hService
,
2821 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
2823 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2825 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
2826 DWORD dwError
= ERROR_SUCCESS
;
2827 PSERVICE_HANDLE hSvc
;
2828 PSERVICE lpService
= NULL
;
2829 HKEY hServiceKey
= NULL
;
2830 LPWSTR lpImagePath
= NULL
;
2831 LPWSTR lpServiceStartName
= NULL
;
2832 DWORD dwRequiredSize
;
2833 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
2834 CHAR lpEmptyString
[]={0,0};
2837 DPRINT("RQueryServiceConfigA() called\n");
2840 return ERROR_SHUTDOWN_IN_PROGRESS
;
2842 hSvc
= (PSERVICE_HANDLE
)hService
;
2843 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2845 DPRINT1("Invalid handle tag!\n");
2846 return ERROR_INVALID_HANDLE
;
2849 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2850 SERVICE_QUERY_CONFIG
))
2852 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2853 return ERROR_ACCESS_DENIED
;
2856 lpService
= hSvc
->ServiceEntry
;
2857 if (lpService
== NULL
)
2859 DPRINT1("lpService == NULL!\n");
2860 return ERROR_INVALID_HANDLE
;
2863 /* FIXME: Lock the service database shared */
2865 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2868 if (dwError
!= ERROR_SUCCESS
)
2871 dwError
= ScmReadString(hServiceKey
,
2874 if (dwError
!= ERROR_SUCCESS
)
2877 ScmReadString(hServiceKey
,
2879 &lpServiceStartName
);
2881 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2883 if (lpImagePath
!= NULL
)
2884 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
2886 dwRequiredSize
+= 2;
2888 if (lpService
->lpGroup
!= NULL
)
2889 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
2891 dwRequiredSize
+= 2;
2893 /* FIXME: Add Dependencies length*/
2894 dwRequiredSize
+= 2;
2896 if (lpServiceStartName
!= NULL
)
2897 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
2899 dwRequiredSize
+= 2;
2901 if (lpService
->lpDisplayName
!= NULL
)
2902 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
2904 dwRequiredSize
+= 2;
2906 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2908 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2912 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
2913 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2914 lpConfig
->dwStartType
= lpService
->dwStartType
;
2915 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2916 lpConfig
->dwTagId
= lpService
->dwTag
;
2918 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
2920 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
2925 WideCharToMultiByte(CP_ACP
,
2930 wcslen(lpImagePath
),
2936 strcpy(lpStr
, lpEmptyString
);
2939 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2940 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
2942 if (lpService
->lpGroup
)
2944 WideCharToMultiByte(CP_ACP
,
2946 lpService
->lpGroup
->lpGroupName
,
2949 wcslen(lpService
->lpGroup
->lpGroupName
),
2955 strcpy(lpStr
, lpEmptyString
);
2958 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2959 lpStr
+= (strlen(lpStr
) + 1);
2961 /* FIXME: Append Dependencies */
2962 strcpy(lpStr
, lpEmptyString
);
2964 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2965 lpStr
+= (strlen(lpStr
) + 1);
2967 if (lpServiceStartName
)
2969 WideCharToMultiByte(CP_ACP
,
2974 wcslen(lpServiceStartName
),
2980 strcpy(lpStr
, lpEmptyString
);
2983 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2984 lpStr
+= (strlen(lpStr
) + 1);
2986 if (lpService
->lpDisplayName
)
2988 WideCharToMultiByte(CP_ACP
,
2990 lpService
->lpDisplayName
,
2993 wcslen(lpService
->lpDisplayName
),
2999 strcpy(lpStr
, lpEmptyString
);
3002 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3005 if (pcbBytesNeeded
!= NULL
)
3006 *pcbBytesNeeded
= dwRequiredSize
;
3009 if (lpImagePath
!= NULL
)
3010 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3012 if (lpServiceStartName
!= NULL
)
3013 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3015 if (hServiceKey
!= NULL
)
3016 RegCloseKey(hServiceKey
);
3018 /* FIXME: Unlock the service database */
3020 DPRINT("RQueryServiceConfigA() done\n");
3027 DWORD
RQueryServiceLockStatusA(
3028 handle_t BindingHandle
,
3029 SC_RPC_HANDLE hSCManager
,
3030 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3032 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3035 return ERROR_CALL_NOT_IMPLEMENTED
;
3040 DWORD
RStartServiceA(
3041 handle_t BindingHandle
,
3042 SC_RPC_HANDLE hService
,
3044 LPSTRING_PTRSA argv
)
3046 DWORD dwError
= ERROR_SUCCESS
;
3047 PSERVICE_HANDLE hSvc
;
3048 PSERVICE lpService
= NULL
;
3050 DPRINT1("RStartServiceA() called\n");
3053 return ERROR_SHUTDOWN_IN_PROGRESS
;
3055 hSvc
= (PSERVICE_HANDLE
)hService
;
3056 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3058 DPRINT1("Invalid handle tag!\n");
3059 return ERROR_INVALID_HANDLE
;
3062 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3065 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3066 return ERROR_ACCESS_DENIED
;
3069 lpService
= hSvc
->ServiceEntry
;
3070 if (lpService
== NULL
)
3072 DPRINT1("lpService == NULL!\n");
3073 return ERROR_INVALID_HANDLE
;
3076 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3077 return ERROR_SERVICE_DISABLED
;
3079 if (lpService
->bDeleted
)
3080 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3082 /* FIXME: Convert argument vector to Unicode */
3084 /* Start the service */
3085 dwError
= ScmStartService(lpService
, 0, NULL
);
3087 /* FIXME: Free argument vector */
3094 DWORD
RGetServiceDisplayNameA(
3095 handle_t BindingHandle
,
3096 SC_RPC_HANDLE hSCManager
,
3097 LPSTR lpServiceName
,
3098 LPSTR lpDisplayName
,
3099 LPBOUNDED_DWORD_4K lpcchBuffer
)
3101 // PMANAGER_HANDLE hManager;
3105 LPWSTR lpServiceNameW
;
3107 DPRINT("RGetServiceDisplayNameA() called\n");
3108 DPRINT("hSCManager = %p\n", hSCManager
);
3109 DPRINT("lpServiceName: %s\n", lpServiceName
);
3110 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3111 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3113 // hManager = (PMANAGER_HANDLE)hSCManager;
3114 // if (hManager->Handle.Tag != MANAGER_TAG)
3116 // DPRINT1("Invalid manager handle!\n");
3117 // return ERROR_INVALID_HANDLE;
3120 dwLength
= strlen(lpServiceName
) + 1;
3121 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3123 dwLength
* sizeof(WCHAR
));
3124 if (!lpServiceNameW
)
3125 return ERROR_NOT_ENOUGH_MEMORY
;
3127 MultiByteToWideChar(CP_ACP
,
3130 strlen(lpServiceName
),
3134 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3136 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3138 if (lpService
== NULL
)
3140 DPRINT1("Could not find a service!\n");
3142 /* If the service could not be found and lpcchBuffer is 0, windows
3143 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3144 if (*lpcchBuffer
== 0)
3147 *lpDisplayName
= '\0';
3149 return ERROR_SERVICE_DOES_NOT_EXIST
;
3152 if (!lpService
->lpDisplayName
)
3154 dwLength
= wcslen(lpService
->lpServiceName
);
3155 if (lpServiceName
!= NULL
&&
3156 *lpcchBuffer
> dwLength
)
3158 WideCharToMultiByte(CP_ACP
,
3160 lpService
->lpServiceName
,
3161 wcslen(lpService
->lpServiceName
),
3166 return ERROR_SUCCESS
;
3171 dwLength
= wcslen(lpService
->lpDisplayName
);
3172 if (lpDisplayName
!= NULL
&&
3173 *lpcchBuffer
> dwLength
)
3175 WideCharToMultiByte(CP_ACP
,
3177 lpService
->lpDisplayName
,
3178 wcslen(lpService
->lpDisplayName
),
3183 return ERROR_SUCCESS
;
3187 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3189 *lpcchBuffer
= dwLength
* 2;
3196 DWORD
RGetServiceKeyNameA(
3197 handle_t BindingHandle
,
3198 SC_RPC_HANDLE hSCManager
,
3199 LPSTR lpDisplayName
,
3200 LPSTR lpServiceName
,
3201 LPBOUNDED_DWORD_4K lpcchBuffer
)
3206 LPWSTR lpDisplayNameW
;
3208 DPRINT("RGetServiceKeyNameA() called\n");
3209 DPRINT("hSCManager = %p\n", hSCManager
);
3210 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3211 DPRINT("lpServiceName: %p\n", lpServiceName
);
3212 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3214 dwLength
= strlen(lpDisplayName
) + 1;
3215 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3217 dwLength
* sizeof(WCHAR
));
3218 if (!lpDisplayNameW
)
3219 return ERROR_NOT_ENOUGH_MEMORY
;
3221 MultiByteToWideChar(CP_ACP
,
3224 strlen(lpDisplayName
),
3228 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
3230 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3232 if (lpService
== NULL
)
3234 DPRINT1("Could not find the service!\n");
3236 /* If the service could not be found and lpcchBuffer is 0,
3237 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
3238 if (*lpcchBuffer
== 0)
3241 *lpServiceName
= '\0';
3244 return ERROR_SERVICE_DOES_NOT_EXIST
;
3247 dwLength
= wcslen(lpService
->lpServiceName
);
3248 if (lpService
!= NULL
&&
3249 *lpcchBuffer
> dwLength
)
3251 WideCharToMultiByte(CP_ACP
,
3253 lpService
->lpServiceName
,
3254 wcslen(lpService
->lpServiceName
),
3259 return ERROR_SUCCESS
;
3262 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3264 *lpcchBuffer
= dwLength
* 2;
3271 DWORD
RGetCurrentGroupStateW(
3272 handle_t BindingHandle
)
3275 return ERROR_CALL_NOT_IMPLEMENTED
;
3280 DWORD
REnumServiceGroupW(
3281 handle_t BindingHandle
,
3282 SC_RPC_HANDLE hSCManager
,
3283 DWORD dwServiceType
,
3284 DWORD dwServiceState
,