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