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