022864bba93df43dea284892f937305ad6b4655d
[reactos.git] / dll / win32 / advapi32 / service / scm.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/service/scm.c
5 * PURPOSE: Service control manager functions
6 * PROGRAMMER: Emanuele Aliberti
7 * Eric Kohl
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <advapi32.h>
13 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
14
15
16 /* FUNCTIONS *****************************************************************/
17
18 handle_t __RPC_USER
19 SVCCTL_HANDLEA_bind(SVCCTL_HANDLEA szMachineName)
20 {
21 handle_t hBinding = NULL;
22 RPC_CSTR pszStringBinding;
23 RPC_STATUS status;
24
25 TRACE("SVCCTL_HANDLEA_bind(%s)\n",
26 debugstr_a(szMachineName));
27
28 status = RpcStringBindingComposeA(NULL,
29 (RPC_CSTR)"ncacn_np",
30 (RPC_CSTR)szMachineName,
31 (RPC_CSTR)"\\pipe\\ntsvcs",
32 NULL,
33 &pszStringBinding);
34 if (status != RPC_S_OK)
35 {
36 ERR("RpcStringBindingCompose returned 0x%x\n", status);
37 return NULL;
38 }
39
40 /* Set the binding handle that will be used to bind to the server. */
41 status = RpcBindingFromStringBindingA(pszStringBinding,
42 &hBinding);
43 if (status != RPC_S_OK)
44 {
45 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
46 }
47
48 status = RpcStringFreeA(&pszStringBinding);
49 if (status != RPC_S_OK)
50 {
51 ERR("RpcStringFree returned 0x%x\n", status);
52 }
53
54 return hBinding;
55 }
56
57
58 void __RPC_USER
59 SVCCTL_HANDLEA_unbind(SVCCTL_HANDLEA szMachineName,
60 handle_t hBinding)
61 {
62 RPC_STATUS status;
63
64 TRACE("SVCCTL_HANDLEA_unbind(%s %p)\n",
65 debugstr_a(szMachineName), hBinding);
66
67 status = RpcBindingFree(&hBinding);
68 if (status != RPC_S_OK)
69 {
70 ERR("RpcBindingFree returned 0x%x\n", status);
71 }
72 }
73
74
75 handle_t __RPC_USER
76 SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW szMachineName)
77 {
78 handle_t hBinding = NULL;
79 RPC_WSTR pszStringBinding;
80 RPC_STATUS status;
81
82 TRACE("SVCCTL_HANDLEW_bind(%s)\n",
83 debugstr_w(szMachineName));
84
85 status = RpcStringBindingComposeW(NULL,
86 L"ncacn_np",
87 szMachineName,
88 L"\\pipe\\ntsvcs",
89 NULL,
90 &pszStringBinding);
91 if (status != RPC_S_OK)
92 {
93 ERR("RpcStringBindingCompose returned 0x%x\n", status);
94 return NULL;
95 }
96
97 /* Set the binding handle that will be used to bind to the server. */
98 status = RpcBindingFromStringBindingW(pszStringBinding,
99 &hBinding);
100 if (status != RPC_S_OK)
101 {
102 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
103 }
104
105 status = RpcStringFreeW(&pszStringBinding);
106 if (status != RPC_S_OK)
107 {
108 ERR("RpcStringFree returned 0x%x\n", status);
109 }
110
111 return hBinding;
112 }
113
114
115 void __RPC_USER
116 SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
117 handle_t hBinding)
118 {
119 RPC_STATUS status;
120
121 TRACE("SVCCTL_HANDLEW_unbind(%s %p)\n",
122 debugstr_w(szMachineName), hBinding);
123
124 status = RpcBindingFree(&hBinding);
125 if (status != RPC_S_OK)
126 {
127 ERR("RpcBindingFree returned 0x%x\n", status);
128 }
129 }
130
131
132 DWORD
133 ScmRpcStatusToWinError(RPC_STATUS Status)
134 {
135 TRACE("ScmRpcStatusToWinError(%lx)\n",
136 Status);
137
138 switch (Status)
139 {
140 case STATUS_ACCESS_VIOLATION:
141 case RPC_S_INVALID_BINDING:
142 case RPC_X_SS_IN_NULL_CONTEXT:
143 return ERROR_INVALID_HANDLE;
144
145 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
146 case RPC_X_BYTE_COUNT_TOO_SMALL:
147 return ERROR_INVALID_PARAMETER;
148
149 case RPC_X_NULL_REF_POINTER:
150 return ERROR_INVALID_ADDRESS;
151
152 default:
153 return (DWORD)Status;
154 }
155 }
156
157
158 static
159 DWORD
160 ScmEncryptPassword(
161 _In_ PCWSTR pClearTextPassword,
162 _Out_ PBYTE *pEncryptedPassword,
163 _Out_ PDWORD pEncryptedPasswordSize)
164 {
165 DWORD dwSize;
166 PBYTE pBuffer;
167
168 dwSize = (wcslen(pClearTextPassword) + 1) * sizeof(WCHAR);
169
170 pBuffer = HeapAlloc(GetProcessHeap(), 0, dwSize);
171 if (pBuffer == NULL)
172 return ERROR_OUTOFMEMORY;
173
174 CopyMemory(pBuffer,
175 pClearTextPassword,
176 dwSize);
177
178 *pEncryptedPassword = pBuffer;
179 *pEncryptedPasswordSize = dwSize;
180
181 return ERROR_SUCCESS;
182 }
183
184
185 /**********************************************************************
186 * ChangeServiceConfig2A
187 *
188 * @implemented
189 */
190 BOOL WINAPI
191 ChangeServiceConfig2A(SC_HANDLE hService,
192 DWORD dwInfoLevel,
193 LPVOID lpInfo)
194 {
195 SC_RPC_CONFIG_INFOA Info;
196 DWORD dwError;
197
198 TRACE("ChangeServiceConfig2A(%p %lu %p)\n",
199 hService, dwInfoLevel, lpInfo);
200
201 if (lpInfo == NULL) return TRUE;
202
203 /* Fill relevant field of the Info structure */
204 Info.dwInfoLevel = dwInfoLevel;
205 switch (dwInfoLevel)
206 {
207 case SERVICE_CONFIG_DESCRIPTION:
208 Info.psd = lpInfo;
209 break;
210
211 case SERVICE_CONFIG_FAILURE_ACTIONS:
212 Info.psfa = lpInfo;
213 break;
214
215 default:
216 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
217 SetLastError(ERROR_INVALID_PARAMETER);
218 return FALSE;
219 }
220
221 RpcTryExcept
222 {
223 dwError = RChangeServiceConfig2A((SC_RPC_HANDLE)hService,
224 Info);
225 }
226 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
227 {
228 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
229 }
230 RpcEndExcept;
231
232 if (dwError != ERROR_SUCCESS)
233 {
234 TRACE("RChangeServiceConfig2A() failed (Error %lu)\n", dwError);
235 SetLastError(dwError);
236 return FALSE;
237 }
238
239 return TRUE;
240 }
241
242
243 /**********************************************************************
244 * ChangeServiceConfig2W
245 *
246 * @implemented
247 */
248 BOOL WINAPI
249 ChangeServiceConfig2W(SC_HANDLE hService,
250 DWORD dwInfoLevel,
251 LPVOID lpInfo)
252 {
253 SC_RPC_CONFIG_INFOW Info;
254 DWORD dwError;
255
256 TRACE("ChangeServiceConfig2W(%p %lu %p)\n",
257 hService, dwInfoLevel, lpInfo);
258
259 if (lpInfo == NULL) return TRUE;
260
261 /* Fill relevant field of the Info structure */
262 Info.dwInfoLevel = dwInfoLevel;
263 switch (dwInfoLevel)
264 {
265 case SERVICE_CONFIG_DESCRIPTION:
266 Info.psd = lpInfo;
267 break;
268
269 case SERVICE_CONFIG_FAILURE_ACTIONS:
270 Info.psfa = lpInfo;
271 break;
272
273 default:
274 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
275 SetLastError(ERROR_INVALID_PARAMETER);
276 return FALSE;
277 }
278
279 RpcTryExcept
280 {
281 dwError = RChangeServiceConfig2W((SC_RPC_HANDLE)hService,
282 Info);
283 }
284 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
285 {
286 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
287 }
288 RpcEndExcept;
289
290 if (dwError != ERROR_SUCCESS)
291 {
292 TRACE("RChangeServiceConfig2W() failed (Error %lu)\n", dwError);
293 SetLastError(dwError);
294 return FALSE;
295 }
296
297 return TRUE;
298 }
299
300
301 /**********************************************************************
302 * ChangeServiceConfigA
303 *
304 * @implemented
305 */
306 BOOL WINAPI
307 ChangeServiceConfigA(SC_HANDLE hService,
308 DWORD dwServiceType,
309 DWORD dwStartType,
310 DWORD dwErrorControl,
311 LPCSTR lpBinaryPathName,
312 LPCSTR lpLoadOrderGroup,
313 LPDWORD lpdwTagId,
314 LPCSTR lpDependencies,
315 LPCSTR lpServiceStartName,
316 LPCSTR lpPassword,
317 LPCSTR lpDisplayName)
318 {
319 DWORD dwError;
320 DWORD dwDependenciesLength = 0;
321 SIZE_T cchLength;
322 LPCSTR lpStr;
323 DWORD dwPasswordSize = 0;
324 LPWSTR lpPasswordW = NULL;
325 LPBYTE lpEncryptedPassword = NULL;
326
327 TRACE("ChangeServiceConfigA(%p %lu %lu %lu %s %s %p %s %s %s %s)\n",
328 hService, dwServiceType, dwStartType, dwErrorControl, debugstr_a(lpBinaryPathName),
329 debugstr_a(lpLoadOrderGroup), lpdwTagId, debugstr_a(lpDependencies),
330 debugstr_a(lpServiceStartName), debugstr_a(lpPassword), debugstr_a(lpDisplayName));
331
332 /* Calculate the Dependencies length*/
333 if (lpDependencies != NULL)
334 {
335 lpStr = lpDependencies;
336 while (*lpStr)
337 {
338 cchLength = strlen(lpStr) + 1;
339 dwDependenciesLength += (DWORD)cchLength;
340 lpStr = lpStr + cchLength;
341 }
342 dwDependenciesLength++;
343 }
344
345 if (lpPassword != NULL)
346 {
347 /* Convert the password to unicode */
348 lpPasswordW = HeapAlloc(GetProcessHeap(),
349 HEAP_ZERO_MEMORY,
350 (strlen(lpPassword) + 1) * sizeof(WCHAR));
351 if (lpPasswordW == NULL)
352 {
353 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
354 return FALSE;
355 }
356
357 MultiByteToWideChar(CP_ACP,
358 0,
359 lpPassword,
360 -1,
361 lpPasswordW,
362 (int)(strlen(lpPassword) + 1));
363
364 /* Encrypt the unicode password */
365 dwError = ScmEncryptPassword(lpPasswordW,
366 &lpEncryptedPassword,
367 &dwPasswordSize);
368 if (dwError != ERROR_SUCCESS)
369 goto done;
370 }
371
372 RpcTryExcept
373 {
374 dwError = RChangeServiceConfigA((SC_RPC_HANDLE)hService,
375 dwServiceType,
376 dwStartType,
377 dwErrorControl,
378 (LPSTR)lpBinaryPathName,
379 (LPSTR)lpLoadOrderGroup,
380 lpdwTagId,
381 (LPBYTE)lpDependencies,
382 dwDependenciesLength,
383 (LPSTR)lpServiceStartName,
384 lpEncryptedPassword,
385 dwPasswordSize,
386 (LPSTR)lpDisplayName);
387 }
388 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
389 {
390 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
391 }
392 RpcEndExcept;
393
394 done:
395 if (lpPasswordW != NULL)
396 {
397 /* Wipe and release the password buffers */
398 ZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR));
399 HeapFree(GetProcessHeap(), 0, lpPasswordW);
400
401 if (lpEncryptedPassword != NULL)
402 {
403 ZeroMemory(lpEncryptedPassword, dwPasswordSize);
404 HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
405 }
406 }
407
408 if (dwError != ERROR_SUCCESS)
409 {
410 TRACE("RChangeServiceConfigA() failed (Error %lu)\n", dwError);
411 SetLastError(dwError);
412 return FALSE;
413 }
414
415 return TRUE;
416 }
417
418
419 /**********************************************************************
420 * ChangeServiceConfigW
421 *
422 * @implemented
423 */
424 BOOL WINAPI
425 ChangeServiceConfigW(SC_HANDLE hService,
426 DWORD dwServiceType,
427 DWORD dwStartType,
428 DWORD dwErrorControl,
429 LPCWSTR lpBinaryPathName,
430 LPCWSTR lpLoadOrderGroup,
431 LPDWORD lpdwTagId,
432 LPCWSTR lpDependencies,
433 LPCWSTR lpServiceStartName,
434 LPCWSTR lpPassword,
435 LPCWSTR lpDisplayName)
436 {
437 DWORD dwError;
438 DWORD dwDependenciesLength = 0;
439 SIZE_T cchLength;
440 LPCWSTR lpStr;
441 DWORD dwPasswordSize = 0;
442 LPBYTE lpEncryptedPassword = NULL;
443
444 TRACE("ChangeServiceConfigW(%p %lu %lu %lu %s %s %p %s %s %s %s)\n",
445 hService, dwServiceType, dwStartType, dwErrorControl, debugstr_w(lpBinaryPathName),
446 debugstr_w(lpLoadOrderGroup), lpdwTagId, debugstr_w(lpDependencies),
447 debugstr_w(lpServiceStartName), debugstr_w(lpPassword), debugstr_w(lpDisplayName));
448
449 /* Calculate the Dependencies length*/
450 if (lpDependencies != NULL)
451 {
452 lpStr = lpDependencies;
453 while (*lpStr)
454 {
455 cchLength = wcslen(lpStr) + 1;
456 dwDependenciesLength += (DWORD)cchLength;
457 lpStr = lpStr + cchLength;
458 }
459 dwDependenciesLength++;
460 dwDependenciesLength *= sizeof(WCHAR);
461 }
462
463 if (lpPassword != NULL)
464 {
465 dwError = ScmEncryptPassword(lpPassword,
466 &lpEncryptedPassword,
467 &dwPasswordSize);
468 if (dwError != ERROR_SUCCESS)
469 {
470 ERR("ScmEncryptPassword failed (Error %lu)\n", dwError);
471 goto done;
472 }
473 }
474
475 RpcTryExcept
476 {
477 dwError = RChangeServiceConfigW((SC_RPC_HANDLE)hService,
478 dwServiceType,
479 dwStartType,
480 dwErrorControl,
481 (LPWSTR)lpBinaryPathName,
482 (LPWSTR)lpLoadOrderGroup,
483 lpdwTagId,
484 (LPBYTE)lpDependencies,
485 dwDependenciesLength,
486 (LPWSTR)lpServiceStartName,
487 lpEncryptedPassword,
488 dwPasswordSize,
489 (LPWSTR)lpDisplayName);
490 }
491 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
492 {
493 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
494 }
495 RpcEndExcept;
496
497 done:
498 if (lpEncryptedPassword != NULL)
499 {
500 /* Wipe and release the password buffer */
501 ZeroMemory(lpEncryptedPassword, dwPasswordSize);
502 HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
503 }
504
505 if (dwError != ERROR_SUCCESS)
506 {
507 TRACE("RChangeServiceConfigW() failed (Error %lu)\n", dwError);
508 SetLastError(dwError);
509 return FALSE;
510 }
511
512 return TRUE;
513 }
514
515
516 /**********************************************************************
517 * CloseServiceHandle
518 *
519 * @implemented
520 */
521 BOOL WINAPI
522 CloseServiceHandle(SC_HANDLE hSCObject)
523 {
524 DWORD dwError;
525
526 TRACE("CloseServiceHandle(%p)\n",
527 hSCObject);
528
529 if (!hSCObject)
530 {
531 SetLastError(ERROR_INVALID_HANDLE);
532 return FALSE;
533 }
534
535 RpcTryExcept
536 {
537 dwError = RCloseServiceHandle((LPSC_RPC_HANDLE)&hSCObject);
538 }
539 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
540 {
541 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
542 }
543 RpcEndExcept;
544
545 if (dwError)
546 {
547 TRACE("RCloseServiceHandle() failed (Error %lu)\n", dwError);
548 SetLastError(dwError);
549 return FALSE;
550 }
551
552 TRACE("CloseServiceHandle() done\n");
553
554 return TRUE;
555 }
556
557
558 /**********************************************************************
559 * ControlService
560 *
561 * @implemented
562 */
563 BOOL WINAPI
564 ControlService(SC_HANDLE hService,
565 DWORD dwControl,
566 LPSERVICE_STATUS lpServiceStatus)
567 {
568 DWORD dwError;
569
570 TRACE("ControlService(%p %lu %p)\n",
571 hService, dwControl, lpServiceStatus);
572
573 RpcTryExcept
574 {
575 dwError = RControlService((SC_RPC_HANDLE)hService,
576 dwControl,
577 lpServiceStatus);
578 }
579 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
580 {
581 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
582 }
583 RpcEndExcept;
584
585 if (dwError != ERROR_SUCCESS)
586 {
587 TRACE("RControlService() failed (Error %lu)\n", dwError);
588 SetLastError(dwError);
589 return FALSE;
590 }
591
592 TRACE("ControlService() done\n");
593
594 return TRUE;
595 }
596
597
598 /**********************************************************************
599 * ControlServiceEx
600 *
601 * @unimplemented
602 */
603 BOOL WINAPI
604 ControlServiceEx(IN SC_HANDLE hService,
605 IN DWORD dwControl,
606 IN DWORD dwInfoLevel,
607 IN OUT PVOID pControlParams)
608 {
609 FIXME("ControlServiceEx(%p %lu %lu %p)\n",
610 hService, dwControl, dwInfoLevel, pControlParams);
611 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
612 return FALSE;
613 }
614
615
616 /**********************************************************************
617 * CreateServiceA
618 *
619 * @implemented
620 */
621 SC_HANDLE WINAPI
622 CreateServiceA(SC_HANDLE hSCManager,
623 LPCSTR lpServiceName,
624 LPCSTR lpDisplayName,
625 DWORD dwDesiredAccess,
626 DWORD dwServiceType,
627 DWORD dwStartType,
628 DWORD dwErrorControl,
629 LPCSTR lpBinaryPathName,
630 LPCSTR lpLoadOrderGroup,
631 LPDWORD lpdwTagId,
632 LPCSTR lpDependencies,
633 LPCSTR lpServiceStartName,
634 LPCSTR lpPassword)
635 {
636 SC_HANDLE hService = NULL;
637 DWORD dwDependenciesLength = 0;
638 DWORD dwError;
639 SIZE_T cchLength;
640 LPCSTR lpStr;
641 DWORD dwPasswordSize = 0;
642 LPWSTR lpPasswordW = NULL;
643 LPBYTE lpEncryptedPassword = NULL;
644
645 TRACE("CreateServiceA(%p %s %s %lx %lu %lu %lu %s %s %p %s %s %s)\n",
646 hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName),
647 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
648 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup), lpdwTagId,
649 debugstr_a(lpDependencies), debugstr_a(lpServiceStartName), debugstr_a(lpPassword));
650
651 if (!hSCManager)
652 {
653 SetLastError(ERROR_INVALID_HANDLE);
654 return NULL;
655 }
656
657 /* Calculate the Dependencies length */
658 if (lpDependencies != NULL)
659 {
660 lpStr = lpDependencies;
661 while (*lpStr)
662 {
663 cchLength = strlen(lpStr) + 1;
664 dwDependenciesLength += (DWORD)cchLength;
665 lpStr = lpStr + cchLength;
666 }
667 dwDependenciesLength++;
668 }
669
670 if (lpPassword != NULL)
671 {
672 /* Convert the password to unicode */
673 lpPasswordW = HeapAlloc(GetProcessHeap(),
674 HEAP_ZERO_MEMORY,
675 (strlen(lpPassword) + 1) * sizeof(WCHAR));
676 if (lpPasswordW == NULL)
677 {
678 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
679 return FALSE;
680 }
681
682 MultiByteToWideChar(CP_ACP,
683 0,
684 lpPassword,
685 -1,
686 lpPasswordW,
687 (int)(strlen(lpPassword) + 1));
688
689 /* Encrypt the password */
690 dwError = ScmEncryptPassword(lpPasswordW,
691 &lpEncryptedPassword,
692 &dwPasswordSize);
693 if (dwError != ERROR_SUCCESS)
694 goto done;
695 }
696
697 RpcTryExcept
698 {
699 dwError = RCreateServiceA((SC_RPC_HANDLE)hSCManager,
700 (LPSTR)lpServiceName,
701 (LPSTR)lpDisplayName,
702 dwDesiredAccess,
703 dwServiceType,
704 dwStartType,
705 dwErrorControl,
706 (LPSTR)lpBinaryPathName,
707 (LPSTR)lpLoadOrderGroup,
708 lpdwTagId,
709 (LPBYTE)lpDependencies,
710 dwDependenciesLength,
711 (LPSTR)lpServiceStartName,
712 lpEncryptedPassword,
713 dwPasswordSize,
714 (SC_RPC_HANDLE *)&hService);
715 }
716 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
717 {
718 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
719 }
720 RpcEndExcept;
721
722 done:
723 if (lpPasswordW != NULL)
724 {
725 /* Wipe and release the password buffers */
726 ZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR));
727 HeapFree(GetProcessHeap(), 0, lpPasswordW);
728
729 if (lpEncryptedPassword != NULL)
730 {
731 ZeroMemory(lpEncryptedPassword, dwPasswordSize);
732 HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
733 }
734 }
735
736 SetLastError(dwError);
737 if (dwError != ERROR_SUCCESS)
738 {
739 TRACE("RCreateServiceA() failed (Error %lu)\n", dwError);
740 return NULL;
741 }
742
743 return hService;
744 }
745
746
747 /**********************************************************************
748 * CreateServiceW
749 *
750 * @implemented
751 */
752 SC_HANDLE WINAPI
753 CreateServiceW(SC_HANDLE hSCManager,
754 LPCWSTR lpServiceName,
755 LPCWSTR lpDisplayName,
756 DWORD dwDesiredAccess,
757 DWORD dwServiceType,
758 DWORD dwStartType,
759 DWORD dwErrorControl,
760 LPCWSTR lpBinaryPathName,
761 LPCWSTR lpLoadOrderGroup,
762 LPDWORD lpdwTagId,
763 LPCWSTR lpDependencies,
764 LPCWSTR lpServiceStartName,
765 LPCWSTR lpPassword)
766 {
767 SC_HANDLE hService = NULL;
768 DWORD dwDependenciesLength = 0;
769 DWORD dwError;
770 SIZE_T cchLength;
771 LPCWSTR lpStr;
772 DWORD dwPasswordSize = 0;
773 LPBYTE lpEncryptedPassword = NULL;
774
775 TRACE("CreateServiceW(%p %s %s %lx %lu %lu %lu %s %s %p %s %s %s)\n",
776 hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName),
777 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
778 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup), lpdwTagId,
779 debugstr_w(lpDependencies), debugstr_w(lpServiceStartName), debugstr_w(lpPassword));
780
781 if (!hSCManager)
782 {
783 SetLastError(ERROR_INVALID_HANDLE);
784 return NULL;
785 }
786
787 /* Calculate the Dependencies length */
788 if (lpDependencies != NULL)
789 {
790 lpStr = lpDependencies;
791 while (*lpStr)
792 {
793 cchLength = wcslen(lpStr) + 1;
794 dwDependenciesLength += (DWORD)cchLength;
795 lpStr = lpStr + cchLength;
796 }
797 dwDependenciesLength++;
798 dwDependenciesLength *= sizeof(WCHAR);
799 }
800
801 if (lpPassword != NULL)
802 {
803 /* Encrypt the password */
804 dwError = ScmEncryptPassword(lpPassword,
805 &lpEncryptedPassword,
806 &dwPasswordSize);
807 if (dwError != ERROR_SUCCESS)
808 goto done;
809 }
810
811 RpcTryExcept
812 {
813 dwError = RCreateServiceW((SC_RPC_HANDLE)hSCManager,
814 lpServiceName,
815 lpDisplayName,
816 dwDesiredAccess,
817 dwServiceType,
818 dwStartType,
819 dwErrorControl,
820 lpBinaryPathName,
821 lpLoadOrderGroup,
822 lpdwTagId,
823 (LPBYTE)lpDependencies,
824 dwDependenciesLength,
825 lpServiceStartName,
826 lpEncryptedPassword,
827 dwPasswordSize,
828 (SC_RPC_HANDLE *)&hService);
829 }
830 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
831 {
832 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
833 }
834 RpcEndExcept;
835
836 done:
837 if (lpEncryptedPassword != NULL)
838 {
839 /* Wipe and release the password buffers */
840 ZeroMemory(lpEncryptedPassword, dwPasswordSize);
841 HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
842 }
843
844 SetLastError(dwError);
845 if (dwError != ERROR_SUCCESS)
846 {
847 TRACE("RCreateServiceW() failed (Error %lu)\n", dwError);
848 return NULL;
849 }
850
851 return hService;
852 }
853
854
855 /**********************************************************************
856 * DeleteService
857 *
858 * @implemented
859 */
860 BOOL WINAPI
861 DeleteService(SC_HANDLE hService)
862 {
863 DWORD dwError;
864
865 TRACE("DeleteService(%p)\n",
866 hService);
867
868 RpcTryExcept
869 {
870 dwError = RDeleteService((SC_RPC_HANDLE)hService);
871 }
872 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
873 {
874 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
875 }
876 RpcEndExcept;
877
878 if (dwError != ERROR_SUCCESS)
879 {
880 TRACE("RDeleteService() failed (Error %lu)\n", dwError);
881 SetLastError(dwError);
882 return FALSE;
883 }
884
885 return TRUE;
886 }
887
888
889 /**********************************************************************
890 * EnumDependentServicesA
891 *
892 * @implemented
893 */
894 BOOL WINAPI
895 EnumDependentServicesA(SC_HANDLE hService,
896 DWORD dwServiceState,
897 LPENUM_SERVICE_STATUSA lpServices,
898 DWORD cbBufSize,
899 LPDWORD pcbBytesNeeded,
900 LPDWORD lpServicesReturned)
901 {
902 ENUM_SERVICE_STATUSA ServiceStatus;
903 LPENUM_SERVICE_STATUSA lpStatusPtr;
904 DWORD dwBufferSize;
905 DWORD dwError;
906 DWORD dwCount;
907
908 TRACE("EnumDependentServicesA(%p %lu %p %lu %p %p)\n",
909 hService, dwServiceState, lpServices, cbBufSize,
910 pcbBytesNeeded, lpServicesReturned);
911
912 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSA))
913 {
914 lpStatusPtr = &ServiceStatus;
915 dwBufferSize = sizeof(ENUM_SERVICE_STATUSA);
916 }
917 else
918 {
919 lpStatusPtr = lpServices;
920 dwBufferSize = cbBufSize;
921 }
922
923 RpcTryExcept
924 {
925 dwError = REnumDependentServicesA((SC_RPC_HANDLE)hService,
926 dwServiceState,
927 (LPBYTE)lpStatusPtr,
928 dwBufferSize,
929 pcbBytesNeeded,
930 lpServicesReturned);
931 }
932 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
933 {
934 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
935 }
936 RpcEndExcept;
937
938 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
939 {
940 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
941 {
942 if (lpStatusPtr->lpServiceName)
943 lpStatusPtr->lpServiceName =
944 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
945
946 if (lpStatusPtr->lpDisplayName)
947 lpStatusPtr->lpDisplayName =
948 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
949
950 lpStatusPtr++;
951 }
952 }
953
954 if (dwError != ERROR_SUCCESS)
955 {
956 TRACE("REnumDependentServicesA() failed (Error %lu)\n", dwError);
957 SetLastError(dwError);
958 return FALSE;
959 }
960
961 TRACE("EnumDependentServicesA() done\n");
962
963 return TRUE;
964 }
965
966
967 /**********************************************************************
968 * EnumDependentServicesW
969 *
970 * @implemented
971 */
972 BOOL WINAPI
973 EnumDependentServicesW(SC_HANDLE hService,
974 DWORD dwServiceState,
975 LPENUM_SERVICE_STATUSW lpServices,
976 DWORD cbBufSize,
977 LPDWORD pcbBytesNeeded,
978 LPDWORD lpServicesReturned)
979 {
980 ENUM_SERVICE_STATUSW ServiceStatus;
981 LPENUM_SERVICE_STATUSW lpStatusPtr;
982 DWORD dwBufferSize;
983 DWORD dwError;
984 DWORD dwCount;
985
986 TRACE("EnumDependentServicesW(%p %lu %p %lu %p %p)\n",
987 hService, dwServiceState, lpServices, cbBufSize,
988 pcbBytesNeeded, lpServicesReturned);
989
990 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
991 {
992 lpStatusPtr = &ServiceStatus;
993 dwBufferSize = sizeof(ENUM_SERVICE_STATUSW);
994 }
995 else
996 {
997 lpStatusPtr = lpServices;
998 dwBufferSize = cbBufSize;
999 }
1000
1001 RpcTryExcept
1002 {
1003 dwError = REnumDependentServicesW((SC_RPC_HANDLE)hService,
1004 dwServiceState,
1005 (LPBYTE)lpStatusPtr,
1006 dwBufferSize,
1007 pcbBytesNeeded,
1008 lpServicesReturned);
1009 }
1010 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1011 {
1012 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1013 }
1014 RpcEndExcept;
1015
1016 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
1017 {
1018 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1019 {
1020 if (lpStatusPtr->lpServiceName)
1021 lpStatusPtr->lpServiceName =
1022 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1023
1024 if (lpStatusPtr->lpDisplayName)
1025 lpStatusPtr->lpDisplayName =
1026 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1027
1028 lpStatusPtr++;
1029 }
1030 }
1031
1032 if (dwError != ERROR_SUCCESS)
1033 {
1034 TRACE("REnumDependentServicesW() failed (Error %lu)\n", dwError);
1035 SetLastError(dwError);
1036 return FALSE;
1037 }
1038
1039 TRACE("EnumDependentServicesW() done\n");
1040
1041 return TRUE;
1042 }
1043
1044
1045 /**********************************************************************
1046 * EnumServiceGroupW
1047 *
1048 * @implemented
1049 */
1050 BOOL WINAPI
1051 EnumServiceGroupW(SC_HANDLE hSCManager,
1052 DWORD dwServiceType,
1053 DWORD dwServiceState,
1054 LPENUM_SERVICE_STATUSW lpServices,
1055 DWORD cbBufSize,
1056 LPDWORD pcbBytesNeeded,
1057 LPDWORD lpServicesReturned,
1058 LPDWORD lpResumeHandle,
1059 LPCWSTR lpGroup)
1060 {
1061 ENUM_SERVICE_STATUSW ServiceStatus;
1062 LPENUM_SERVICE_STATUSW lpStatusPtr;
1063 DWORD dwBufferSize;
1064 DWORD dwError;
1065 DWORD dwCount;
1066
1067 TRACE("EnumServiceGroupW(%p %lu %lu %p %lu %p %p %p %s)\n",
1068 hSCManager, dwServiceType, dwServiceState, lpServices,
1069 cbBufSize, pcbBytesNeeded, lpServicesReturned,
1070 lpResumeHandle, debugstr_w(lpGroup));
1071
1072 if (!hSCManager)
1073 {
1074 SetLastError(ERROR_INVALID_HANDLE);
1075 return FALSE;
1076 }
1077
1078 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
1079 {
1080 SetLastError(ERROR_INVALID_ADDRESS);
1081 return FALSE;
1082 }
1083
1084 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
1085 {
1086 lpStatusPtr = &ServiceStatus;
1087 dwBufferSize = sizeof(ENUM_SERVICE_STATUSW);
1088 }
1089 else
1090 {
1091 lpStatusPtr = lpServices;
1092 dwBufferSize = cbBufSize;
1093 }
1094
1095 RpcTryExcept
1096 {
1097 if (lpGroup == NULL)
1098 {
1099 dwError = REnumServicesStatusW((SC_RPC_HANDLE)hSCManager,
1100 dwServiceType,
1101 dwServiceState,
1102 (LPBYTE)lpStatusPtr,
1103 dwBufferSize,
1104 pcbBytesNeeded,
1105 lpServicesReturned,
1106 lpResumeHandle);
1107 }
1108 else
1109 {
1110 dwError = REnumServiceGroupW((SC_RPC_HANDLE)hSCManager,
1111 dwServiceType,
1112 dwServiceState,
1113 (LPBYTE)lpStatusPtr,
1114 dwBufferSize,
1115 pcbBytesNeeded,
1116 lpServicesReturned,
1117 lpResumeHandle,
1118 lpGroup);
1119 }
1120 }
1121 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1122 {
1123 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1124 }
1125 RpcEndExcept;
1126
1127 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
1128 {
1129 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1130 {
1131 if (lpStatusPtr->lpServiceName)
1132 lpStatusPtr->lpServiceName =
1133 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1134
1135 if (lpStatusPtr->lpDisplayName)
1136 lpStatusPtr->lpDisplayName =
1137 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1138
1139 lpStatusPtr++;
1140 }
1141 }
1142
1143 if (dwError != ERROR_SUCCESS)
1144 {
1145 TRACE("REnumServiceGroupW() failed (Error %lu)\n", dwError);
1146 SetLastError(dwError);
1147 return FALSE;
1148 }
1149
1150 TRACE("EnumServiceGroupW() done\n");
1151
1152 return TRUE;
1153 }
1154
1155
1156 /**********************************************************************
1157 * EnumServicesStatusA
1158 *
1159 * @implemented
1160 */
1161 BOOL WINAPI
1162 EnumServicesStatusA(SC_HANDLE hSCManager,
1163 DWORD dwServiceType,
1164 DWORD dwServiceState,
1165 LPENUM_SERVICE_STATUSA lpServices,
1166 DWORD cbBufSize,
1167 LPDWORD pcbBytesNeeded,
1168 LPDWORD lpServicesReturned,
1169 LPDWORD lpResumeHandle)
1170 {
1171 ENUM_SERVICE_STATUSA ServiceStatus;
1172 LPENUM_SERVICE_STATUSA lpStatusPtr;
1173 DWORD dwBufferSize;
1174 DWORD dwError;
1175 DWORD dwCount;
1176
1177 TRACE("EnumServicesStatusA(%p %lu %lu %p %lu %p %p %p)\n",
1178 hSCManager, dwServiceType, dwServiceState, lpServices,
1179 cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1180
1181 if (!hSCManager)
1182 {
1183 SetLastError(ERROR_INVALID_HANDLE);
1184 return FALSE;
1185 }
1186
1187 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
1188 {
1189 SetLastError(ERROR_INVALID_ADDRESS);
1190 return FALSE;
1191 }
1192
1193 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSA))
1194 {
1195 lpStatusPtr = &ServiceStatus;
1196 dwBufferSize = sizeof(ENUM_SERVICE_STATUSA);
1197 }
1198 else
1199 {
1200 lpStatusPtr = lpServices;
1201 dwBufferSize = cbBufSize;
1202 }
1203
1204 RpcTryExcept
1205 {
1206 dwError = REnumServicesStatusA((SC_RPC_HANDLE)hSCManager,
1207 dwServiceType,
1208 dwServiceState,
1209 (LPBYTE)lpStatusPtr,
1210 dwBufferSize,
1211 pcbBytesNeeded,
1212 lpServicesReturned,
1213 lpResumeHandle);
1214 }
1215 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1216 {
1217 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1218 }
1219 RpcEndExcept;
1220
1221 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
1222 {
1223 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1224 {
1225 if (lpStatusPtr->lpServiceName)
1226 lpStatusPtr->lpServiceName =
1227 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1228
1229 if (lpStatusPtr->lpDisplayName)
1230 lpStatusPtr->lpDisplayName =
1231 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1232
1233 lpStatusPtr++;
1234 }
1235 }
1236
1237 if (dwError != ERROR_SUCCESS)
1238 {
1239 TRACE("REnumServicesStatusA() failed (Error %lu)\n", dwError);
1240 SetLastError(dwError);
1241 return FALSE;
1242 }
1243
1244 TRACE("EnumServicesStatusA() done\n");
1245
1246 return TRUE;
1247 }
1248
1249
1250 /**********************************************************************
1251 * EnumServicesStatusW
1252 *
1253 * @implemented
1254 */
1255 BOOL WINAPI
1256 EnumServicesStatusW(SC_HANDLE hSCManager,
1257 DWORD dwServiceType,
1258 DWORD dwServiceState,
1259 LPENUM_SERVICE_STATUSW lpServices,
1260 DWORD cbBufSize,
1261 LPDWORD pcbBytesNeeded,
1262 LPDWORD lpServicesReturned,
1263 LPDWORD lpResumeHandle)
1264 {
1265 ENUM_SERVICE_STATUSW ServiceStatus;
1266 LPENUM_SERVICE_STATUSW lpStatusPtr;
1267 DWORD dwBufferSize;
1268 DWORD dwError;
1269 DWORD dwCount;
1270
1271 TRACE("EnumServicesStatusW(%p %lu %lu %p %lu %p %p %p)\n",
1272 hSCManager, dwServiceType, dwServiceState, lpServices,
1273 cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1274
1275 if (!hSCManager)
1276 {
1277 SetLastError(ERROR_INVALID_HANDLE);
1278 return FALSE;
1279 }
1280
1281 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
1282 {
1283 SetLastError(ERROR_INVALID_ADDRESS);
1284 return FALSE;
1285 }
1286
1287 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
1288 {
1289 lpStatusPtr = &ServiceStatus;
1290 dwBufferSize = sizeof(ENUM_SERVICE_STATUSW);
1291 }
1292 else
1293 {
1294 lpStatusPtr = lpServices;
1295 dwBufferSize = cbBufSize;
1296 }
1297
1298 RpcTryExcept
1299 {
1300 dwError = REnumServicesStatusW((SC_RPC_HANDLE)hSCManager,
1301 dwServiceType,
1302 dwServiceState,
1303 (LPBYTE)lpStatusPtr,
1304 dwBufferSize,
1305 pcbBytesNeeded,
1306 lpServicesReturned,
1307 lpResumeHandle);
1308 }
1309 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1310 {
1311 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1312 }
1313 RpcEndExcept;
1314
1315 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
1316 {
1317 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1318 {
1319 if (lpStatusPtr->lpServiceName)
1320 lpStatusPtr->lpServiceName =
1321 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1322
1323 if (lpStatusPtr->lpDisplayName)
1324 lpStatusPtr->lpDisplayName =
1325 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1326
1327 lpStatusPtr++;
1328 }
1329 }
1330
1331 if (dwError != ERROR_SUCCESS)
1332 {
1333 TRACE("REnumServicesStatusW() failed (Error %lu)\n", dwError);
1334 SetLastError(dwError);
1335 return FALSE;
1336 }
1337
1338 TRACE("EnumServicesStatusW() done\n");
1339
1340 return TRUE;
1341 }
1342
1343
1344 /**********************************************************************
1345 * EnumServicesStatusExA
1346 *
1347 * @implemented
1348 */
1349 BOOL WINAPI
1350 EnumServicesStatusExA(SC_HANDLE hSCManager,
1351 SC_ENUM_TYPE InfoLevel,
1352 DWORD dwServiceType,
1353 DWORD dwServiceState,
1354 LPBYTE lpServices,
1355 DWORD cbBufSize,
1356 LPDWORD pcbBytesNeeded,
1357 LPDWORD lpServicesReturned,
1358 LPDWORD lpResumeHandle,
1359 LPCSTR pszGroupName)
1360 {
1361 ENUM_SERVICE_STATUS_PROCESSA ServiceStatus;
1362 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
1363 DWORD dwBufferSize;
1364 DWORD dwError;
1365 DWORD dwCount;
1366
1367 TRACE("EnumServicesStatusExA(%p %lu %lu %p %lu %p %p %p %s)\n",
1368 hSCManager, dwServiceType, dwServiceState, lpServices,
1369 cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle,
1370 debugstr_a(pszGroupName));
1371
1372 if (InfoLevel != SC_ENUM_PROCESS_INFO)
1373 {
1374 SetLastError(ERROR_INVALID_LEVEL);
1375 return FALSE;
1376 }
1377
1378 if (!hSCManager)
1379 {
1380 SetLastError(ERROR_INVALID_HANDLE);
1381 return FALSE;
1382 }
1383
1384 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
1385 {
1386 SetLastError(ERROR_INVALID_ADDRESS);
1387 return FALSE;
1388 }
1389
1390 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSA))
1391 {
1392 lpStatusPtr = &ServiceStatus;
1393 dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSA);
1394 }
1395 else
1396 {
1397 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices;
1398 dwBufferSize = cbBufSize;
1399 }
1400
1401 RpcTryExcept
1402 {
1403 dwError = REnumServicesStatusExA((SC_RPC_HANDLE)hSCManager,
1404 InfoLevel,
1405 dwServiceType,
1406 dwServiceState,
1407 (LPBYTE)lpStatusPtr,
1408 dwBufferSize,
1409 pcbBytesNeeded,
1410 lpServicesReturned,
1411 lpResumeHandle,
1412 (LPSTR)pszGroupName);
1413 }
1414 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1415 {
1416 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1417 }
1418 RpcEndExcept;
1419
1420 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
1421 {
1422 if (InfoLevel == SC_ENUM_PROCESS_INFO)
1423 {
1424 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1425 {
1426 if (lpStatusPtr->lpServiceName)
1427 lpStatusPtr->lpServiceName =
1428 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1429
1430 if (lpStatusPtr->lpDisplayName)
1431 lpStatusPtr->lpDisplayName =
1432 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1433
1434 lpStatusPtr++;
1435 }
1436 }
1437 }
1438
1439 if (dwError != ERROR_SUCCESS)
1440 {
1441 TRACE("REnumServicesStatusExA() failed (Error %lu)\n", dwError);
1442 SetLastError(dwError);
1443 return FALSE;
1444 }
1445
1446 TRACE("EnumServicesStatusExA() done\n");
1447
1448 return TRUE;
1449 }
1450
1451
1452 /**********************************************************************
1453 * EnumServicesStatusExW
1454 *
1455 * @implemented
1456 */
1457 BOOL WINAPI
1458 EnumServicesStatusExW(SC_HANDLE hSCManager,
1459 SC_ENUM_TYPE InfoLevel,
1460 DWORD dwServiceType,
1461 DWORD dwServiceState,
1462 LPBYTE lpServices,
1463 DWORD cbBufSize,
1464 LPDWORD pcbBytesNeeded,
1465 LPDWORD lpServicesReturned,
1466 LPDWORD lpResumeHandle,
1467 LPCWSTR pszGroupName)
1468 {
1469 ENUM_SERVICE_STATUS_PROCESSW ServiceStatus;
1470 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
1471 DWORD dwBufferSize;
1472 DWORD dwError;
1473 DWORD dwCount;
1474
1475 TRACE("EnumServicesStatusExW(%p %lu %lu %p %lu %p %p %p %s)\n",
1476 hSCManager, dwServiceType, dwServiceState, lpServices,
1477 cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle,
1478 debugstr_w(pszGroupName));
1479
1480 if (InfoLevel != SC_ENUM_PROCESS_INFO)
1481 {
1482 SetLastError(ERROR_INVALID_LEVEL);
1483 return FALSE;
1484 }
1485
1486 if (!hSCManager)
1487 {
1488 SetLastError(ERROR_INVALID_HANDLE);
1489 return FALSE;
1490 }
1491
1492 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
1493 {
1494 SetLastError(ERROR_INVALID_ADDRESS);
1495 return FALSE;
1496 }
1497
1498 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSW))
1499 {
1500 lpStatusPtr = &ServiceStatus;
1501 dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW);
1502 }
1503 else
1504 {
1505 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
1506 dwBufferSize = cbBufSize;
1507 }
1508
1509 RpcTryExcept
1510 {
1511 dwError = REnumServicesStatusExW((SC_RPC_HANDLE)hSCManager,
1512 InfoLevel,
1513 dwServiceType,
1514 dwServiceState,
1515 (LPBYTE)lpStatusPtr,
1516 dwBufferSize,
1517 pcbBytesNeeded,
1518 lpServicesReturned,
1519 lpResumeHandle,
1520 (LPWSTR)pszGroupName);
1521 }
1522 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1523 {
1524 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1525 }
1526 RpcEndExcept;
1527
1528 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
1529 {
1530 if (InfoLevel == SC_ENUM_PROCESS_INFO)
1531 {
1532 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1533 {
1534 if (lpStatusPtr->lpServiceName)
1535 lpStatusPtr->lpServiceName =
1536 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1537
1538 if (lpStatusPtr->lpDisplayName)
1539 lpStatusPtr->lpDisplayName =
1540 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1541
1542 lpStatusPtr++;
1543 }
1544 }
1545 }
1546
1547 if (dwError != ERROR_SUCCESS)
1548 {
1549 TRACE("REnumServicesStatusExW() failed (Error %lu)\n", dwError);
1550 SetLastError(dwError);
1551 return FALSE;
1552 }
1553
1554 TRACE("EnumServicesStatusExW() done\n");
1555
1556 return TRUE;
1557 }
1558
1559
1560 /**********************************************************************
1561 * GetServiceDisplayNameA
1562 *
1563 * @implemented
1564 */
1565 BOOL WINAPI
1566 GetServiceDisplayNameA(SC_HANDLE hSCManager,
1567 LPCSTR lpServiceName,
1568 LPSTR lpDisplayName,
1569 LPDWORD lpcchBuffer)
1570 {
1571 DWORD dwError;
1572 LPSTR lpNameBuffer;
1573 CHAR szEmptyName[] = "";
1574
1575 TRACE("GetServiceDisplayNameA(%p %s %p %p)\n",
1576 hSCManager, debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1577
1578 if (!hSCManager)
1579 {
1580 SetLastError(ERROR_INVALID_HANDLE);
1581 return FALSE;
1582 }
1583
1584 if (!lpDisplayName || *lpcchBuffer < sizeof(CHAR))
1585 {
1586 lpNameBuffer = szEmptyName;
1587 *lpcchBuffer = sizeof(CHAR);
1588 }
1589 else
1590 {
1591 lpNameBuffer = lpDisplayName;
1592 }
1593
1594 RpcTryExcept
1595 {
1596 dwError = RGetServiceDisplayNameA((SC_RPC_HANDLE)hSCManager,
1597 lpServiceName,
1598 lpNameBuffer,
1599 lpcchBuffer);
1600 }
1601 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1602 {
1603 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1604 }
1605 RpcEndExcept;
1606
1607 if (dwError != ERROR_SUCCESS)
1608 {
1609 TRACE("RGetServiceDisplayNameA() failed (Error %lu)\n", dwError);
1610 SetLastError(dwError);
1611 return FALSE;
1612 }
1613
1614 return TRUE;
1615 }
1616
1617
1618 /**********************************************************************
1619 * GetServiceDisplayNameW
1620 *
1621 * @implemented
1622 */
1623 BOOL WINAPI
1624 GetServiceDisplayNameW(SC_HANDLE hSCManager,
1625 LPCWSTR lpServiceName,
1626 LPWSTR lpDisplayName,
1627 LPDWORD lpcchBuffer)
1628 {
1629 DWORD dwError;
1630 LPWSTR lpNameBuffer;
1631 WCHAR szEmptyName[] = L"";
1632
1633 TRACE("GetServiceDisplayNameW(%p %s %p %p)\n",
1634 hSCManager, debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1635
1636 if (!hSCManager)
1637 {
1638 SetLastError(ERROR_INVALID_HANDLE);
1639 return FALSE;
1640 }
1641
1642 if (!lpDisplayName || *lpcchBuffer < sizeof(WCHAR))
1643 {
1644 lpNameBuffer = szEmptyName;
1645 *lpcchBuffer = sizeof(WCHAR);
1646 }
1647 else
1648 {
1649 lpNameBuffer = lpDisplayName;
1650 }
1651
1652 RpcTryExcept
1653 {
1654 dwError = RGetServiceDisplayNameW((SC_RPC_HANDLE)hSCManager,
1655 lpServiceName,
1656 lpNameBuffer,
1657 lpcchBuffer);
1658 }
1659 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1660 {
1661 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1662 }
1663 RpcEndExcept;
1664
1665 if (dwError != ERROR_SUCCESS)
1666 {
1667 TRACE("RGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
1668 SetLastError(dwError);
1669 return FALSE;
1670 }
1671
1672 return TRUE;
1673 }
1674
1675
1676 /**********************************************************************
1677 * GetServiceKeyNameA
1678 *
1679 * @implemented
1680 */
1681 BOOL WINAPI
1682 GetServiceKeyNameA(SC_HANDLE hSCManager,
1683 LPCSTR lpDisplayName,
1684 LPSTR lpServiceName,
1685 LPDWORD lpcchBuffer)
1686 {
1687 DWORD dwError;
1688 LPSTR lpNameBuffer;
1689 CHAR szEmptyName[] = "";
1690
1691 TRACE("GetServiceKeyNameA(%p %s %p %p)\n",
1692 hSCManager, debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1693
1694 if (!hSCManager)
1695 {
1696 SetLastError(ERROR_INVALID_HANDLE);
1697 return FALSE;
1698 }
1699
1700 if (!lpServiceName || *lpcchBuffer < sizeof(CHAR))
1701 {
1702 lpNameBuffer = szEmptyName;
1703 *lpcchBuffer = sizeof(CHAR);
1704 }
1705 else
1706 {
1707 lpNameBuffer = lpServiceName;
1708 }
1709
1710 RpcTryExcept
1711 {
1712 dwError = RGetServiceKeyNameA((SC_RPC_HANDLE)hSCManager,
1713 lpDisplayName,
1714 lpNameBuffer,
1715 lpcchBuffer);
1716 }
1717 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1718 {
1719 /* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
1720 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1721 }
1722 RpcEndExcept;
1723
1724 if (dwError != ERROR_SUCCESS)
1725 {
1726 TRACE("RGetServiceKeyNameA() failed (Error %lu)\n", dwError);
1727 SetLastError(dwError);
1728 return FALSE;
1729 }
1730
1731 return TRUE;
1732 }
1733
1734
1735 /**********************************************************************
1736 * GetServiceKeyNameW
1737 *
1738 * @implemented
1739 */
1740 BOOL WINAPI
1741 GetServiceKeyNameW(SC_HANDLE hSCManager,
1742 LPCWSTR lpDisplayName,
1743 LPWSTR lpServiceName,
1744 LPDWORD lpcchBuffer)
1745 {
1746 DWORD dwError;
1747 LPWSTR lpNameBuffer;
1748 WCHAR szEmptyName[] = L"";
1749
1750 TRACE("GetServiceKeyNameW(%p %s %p %p)\n",
1751 hSCManager, debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1752
1753 if (!hSCManager)
1754 {
1755 SetLastError(ERROR_INVALID_HANDLE);
1756 return FALSE;
1757 }
1758
1759 if (!lpServiceName || *lpcchBuffer < sizeof(WCHAR))
1760 {
1761 lpNameBuffer = szEmptyName;
1762 *lpcchBuffer = sizeof(WCHAR);
1763 }
1764 else
1765 {
1766 lpNameBuffer = lpServiceName;
1767 }
1768
1769 RpcTryExcept
1770 {
1771 dwError = RGetServiceKeyNameW((SC_RPC_HANDLE)hSCManager,
1772 lpDisplayName,
1773 lpNameBuffer,
1774 lpcchBuffer);
1775 }
1776 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1777 {
1778 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1779 }
1780 RpcEndExcept;
1781
1782 if (dwError != ERROR_SUCCESS)
1783 {
1784 TRACE("RGetServiceKeyNameW() failed (Error %lu)\n", dwError);
1785 SetLastError(dwError);
1786 return FALSE;
1787 }
1788
1789 return TRUE;
1790 }
1791
1792
1793 /**********************************************************************
1794 * I_ScGetCurrentGroupStateW
1795 *
1796 * @implemented
1797 */
1798 DWORD WINAPI
1799 I_ScGetCurrentGroupStateW(SC_HANDLE hSCManager,
1800 LPWSTR pszGroupName,
1801 LPDWORD pdwGroupState)
1802 {
1803 DWORD dwError;
1804
1805 TRACE("I_ScGetCurrentGroupStateW(%p %s %p)\n",
1806 hSCManager, debugstr_w(pszGroupName), pdwGroupState);
1807
1808 RpcTryExcept
1809 {
1810 dwError = RI_ScGetCurrentGroupStateW((SC_RPC_HANDLE)hSCManager,
1811 pszGroupName,
1812 pdwGroupState);
1813 }
1814 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1815 {
1816 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1817 }
1818 RpcEndExcept
1819
1820 if (dwError != ERROR_SUCCESS)
1821 {
1822 TRACE("RI_ScGetCurrentGroupStateW() failed (Error %lu)\n", dwError);
1823 SetLastError(dwError);
1824 }
1825
1826 return dwError;
1827 }
1828
1829
1830 /**********************************************************************
1831 * LockServiceDatabase
1832 *
1833 * @implemented
1834 */
1835 SC_LOCK WINAPI
1836 LockServiceDatabase(SC_HANDLE hSCManager)
1837 {
1838 SC_LOCK hLock;
1839 DWORD dwError;
1840
1841 TRACE("LockServiceDatabase(%p)\n",
1842 hSCManager);
1843
1844 RpcTryExcept
1845 {
1846 dwError = RLockServiceDatabase((SC_RPC_HANDLE)hSCManager,
1847 (SC_RPC_LOCK *)&hLock);
1848 }
1849 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1850 {
1851 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1852 }
1853 RpcEndExcept;
1854
1855 if (dwError != ERROR_SUCCESS)
1856 {
1857 TRACE("RLockServiceDatabase() failed (Error %lu)\n", dwError);
1858 SetLastError(dwError);
1859 return NULL;
1860 }
1861
1862 TRACE("hLock = %p\n", hLock);
1863
1864 return hLock;
1865 }
1866
1867
1868 static VOID
1869 WaitForSCManager(VOID)
1870 {
1871 HANDLE hEvent;
1872
1873 TRACE("WaitForSCManager()\n");
1874
1875 /* Try to open the existing event */
1876 hEvent = OpenEventW(SYNCHRONIZE, FALSE, SCM_START_EVENT);
1877 if (hEvent == NULL)
1878 {
1879 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1880 return;
1881
1882 /* Try to create a new event */
1883 hEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
1884 if (hEvent == NULL)
1885 return;
1886 }
1887
1888 /* Wait for 3 minutes */
1889 WaitForSingleObject(hEvent, 180000);
1890 CloseHandle(hEvent);
1891
1892 TRACE("ScmWaitForSCManager() done\n");
1893 }
1894
1895
1896 /**********************************************************************
1897 * OpenSCManagerA
1898 *
1899 * @implemented
1900 */
1901 SC_HANDLE WINAPI
1902 OpenSCManagerA(LPCSTR lpMachineName,
1903 LPCSTR lpDatabaseName,
1904 DWORD dwDesiredAccess)
1905 {
1906 SC_HANDLE hScm = NULL;
1907 DWORD dwError;
1908
1909 TRACE("OpenSCManagerA(%s %s %lx)\n",
1910 debugstr_a(lpMachineName), debugstr_a(lpDatabaseName), dwDesiredAccess);
1911
1912 WaitForSCManager();
1913
1914 RpcTryExcept
1915 {
1916 dwError = ROpenSCManagerA((LPSTR)lpMachineName,
1917 (LPSTR)lpDatabaseName,
1918 dwDesiredAccess,
1919 (SC_RPC_HANDLE *)&hScm);
1920 }
1921 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1922 {
1923 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1924 }
1925 RpcEndExcept;
1926
1927 if (dwError != ERROR_SUCCESS)
1928 {
1929 TRACE("ROpenSCManagerA() failed (Error %lu)\n", dwError);
1930 SetLastError(dwError);
1931 return NULL;
1932 }
1933
1934 TRACE("hScm = %p\n", hScm);
1935
1936 return hScm;
1937 }
1938
1939
1940 /**********************************************************************
1941 * OpenSCManagerW
1942 *
1943 * @implemented
1944 */
1945 SC_HANDLE WINAPI
1946 OpenSCManagerW(LPCWSTR lpMachineName,
1947 LPCWSTR lpDatabaseName,
1948 DWORD dwDesiredAccess)
1949 {
1950 SC_HANDLE hScm = NULL;
1951 DWORD dwError;
1952
1953 TRACE("OpenSCManagerW(%s %s %lx)\n",
1954 debugstr_w(lpMachineName), debugstr_w(lpDatabaseName), dwDesiredAccess);
1955
1956 WaitForSCManager();
1957
1958 RpcTryExcept
1959 {
1960 dwError = ROpenSCManagerW((LPWSTR)lpMachineName,
1961 (LPWSTR)lpDatabaseName,
1962 dwDesiredAccess,
1963 (SC_RPC_HANDLE *)&hScm);
1964 }
1965 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1966 {
1967 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1968 }
1969 RpcEndExcept;
1970
1971 if (dwError != ERROR_SUCCESS)
1972 {
1973 TRACE("ROpenSCManagerW() failed (Error %lu)\n", dwError);
1974 SetLastError(dwError);
1975 return NULL;
1976 }
1977
1978 TRACE("hScm = %p\n", hScm);
1979
1980 return hScm;
1981 }
1982
1983
1984 /**********************************************************************
1985 * OpenServiceA
1986 *
1987 * @implemented
1988 */
1989 SC_HANDLE WINAPI
1990 OpenServiceA(SC_HANDLE hSCManager,
1991 LPCSTR lpServiceName,
1992 DWORD dwDesiredAccess)
1993 {
1994 SC_HANDLE hService = NULL;
1995 DWORD dwError;
1996
1997 TRACE("OpenServiceA(%p %s %lx)\n",
1998 hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
1999
2000 if (!hSCManager)
2001 {
2002 SetLastError(ERROR_INVALID_HANDLE);
2003 return NULL;
2004 }
2005
2006 RpcTryExcept
2007 {
2008 dwError = ROpenServiceA((SC_RPC_HANDLE)hSCManager,
2009 (LPSTR)lpServiceName,
2010 dwDesiredAccess,
2011 (SC_RPC_HANDLE *)&hService);
2012 }
2013 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2014 {
2015 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2016 }
2017 RpcEndExcept;
2018
2019 SetLastError(dwError);
2020 if (dwError != ERROR_SUCCESS)
2021 {
2022 TRACE("ROpenServiceA() failed (Error %lu)\n", dwError);
2023 return NULL;
2024 }
2025
2026 TRACE("hService = %p\n", hService);
2027
2028 return hService;
2029 }
2030
2031
2032 /**********************************************************************
2033 * OpenServiceW
2034 *
2035 * @implemented
2036 */
2037 SC_HANDLE WINAPI
2038 OpenServiceW(SC_HANDLE hSCManager,
2039 LPCWSTR lpServiceName,
2040 DWORD dwDesiredAccess)
2041 {
2042 SC_HANDLE hService = NULL;
2043 DWORD dwError;
2044
2045 TRACE("OpenServiceW(%p %s %lx)\n",
2046 hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
2047
2048 if (!hSCManager)
2049 {
2050 SetLastError(ERROR_INVALID_HANDLE);
2051 return NULL;
2052 }
2053
2054 RpcTryExcept
2055 {
2056 dwError = ROpenServiceW((SC_RPC_HANDLE)hSCManager,
2057 (LPWSTR)lpServiceName,
2058 dwDesiredAccess,
2059 (SC_RPC_HANDLE *)&hService);
2060 }
2061 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2062 {
2063 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2064 }
2065 RpcEndExcept;
2066
2067 SetLastError(dwError);
2068 if (dwError != ERROR_SUCCESS)
2069 {
2070 TRACE("ROpenServiceW() failed (Error %lu)\n", dwError);
2071 return NULL;
2072 }
2073
2074 TRACE("hService = %p\n", hService);
2075
2076 return hService;
2077 }
2078
2079
2080 /**********************************************************************
2081 * QueryServiceConfigA
2082 *
2083 * @implemented
2084 */
2085 BOOL WINAPI
2086 QueryServiceConfigA(SC_HANDLE hService,
2087 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
2088 DWORD cbBufSize,
2089 LPDWORD pcbBytesNeeded)
2090 {
2091 QUERY_SERVICE_CONFIGA ServiceConfig;
2092 LPQUERY_SERVICE_CONFIGA lpConfigPtr;
2093 DWORD dwBufferSize;
2094 DWORD dwError;
2095
2096 TRACE("QueryServiceConfigA(%p %p %lu %p)\n",
2097 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
2098
2099 if (lpServiceConfig == NULL ||
2100 cbBufSize < sizeof(QUERY_SERVICE_CONFIGA))
2101 {
2102 lpConfigPtr = &ServiceConfig;
2103 dwBufferSize = sizeof(QUERY_SERVICE_CONFIGA);
2104 }
2105 else
2106 {
2107 lpConfigPtr = lpServiceConfig;
2108 dwBufferSize = cbBufSize;
2109 }
2110
2111 RpcTryExcept
2112 {
2113 dwError = RQueryServiceConfigA((SC_RPC_HANDLE)hService,
2114 (LPBYTE)lpConfigPtr,
2115 dwBufferSize,
2116 pcbBytesNeeded);
2117 }
2118 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2119 {
2120 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2121 }
2122 RpcEndExcept;
2123
2124 if (dwError != ERROR_SUCCESS)
2125 {
2126 TRACE("RQueryServiceConfigA() failed (Error %lu)\n", dwError);
2127 SetLastError(dwError);
2128 return FALSE;
2129 }
2130
2131 /* Adjust the pointers */
2132 if (lpConfigPtr->lpBinaryPathName)
2133 lpConfigPtr->lpBinaryPathName =
2134 (LPSTR)((ULONG_PTR)lpConfigPtr +
2135 (ULONG_PTR)lpConfigPtr->lpBinaryPathName);
2136
2137 if (lpConfigPtr->lpLoadOrderGroup)
2138 lpConfigPtr->lpLoadOrderGroup =
2139 (LPSTR)((ULONG_PTR)lpConfigPtr +
2140 (ULONG_PTR)lpConfigPtr->lpLoadOrderGroup);
2141
2142 if (lpConfigPtr->lpDependencies)
2143 lpConfigPtr->lpDependencies =
2144 (LPSTR)((ULONG_PTR)lpConfigPtr +
2145 (ULONG_PTR)lpConfigPtr->lpDependencies);
2146
2147 if (lpConfigPtr->lpServiceStartName)
2148 lpConfigPtr->lpServiceStartName =
2149 (LPSTR)((ULONG_PTR)lpConfigPtr +
2150 (ULONG_PTR)lpConfigPtr->lpServiceStartName);
2151
2152 if (lpConfigPtr->lpDisplayName)
2153 lpConfigPtr->lpDisplayName =
2154 (LPSTR)((ULONG_PTR)lpConfigPtr +
2155 (ULONG_PTR)lpConfigPtr->lpDisplayName);
2156
2157 TRACE("QueryServiceConfigA() done\n");
2158
2159 return TRUE;
2160 }
2161
2162
2163 /**********************************************************************
2164 * QueryServiceConfigW
2165 *
2166 * @implemented
2167 */
2168 BOOL WINAPI
2169 QueryServiceConfigW(SC_HANDLE hService,
2170 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2171 DWORD cbBufSize,
2172 LPDWORD pcbBytesNeeded)
2173 {
2174 QUERY_SERVICE_CONFIGW ServiceConfig;
2175 LPQUERY_SERVICE_CONFIGW lpConfigPtr;
2176 DWORD dwBufferSize;
2177 DWORD dwError;
2178
2179 TRACE("QueryServiceConfigW(%p %p %lu %p)\n",
2180 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
2181
2182 if (lpServiceConfig == NULL ||
2183 cbBufSize < sizeof(QUERY_SERVICE_CONFIGW))
2184 {
2185 lpConfigPtr = &ServiceConfig;
2186 dwBufferSize = sizeof(QUERY_SERVICE_CONFIGW);
2187 }
2188 else
2189 {
2190 lpConfigPtr = lpServiceConfig;
2191 dwBufferSize = cbBufSize;
2192 }
2193
2194 RpcTryExcept
2195 {
2196 dwError = RQueryServiceConfigW((SC_RPC_HANDLE)hService,
2197 (LPBYTE)lpConfigPtr,
2198 dwBufferSize,
2199 pcbBytesNeeded);
2200 }
2201 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2202 {
2203 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2204 }
2205 RpcEndExcept;
2206
2207 if (dwError != ERROR_SUCCESS)
2208 {
2209 TRACE("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
2210 SetLastError(dwError);
2211 return FALSE;
2212 }
2213
2214 /* Adjust the pointers */
2215 if (lpConfigPtr->lpBinaryPathName)
2216 lpConfigPtr->lpBinaryPathName =
2217 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2218 (ULONG_PTR)lpConfigPtr->lpBinaryPathName);
2219
2220 if (lpConfigPtr->lpLoadOrderGroup)
2221 lpConfigPtr->lpLoadOrderGroup =
2222 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2223 (ULONG_PTR)lpConfigPtr->lpLoadOrderGroup);
2224
2225 if (lpConfigPtr->lpDependencies)
2226 lpConfigPtr->lpDependencies =
2227 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2228 (ULONG_PTR)lpConfigPtr->lpDependencies);
2229
2230 if (lpConfigPtr->lpServiceStartName)
2231 lpConfigPtr->lpServiceStartName =
2232 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2233 (ULONG_PTR)lpConfigPtr->lpServiceStartName);
2234
2235 if (lpConfigPtr->lpDisplayName)
2236 lpConfigPtr->lpDisplayName =
2237 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2238 (ULONG_PTR)lpConfigPtr->lpDisplayName);
2239
2240 TRACE("QueryServiceConfigW() done\n");
2241
2242 return TRUE;
2243 }
2244
2245
2246 /**********************************************************************
2247 * QueryServiceConfig2A
2248 *
2249 * @implemented
2250 */
2251 BOOL WINAPI
2252 QueryServiceConfig2A(SC_HANDLE hService,
2253 DWORD dwInfoLevel,
2254 LPBYTE lpBuffer,
2255 DWORD cbBufSize,
2256 LPDWORD pcbBytesNeeded)
2257 {
2258 SERVICE_DESCRIPTIONA ServiceDescription;
2259 SERVICE_FAILURE_ACTIONSA ServiceFailureActions;
2260 LPBYTE lpTempBuffer;
2261 BOOL bUseTempBuffer = FALSE;
2262 DWORD dwBufferSize;
2263 DWORD dwError;
2264
2265 TRACE("QueryServiceConfig2A(%p %lu %p %lu %p)\n",
2266 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2267
2268 lpTempBuffer = lpBuffer;
2269 dwBufferSize = cbBufSize;
2270
2271 switch (dwInfoLevel)
2272 {
2273 case SERVICE_CONFIG_DESCRIPTION:
2274 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONA)))
2275 {
2276 lpTempBuffer = (LPBYTE)&ServiceDescription;
2277 dwBufferSize = sizeof(SERVICE_DESCRIPTIONA);
2278 bUseTempBuffer = TRUE;
2279 }
2280 break;
2281
2282 case SERVICE_CONFIG_FAILURE_ACTIONS:
2283 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSA)))
2284 {
2285 lpTempBuffer = (LPBYTE)&ServiceFailureActions;
2286 dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSA);
2287 bUseTempBuffer = TRUE;
2288 }
2289 break;
2290
2291 default:
2292 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
2293 SetLastError(ERROR_INVALID_LEVEL);
2294 return FALSE;
2295 }
2296
2297 RpcTryExcept
2298 {
2299 dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
2300 dwInfoLevel,
2301 lpTempBuffer,
2302 dwBufferSize,
2303 pcbBytesNeeded);
2304 }
2305 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2306 {
2307 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2308 }
2309 RpcEndExcept;
2310
2311 if (dwError != ERROR_SUCCESS)
2312 {
2313 TRACE("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
2314 SetLastError(dwError);
2315 return FALSE;
2316 }
2317
2318 if (bUseTempBuffer != FALSE)
2319 {
2320 TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n");
2321 *pcbBytesNeeded = dwBufferSize;
2322 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2323 return FALSE;
2324 }
2325
2326 switch (dwInfoLevel)
2327 {
2328 case SERVICE_CONFIG_DESCRIPTION:
2329 {
2330 LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpTempBuffer;
2331
2332 if (lpPtr->lpDescription != NULL)
2333 lpPtr->lpDescription =
2334 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
2335 }
2336 break;
2337
2338 case SERVICE_CONFIG_FAILURE_ACTIONS:
2339 {
2340 LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpTempBuffer;
2341
2342 if (lpPtr->lpRebootMsg != NULL)
2343 lpPtr->lpRebootMsg =
2344 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
2345
2346 if (lpPtr->lpCommand != NULL)
2347 lpPtr->lpCommand =
2348 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
2349
2350 if (lpPtr->lpsaActions != NULL)
2351 lpPtr->lpsaActions =
2352 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
2353 }
2354 break;
2355 }
2356
2357 TRACE("QueryServiceConfig2A() done\n");
2358
2359 return TRUE;
2360 }
2361
2362
2363 /**********************************************************************
2364 * QueryServiceConfig2W
2365 *
2366 * @implemented
2367 */
2368 BOOL WINAPI
2369 QueryServiceConfig2W(SC_HANDLE hService,
2370 DWORD dwInfoLevel,
2371 LPBYTE lpBuffer,
2372 DWORD cbBufSize,
2373 LPDWORD pcbBytesNeeded)
2374 {
2375 SERVICE_DESCRIPTIONW ServiceDescription;
2376 SERVICE_FAILURE_ACTIONSW ServiceFailureActions;
2377 LPBYTE lpTempBuffer;
2378 BOOL bUseTempBuffer = FALSE;
2379 DWORD dwBufferSize;
2380 DWORD dwError;
2381
2382 TRACE("QueryServiceConfig2W(%p %lu %p %lu %p)\n",
2383 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2384
2385 lpTempBuffer = lpBuffer;
2386 dwBufferSize = cbBufSize;
2387
2388 switch (dwInfoLevel)
2389 {
2390 case SERVICE_CONFIG_DESCRIPTION:
2391 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONW)))
2392 {
2393 lpTempBuffer = (LPBYTE)&ServiceDescription;
2394 dwBufferSize = sizeof(SERVICE_DESCRIPTIONW);
2395 bUseTempBuffer = TRUE;
2396 }
2397 break;
2398
2399 case SERVICE_CONFIG_FAILURE_ACTIONS:
2400 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSW)))
2401 {
2402 lpTempBuffer = (LPBYTE)&ServiceFailureActions;
2403 dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSW);
2404 bUseTempBuffer = TRUE;
2405 }
2406 break;
2407
2408 default:
2409 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
2410 SetLastError(ERROR_INVALID_LEVEL);
2411 return FALSE;
2412 }
2413
2414 RpcTryExcept
2415 {
2416 dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
2417 dwInfoLevel,
2418 lpTempBuffer,
2419 dwBufferSize,
2420 pcbBytesNeeded);
2421 }
2422 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2423 {
2424 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2425 }
2426 RpcEndExcept;
2427
2428 if (dwError != ERROR_SUCCESS)
2429 {
2430 TRACE("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
2431 SetLastError(dwError);
2432 return FALSE;
2433 }
2434
2435 if (bUseTempBuffer != FALSE)
2436 {
2437 TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n");
2438 *pcbBytesNeeded = dwBufferSize;
2439 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2440 return FALSE;
2441 }
2442
2443 switch (dwInfoLevel)
2444 {
2445 case SERVICE_CONFIG_DESCRIPTION:
2446 {
2447 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer;
2448
2449 if (lpPtr->lpDescription != NULL)
2450 lpPtr->lpDescription =
2451 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
2452 }
2453 break;
2454
2455 case SERVICE_CONFIG_FAILURE_ACTIONS:
2456 {
2457 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpTempBuffer;
2458
2459 if (lpPtr->lpRebootMsg != NULL)
2460 lpPtr->lpRebootMsg =
2461 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
2462
2463 if (lpPtr->lpCommand != NULL)
2464 lpPtr->lpCommand =
2465 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
2466
2467 if (lpPtr->lpsaActions != NULL)
2468 lpPtr->lpsaActions =
2469 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
2470 }
2471 break;
2472 }
2473
2474 TRACE("QueryServiceConfig2W() done\n");
2475
2476 return TRUE;
2477 }
2478
2479
2480 /**********************************************************************
2481 * QueryServiceLockStatusA
2482 *
2483 * @implemented
2484 */
2485 BOOL WINAPI
2486 QueryServiceLockStatusA(SC_HANDLE hSCManager,
2487 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
2488 DWORD cbBufSize,
2489 LPDWORD pcbBytesNeeded)
2490 {
2491 QUERY_SERVICE_LOCK_STATUSA LockStatus;
2492 LPQUERY_SERVICE_LOCK_STATUSA lpStatusPtr;
2493 DWORD dwBufferSize;
2494 DWORD dwError;
2495
2496 TRACE("QueryServiceLockStatusA(%p %p %lu %p)\n",
2497 hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
2498
2499 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA))
2500 {
2501 lpStatusPtr = &LockStatus;
2502 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSA);
2503 }
2504 else
2505 {
2506 lpStatusPtr = lpLockStatus;
2507 dwBufferSize = cbBufSize;
2508 }
2509
2510 RpcTryExcept
2511 {
2512 dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
2513 (LPBYTE)lpStatusPtr,
2514 dwBufferSize,
2515 pcbBytesNeeded);
2516 }
2517 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2518 {
2519 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2520 }
2521 RpcEndExcept;
2522
2523 if (dwError != ERROR_SUCCESS)
2524 {
2525 TRACE("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
2526 SetLastError(dwError);
2527 return FALSE;
2528 }
2529
2530 if (lpStatusPtr->lpLockOwner != NULL)
2531 {
2532 lpStatusPtr->lpLockOwner =
2533 (LPSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
2534 }
2535
2536 TRACE("QueryServiceLockStatusA() done\n");
2537
2538 return TRUE;
2539 }
2540
2541
2542 /**********************************************************************
2543 * QueryServiceLockStatusW
2544 *
2545 * @implemented
2546 */
2547 BOOL WINAPI
2548 QueryServiceLockStatusW(SC_HANDLE hSCManager,
2549 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
2550 DWORD cbBufSize,
2551 LPDWORD pcbBytesNeeded)
2552 {
2553 QUERY_SERVICE_LOCK_STATUSW LockStatus;
2554 LPQUERY_SERVICE_LOCK_STATUSW lpStatusPtr;
2555 DWORD dwBufferSize;
2556 DWORD dwError;
2557
2558 TRACE("QueryServiceLockStatusW(%p %p %lu %p)\n",
2559 hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
2560
2561 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW))
2562 {
2563 lpStatusPtr = &LockStatus;
2564 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSW);
2565 }
2566 else
2567 {
2568 lpStatusPtr = lpLockStatus;
2569 dwBufferSize = cbBufSize;
2570 }
2571
2572 RpcTryExcept
2573 {
2574 dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
2575 (LPBYTE)lpStatusPtr,
2576 dwBufferSize,
2577 pcbBytesNeeded);
2578 }
2579 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2580 {
2581 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2582 }
2583 RpcEndExcept;
2584
2585 if (dwError != ERROR_SUCCESS)
2586 {
2587 TRACE("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
2588 SetLastError(dwError);
2589 return FALSE;
2590 }
2591
2592 if (lpStatusPtr->lpLockOwner != NULL)
2593 {
2594 lpStatusPtr->lpLockOwner =
2595 (LPWSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
2596 }
2597
2598 TRACE("QueryServiceLockStatusW() done\n");
2599
2600 return TRUE;
2601 }
2602
2603
2604 /**********************************************************************
2605 * QueryServiceObjectSecurity
2606 *
2607 * @implemented
2608 */
2609 BOOL WINAPI
2610 QueryServiceObjectSecurity(SC_HANDLE hService,
2611 SECURITY_INFORMATION dwSecurityInformation,
2612 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2613 DWORD cbBufSize,
2614 LPDWORD pcbBytesNeeded)
2615 {
2616 DWORD dwError;
2617
2618 TRACE("QueryServiceObjectSecurity(%p %lu %p)\n",
2619 hService, dwSecurityInformation, lpSecurityDescriptor);
2620
2621 RpcTryExcept
2622 {
2623 dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
2624 dwSecurityInformation,
2625 (LPBYTE)lpSecurityDescriptor,
2626 cbBufSize,
2627 pcbBytesNeeded);
2628 }
2629 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2630 {
2631 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2632 }
2633 RpcEndExcept;
2634
2635 if (dwError != ERROR_SUCCESS)
2636 {
2637 TRACE("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
2638 SetLastError(dwError);
2639 return FALSE;
2640 }
2641
2642 return TRUE;
2643 }
2644
2645
2646 /**********************************************************************
2647 * SetServiceObjectSecurity
2648 *
2649 * @implemented
2650 */
2651 BOOL WINAPI
2652 SetServiceObjectSecurity(SC_HANDLE hService,
2653 SECURITY_INFORMATION dwSecurityInformation,
2654 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2655 {
2656 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
2657 ULONG Length;
2658 NTSTATUS Status;
2659 DWORD dwError;
2660
2661 TRACE("SetServiceObjectSecurity(%p %lu %p)\n",
2662 hService, dwSecurityInformation, lpSecurityDescriptor);
2663
2664 Length = 0;
2665 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2666 SelfRelativeSD,
2667 &Length);
2668 if (Status != STATUS_BUFFER_TOO_SMALL)
2669 {
2670 SetLastError(ERROR_INVALID_PARAMETER);
2671 return FALSE;
2672 }
2673
2674 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
2675 if (SelfRelativeSD == NULL)
2676 {
2677 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2678 return FALSE;
2679 }
2680
2681 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2682 SelfRelativeSD,
2683 &Length);
2684 if (!NT_SUCCESS(Status))
2685 {
2686 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2687 SetLastError(RtlNtStatusToDosError(Status));
2688 return FALSE;
2689 }
2690
2691 RpcTryExcept
2692 {
2693 dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
2694 dwSecurityInformation,
2695 (LPBYTE)SelfRelativeSD,
2696 Length);
2697 }
2698 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2699 {
2700 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2701 }
2702 RpcEndExcept;
2703
2704 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2705
2706 if (dwError != ERROR_SUCCESS)
2707 {
2708 TRACE("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
2709 SetLastError(dwError);
2710 return FALSE;
2711 }
2712
2713 return TRUE;
2714 }
2715
2716
2717 /**********************************************************************
2718 * QueryServiceStatus
2719 *
2720 * @implemented
2721 */
2722 BOOL WINAPI
2723 QueryServiceStatus(SC_HANDLE hService,
2724 LPSERVICE_STATUS lpServiceStatus)
2725 {
2726 DWORD dwError;
2727
2728 TRACE("QueryServiceStatus(%p %p)\n",
2729 hService, lpServiceStatus);
2730
2731 if (!hService)
2732 {
2733 SetLastError(ERROR_INVALID_HANDLE);
2734 return FALSE;
2735 }
2736
2737 RpcTryExcept
2738 {
2739 dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
2740 lpServiceStatus);
2741 }
2742 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2743 {
2744 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2745 }
2746 RpcEndExcept;
2747
2748 if (dwError != ERROR_SUCCESS)
2749 {
2750 TRACE("RQueryServiceStatus() failed (Error %lu)\n", dwError);
2751 SetLastError(dwError);
2752 return FALSE;
2753 }
2754
2755 return TRUE;
2756 }
2757
2758
2759 /**********************************************************************
2760 * QueryServiceStatusEx
2761 *
2762 * @implemented
2763 */
2764 BOOL WINAPI
2765 QueryServiceStatusEx(SC_HANDLE hService,
2766 SC_STATUS_TYPE InfoLevel,
2767 LPBYTE lpBuffer,
2768 DWORD cbBufSize,
2769 LPDWORD pcbBytesNeeded)
2770 {
2771 DWORD dwError;
2772
2773 TRACE("QueryServiceStatusEx(%p %lu %p %lu %p)\n",
2774 hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2775
2776 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2777 {
2778 SetLastError(ERROR_INVALID_LEVEL);
2779 return FALSE;
2780 }
2781
2782 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2783 {
2784 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2785 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2786 return FALSE;
2787 }
2788
2789 RpcTryExcept
2790 {
2791 dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
2792 InfoLevel,
2793 lpBuffer,
2794 cbBufSize,
2795 pcbBytesNeeded);
2796 }
2797 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2798 {
2799 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2800 }
2801 RpcEndExcept;
2802
2803 if (dwError != ERROR_SUCCESS)
2804 {
2805 TRACE("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
2806 SetLastError(dwError);
2807 return FALSE;
2808 }
2809
2810 return TRUE;
2811 }
2812
2813
2814 /**********************************************************************
2815 * StartServiceA
2816 *
2817 * @implemented
2818 */
2819 BOOL WINAPI
2820 StartServiceA(SC_HANDLE hService,
2821 DWORD dwNumServiceArgs,
2822 LPCSTR *lpServiceArgVectors)
2823 {
2824 DWORD dwError;
2825
2826 TRACE("StartServiceA(%p %lu %p)\n",
2827 hService, dwNumServiceArgs, lpServiceArgVectors);
2828
2829 RpcTryExcept
2830 {
2831 dwError = RStartServiceA((SC_RPC_HANDLE)hService,
2832 dwNumServiceArgs,
2833 (LPSTRING_PTRSA)lpServiceArgVectors);
2834 }
2835 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2836 {
2837 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2838 }
2839 RpcEndExcept;
2840
2841 if (dwError != ERROR_SUCCESS)
2842 {
2843 ERR("RStartServiceA() failed (Error %lu)\n", dwError);
2844 SetLastError(dwError);
2845 return FALSE;
2846 }
2847
2848 return TRUE;
2849 }
2850
2851
2852 /**********************************************************************
2853 * StartServiceW
2854 *
2855 * @implemented
2856 */
2857 BOOL WINAPI
2858 StartServiceW(SC_HANDLE hService,
2859 DWORD dwNumServiceArgs,
2860 LPCWSTR *lpServiceArgVectors)
2861 {
2862 DWORD dwError;
2863
2864 TRACE("StartServiceW(%p %lu %p)\n",
2865 hService, dwNumServiceArgs, lpServiceArgVectors);
2866
2867 RpcTryExcept
2868 {
2869 dwError = RStartServiceW((SC_RPC_HANDLE)hService,
2870 dwNumServiceArgs,
2871 (LPSTRING_PTRSW)lpServiceArgVectors);
2872 }
2873 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2874 {
2875 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2876 }
2877 RpcEndExcept;
2878
2879 if (dwError != ERROR_SUCCESS)
2880 {
2881 ERR("RStartServiceW() failed (Error %lu)\n", dwError);
2882 SetLastError(dwError);
2883 return FALSE;
2884 }
2885
2886 return TRUE;
2887 }
2888
2889
2890 /**********************************************************************
2891 * UnlockServiceDatabase
2892 *
2893 * @implemented
2894 */
2895 BOOL WINAPI
2896 UnlockServiceDatabase(SC_LOCK ScLock)
2897 {
2898 DWORD dwError;
2899
2900 TRACE("UnlockServiceDatabase(%x)\n",
2901 ScLock);
2902
2903 RpcTryExcept
2904 {
2905 dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
2906 }
2907 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2908 {
2909 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2910 }
2911 RpcEndExcept;
2912
2913 if (dwError == ERROR_INVALID_HANDLE)
2914 dwError = ERROR_INVALID_SERVICE_LOCK;
2915
2916 if (dwError != ERROR_SUCCESS)
2917 {
2918 TRACE("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
2919 SetLastError(dwError);
2920 return FALSE;
2921 }
2922
2923 return TRUE;
2924 }
2925
2926
2927 /**********************************************************************
2928 * NotifyBootConfigStatus
2929 *
2930 * @implemented
2931 */
2932 BOOL WINAPI
2933 NotifyBootConfigStatus(BOOL BootAcceptable)
2934 {
2935 DWORD dwError;
2936
2937 TRACE("NotifyBootConfigStatus(%u)\n",
2938 BootAcceptable);
2939
2940 RpcTryExcept
2941 {
2942 dwError = RNotifyBootConfigStatus(NULL,
2943 BootAcceptable);
2944 }
2945 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2946 {
2947 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2948 }
2949 RpcEndExcept;
2950
2951 if (dwError != ERROR_SUCCESS)
2952 {
2953 TRACE("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
2954 SetLastError(dwError);
2955 return FALSE;
2956 }
2957
2958 return TRUE;
2959 }
2960
2961 /* EOF */