08baad1cb902d83e651c9b28f65f0579ff032659
[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 /*
1697 * NOTE: A size of 1 character would be enough, but tests show that
1698 * Windows returns 2 characters instead, certainly due to a WCHAR/bytes
1699 * mismatch in their code.
1700 */
1701 if (!lpDisplayName || *lpcchBuffer < sizeof(WCHAR))
1702 {
1703 lpNameBuffer = szEmptyName;
1704 *lpcchBuffer = sizeof(WCHAR);
1705 }
1706 else
1707 {
1708 lpNameBuffer = lpDisplayName;
1709 }
1710
1711 RpcTryExcept
1712 {
1713 dwError = RGetServiceDisplayNameW((SC_RPC_HANDLE)hSCManager,
1714 lpServiceName,
1715 lpNameBuffer,
1716 lpcchBuffer);
1717 }
1718 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1719 {
1720 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1721 }
1722 RpcEndExcept;
1723
1724 if (dwError != ERROR_SUCCESS)
1725 {
1726 TRACE("RGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
1727 SetLastError(dwError);
1728 return FALSE;
1729 }
1730
1731 return TRUE;
1732 }
1733
1734
1735 /**********************************************************************
1736 * GetServiceKeyNameA
1737 *
1738 * @implemented
1739 */
1740 BOOL WINAPI
1741 GetServiceKeyNameA(SC_HANDLE hSCManager,
1742 LPCSTR lpDisplayName,
1743 LPSTR lpServiceName,
1744 LPDWORD lpcchBuffer)
1745 {
1746 DWORD dwError;
1747 LPSTR lpNameBuffer;
1748 CHAR szEmptyName[] = "";
1749
1750 TRACE("GetServiceKeyNameA(%p %s %p %p)\n",
1751 hSCManager, debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1752
1753 if (!hSCManager)
1754 {
1755 SetLastError(ERROR_INVALID_HANDLE);
1756 return FALSE;
1757 }
1758
1759 if (!lpServiceName || *lpcchBuffer < sizeof(CHAR))
1760 {
1761 lpNameBuffer = szEmptyName;
1762 *lpcchBuffer = sizeof(CHAR);
1763 }
1764 else
1765 {
1766 lpNameBuffer = lpServiceName;
1767 }
1768
1769 RpcTryExcept
1770 {
1771 dwError = RGetServiceKeyNameA((SC_RPC_HANDLE)hSCManager,
1772 lpDisplayName,
1773 lpNameBuffer,
1774 lpcchBuffer);
1775 }
1776 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1777 {
1778 /* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
1779 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1780 }
1781 RpcEndExcept;
1782
1783 if (dwError != ERROR_SUCCESS)
1784 {
1785 TRACE("RGetServiceKeyNameA() failed (Error %lu)\n", dwError);
1786 SetLastError(dwError);
1787 return FALSE;
1788 }
1789
1790 return TRUE;
1791 }
1792
1793
1794 /**********************************************************************
1795 * GetServiceKeyNameW
1796 *
1797 * @implemented
1798 */
1799 BOOL WINAPI
1800 GetServiceKeyNameW(SC_HANDLE hSCManager,
1801 LPCWSTR lpDisplayName,
1802 LPWSTR lpServiceName,
1803 LPDWORD lpcchBuffer)
1804 {
1805 DWORD dwError;
1806 LPWSTR lpNameBuffer;
1807 WCHAR szEmptyName[] = L"";
1808
1809 TRACE("GetServiceKeyNameW(%p %s %p %p)\n",
1810 hSCManager, debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1811
1812 if (!hSCManager)
1813 {
1814 SetLastError(ERROR_INVALID_HANDLE);
1815 return FALSE;
1816 }
1817
1818 /*
1819 * NOTE: A size of 1 character would be enough, but tests show that
1820 * Windows returns 2 characters instead, certainly due to a WCHAR/bytes
1821 * mismatch in their code.
1822 */
1823 if (!lpServiceName || *lpcchBuffer < sizeof(WCHAR))
1824 {
1825 lpNameBuffer = szEmptyName;
1826 *lpcchBuffer = sizeof(WCHAR);
1827 }
1828 else
1829 {
1830 lpNameBuffer = lpServiceName;
1831 }
1832
1833 RpcTryExcept
1834 {
1835 dwError = RGetServiceKeyNameW((SC_RPC_HANDLE)hSCManager,
1836 lpDisplayName,
1837 lpNameBuffer,
1838 lpcchBuffer);
1839 }
1840 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1841 {
1842 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1843 }
1844 RpcEndExcept;
1845
1846 if (dwError != ERROR_SUCCESS)
1847 {
1848 TRACE("RGetServiceKeyNameW() failed (Error %lu)\n", dwError);
1849 SetLastError(dwError);
1850 return FALSE;
1851 }
1852
1853 return TRUE;
1854 }
1855
1856
1857 /**********************************************************************
1858 * I_ScGetCurrentGroupStateW
1859 *
1860 * @implemented
1861 */
1862 DWORD WINAPI
1863 I_ScGetCurrentGroupStateW(SC_HANDLE hSCManager,
1864 LPWSTR pszGroupName,
1865 LPDWORD pdwGroupState)
1866 {
1867 DWORD dwError;
1868
1869 TRACE("I_ScGetCurrentGroupStateW(%p %s %p)\n",
1870 hSCManager, debugstr_w(pszGroupName), pdwGroupState);
1871
1872 RpcTryExcept
1873 {
1874 dwError = RI_ScGetCurrentGroupStateW((SC_RPC_HANDLE)hSCManager,
1875 pszGroupName,
1876 pdwGroupState);
1877 }
1878 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1879 {
1880 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1881 }
1882 RpcEndExcept
1883
1884 if (dwError != ERROR_SUCCESS)
1885 {
1886 TRACE("RI_ScGetCurrentGroupStateW() failed (Error %lu)\n", dwError);
1887 SetLastError(dwError);
1888 }
1889
1890 return dwError;
1891 }
1892
1893
1894 /**********************************************************************
1895 * LockServiceDatabase
1896 *
1897 * @implemented
1898 */
1899 SC_LOCK WINAPI
1900 LockServiceDatabase(SC_HANDLE hSCManager)
1901 {
1902 SC_LOCK hLock;
1903 DWORD dwError;
1904
1905 TRACE("LockServiceDatabase(%p)\n",
1906 hSCManager);
1907
1908 RpcTryExcept
1909 {
1910 dwError = RLockServiceDatabase((SC_RPC_HANDLE)hSCManager,
1911 (SC_RPC_LOCK *)&hLock);
1912 }
1913 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1914 {
1915 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1916 }
1917 RpcEndExcept;
1918
1919 if (dwError != ERROR_SUCCESS)
1920 {
1921 TRACE("RLockServiceDatabase() failed (Error %lu)\n", dwError);
1922 SetLastError(dwError);
1923 return NULL;
1924 }
1925
1926 TRACE("hLock = %p\n", hLock);
1927
1928 return hLock;
1929 }
1930
1931
1932 static VOID
1933 WaitForSCManager(VOID)
1934 {
1935 HANDLE hEvent;
1936
1937 TRACE("WaitForSCManager()\n");
1938
1939 /* Try to open the existing event */
1940 hEvent = OpenEventW(SYNCHRONIZE, FALSE, SCM_START_EVENT);
1941 if (hEvent == NULL)
1942 {
1943 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1944 return;
1945
1946 /* Try to create a new event */
1947 hEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
1948 if (hEvent == NULL)
1949 return;
1950 }
1951
1952 /* Wait for 3 minutes */
1953 WaitForSingleObject(hEvent, 180000);
1954 CloseHandle(hEvent);
1955
1956 TRACE("ScmWaitForSCManager() done\n");
1957 }
1958
1959
1960 /**********************************************************************
1961 * OpenSCManagerA
1962 *
1963 * @implemented
1964 */
1965 SC_HANDLE WINAPI
1966 OpenSCManagerA(LPCSTR lpMachineName,
1967 LPCSTR lpDatabaseName,
1968 DWORD dwDesiredAccess)
1969 {
1970 SC_HANDLE hScm = NULL;
1971 DWORD dwError;
1972
1973 TRACE("OpenSCManagerA(%s %s %lx)\n",
1974 debugstr_a(lpMachineName), debugstr_a(lpDatabaseName), dwDesiredAccess);
1975
1976 WaitForSCManager();
1977
1978 RpcTryExcept
1979 {
1980 dwError = ROpenSCManagerA((LPSTR)lpMachineName,
1981 (LPSTR)lpDatabaseName,
1982 dwDesiredAccess,
1983 (SC_RPC_HANDLE *)&hScm);
1984 }
1985 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1986 {
1987 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1988 }
1989 RpcEndExcept;
1990
1991 if (dwError != ERROR_SUCCESS)
1992 {
1993 TRACE("ROpenSCManagerA() failed (Error %lu)\n", dwError);
1994 SetLastError(dwError);
1995 return NULL;
1996 }
1997
1998 TRACE("hScm = %p\n", hScm);
1999
2000 return hScm;
2001 }
2002
2003
2004 /**********************************************************************
2005 * OpenSCManagerW
2006 *
2007 * @implemented
2008 */
2009 SC_HANDLE WINAPI
2010 OpenSCManagerW(LPCWSTR lpMachineName,
2011 LPCWSTR lpDatabaseName,
2012 DWORD dwDesiredAccess)
2013 {
2014 SC_HANDLE hScm = NULL;
2015 DWORD dwError;
2016
2017 TRACE("OpenSCManagerW(%s %s %lx)\n",
2018 debugstr_w(lpMachineName), debugstr_w(lpDatabaseName), dwDesiredAccess);
2019
2020 WaitForSCManager();
2021
2022 RpcTryExcept
2023 {
2024 dwError = ROpenSCManagerW((LPWSTR)lpMachineName,
2025 (LPWSTR)lpDatabaseName,
2026 dwDesiredAccess,
2027 (SC_RPC_HANDLE *)&hScm);
2028 }
2029 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2030 {
2031 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2032 }
2033 RpcEndExcept;
2034
2035 if (dwError != ERROR_SUCCESS)
2036 {
2037 TRACE("ROpenSCManagerW() failed (Error %lu)\n", dwError);
2038 SetLastError(dwError);
2039 return NULL;
2040 }
2041
2042 TRACE("hScm = %p\n", hScm);
2043
2044 return hScm;
2045 }
2046
2047
2048 /**********************************************************************
2049 * OpenServiceA
2050 *
2051 * @implemented
2052 */
2053 SC_HANDLE WINAPI
2054 OpenServiceA(SC_HANDLE hSCManager,
2055 LPCSTR lpServiceName,
2056 DWORD dwDesiredAccess)
2057 {
2058 SC_HANDLE hService = NULL;
2059 DWORD dwError;
2060
2061 TRACE("OpenServiceA(%p %s %lx)\n",
2062 hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
2063
2064 if (!hSCManager)
2065 {
2066 SetLastError(ERROR_INVALID_HANDLE);
2067 return NULL;
2068 }
2069
2070 RpcTryExcept
2071 {
2072 dwError = ROpenServiceA((SC_RPC_HANDLE)hSCManager,
2073 (LPSTR)lpServiceName,
2074 dwDesiredAccess,
2075 (SC_RPC_HANDLE *)&hService);
2076 }
2077 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2078 {
2079 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2080 }
2081 RpcEndExcept;
2082
2083 SetLastError(dwError);
2084 if (dwError != ERROR_SUCCESS)
2085 {
2086 TRACE("ROpenServiceA() failed (Error %lu)\n", dwError);
2087 return NULL;
2088 }
2089
2090 TRACE("hService = %p\n", hService);
2091
2092 return hService;
2093 }
2094
2095
2096 /**********************************************************************
2097 * OpenServiceW
2098 *
2099 * @implemented
2100 */
2101 SC_HANDLE WINAPI
2102 OpenServiceW(SC_HANDLE hSCManager,
2103 LPCWSTR lpServiceName,
2104 DWORD dwDesiredAccess)
2105 {
2106 SC_HANDLE hService = NULL;
2107 DWORD dwError;
2108
2109 TRACE("OpenServiceW(%p %s %lx)\n",
2110 hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
2111
2112 if (!hSCManager)
2113 {
2114 SetLastError(ERROR_INVALID_HANDLE);
2115 return NULL;
2116 }
2117
2118 RpcTryExcept
2119 {
2120 dwError = ROpenServiceW((SC_RPC_HANDLE)hSCManager,
2121 (LPWSTR)lpServiceName,
2122 dwDesiredAccess,
2123 (SC_RPC_HANDLE *)&hService);
2124 }
2125 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2126 {
2127 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2128 }
2129 RpcEndExcept;
2130
2131 SetLastError(dwError);
2132 if (dwError != ERROR_SUCCESS)
2133 {
2134 TRACE("ROpenServiceW() failed (Error %lu)\n", dwError);
2135 return NULL;
2136 }
2137
2138 TRACE("hService = %p\n", hService);
2139
2140 return hService;
2141 }
2142
2143
2144 /**********************************************************************
2145 * QueryServiceConfigA
2146 *
2147 * @implemented
2148 */
2149 BOOL WINAPI
2150 QueryServiceConfigA(SC_HANDLE hService,
2151 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
2152 DWORD cbBufSize,
2153 LPDWORD pcbBytesNeeded)
2154 {
2155 QUERY_SERVICE_CONFIGA ServiceConfig;
2156 LPQUERY_SERVICE_CONFIGA lpConfigPtr;
2157 DWORD dwBufferSize;
2158 DWORD dwError;
2159
2160 TRACE("QueryServiceConfigA(%p %p %lu %p)\n",
2161 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
2162
2163 if (lpServiceConfig == NULL ||
2164 cbBufSize < sizeof(QUERY_SERVICE_CONFIGA))
2165 {
2166 lpConfigPtr = &ServiceConfig;
2167 dwBufferSize = sizeof(QUERY_SERVICE_CONFIGA);
2168 }
2169 else
2170 {
2171 lpConfigPtr = lpServiceConfig;
2172 dwBufferSize = cbBufSize;
2173 }
2174
2175 RpcTryExcept
2176 {
2177 dwError = RQueryServiceConfigA((SC_RPC_HANDLE)hService,
2178 (LPBYTE)lpConfigPtr,
2179 dwBufferSize,
2180 pcbBytesNeeded);
2181 }
2182 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2183 {
2184 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2185 }
2186 RpcEndExcept;
2187
2188 if (dwError != ERROR_SUCCESS)
2189 {
2190 TRACE("RQueryServiceConfigA() failed (Error %lu)\n", dwError);
2191 SetLastError(dwError);
2192 return FALSE;
2193 }
2194
2195 /* Adjust the pointers */
2196 if (lpConfigPtr->lpBinaryPathName)
2197 lpConfigPtr->lpBinaryPathName =
2198 (LPSTR)((ULONG_PTR)lpConfigPtr +
2199 (ULONG_PTR)lpConfigPtr->lpBinaryPathName);
2200
2201 if (lpConfigPtr->lpLoadOrderGroup)
2202 lpConfigPtr->lpLoadOrderGroup =
2203 (LPSTR)((ULONG_PTR)lpConfigPtr +
2204 (ULONG_PTR)lpConfigPtr->lpLoadOrderGroup);
2205
2206 if (lpConfigPtr->lpDependencies)
2207 lpConfigPtr->lpDependencies =
2208 (LPSTR)((ULONG_PTR)lpConfigPtr +
2209 (ULONG_PTR)lpConfigPtr->lpDependencies);
2210
2211 if (lpConfigPtr->lpServiceStartName)
2212 lpConfigPtr->lpServiceStartName =
2213 (LPSTR)((ULONG_PTR)lpConfigPtr +
2214 (ULONG_PTR)lpConfigPtr->lpServiceStartName);
2215
2216 if (lpConfigPtr->lpDisplayName)
2217 lpConfigPtr->lpDisplayName =
2218 (LPSTR)((ULONG_PTR)lpConfigPtr +
2219 (ULONG_PTR)lpConfigPtr->lpDisplayName);
2220
2221 TRACE("QueryServiceConfigA() done\n");
2222
2223 return TRUE;
2224 }
2225
2226
2227 /**********************************************************************
2228 * QueryServiceConfigW
2229 *
2230 * @implemented
2231 */
2232 BOOL WINAPI
2233 QueryServiceConfigW(SC_HANDLE hService,
2234 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2235 DWORD cbBufSize,
2236 LPDWORD pcbBytesNeeded)
2237 {
2238 QUERY_SERVICE_CONFIGW ServiceConfig;
2239 LPQUERY_SERVICE_CONFIGW lpConfigPtr;
2240 DWORD dwBufferSize;
2241 DWORD dwError;
2242
2243 TRACE("QueryServiceConfigW(%p %p %lu %p)\n",
2244 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
2245
2246 if (lpServiceConfig == NULL ||
2247 cbBufSize < sizeof(QUERY_SERVICE_CONFIGW))
2248 {
2249 lpConfigPtr = &ServiceConfig;
2250 dwBufferSize = sizeof(QUERY_SERVICE_CONFIGW);
2251 }
2252 else
2253 {
2254 lpConfigPtr = lpServiceConfig;
2255 dwBufferSize = cbBufSize;
2256 }
2257
2258 RpcTryExcept
2259 {
2260 dwError = RQueryServiceConfigW((SC_RPC_HANDLE)hService,
2261 (LPBYTE)lpConfigPtr,
2262 dwBufferSize,
2263 pcbBytesNeeded);
2264 }
2265 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2266 {
2267 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2268 }
2269 RpcEndExcept;
2270
2271 if (dwError != ERROR_SUCCESS)
2272 {
2273 TRACE("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
2274 SetLastError(dwError);
2275 return FALSE;
2276 }
2277
2278 /* Adjust the pointers */
2279 if (lpConfigPtr->lpBinaryPathName)
2280 lpConfigPtr->lpBinaryPathName =
2281 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2282 (ULONG_PTR)lpConfigPtr->lpBinaryPathName);
2283
2284 if (lpConfigPtr->lpLoadOrderGroup)
2285 lpConfigPtr->lpLoadOrderGroup =
2286 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2287 (ULONG_PTR)lpConfigPtr->lpLoadOrderGroup);
2288
2289 if (lpConfigPtr->lpDependencies)
2290 lpConfigPtr->lpDependencies =
2291 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2292 (ULONG_PTR)lpConfigPtr->lpDependencies);
2293
2294 if (lpConfigPtr->lpServiceStartName)
2295 lpConfigPtr->lpServiceStartName =
2296 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2297 (ULONG_PTR)lpConfigPtr->lpServiceStartName);
2298
2299 if (lpConfigPtr->lpDisplayName)
2300 lpConfigPtr->lpDisplayName =
2301 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2302 (ULONG_PTR)lpConfigPtr->lpDisplayName);
2303
2304 TRACE("QueryServiceConfigW() done\n");
2305
2306 return TRUE;
2307 }
2308
2309
2310 /**********************************************************************
2311 * QueryServiceConfig2A
2312 *
2313 * @implemented
2314 */
2315 BOOL WINAPI
2316 QueryServiceConfig2A(SC_HANDLE hService,
2317 DWORD dwInfoLevel,
2318 LPBYTE lpBuffer,
2319 DWORD cbBufSize,
2320 LPDWORD pcbBytesNeeded)
2321 {
2322 SERVICE_DESCRIPTIONA ServiceDescription;
2323 SERVICE_FAILURE_ACTIONSA ServiceFailureActions;
2324 LPBYTE lpTempBuffer;
2325 BOOL bUseTempBuffer = FALSE;
2326 DWORD dwBufferSize;
2327 DWORD dwError;
2328
2329 TRACE("QueryServiceConfig2A(%p %lu %p %lu %p)\n",
2330 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2331
2332 lpTempBuffer = lpBuffer;
2333 dwBufferSize = cbBufSize;
2334
2335 switch (dwInfoLevel)
2336 {
2337 case SERVICE_CONFIG_DESCRIPTION:
2338 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONA)))
2339 {
2340 lpTempBuffer = (LPBYTE)&ServiceDescription;
2341 dwBufferSize = sizeof(SERVICE_DESCRIPTIONA);
2342 bUseTempBuffer = TRUE;
2343 }
2344 break;
2345
2346 case SERVICE_CONFIG_FAILURE_ACTIONS:
2347 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSA)))
2348 {
2349 lpTempBuffer = (LPBYTE)&ServiceFailureActions;
2350 dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSA);
2351 bUseTempBuffer = TRUE;
2352 }
2353 break;
2354
2355 default:
2356 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
2357 SetLastError(ERROR_INVALID_LEVEL);
2358 return FALSE;
2359 }
2360
2361 RpcTryExcept
2362 {
2363 dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
2364 dwInfoLevel,
2365 lpTempBuffer,
2366 dwBufferSize,
2367 pcbBytesNeeded);
2368 }
2369 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2370 {
2371 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2372 }
2373 RpcEndExcept;
2374
2375 if (dwError != ERROR_SUCCESS)
2376 {
2377 TRACE("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
2378 SetLastError(dwError);
2379 return FALSE;
2380 }
2381
2382 if (bUseTempBuffer != FALSE)
2383 {
2384 TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n");
2385 *pcbBytesNeeded = dwBufferSize;
2386 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2387 return FALSE;
2388 }
2389
2390 switch (dwInfoLevel)
2391 {
2392 case SERVICE_CONFIG_DESCRIPTION:
2393 {
2394 LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpTempBuffer;
2395
2396 if (lpPtr->lpDescription != NULL)
2397 lpPtr->lpDescription =
2398 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
2399 }
2400 break;
2401
2402 case SERVICE_CONFIG_FAILURE_ACTIONS:
2403 {
2404 LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpTempBuffer;
2405
2406 if (lpPtr->lpRebootMsg != NULL)
2407 lpPtr->lpRebootMsg =
2408 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
2409
2410 if (lpPtr->lpCommand != NULL)
2411 lpPtr->lpCommand =
2412 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
2413
2414 if (lpPtr->lpsaActions != NULL)
2415 lpPtr->lpsaActions =
2416 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
2417 }
2418 break;
2419 }
2420
2421 TRACE("QueryServiceConfig2A() done\n");
2422
2423 return TRUE;
2424 }
2425
2426
2427 /**********************************************************************
2428 * QueryServiceConfig2W
2429 *
2430 * @implemented
2431 */
2432 BOOL WINAPI
2433 QueryServiceConfig2W(SC_HANDLE hService,
2434 DWORD dwInfoLevel,
2435 LPBYTE lpBuffer,
2436 DWORD cbBufSize,
2437 LPDWORD pcbBytesNeeded)
2438 {
2439 SERVICE_DESCRIPTIONW ServiceDescription;
2440 SERVICE_FAILURE_ACTIONSW ServiceFailureActions;
2441 LPBYTE lpTempBuffer;
2442 BOOL bUseTempBuffer = FALSE;
2443 DWORD dwBufferSize;
2444 DWORD dwError;
2445
2446 TRACE("QueryServiceConfig2W(%p %lu %p %lu %p)\n",
2447 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2448
2449 lpTempBuffer = lpBuffer;
2450 dwBufferSize = cbBufSize;
2451
2452 switch (dwInfoLevel)
2453 {
2454 case SERVICE_CONFIG_DESCRIPTION:
2455 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONW)))
2456 {
2457 lpTempBuffer = (LPBYTE)&ServiceDescription;
2458 dwBufferSize = sizeof(SERVICE_DESCRIPTIONW);
2459 bUseTempBuffer = TRUE;
2460 }
2461 break;
2462
2463 case SERVICE_CONFIG_FAILURE_ACTIONS:
2464 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSW)))
2465 {
2466 lpTempBuffer = (LPBYTE)&ServiceFailureActions;
2467 dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSW);
2468 bUseTempBuffer = TRUE;
2469 }
2470 break;
2471
2472 default:
2473 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
2474 SetLastError(ERROR_INVALID_LEVEL);
2475 return FALSE;
2476 }
2477
2478 RpcTryExcept
2479 {
2480 dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
2481 dwInfoLevel,
2482 lpTempBuffer,
2483 dwBufferSize,
2484 pcbBytesNeeded);
2485 }
2486 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2487 {
2488 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2489 }
2490 RpcEndExcept;
2491
2492 if (dwError != ERROR_SUCCESS)
2493 {
2494 TRACE("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
2495 SetLastError(dwError);
2496 return FALSE;
2497 }
2498
2499 if (bUseTempBuffer != FALSE)
2500 {
2501 TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n");
2502 *pcbBytesNeeded = dwBufferSize;
2503 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2504 return FALSE;
2505 }
2506
2507 switch (dwInfoLevel)
2508 {
2509 case SERVICE_CONFIG_DESCRIPTION:
2510 {
2511 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer;
2512
2513 if (lpPtr->lpDescription != NULL)
2514 lpPtr->lpDescription =
2515 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
2516 }
2517 break;
2518
2519 case SERVICE_CONFIG_FAILURE_ACTIONS:
2520 {
2521 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpTempBuffer;
2522
2523 if (lpPtr->lpRebootMsg != NULL)
2524 lpPtr->lpRebootMsg =
2525 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
2526
2527 if (lpPtr->lpCommand != NULL)
2528 lpPtr->lpCommand =
2529 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
2530
2531 if (lpPtr->lpsaActions != NULL)
2532 lpPtr->lpsaActions =
2533 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
2534 }
2535 break;
2536 }
2537
2538 TRACE("QueryServiceConfig2W() done\n");
2539
2540 return TRUE;
2541 }
2542
2543
2544 /**********************************************************************
2545 * QueryServiceLockStatusA
2546 *
2547 * @implemented
2548 */
2549 BOOL WINAPI
2550 QueryServiceLockStatusA(SC_HANDLE hSCManager,
2551 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
2552 DWORD cbBufSize,
2553 LPDWORD pcbBytesNeeded)
2554 {
2555 QUERY_SERVICE_LOCK_STATUSA LockStatus;
2556 LPQUERY_SERVICE_LOCK_STATUSA lpStatusPtr;
2557 DWORD dwBufferSize;
2558 DWORD dwError;
2559
2560 TRACE("QueryServiceLockStatusA(%p %p %lu %p)\n",
2561 hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
2562
2563 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA))
2564 {
2565 lpStatusPtr = &LockStatus;
2566 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSA);
2567 }
2568 else
2569 {
2570 lpStatusPtr = lpLockStatus;
2571 dwBufferSize = cbBufSize;
2572 }
2573
2574 RpcTryExcept
2575 {
2576 dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
2577 (LPBYTE)lpStatusPtr,
2578 dwBufferSize,
2579 pcbBytesNeeded);
2580 }
2581 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2582 {
2583 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2584 }
2585 RpcEndExcept;
2586
2587 if (dwError != ERROR_SUCCESS)
2588 {
2589 TRACE("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
2590 SetLastError(dwError);
2591 return FALSE;
2592 }
2593
2594 if (lpStatusPtr->lpLockOwner != NULL)
2595 {
2596 lpStatusPtr->lpLockOwner =
2597 (LPSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
2598 }
2599
2600 TRACE("QueryServiceLockStatusA() done\n");
2601
2602 return TRUE;
2603 }
2604
2605
2606 /**********************************************************************
2607 * QueryServiceLockStatusW
2608 *
2609 * @implemented
2610 */
2611 BOOL WINAPI
2612 QueryServiceLockStatusW(SC_HANDLE hSCManager,
2613 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
2614 DWORD cbBufSize,
2615 LPDWORD pcbBytesNeeded)
2616 {
2617 QUERY_SERVICE_LOCK_STATUSW LockStatus;
2618 LPQUERY_SERVICE_LOCK_STATUSW lpStatusPtr;
2619 DWORD dwBufferSize;
2620 DWORD dwError;
2621
2622 TRACE("QueryServiceLockStatusW(%p %p %lu %p)\n",
2623 hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
2624
2625 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW))
2626 {
2627 lpStatusPtr = &LockStatus;
2628 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSW);
2629 }
2630 else
2631 {
2632 lpStatusPtr = lpLockStatus;
2633 dwBufferSize = cbBufSize;
2634 }
2635
2636 RpcTryExcept
2637 {
2638 dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
2639 (LPBYTE)lpStatusPtr,
2640 dwBufferSize,
2641 pcbBytesNeeded);
2642 }
2643 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2644 {
2645 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2646 }
2647 RpcEndExcept;
2648
2649 if (dwError != ERROR_SUCCESS)
2650 {
2651 TRACE("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
2652 SetLastError(dwError);
2653 return FALSE;
2654 }
2655
2656 if (lpStatusPtr->lpLockOwner != NULL)
2657 {
2658 lpStatusPtr->lpLockOwner =
2659 (LPWSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
2660 }
2661
2662 TRACE("QueryServiceLockStatusW() done\n");
2663
2664 return TRUE;
2665 }
2666
2667
2668 /**********************************************************************
2669 * QueryServiceObjectSecurity
2670 *
2671 * @implemented
2672 */
2673 BOOL WINAPI
2674 QueryServiceObjectSecurity(SC_HANDLE hService,
2675 SECURITY_INFORMATION dwSecurityInformation,
2676 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2677 DWORD cbBufSize,
2678 LPDWORD pcbBytesNeeded)
2679 {
2680 DWORD dwError;
2681
2682 TRACE("QueryServiceObjectSecurity(%p %lu %p)\n",
2683 hService, dwSecurityInformation, lpSecurityDescriptor);
2684
2685 RpcTryExcept
2686 {
2687 dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
2688 dwSecurityInformation,
2689 (LPBYTE)lpSecurityDescriptor,
2690 cbBufSize,
2691 pcbBytesNeeded);
2692 }
2693 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2694 {
2695 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2696 }
2697 RpcEndExcept;
2698
2699 if (dwError != ERROR_SUCCESS)
2700 {
2701 TRACE("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
2702 SetLastError(dwError);
2703 return FALSE;
2704 }
2705
2706 return TRUE;
2707 }
2708
2709
2710 /**********************************************************************
2711 * SetServiceObjectSecurity
2712 *
2713 * @implemented
2714 */
2715 BOOL WINAPI
2716 SetServiceObjectSecurity(SC_HANDLE hService,
2717 SECURITY_INFORMATION dwSecurityInformation,
2718 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2719 {
2720 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
2721 ULONG Length;
2722 NTSTATUS Status;
2723 DWORD dwError;
2724
2725 TRACE("SetServiceObjectSecurity(%p %lu %p)\n",
2726 hService, dwSecurityInformation, lpSecurityDescriptor);
2727
2728 Length = 0;
2729 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2730 SelfRelativeSD,
2731 &Length);
2732 if (Status != STATUS_BUFFER_TOO_SMALL)
2733 {
2734 SetLastError(ERROR_INVALID_PARAMETER);
2735 return FALSE;
2736 }
2737
2738 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
2739 if (SelfRelativeSD == NULL)
2740 {
2741 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2742 return FALSE;
2743 }
2744
2745 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2746 SelfRelativeSD,
2747 &Length);
2748 if (!NT_SUCCESS(Status))
2749 {
2750 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2751 SetLastError(RtlNtStatusToDosError(Status));
2752 return FALSE;
2753 }
2754
2755 RpcTryExcept
2756 {
2757 dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
2758 dwSecurityInformation,
2759 (LPBYTE)SelfRelativeSD,
2760 Length);
2761 }
2762 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2763 {
2764 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2765 }
2766 RpcEndExcept;
2767
2768 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2769
2770 if (dwError != ERROR_SUCCESS)
2771 {
2772 TRACE("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
2773 SetLastError(dwError);
2774 return FALSE;
2775 }
2776
2777 return TRUE;
2778 }
2779
2780
2781 /**********************************************************************
2782 * QueryServiceStatus
2783 *
2784 * @implemented
2785 */
2786 BOOL WINAPI
2787 QueryServiceStatus(SC_HANDLE hService,
2788 LPSERVICE_STATUS lpServiceStatus)
2789 {
2790 DWORD dwError;
2791
2792 TRACE("QueryServiceStatus(%p %p)\n",
2793 hService, lpServiceStatus);
2794
2795 if (!hService)
2796 {
2797 SetLastError(ERROR_INVALID_HANDLE);
2798 return FALSE;
2799 }
2800
2801 RpcTryExcept
2802 {
2803 dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
2804 lpServiceStatus);
2805 }
2806 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2807 {
2808 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2809 }
2810 RpcEndExcept;
2811
2812 if (dwError != ERROR_SUCCESS)
2813 {
2814 TRACE("RQueryServiceStatus() failed (Error %lu)\n", dwError);
2815 SetLastError(dwError);
2816 return FALSE;
2817 }
2818
2819 return TRUE;
2820 }
2821
2822
2823 /**********************************************************************
2824 * QueryServiceStatusEx
2825 *
2826 * @implemented
2827 */
2828 BOOL WINAPI
2829 QueryServiceStatusEx(SC_HANDLE hService,
2830 SC_STATUS_TYPE InfoLevel,
2831 LPBYTE lpBuffer,
2832 DWORD cbBufSize,
2833 LPDWORD pcbBytesNeeded)
2834 {
2835 DWORD dwError;
2836
2837 TRACE("QueryServiceStatusEx(%p %lu %p %lu %p)\n",
2838 hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2839
2840 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2841 {
2842 SetLastError(ERROR_INVALID_LEVEL);
2843 return FALSE;
2844 }
2845
2846 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2847 {
2848 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2849 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2850 return FALSE;
2851 }
2852
2853 RpcTryExcept
2854 {
2855 dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
2856 InfoLevel,
2857 lpBuffer,
2858 cbBufSize,
2859 pcbBytesNeeded);
2860 }
2861 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2862 {
2863 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2864 }
2865 RpcEndExcept;
2866
2867 if (dwError != ERROR_SUCCESS)
2868 {
2869 TRACE("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
2870 SetLastError(dwError);
2871 return FALSE;
2872 }
2873
2874 return TRUE;
2875 }
2876
2877
2878 /**********************************************************************
2879 * StartServiceA
2880 *
2881 * @implemented
2882 */
2883 BOOL WINAPI
2884 StartServiceA(SC_HANDLE hService,
2885 DWORD dwNumServiceArgs,
2886 LPCSTR *lpServiceArgVectors)
2887 {
2888 DWORD dwError;
2889
2890 TRACE("StartServiceA(%p %lu %p)\n",
2891 hService, dwNumServiceArgs, lpServiceArgVectors);
2892
2893 RpcTryExcept
2894 {
2895 dwError = RStartServiceA((SC_RPC_HANDLE)hService,
2896 dwNumServiceArgs,
2897 (LPSTRING_PTRSA)lpServiceArgVectors);
2898 }
2899 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2900 {
2901 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2902 }
2903 RpcEndExcept;
2904
2905 if (dwError != ERROR_SUCCESS)
2906 {
2907 ERR("RStartServiceA() failed (Error %lu)\n", dwError);
2908 SetLastError(dwError);
2909 return FALSE;
2910 }
2911
2912 return TRUE;
2913 }
2914
2915
2916 /**********************************************************************
2917 * StartServiceW
2918 *
2919 * @implemented
2920 */
2921 BOOL WINAPI
2922 StartServiceW(SC_HANDLE hService,
2923 DWORD dwNumServiceArgs,
2924 LPCWSTR *lpServiceArgVectors)
2925 {
2926 DWORD dwError;
2927
2928 TRACE("StartServiceW(%p %lu %p)\n",
2929 hService, dwNumServiceArgs, lpServiceArgVectors);
2930
2931 RpcTryExcept
2932 {
2933 dwError = RStartServiceW((SC_RPC_HANDLE)hService,
2934 dwNumServiceArgs,
2935 (LPSTRING_PTRSW)lpServiceArgVectors);
2936 }
2937 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2938 {
2939 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2940 }
2941 RpcEndExcept;
2942
2943 if (dwError != ERROR_SUCCESS)
2944 {
2945 ERR("RStartServiceW() failed (Error %lu)\n", dwError);
2946 SetLastError(dwError);
2947 return FALSE;
2948 }
2949
2950 return TRUE;
2951 }
2952
2953
2954 /**********************************************************************
2955 * UnlockServiceDatabase
2956 *
2957 * @implemented
2958 */
2959 BOOL WINAPI
2960 UnlockServiceDatabase(SC_LOCK ScLock)
2961 {
2962 DWORD dwError;
2963
2964 TRACE("UnlockServiceDatabase(%x)\n",
2965 ScLock);
2966
2967 RpcTryExcept
2968 {
2969 dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
2970 }
2971 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2972 {
2973 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2974 }
2975 RpcEndExcept;
2976
2977 if (dwError == ERROR_INVALID_HANDLE)
2978 dwError = ERROR_INVALID_SERVICE_LOCK;
2979
2980 if (dwError != ERROR_SUCCESS)
2981 {
2982 TRACE("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
2983 SetLastError(dwError);
2984 return FALSE;
2985 }
2986
2987 return TRUE;
2988 }
2989
2990
2991 /**********************************************************************
2992 * NotifyBootConfigStatus
2993 *
2994 * @implemented
2995 */
2996 BOOL WINAPI
2997 NotifyBootConfigStatus(BOOL BootAcceptable)
2998 {
2999 DWORD dwError;
3000
3001 TRACE("NotifyBootConfigStatus(%u)\n",
3002 BootAcceptable);
3003
3004 RpcTryExcept
3005 {
3006 dwError = RNotifyBootConfigStatus(NULL,
3007 BootAcceptable);
3008 }
3009 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3010 {
3011 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
3012 }
3013 RpcEndExcept;
3014
3015 if (dwError != ERROR_SUCCESS)
3016 {
3017 TRACE("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
3018 SetLastError(dwError);
3019 return FALSE;
3020 }
3021
3022 return TRUE;
3023 }
3024
3025 DWORD
3026 I_ScQueryServiceTagInfo(PVOID Unused,
3027 TAG_INFO_LEVEL dwInfoLevel,
3028 PTAG_INFO_NAME_FROM_TAG InOutParams)
3029 {
3030 return ERROR_CALL_NOT_IMPLEMENTED;
3031 }
3032
3033 /**********************************************************************
3034 * I_QueryTagInformation
3035 *
3036 * @implemented
3037 */
3038 DWORD WINAPI
3039 I_QueryTagInformation(PVOID Unused,
3040 TAG_INFO_LEVEL dwInfoLevel,
3041 PTAG_INFO_NAME_FROM_TAG InOutParams)
3042 {
3043 /*
3044 * We only support one information class and it
3045 * needs parameters
3046 */
3047 if (dwInfoLevel != TagInfoLevelNameFromTag ||
3048 InOutParams == NULL)
3049 {
3050 return ERROR_INVALID_PARAMETER;
3051 }
3052
3053 /* Validate input structure */
3054 if (InOutParams->InParams.dwPid == 0 || InOutParams->InParams.dwTag == 0)
3055 {
3056 return ERROR_INVALID_PARAMETER;
3057 }
3058
3059 /* Validate output structure */
3060 if (InOutParams->OutParams.pszName != NULL)
3061 {
3062 return ERROR_INVALID_PARAMETER;
3063 }
3064
3065 /* Call internal function for the RPC call */
3066 return I_ScQueryServiceTagInfo(Unused, TagInfoLevelNameFromTag, InOutParams);
3067 }
3068
3069 /* EOF */