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