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