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