5 /* INCLUDES ****************************************************************/
18 /* GLOBALS *****************************************************************/
20 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
21 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
23 typedef struct _SCMGR_HANDLE
31 typedef struct _MANAGER_HANDLE
35 /* FIXME: Insert more data here */
37 WCHAR DatabaseName
[1];
38 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
41 typedef struct _SERVICE_HANDLE
46 PSERVICE ServiceEntry
;
48 /* FIXME: Insert more data here */
50 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
53 #define SC_MANAGER_READ \
54 (STANDARD_RIGHTS_READ | \
55 SC_MANAGER_QUERY_LOCK_STATUS | \
56 SC_MANAGER_ENUMERATE_SERVICE)
58 #define SC_MANAGER_WRITE \
59 (STANDARD_RIGHTS_WRITE | \
60 SC_MANAGER_MODIFY_BOOT_CONFIG | \
61 SC_MANAGER_CREATE_SERVICE)
63 #define SC_MANAGER_EXECUTE \
64 (STANDARD_RIGHTS_EXECUTE | \
66 SC_MANAGER_ENUMERATE_SERVICE | \
67 SC_MANAGER_CONNECT | \
68 SC_MANAGER_CREATE_SERVICE)
71 #define SERVICE_READ \
72 (STANDARD_RIGHTS_READ | \
73 SERVICE_INTERROGATE | \
74 SERVICE_ENUMERATE_DEPENDENTS | \
75 SERVICE_QUERY_STATUS | \
78 #define SERVICE_WRITE \
79 (STANDARD_RIGHTS_WRITE | \
80 SERVICE_CHANGE_CONFIG)
82 #define SERVICE_EXECUTE \
83 (STANDARD_RIGHTS_EXECUTE | \
84 SERVICE_USER_DEFINED_CONTROL | \
85 SERVICE_PAUSE_CONTINUE | \
90 /* VARIABLES ***************************************************************/
92 static GENERIC_MAPPING
93 ScmManagerMapping
= {SC_MANAGER_READ
,
96 SC_MANAGER_ALL_ACCESS
};
98 static GENERIC_MAPPING
99 ScmServiceMapping
= {SERVICE_READ
,
102 SC_MANAGER_ALL_ACCESS
};
105 /* FUNCTIONS ***************************************************************/
108 ScmStartRpcServer(VOID
)
112 DPRINT("ScmStartRpcServer() called");
114 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
118 if (Status
!= RPC_S_OK
)
120 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
124 Status
= RpcServerRegisterIf(svcctl_ServerIfHandle
,
127 if (Status
!= RPC_S_OK
)
129 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
133 Status
= RpcServerListen(1, 20, TRUE
);
134 if (Status
!= RPC_S_OK
)
136 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
140 DPRINT("ScmStartRpcServer() done");
145 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
150 if (lpDatabaseName
== NULL
)
151 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
153 Ptr
= HeapAlloc(GetProcessHeap(),
155 sizeof(MANAGER_HANDLE
) + wcslen(lpDatabaseName
) * sizeof(WCHAR
));
157 return ERROR_NOT_ENOUGH_MEMORY
;
159 Ptr
->Handle
.Tag
= MANAGER_TAG
;
160 Ptr
->Handle
.RefCount
= 1;
162 /* FIXME: initialize more data here */
164 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
166 *Handle
= (SC_HANDLE
)Ptr
;
168 return ERROR_SUCCESS
;
173 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
178 Ptr
= HeapAlloc(GetProcessHeap(),
180 sizeof(SERVICE_HANDLE
));
182 return ERROR_NOT_ENOUGH_MEMORY
;
184 Ptr
->Handle
.Tag
= SERVICE_TAG
;
185 Ptr
->Handle
.RefCount
= 1;
187 /* FIXME: initialize more data here */
188 Ptr
->ServiceEntry
= lpServiceEntry
;
190 *Handle
= (SC_HANDLE
)Ptr
;
192 return ERROR_SUCCESS
;
197 ScmCheckAccess(SC_HANDLE Handle
,
198 DWORD dwDesiredAccess
)
200 PMANAGER_HANDLE hMgr
;
202 hMgr
= (PMANAGER_HANDLE
)Handle
;
203 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
205 RtlMapGenericMask(&dwDesiredAccess
,
208 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
210 return ERROR_SUCCESS
;
212 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
214 RtlMapGenericMask(&dwDesiredAccess
,
217 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
219 return ERROR_SUCCESS
;
222 return ERROR_INVALID_HANDLE
;
228 ScmrCloseServiceHandle(handle_t BindingHandle
,
229 unsigned int hScObject
)
231 PMANAGER_HANDLE hManager
;
233 DPRINT("ScmrCloseServiceHandle() called\n");
235 DPRINT("hScObject = %X\n", hScObject
);
238 return ERROR_INVALID_HANDLE
;
240 hManager
= (PMANAGER_HANDLE
)hScObject
;
241 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
243 DPRINT("Found manager handle\n");
245 hManager
->Handle
.RefCount
--;
246 if (hManager
->Handle
.RefCount
== 0)
248 /* FIXME: add cleanup code */
250 HeapFree(GetProcessHeap(), 0, hManager
);
253 DPRINT("ScmrCloseServiceHandle() done\n");
254 return ERROR_SUCCESS
;
256 else if (hManager
->Handle
.Tag
== SERVICE_TAG
)
258 DPRINT("Found service handle\n");
260 hManager
->Handle
.RefCount
--;
261 if (hManager
->Handle
.RefCount
== 0)
263 /* FIXME: add cleanup code */
265 HeapFree(GetProcessHeap(), 0, hManager
);
268 DPRINT("ScmrCloseServiceHandle() done\n");
269 return ERROR_SUCCESS
;
272 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
274 return ERROR_INVALID_HANDLE
;
280 ScmrControlService(handle_t BindingHandle
,
281 unsigned int hService
,
282 unsigned long dwControl
,
283 LPSERVICE_STATUS lpServiceStatus
)
285 PSERVICE_HANDLE hSvc
;
288 DPRINT1("ScmrControlService() called\n");
290 hSvc
= (PSERVICE_HANDLE
)hService
;
291 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
293 DPRINT1("Invalid handle tag!\n");
294 return ERROR_INVALID_HANDLE
;
298 /* FIXME: Check access rights */
301 lpService
= hSvc
->ServiceEntry
;
302 if (lpService
== NULL
)
304 DPRINT1("lpService == NULL!\n");
305 return ERROR_INVALID_HANDLE
;
309 /* FIXME: Send control code to the service */
312 /* Return service status information */
313 lpServiceStatus
->dwServiceType
= lpService
->Type
;
314 lpServiceStatus
->dwCurrentState
= lpService
->CurrentState
;
315 lpServiceStatus
->dwControlsAccepted
= lpService
->ControlsAccepted
;
316 lpServiceStatus
->dwWin32ExitCode
= lpService
->Win32ExitCode
;
317 lpServiceStatus
->dwServiceSpecificExitCode
= lpService
->ServiceSpecificExitCode
;
318 lpServiceStatus
->dwCheckPoint
= lpService
->CheckPoint
;
319 lpServiceStatus
->dwWaitHint
= lpService
->WaitHint
;
321 return ERROR_SUCCESS
;
327 ScmrDeleteService(handle_t BindingHandle
,
328 unsigned int hService
)
330 PSERVICE_HANDLE hSvc
;
334 DPRINT1("ScmrDeleteService() called\n");
336 hSvc
= (PSERVICE_HANDLE
)hService
;
337 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
338 return ERROR_INVALID_HANDLE
;
340 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
341 STANDARD_RIGHTS_REQUIRED
))
342 return ERROR_ACCESS_DENIED
;
344 lpService
= hSvc
->ServiceEntry
;
345 if (lpService
== NULL
)
347 DPRINT1("lpService == NULL!\n");
348 return ERROR_INVALID_HANDLE
;
351 /* FIXME: Acquire service database lock exclusively */
353 /* Mark service for delete */
354 dwError
= ScmMarkServiceForDelete(lpService
);
356 /* FIXME: Release service database lock */
358 DPRINT1("ScmrDeleteService() done\n");
366 ScmrLockServiceDatabase(handle_t BindingHandle
,
367 unsigned int hSCManager
,
370 PMANAGER_HANDLE hMgr
;
372 DPRINT("ScmrLockServiceDatabase() called\n");
376 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
377 if (hMgr
->Handle
.Tag
!= MANAGER_TAG
)
378 return ERROR_INVALID_HANDLE
;
380 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
382 return ERROR_ACCESS_DENIED
;
384 /* FIXME: Lock the database */
385 *hLock
= 0x12345678; /* Dummy! */
387 return ERROR_SUCCESS
;
393 ScmrQueryServiceObjectSecurity(handle_t BindingHandle
)
395 DPRINT1("ScmrQueryServiceSecurity() is unimplemented\n");
396 return ERROR_CALL_NOT_IMPLEMENTED
;
402 ScmrSetServiceObjectSecurity(handle_t BindingHandle
)
404 DPRINT1("ScmrSetServiceSecurity() is unimplemented\n");
405 return ERROR_CALL_NOT_IMPLEMENTED
;
411 ScmrQueryServiceStatus(handle_t BindingHandle
,
412 unsigned int hService
,
413 LPSERVICE_STATUS lpServiceStatus
)
415 PSERVICE_HANDLE hSvc
;
418 DPRINT("ScmrQueryServiceStatus() called\n");
420 hSvc
= (PSERVICE_HANDLE
)hService
;
421 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
423 DPRINT1("Invalid handle tag!\n");
424 return ERROR_INVALID_HANDLE
;
427 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
428 SERVICE_QUERY_STATUS
))
430 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
431 return ERROR_ACCESS_DENIED
;
434 lpService
= hSvc
->ServiceEntry
;
435 if (lpService
== NULL
)
437 DPRINT1("lpService == NULL!\n");
438 return ERROR_INVALID_HANDLE
;
441 /* Return service status information */
442 lpServiceStatus
->dwServiceType
= lpService
->Type
;
443 lpServiceStatus
->dwCurrentState
= lpService
->CurrentState
;
444 lpServiceStatus
->dwControlsAccepted
= lpService
->ControlsAccepted
;
445 lpServiceStatus
->dwWin32ExitCode
= lpService
->Win32ExitCode
;
446 lpServiceStatus
->dwServiceSpecificExitCode
= lpService
->ServiceSpecificExitCode
;
447 lpServiceStatus
->dwCheckPoint
= lpService
->CheckPoint
;
448 lpServiceStatus
->dwWaitHint
= lpService
->WaitHint
;
450 return ERROR_SUCCESS
;
456 ScmrSetServiceStatus(handle_t BindingHandle
)
458 DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
460 return ERROR_CALL_NOT_IMPLEMENTED
;
466 ScmrUnlockServiceDatabase(handle_t BindingHandle
,
469 DPRINT1("ScmrUnlockServiceDatabase() called\n");
471 return ERROR_SUCCESS
;
477 ScmrNotifyBootConfigStatus(handle_t BindingHandle
,
478 unsigned long BootAcceptable
)
480 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
482 return ERROR_SUCCESS
;
488 CreateServiceKey(LPWSTR lpServiceName
, PHKEY phKey
)
490 HKEY hServicesKey
= NULL
;
496 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
497 L
"System\\CurrentControlSet\\Services",
501 if (dwError
!= ERROR_SUCCESS
)
504 dwError
= RegCreateKeyExW(hServicesKey
,
508 REG_OPTION_NON_VOLATILE
,
513 if ((dwError
== ERROR_SUCCESS
) &&
514 (dwDisposition
== REG_OPENED_EXISTING_KEY
))
518 dwError
= ERROR_SERVICE_EXISTS
;
521 RegCloseKey(hServicesKey
);
530 ScmrCreateServiceW(handle_t BindingHandle
,
531 unsigned int hSCManager
,
532 wchar_t *lpServiceName
,
533 wchar_t *lpDisplayName
,
534 unsigned long dwDesiredAccess
,
535 unsigned long dwServiceType
,
536 unsigned long dwStartType
,
537 unsigned long dwErrorControl
,
538 wchar_t *lpBinaryPathName
,
539 wchar_t *lpLoadOrderGroup
,
540 unsigned long *lpdwTagId
, /* in, out */
541 wchar_t *lpDependencies
,
542 unsigned long dwDependenciesLength
,
543 wchar_t *lpServiceStartName
,
545 unsigned long dwPasswordLength
,
546 unsigned int *hService
) /* out */
548 PMANAGER_HANDLE hManager
;
549 DWORD dwError
= ERROR_SUCCESS
;
551 HKEY hServiceKey
= NULL
;
552 LPWSTR lpImagePath
= NULL
;
555 DPRINT1("ScmrCreateServiceW() called\n");
556 DPRINT1("lpServiceName = %S\n", lpServiceName
);
557 DPRINT1("lpDisplayName = %S\n", lpDisplayName
);
558 DPRINT1("dwDesiredAccess = %lx\n", dwDesiredAccess
);
559 DPRINT1("dwServiceType = %lu\n", dwServiceType
);
560 DPRINT1("dwStartType = %lu\n", dwStartType
);
561 DPRINT1("dwErrorControl = %lu\n", dwErrorControl
);
562 DPRINT1("lpBinaryPathName = %S\n", lpBinaryPathName
);
563 DPRINT1("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
565 hManager
= (PMANAGER_HANDLE
)hSCManager
;
566 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
568 DPRINT1("Invalid manager handle!\n");
569 return ERROR_INVALID_HANDLE
;
572 /* Check access rights */
573 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
574 SC_MANAGER_CREATE_SERVICE
))
576 DPRINT1("Insufficient access rights! 0x%lx\n",
577 hManager
->Handle
.DesiredAccess
);
578 return ERROR_ACCESS_DENIED
;
581 /* FIXME: Fail if the service already exists! */
584 if (dwServiceType
& SERVICE_DRIVER
)
586 /* FIXME: Adjust the image path */
587 lpImagePath
= HeapAlloc(GetProcessHeap(),
589 wcslen(lpBinaryPathName
) + sizeof(WCHAR
));
590 if (lpImagePath
== NULL
)
592 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
595 wcscpy(lpImagePath
, lpBinaryPathName
);
598 /* FIXME: Allocate and fill a service entry */
600 // if (lpdwTagId != NULL)
606 /* Write service data to the registry */
607 /* Create the service key */
608 dwError
= CreateServiceKey(lpServiceName
, &hServiceKey
);
609 if (dwError
!= ERROR_SUCCESS
)
612 if ((lpDisplayName
!= NULL
) && (wcslen(lpDisplayName
) > 0))
614 RegSetValueExW(hServiceKey
,
618 (LPBYTE
)lpDisplayName
,
619 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
622 /* Set the service type */
623 dwError
= RegSetValueExW(hServiceKey
,
627 (LPBYTE
)&dwServiceType
,
629 if (dwError
!= ERROR_SUCCESS
)
632 /* Set the start value */
633 dwError
= RegSetValueExW(hServiceKey
,
637 (LPBYTE
)&dwStartType
,
639 if (dwError
!= ERROR_SUCCESS
)
642 /* Set the error control value */
643 dwError
= RegSetValueExW(hServiceKey
,
647 (LPBYTE
)&dwErrorControl
,
649 if (dwError
!= ERROR_SUCCESS
)
652 /* Set the image path */
653 if (dwServiceType
& SERVICE_WIN32
)
655 dwError
= RegSetValueExW(hServiceKey
,
659 (LPBYTE
)lpBinaryPathName
,
660 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
661 if (dwError
!= ERROR_SUCCESS
)
664 else if (dwServiceType
& SERVICE_DRIVER
)
666 /* FIXME: Adjust the path name */
667 dwError
= RegSetValueExW(hServiceKey
,
672 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
673 if (dwError
!= ERROR_SUCCESS
)
677 /* Set the group name */
678 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
680 dwError
= RegSetValueExW(hServiceKey
,
684 (LPBYTE
)lpLoadOrderGroup
,
685 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
686 if (dwError
!= ERROR_SUCCESS
)
691 if (hServiceKey
!= NULL
)
692 RegCloseKey(hServiceKey
);
694 if (lpImagePath
!= NULL
)
695 HeapFree(GetProcessHeap(), 0, lpImagePath
);
698 DPRINT1("ScmrCreateServiceW() done (Error %lu)\n", dwError
);
706 ScmrOpenSCManagerW(handle_t BindingHandle
,
707 wchar_t *lpMachineName
,
708 wchar_t *lpDatabaseName
,
709 unsigned long dwDesiredAccess
,
715 DPRINT("ScmrOpenSCManagerW() called\n");
716 DPRINT("lpMachineName = %p\n", lpMachineName
);
717 DPRINT("lpMachineName: %S\n", lpMachineName
);
718 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
719 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
720 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
722 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
724 if (dwError
!= ERROR_SUCCESS
)
726 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
730 /* Check the desired access */
731 dwError
= ScmCheckAccess(hHandle
,
732 dwDesiredAccess
| SC_MANAGER_CONNECT
);
733 if (dwError
!= ERROR_SUCCESS
)
735 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
736 HeapFree(GetProcessHeap(), 0, hHandle
);
740 *hScm
= (unsigned int)hHandle
;
741 DPRINT("*hScm = %x\n", *hScm
);
743 DPRINT("ScmrOpenSCManagerW() done\n");
745 return ERROR_SUCCESS
;
751 ScmrOpenServiceW(handle_t BindingHandle
,
752 unsigned int hSCManager
,
753 wchar_t *lpServiceName
,
754 unsigned long dwDesiredAccess
,
755 unsigned int *hService
)
757 UNICODE_STRING ServiceName
;
759 PMANAGER_HANDLE hManager
;
763 DPRINT("ScmrOpenServiceW() called\n");
764 DPRINT("hSCManager = %x\n", hSCManager
);
765 DPRINT("lpServiceName = %p\n", lpServiceName
);
766 DPRINT("lpServiceName: %S\n", lpServiceName
);
767 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
769 hManager
= (PMANAGER_HANDLE
)hSCManager
;
770 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
772 DPRINT1("Invalid manager handle!\n");
773 return ERROR_INVALID_HANDLE
;
776 /* FIXME: Lock the service list */
778 /* Get service database entry */
779 RtlInitUnicodeString(&ServiceName
,
782 lpService
= ScmGetServiceEntryByName(&ServiceName
);
783 if (lpService
== NULL
)
785 DPRINT1("Could not find a service!\n");
786 return ERROR_SERVICE_DOES_NOT_EXIST
;
789 /* Create a service handle */
790 dwError
= ScmCreateServiceHandle(lpService
,
792 if (dwError
!= ERROR_SUCCESS
)
794 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
798 /* Check the desired access */
799 dwError
= ScmCheckAccess(hHandle
,
801 if (dwError
!= ERROR_SUCCESS
)
803 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
804 HeapFree(GetProcessHeap(), 0, hHandle
);
808 *hService
= (unsigned int)hHandle
;
809 DPRINT("*hService = %x\n", *hService
);
811 DPRINT("ScmrOpenServiceW() done\n");
813 return ERROR_SUCCESS
;
820 ScmrOpenSCManagerA(handle_t BindingHandle
,
822 char *lpDatabaseName
,
823 unsigned long dwDesiredAccess
,
826 UNICODE_STRING MachineName
;
827 UNICODE_STRING DatabaseName
;
830 DPRINT("ScmrOpenSCManagerA() called\n");
833 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
837 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
840 dwError
= ScmrOpenSCManagerW(BindingHandle
,
841 lpMachineName
? MachineName
.Buffer
: NULL
,
842 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
847 RtlFreeUnicodeString(&MachineName
);
850 RtlFreeUnicodeString(&DatabaseName
);
858 ScmrOpenServiceA(handle_t BindingHandle
,
859 unsigned int hSCManager
,
861 unsigned long dwDesiredAccess
,
862 unsigned int *hService
)
864 UNICODE_STRING ServiceName
;
867 DPRINT("ScmrOpenServiceA() called\n");
869 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
872 dwError
= ScmrOpenServiceW(BindingHandle
,
878 RtlFreeUnicodeString(&ServiceName
);
885 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
887 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
891 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
893 HeapFree(GetProcessHeap(), 0, ptr
);