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