ReactOS 0.4.16-dev-188-g678aa63
rpcserver.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/rpcserver.c
5 * PURPOSE: RPC server interface for the advapi32 calls
6 * COPYRIGHT: Copyright 2005-2006 Eric Kohl
7 * Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
8 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
9 */
10
11/* INCLUDES ****************************************************************/
12
13#include "services.h"
14
15#include <winnls.h>
16#include <strsafe.h>
17
18#include <pseh/pseh2.h>
19
20#define NDEBUG
21#include <debug.h>
22
23/* GLOBALS *****************************************************************/
24
25#define MANAGER_TAG 0x72674D68 /* 'hMgr' */
26#define SERVICE_TAG 0x63765368 /* 'hSvc' */
27#define INVALID_TAG 0xAABBCCDD
28
29typedef struct _SCMGR_HANDLE
30{
34
35
36typedef struct _MANAGER_HANDLE
37{
41
42
43typedef struct _SERVICE_HANDLE
44{
48
49
50#define SC_MANAGER_READ \
51 (STANDARD_RIGHTS_READ | \
52 SC_MANAGER_QUERY_LOCK_STATUS | \
53 SC_MANAGER_ENUMERATE_SERVICE)
54
55#define SC_MANAGER_WRITE \
56 (STANDARD_RIGHTS_WRITE | \
57 SC_MANAGER_MODIFY_BOOT_CONFIG | \
58 SC_MANAGER_CREATE_SERVICE)
59
60#define SC_MANAGER_EXECUTE \
61 (STANDARD_RIGHTS_EXECUTE | \
62 SC_MANAGER_LOCK | \
63 SC_MANAGER_ENUMERATE_SERVICE | \
64 SC_MANAGER_CONNECT | \
65 SC_MANAGER_CREATE_SERVICE)
66
67
68#define SERVICE_READ \
69 (STANDARD_RIGHTS_READ | \
70 SERVICE_INTERROGATE | \
71 SERVICE_ENUMERATE_DEPENDENTS | \
72 SERVICE_QUERY_STATUS | \
73 SERVICE_QUERY_CONFIG)
74
75#define SERVICE_WRITE \
76 (STANDARD_RIGHTS_WRITE | \
77 SERVICE_CHANGE_CONFIG)
78
79#define SERVICE_EXECUTE \
80 (STANDARD_RIGHTS_EXECUTE | \
81 SERVICE_USER_DEFINED_CONTROL | \
82 SERVICE_PAUSE_CONTINUE | \
83 SERVICE_STOP | \
84 SERVICE_START)
85
86#define TAG_ARRAY_SIZE 32
87
88/* VARIABLES ***************************************************************/
89
90static GENERIC_MAPPING
95
96static GENERIC_MAPPING
101
103
104/* FUNCTIONS ***************************************************************/
105
106VOID
108{
110
111 DPRINT("ScmStartRpcServer() called\n");
112
113 Status = RpcServerUseProtseqEpW(L"ncacn_np",
114 10,
115 L"\\pipe\\ntsvcs",
116 NULL);
117 if (Status != RPC_S_OK)
118 {
119 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
120 return;
121 }
122
123 Status = RpcServerRegisterIf(svcctl_v2_0_s_ifspec,
124 NULL,
125 NULL);
126 if (Status != RPC_S_OK)
127 {
128 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
129 return;
130 }
131
132 Status = RpcServerListen(1, 20, TRUE);
133 if (Status != RPC_S_OK)
134 {
135 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
136 return;
137 }
138
139 DPRINT("ScmStartRpcServer() done\n");
140}
141
142
143static DWORD
145 SC_HANDLE *Handle)
146{
148
149 if (lpDatabaseName == NULL)
150 lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
151
152 if (_wcsicmp(lpDatabaseName, SERVICES_FAILED_DATABASEW) == 0)
153 {
154 DPRINT("Database %S, does not exist\n", lpDatabaseName);
156 }
157 else if (_wcsicmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
158 {
159 DPRINT("Invalid Database name %S\n", lpDatabaseName);
160 return ERROR_INVALID_NAME;
161 }
162
165 FIELD_OFFSET(MANAGER_HANDLE, DatabaseName[wcslen(lpDatabaseName) + 1]));
166 if (Ptr == NULL)
168
169 Ptr->Handle.Tag = MANAGER_TAG;
170
171 wcscpy(Ptr->DatabaseName, lpDatabaseName);
172
173 *Handle = (SC_HANDLE)Ptr;
174
175 return ERROR_SUCCESS;
176}
177
178
179static DWORD
181 SC_HANDLE *Handle)
182{
184
187 sizeof(SERVICE_HANDLE));
188 if (Ptr == NULL)
190
191 Ptr->Handle.Tag = SERVICE_TAG;
192
193 Ptr->ServiceEntry = lpServiceEntry;
194
195 *Handle = (SC_HANDLE)Ptr;
196
197 return ERROR_SUCCESS;
198}
199
200
201static PMANAGER_HANDLE
203{
204 PMANAGER_HANDLE pManager = NULL;
205
207 {
209 pManager = (PMANAGER_HANDLE)Handle;
210 }
212 {
213 DPRINT1("Exception: Invalid Service Manager handle\n");
214 }
215 _SEH2_END;
216
217 return pManager;
218}
219
220
221static PSERVICE_HANDLE
223{
224 PSERVICE_HANDLE pService = NULL;
225
227 {
229 pService = (PSERVICE_HANDLE)Handle;
230 }
232 {
233 DPRINT1("Exception: Invalid Service handle\n");
234 }
235 _SEH2_END;
236
237 return pService;
238}
239
240
241static DWORD
243 DWORD dwDesiredAccess)
244{
245 PMANAGER_HANDLE hMgr;
246
247 hMgr = (PMANAGER_HANDLE)Handle;
248 if (hMgr->Handle.Tag == MANAGER_TAG)
249 {
250 RtlMapGenericMask(&dwDesiredAccess,
252
253 hMgr->Handle.DesiredAccess = dwDesiredAccess;
254
255 return ERROR_SUCCESS;
256 }
257 else if (hMgr->Handle.Tag == SERVICE_TAG)
258 {
259 RtlMapGenericMask(&dwDesiredAccess,
261
262 hMgr->Handle.DesiredAccess = dwDesiredAccess;
263
264 return ERROR_SUCCESS;
265 }
266
268}
269
270
271DWORD
273{
274 HKEY hKey = NULL;
275 DWORD dwError;
276 DWORD dwGroupTagCount = 0;
277 PDWORD pdwGroupTags = NULL;
278 DWORD dwFreeTag = 0;
279 DWORD dwTagUsedBase = 1;
280 BOOLEAN TagUsed[TAG_ARRAY_SIZE];
281 INT nTagOffset;
282 DWORD i;
283 DWORD cbDataSize;
284 PLIST_ENTRY ServiceEntry;
285 PSERVICE CurrentService;
286
287 ASSERT(lpService != NULL);
288 ASSERT(lpService->lpGroup != NULL);
289
291 L"System\\CurrentControlSet\\Control\\GroupOrderList",
292 0,
293 KEY_READ,
294 &hKey);
295
296 if (dwError != ERROR_SUCCESS)
297 goto findFreeTag;
298
299 /* query value length */
300 cbDataSize = 0;
301 dwError = RegQueryValueExW(hKey,
302 lpService->lpGroup->szGroupName,
303 NULL,
304 NULL,
305 NULL,
306 &cbDataSize);
307
308 if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA)
309 goto findFreeTag;
310
311 pdwGroupTags = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDataSize);
312 if (!pdwGroupTags)
313 {
314 dwError = ERROR_NOT_ENOUGH_MEMORY;
315 goto cleanup;
316 }
317
318 dwError = RegQueryValueExW(hKey,
319 lpService->lpGroup->szGroupName,
320 NULL,
321 NULL,
322 (LPBYTE)pdwGroupTags,
323 &cbDataSize);
324
325 if (dwError != ERROR_SUCCESS)
326 goto findFreeTag;
327
328 if (cbDataSize < sizeof(pdwGroupTags[0]))
329 goto findFreeTag;
330
331 dwGroupTagCount = min(pdwGroupTags[0], cbDataSize / sizeof(pdwGroupTags[0]) - 1);
332
333findFreeTag:
334 do
335 {
336 /* mark all tags as unused */
337 for (i = 0; i < TAG_ARRAY_SIZE; i++)
338 TagUsed[i] = FALSE;
339
340 /* mark tags in GroupOrderList as used */
341 for (i = 1; i <= dwGroupTagCount; i++)
342 {
343 nTagOffset = pdwGroupTags[i] - dwTagUsedBase;
344 if (nTagOffset >= 0 && nTagOffset < TAG_ARRAY_SIZE)
345 TagUsed[nTagOffset] = TRUE;
346 }
347
348 /* mark tags in service list as used */
349 ServiceEntry = lpService->ServiceListEntry.Flink;
350 while (ServiceEntry != &lpService->ServiceListEntry)
351 {
352 ASSERT(ServiceEntry != NULL);
353 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
354 if (CurrentService->lpGroup == lpService->lpGroup)
355 {
356 nTagOffset = CurrentService->dwTag - dwTagUsedBase;
357 if (nTagOffset >= 0 && nTagOffset < TAG_ARRAY_SIZE)
358 TagUsed[nTagOffset] = TRUE;
359 }
360
361 ServiceEntry = ServiceEntry->Flink;
362 }
363
364 /* find unused tag, if any */
365 for (i = 0; i < TAG_ARRAY_SIZE; i++)
366 {
367 if (!TagUsed[i])
368 {
369 dwFreeTag = dwTagUsedBase + i;
370 break;
371 }
372 }
373
374 dwTagUsedBase += TAG_ARRAY_SIZE;
375 } while (!dwFreeTag);
376
377cleanup:
378 if (pdwGroupTags)
379 HeapFree(GetProcessHeap(), 0, pdwGroupTags);
380
381 if (hKey)
383
384 if (dwFreeTag)
385 {
386 lpService->dwTag = dwFreeTag;
387 DPRINT("Assigning new tag %lu to service %S in group %S\n",
388 lpService->dwTag, lpService->lpServiceName, lpService->lpGroup->szGroupName);
389 dwError = ERROR_SUCCESS;
390 }
391 else
392 {
393 DPRINT1("Failed to assign new tag to service %S, error=%lu\n",
394 lpService->lpServiceName, dwError);
395 }
396
397 return dwError;
398}
399
400
401/* Create a path suitable for the bootloader out of the full path */
402DWORD
403ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
404{
405 SIZE_T ServiceNameLen, ExpandedLen;
407 WCHAR Dest;
408 WCHAR *Expanded;
412 HANDLE SymbolicLinkHandle;
413
414 DPRINT("ScmConvertToBootPathName %S\n", CanonName);
415
416 if (!RelativeName)
418
419 *RelativeName = NULL;
420
421 ServiceNameLen = wcslen(CanonName);
422
423 /* First check, if it's already good */
424 if (ServiceNameLen > 12 &&
425 !_wcsnicmp(L"\\SystemRoot\\", CanonName, 12))
426 {
427 *RelativeName = HeapAlloc(GetProcessHeap(),
429 (ServiceNameLen + 1) * sizeof(WCHAR));
430 if (*RelativeName == NULL)
431 {
432 DPRINT("Error allocating memory for boot driver name\n");
434 }
435
436 /* Copy it */
437 wcscpy(*RelativeName, CanonName);
438
439 DPRINT("Bootdriver name %S\n", *RelativeName);
440 return ERROR_SUCCESS;
441 }
442
443 /* If it has %SystemRoot% prefix, substitute it to \System*/
444 if (ServiceNameLen > 13 &&
445 !_wcsnicmp(L"%SystemRoot%\\", CanonName, 13))
446 {
447 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
448 *RelativeName = HeapAlloc(GetProcessHeap(),
450 ServiceNameLen * sizeof(WCHAR));
451
452 if (*RelativeName == NULL)
453 {
454 DPRINT("Error allocating memory for boot driver name\n");
456 }
457
458 /* Copy it */
459 wcscpy(*RelativeName, L"\\SystemRoot\\");
460 wcscat(*RelativeName, CanonName + 13);
461
462 DPRINT("Bootdriver name %S\n", *RelativeName);
463 return ERROR_SUCCESS;
464 }
465
466 /* Get buffer size needed for expanding env strings */
467 BufferSize = ExpandEnvironmentStringsW(L"%SystemRoot%\\", &Dest, 1);
468 if (BufferSize <= 1)
469 {
470 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
472 }
473
474 /* Allocate memory, since the size is known now */
475 Expanded = HeapAlloc(GetProcessHeap(),
477 (BufferSize + 1) * sizeof(WCHAR));
478 if (!Expanded)
479 {
480 DPRINT("Error allocating memory for boot driver name\n");
482 }
483
484 /* Expand it */
485 if (ExpandEnvironmentStringsW(L"%SystemRoot%\\", Expanded, BufferSize) >
487 {
488 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
489 HeapFree(GetProcessHeap(), 0, Expanded);
491 }
492
493 /* Convert to NT-style path */
494 if (!RtlDosPathNameToNtPathName_U(Expanded, &NtPathName, NULL, NULL))
495 {
496 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
498 }
499
500 DPRINT("Converted to NT-style %wZ\n", &NtPathName);
501
502 /* No need to keep the dos-path anymore */
503 HeapFree(GetProcessHeap(), 0, Expanded);
504
505 /* Copy it to the allocated place */
506 Expanded = HeapAlloc(GetProcessHeap(),
508 NtPathName.Length + sizeof(UNICODE_NULL));
509 if (!Expanded)
510 {
511 DPRINT("Error allocating memory for boot driver name\n");
512 RtlFreeUnicodeString(&NtPathName);
514 }
515
516 ExpandedLen = NtPathName.Length / sizeof(WCHAR);
517 wcsncpy(Expanded, NtPathName.Buffer, ExpandedLen);
518 Expanded[ExpandedLen] = UNICODE_NULL;
519 RtlFreeUnicodeString(&NtPathName);
520
521 if (ServiceNameLen > ExpandedLen &&
522 !_wcsnicmp(Expanded, CanonName, ExpandedLen))
523 {
524 HeapFree(GetProcessHeap(), 0, Expanded);
525
526 /* Only \SystemRoot\ is missing */
527 *RelativeName = HeapAlloc(GetProcessHeap(),
529 (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
530 if (*RelativeName == NULL)
531 {
532 DPRINT("Error allocating memory for boot driver name\n");
534 }
535
536 wcscpy(*RelativeName, L"\\SystemRoot\\");
537 wcscat(*RelativeName, CanonName + ExpandedLen);
538
539 return ERROR_SUCCESS;
540 }
541
542 /* No longer need this */
543 HeapFree(GetProcessHeap(), 0, Expanded);
544
545 /* The most complex case starts here */
546 RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot");
548 &SystemRoot,
550 NULL,
551 NULL);
552
553 /* Open this symlink */
555 if (NT_SUCCESS(Status))
556 {
557 DPRINT("Opened symbolic link object\n");
558
559 RtlInitEmptyUnicodeString(&LinkTarget, NULL, 0);
560 Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
562 {
563 /* Check if required buffer size is sane */
565 {
566 DPRINT("Too large buffer required\n");
567
568 NtClose(SymbolicLinkHandle);
570 }
571
572 /* Alloc the string */
578 if (!LinkTarget.Buffer)
579 {
580 DPRINT("Unable to alloc buffer\n");
581 NtClose(SymbolicLinkHandle);
583 }
584
585 /* Do a real query now */
586 Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
587 NtClose(SymbolicLinkHandle);
588 if (NT_SUCCESS(Status))
589 {
590 DPRINT("LinkTarget: %wZ\n", &LinkTarget);
591
592 ExpandedLen = LinkTarget.Length / sizeof(WCHAR);
593 if ((ServiceNameLen > ExpandedLen) &&
594 !_wcsnicmp(LinkTarget.Buffer, CanonName, ExpandedLen))
595 {
596 *RelativeName = HeapAlloc(GetProcessHeap(),
598 (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
599
600 if (*RelativeName == NULL)
601 {
602 DPRINT("Unable to alloc buffer\n");
604 }
605
606 /* Copy it over, substituting the first part
607 with SystemRoot */
608 wcscpy(*RelativeName, L"\\SystemRoot\\");
609 wcscat(*RelativeName, CanonName+ExpandedLen+1);
610
611 /* Return success */
612 return ERROR_SUCCESS;
613 }
614 else
615 {
617 }
618 }
619 else
620 {
621 DPRINT("Error, Status = %08X\n", Status);
623 }
624 }
625 else
626 {
627 DPRINT("Error, Status = %08X\n", Status);
628 NtClose(SymbolicLinkHandle);
630 }
631 }
632 else
633 {
634 /* Failure */
635 DPRINT("Error, Status = %08X\n", Status);
637 }
638}
639
640
641DWORD
643 const wchar_t *lpServiceName,
644 wchar_t **lpCanonName)
645{
647 SIZE_T ServiceNameLen;
648 UNICODE_STRING NtServiceName;
649 WCHAR *RelativeName;
650 const WCHAR *SourceName = lpServiceName;
651
652 /* Calculate the length of the service's name */
653 ServiceNameLen = wcslen(lpServiceName);
654
655 /* 12 is wcslen(L"\\SystemRoot\\") */
656 if (ServiceNameLen > 12 &&
657 !_wcsnicmp(L"\\SystemRoot\\", lpServiceName, 12))
658 {
659 /* SystemRoot prefix is already included */
660 *lpCanonName = HeapAlloc(GetProcessHeap(),
662 (ServiceNameLen + 1) * sizeof(WCHAR));
663
664 if (*lpCanonName == NULL)
665 {
666 DPRINT("Error allocating memory for canonized service name\n");
668 }
669
670 /* If it's a boot-time driver, it must be systemroot relative */
671 if (dwStartType == SERVICE_BOOT_START)
672 SourceName += 12;
673
674 /* Copy it */
675 wcscpy(*lpCanonName, SourceName);
676
677 DPRINT("Canonicalized name %S\n", *lpCanonName);
678 return NO_ERROR;
679 }
680
681 /* Check if it has %SystemRoot% (len=13) */
682 if (ServiceNameLen > 13 &&
683 !_wcsnicmp(L"%SystemRoot%\\", lpServiceName, 13))
684 {
685 /* Substitute %SystemRoot% with \\SystemRoot\\ */
686 *lpCanonName = HeapAlloc(GetProcessHeap(),
688 (ServiceNameLen + 1) * sizeof(WCHAR));
689
690 if (*lpCanonName == NULL)
691 {
692 DPRINT("Error allocating memory for canonized service name\n");
694 }
695
696 /* If it's a boot-time driver, it must be systemroot relative */
697 if (dwStartType == SERVICE_BOOT_START)
698 wcscpy(*lpCanonName, L"\\SystemRoot\\");
699
700 wcscat(*lpCanonName, lpServiceName + 13);
701
702 DPRINT("Canonicalized name %S\n", *lpCanonName);
703 return NO_ERROR;
704 }
705
706 /* Check if it's a relative path name */
707 if (lpServiceName[0] != L'\\' && lpServiceName[1] != L':')
708 {
709 *lpCanonName = HeapAlloc(GetProcessHeap(),
711 (ServiceNameLen + 1) * sizeof(WCHAR));
712
713 if (*lpCanonName == NULL)
714 {
715 DPRINT("Error allocating memory for canonized service name\n");
717 }
718
719 /* Just copy it over without changing */
720 wcscpy(*lpCanonName, lpServiceName);
721
722 return NO_ERROR;
723 }
724
725 /* It seems to be a DOS path, convert it */
726 if (!RtlDosPathNameToNtPathName_U(lpServiceName, &NtServiceName, NULL, NULL))
727 {
728 DPRINT("RtlDosPathNameToNtPathName_U() failed\n");
730 }
731
732 *lpCanonName = HeapAlloc(GetProcessHeap(),
734 NtServiceName.Length + sizeof(WCHAR));
735
736 if (*lpCanonName == NULL)
737 {
738 DPRINT("Error allocating memory for canonized service name\n");
739 RtlFreeUnicodeString(&NtServiceName);
741 }
742
743 /* Copy the string */
744 wcsncpy(*lpCanonName, NtServiceName.Buffer, NtServiceName.Length / sizeof(WCHAR));
745
746 /* The unicode string is not needed anymore */
747 RtlFreeUnicodeString(&NtServiceName);
748
749 if (dwStartType != SERVICE_BOOT_START)
750 {
751 DPRINT("Canonicalized name %S\n", *lpCanonName);
752 return NO_ERROR;
753 }
754
755 /* The service is boot-started, so must be relative */
756 Result = ScmConvertToBootPathName(*lpCanonName, &RelativeName);
757 if (Result)
758 {
759 /* There is a problem, free name and return */
760 HeapFree(GetProcessHeap(), 0, *lpCanonName);
761 DPRINT("Error converting named\n");
762 return Result;
763 }
764
765 ASSERT(RelativeName);
766
767 /* Copy that string */
768 wcscpy(*lpCanonName, RelativeName + 12);
769
770 /* Free the allocated buffer */
771 HeapFree(GetProcessHeap(), 0, RelativeName);
772
773 DPRINT("Canonicalized name %S\n", *lpCanonName);
774
775 /* Success */
776 return NO_ERROR;
777}
778
779
780/* Recursively search for every dependency on every service */
781DWORD
783 PSERVICE lpService,
784 DWORD dwServiceState,
785 PSERVICE *lpServices,
787 LPDWORD lpServicesReturned)
788{
789 DWORD dwError = ERROR_SUCCESS;
790 WCHAR szNameBuf[MAX_PATH];
791 WCHAR szValueBuf[MAX_PATH];
792 WCHAR *lpszNameBuf = szNameBuf;
793 WCHAR *lpszValueBuf = szValueBuf;
795 DWORD dwNumSubKeys;
796 DWORD dwIteration;
797 PSERVICE lpCurrentService;
798 HKEY hServiceEnumKey;
799 DWORD dwCurrentServiceState = SERVICE_ACTIVE;
800 DWORD dwDependServiceStrPtr = 0;
801 DWORD dwRequiredSize = 0;
802
803 /* Get the number of service keys */
805 NULL,
806 NULL,
807 NULL,
808 &dwNumSubKeys,
809 NULL,
810 NULL,
811 NULL,
812 NULL,
813 NULL,
814 NULL,
815 NULL);
816 if (dwError != ERROR_SUCCESS)
817 {
818 DPRINT("ERROR! Unable to get number of services keys\n");
819 return dwError;
820 }
821
822 /* Iterate the service keys to see if another service depends on the this service */
823 for (dwIteration = 0; dwIteration < dwNumSubKeys; dwIteration++)
824 {
826 dwError = RegEnumKeyExW(hServicesKey,
827 dwIteration,
828 lpszNameBuf,
829 &dwSize,
830 NULL,
831 NULL,
832 NULL,
833 NULL);
834 if (dwError != ERROR_SUCCESS)
835 return dwError;
836
837 /* Open the Service key */
838 dwError = RegOpenKeyExW(hServicesKey,
839 lpszNameBuf,
840 0,
841 KEY_READ,
842 &hServiceEnumKey);
843 if (dwError != ERROR_SUCCESS)
844 return dwError;
845
846 dwSize = MAX_PATH * sizeof(WCHAR);
847
848 /* Check for the DependOnService Value */
849 dwError = RegQueryValueExW(hServiceEnumKey,
850 L"DependOnService",
851 NULL,
852 NULL,
853 (LPBYTE)lpszValueBuf,
854 &dwSize);
855
856 /* FIXME: Handle load order. */
857
858 /* If the service found has a DependOnService value */
859 if (dwError == ERROR_SUCCESS)
860 {
861 dwDependServiceStrPtr = 0;
862
863 /* Can be more than one Dependencies in the DependOnService string */
864 while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0)
865 {
866 if (_wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0)
867 {
868 /* Get the current enumed service pointer */
869 lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf);
870
871 /* Check for valid Service */
872 if (!lpCurrentService)
873 {
874 /* This should never happen! */
875 DPRINT("This should not happen at this point, report to Developer\n");
876 return ERROR_NOT_FOUND;
877 }
878
879 /* Determine state the service is in */
880 if (lpCurrentService->Status.dwCurrentState == SERVICE_STOPPED)
881 dwCurrentServiceState = SERVICE_INACTIVE;
882
883 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
884 if ((dwCurrentServiceState == dwServiceState) ||
885 (dwServiceState == SERVICE_STATE_ALL))
886 {
887 /* Calculate the required size */
888 dwRequiredSize += sizeof(SERVICE_STATUS);
889 dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR));
890 dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
891
892 /* Add the size for service name and display name pointers */
893 dwRequiredSize += (2 * sizeof(PVOID));
894
895 /* increase the BytesNeeded size */
896 *pcbBytesNeeded = *pcbBytesNeeded + dwRequiredSize;
897
898 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
899 comes first */
900
901 /* Recursive call to check for its dependencies */
903 lpCurrentService,
904 dwServiceState,
905 lpServices,
907 lpServicesReturned);
908
909 /* If the lpServices is valid set the service pointer */
910 if (lpServices)
911 lpServices[*lpServicesReturned] = lpCurrentService;
912
913 *lpServicesReturned = *lpServicesReturned + 1;
914 }
915 }
916
917 dwDependServiceStrPtr += (DWORD)(wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1);
918 }
919 }
920 else if (*pcbBytesNeeded)
921 {
922 dwError = ERROR_SUCCESS;
923 }
924
925 RegCloseKey(hServiceEnumKey);
926 }
927
928 return dwError;
929}
930
931
932/* Function 0 */
933DWORD
934WINAPI
936 LPSC_RPC_HANDLE hSCObject)
937{
938 PMANAGER_HANDLE hManager;
939 PSERVICE_HANDLE hService;
940 PSERVICE lpService;
941
942 DPRINT("RCloseServiceHandle() called\n");
943
944 DPRINT("hSCObject = %p\n", *hSCObject);
945
946 if (*hSCObject == 0)
948
949 hManager = ScmGetServiceManagerFromHandle(*hSCObject);
950 hService = ScmGetServiceFromHandle(*hSCObject);
951
952 if (hManager != NULL)
953 {
954 DPRINT("Found manager handle\n");
955
956 /* Make sure we don't access stale memory if someone tries to use this handle again. */
957 hManager->Handle.Tag = INVALID_TAG;
958
959 HeapFree(GetProcessHeap(), 0, hManager);
960 hManager = NULL;
961
962 *hSCObject = NULL;
963
964 DPRINT("RCloseServiceHandle() done\n");
965 return ERROR_SUCCESS;
966 }
967 else if (hService != NULL)
968 {
969 DPRINT("Found service handle\n");
970
971 /* Lock the service database exclusively */
973
974 /* Get the pointer to the service record */
975 lpService = hService->ServiceEntry;
976
977 /* Make sure we don't access stale memory if someone tries to use this handle again. */
978 hService->Handle.Tag = INVALID_TAG;
979
980 /* Free the handle */
981 HeapFree(GetProcessHeap(), 0, hService);
982 hService = NULL;
983
984
985 DPRINT("Closing service %S with %d references\n", lpService->lpServiceName, lpService->RefCount);
986 ScmDereferenceService(lpService);
987
989
990 *hSCObject = NULL;
991
992 DPRINT("RCloseServiceHandle() done\n");
993 return ERROR_SUCCESS;
994 }
995
996 DPRINT("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
997
999}
1000
1001
1002/* Function 1 */
1003DWORD
1004WINAPI
1006 SC_RPC_HANDLE hService,
1007 DWORD dwControl,
1008 LPSERVICE_STATUS lpServiceStatus)
1009{
1010 PSERVICE_HANDLE hSvc;
1011 PSERVICE lpService;
1013 DWORD dwError = ERROR_SUCCESS;
1015 DWORD dwServicesReturned = 0;
1016 DWORD dwControlsAccepted;
1017 DWORD dwCurrentState;
1019 LPCWSTR lpLogStrings[2];
1020 WCHAR szLogBuffer[80];
1021 UINT uID;
1022
1023 DPRINT("RControlService() called\n");
1024
1025 if (ScmShutdown)
1027
1028 /* Check the service handle */
1029 hSvc = ScmGetServiceFromHandle(hService);
1030 if (hSvc == NULL)
1031 {
1032 DPRINT1("Invalid service handle\n");
1033 return ERROR_INVALID_HANDLE;
1034 }
1035
1036 /* Check the service entry point */
1037 lpService = hSvc->ServiceEntry;
1038 if (lpService == NULL)
1039 {
1040 DPRINT1("lpService == NULL\n");
1041 return ERROR_INVALID_HANDLE;
1042 }
1043
1044 /* Check access rights */
1045 switch (dwControl)
1046 {
1049 break;
1050
1059 break;
1060
1063 break;
1064
1065 default:
1066 if (dwControl >= 128 && dwControl <= 255)
1068 else
1070 break;
1071 }
1072
1075 return ERROR_ACCESS_DENIED;
1076
1077 /* Return the current service status information */
1078 RtlCopyMemory(lpServiceStatus,
1079 &lpService->Status,
1080 sizeof(SERVICE_STATUS));
1081
1082 if (dwControl == SERVICE_CONTROL_STOP)
1083 {
1084 /* Check if the service has dependencies running as windows
1085 doesn't stop a service that does */
1086
1087 /* Open the Services Reg key */
1089 L"System\\CurrentControlSet\\Services",
1090 0,
1091 KEY_READ,
1092 &hServicesKey);
1093 if (dwError != ERROR_SUCCESS)
1094 {
1095 DPRINT("Failed to open services key\n");
1096 return dwError;
1097 }
1098
1099 /* Call the internal function with NULL, just to get bytes we need */
1101 lpService,
1103 NULL,
1105 &dwServicesReturned);
1106
1108
1109 /* If pcbBytesNeeded is not zero then there are services running that
1110 are dependent on this service */
1111 if (pcbBytesNeeded != 0)
1112 {
1113 DPRINT("Service has running dependencies. Failed to stop service\n");
1115 }
1116 }
1117
1118 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
1119 {
1120 /* Send control code to the driver */
1121 dwError = ScmControlDriver(lpService,
1122 dwControl,
1123 lpServiceStatus);
1124 }
1125 else
1126 {
1127 dwControlsAccepted = lpService->Status.dwControlsAccepted;
1128 dwCurrentState = lpService->Status.dwCurrentState;
1129
1130 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1131 if (lpService->lpImage == NULL || dwCurrentState == SERVICE_STOPPED)
1133
1134 /* Check the current state before sending a control request */
1135 switch (dwCurrentState)
1136 {
1138 case SERVICE_STOPPED:
1140
1142 switch (dwControl)
1143 {
1145 break;
1146
1148 RtlCopyMemory(lpServiceStatus,
1149 &lpService->Status,
1150 sizeof(SERVICE_STATUS));
1151 return ERROR_SUCCESS;
1152
1153 default:
1155 }
1156 break;
1157 }
1158
1159 /* Check if the control code is acceptable to the service */
1160 switch (dwControl)
1161 {
1163 if ((dwControlsAccepted & SERVICE_ACCEPT_STOP) == 0)
1165 break;
1166
1169 if ((dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) == 0)
1171 break;
1172
1174 if ((dwControlsAccepted & SERVICE_ACCEPT_PARAMCHANGE) == 0)
1176 break;
1177
1182 if ((dwControlsAccepted & SERVICE_ACCEPT_NETBINDCHANGE) == 0)
1184 break;
1185 }
1186
1187 /* Send control code to the service */
1188 dwError = ScmControlService(lpService->lpImage->hControlPipe,
1189 lpService->lpServiceName,
1190 dwControl,
1191 (SERVICE_STATUS_HANDLE)lpService);
1192
1193 /* Return service status information */
1194 RtlCopyMemory(lpServiceStatus,
1195 &lpService->Status,
1196 sizeof(SERVICE_STATUS));
1197 }
1198
1199 if (dwError == ERROR_SUCCESS)
1200 {
1201 if (dwControl == SERVICE_CONTROL_STOP ||
1202 dwControl == SERVICE_CONTROL_PAUSE ||
1203 dwControl == SERVICE_CONTROL_CONTINUE)
1204 {
1205 /* Log a successful send control */
1206
1207 switch (dwControl)
1208 {
1210 uID = IDS_SERVICE_STOP;
1211 break;
1212
1214 uID = IDS_SERVICE_PAUSE;
1215 break;
1216
1218 uID = IDS_SERVICE_RESUME;
1219 break;
1220 }
1221 LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer));
1222
1223 lpLogStrings[0] = lpService->lpDisplayName;
1224 lpLogStrings[1] = szLogBuffer;
1225
1228 2,
1229 lpLogStrings);
1230 }
1231 }
1232
1233 return dwError;
1234}
1235
1236
1237/* Function 2 */
1238DWORD
1239WINAPI
1241 SC_RPC_HANDLE hService)
1242{
1243 PSERVICE_HANDLE hSvc;
1244 PSERVICE lpService;
1245 DWORD dwError;
1246
1247 DPRINT("RDeleteService() called\n");
1248
1249 if (ScmShutdown)
1251
1252 hSvc = ScmGetServiceFromHandle(hService);
1253 if (hSvc == NULL)
1254 {
1255 DPRINT1("Invalid service handle\n");
1256 return ERROR_INVALID_HANDLE;
1257 }
1258
1260 DELETE))
1261 return ERROR_ACCESS_DENIED;
1262
1263 lpService = hSvc->ServiceEntry;
1264 if (lpService == NULL)
1265 {
1266 DPRINT("lpService == NULL\n");
1267 return ERROR_INVALID_HANDLE;
1268 }
1269
1270 /* Lock the service database exclusively */
1272
1273 if (lpService->bDeleted)
1274 {
1275 DPRINT("Service has already been marked for delete\n");
1277 goto Done;
1278 }
1279
1280 /* Mark service for delete */
1281 lpService->bDeleted = TRUE;
1282
1283 dwError = ScmMarkServiceForDelete(lpService);
1284
1285Done:
1286 /* Unlock the service database */
1288
1289 DPRINT("RDeleteService() done\n");
1290
1291 return dwError;
1292}
1293
1294
1295/* Function 3 */
1296DWORD
1297WINAPI
1300 LPSC_RPC_LOCK lpLock)
1301{
1302 PMANAGER_HANDLE hMgr;
1303
1304 DPRINT("RLockServiceDatabase() called\n");
1305
1306 *lpLock = NULL;
1307
1309 if (hMgr == NULL)
1310 {
1311 DPRINT1("Invalid service manager handle\n");
1312 return ERROR_INVALID_HANDLE;
1313 }
1314
1317 return ERROR_ACCESS_DENIED;
1318
1319 return ScmAcquireServiceStartLock(FALSE, lpLock);
1320}
1321
1322
1323/* Function 4 */
1324DWORD
1325WINAPI
1327 SC_RPC_HANDLE hService,
1328 SECURITY_INFORMATION dwSecurityInformation,
1329 LPBYTE lpSecurityDescriptor,
1332{
1333 PSERVICE_HANDLE hSvc;
1334 PSERVICE lpService;
1335 ULONG DesiredAccess = 0;
1337 DWORD dwBytesNeeded;
1338 DWORD dwError;
1339
1340 DPRINT("RQueryServiceObjectSecurity() called\n");
1341
1342 hSvc = ScmGetServiceFromHandle(hService);
1343 if (hSvc == NULL)
1344 {
1345 DPRINT1("Invalid service handle\n");
1346 return ERROR_INVALID_HANDLE;
1347 }
1348
1349 if (dwSecurityInformation & (DACL_SECURITY_INFORMATION |
1353
1354 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
1356
1359 {
1360 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1361 return ERROR_ACCESS_DENIED;
1362 }
1363
1364 lpService = hSvc->ServiceEntry;
1365 if (lpService == NULL)
1366 {
1367 DPRINT("lpService == NULL\n");
1368 return ERROR_INVALID_HANDLE;
1369 }
1370
1371 /* Lock the service database */
1373
1374 /* Retrieve the security descriptor */
1376 dwSecurityInformation,
1377 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
1378 cbBufSize,
1379 &dwBytesNeeded);
1380
1381 /* Unlock the service database */
1383
1384 if (NT_SUCCESS(Status))
1385 {
1386 *pcbBytesNeeded = dwBytesNeeded;
1387 dwError = STATUS_SUCCESS;
1388 }
1389 else if (Status == STATUS_BUFFER_TOO_SMALL)
1390 {
1391 *pcbBytesNeeded = dwBytesNeeded;
1392 dwError = ERROR_INSUFFICIENT_BUFFER;
1393 }
1395 {
1396 dwError = ERROR_GEN_FAILURE;
1397 }
1398 else
1399 {
1400 dwError = RtlNtStatusToDosError(Status);
1401 }
1402
1403 return dwError;
1404}
1405
1406
1407/* Function 5 */
1408DWORD
1409WINAPI
1411 SC_RPC_HANDLE hService,
1412 DWORD dwSecurityInformation,
1413 LPBYTE lpSecurityDescriptor,
1414 DWORD dwSecurityDescriptorSize)
1415{
1416 PSERVICE_HANDLE hSvc;
1417 PSERVICE lpService;
1419 HANDLE hToken = NULL;
1420 HKEY hServiceKey = NULL;
1421 BOOL bDatabaseLocked = FALSE;
1423 DWORD dwError;
1424
1425 DPRINT("RSetServiceObjectSecurity() called\n");
1426
1427 hSvc = ScmGetServiceFromHandle(hService);
1428 if (hSvc == NULL)
1429 {
1430 DPRINT1("Invalid service handle\n");
1431 return ERROR_INVALID_HANDLE;
1432 }
1433
1434 if (dwSecurityInformation == 0 ||
1435 dwSecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
1437 {
1439 }
1440
1441 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
1443
1444 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
1446
1447 if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
1449
1450 if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
1452
1453 if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
1454 (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
1455 {
1457 }
1458
1459 if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
1460 (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
1461 {
1463 }
1464
1467 {
1468 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1469 return ERROR_ACCESS_DENIED;
1470 }
1471
1472 lpService = hSvc->ServiceEntry;
1473 if (lpService == NULL)
1474 {
1475 DPRINT1("lpService == NULL\n");
1476 return ERROR_INVALID_HANDLE;
1477 }
1478
1479 if (lpService->bDeleted)
1481
1482#if 0
1484
1486 8,
1487 TRUE,
1488 &hToken);
1489 if (!NT_SUCCESS(Status))
1491
1493#endif
1494
1495 /* Build the new security descriptor */
1496 Status = RtlSetSecurityObject(dwSecurityInformation,
1497 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
1498 &lpService->pSecurityDescriptor,
1500 hToken);
1501 if (!NT_SUCCESS(Status))
1502 {
1503 dwError = RtlNtStatusToDosError(Status);
1504 goto Done;
1505 }
1506
1507 /* Lock the service database exclusive */
1509 bDatabaseLocked = TRUE;
1510
1511 /* Open the service key */
1512 dwError = ScmOpenServiceKey(lpService->lpServiceName,
1514 &hServiceKey);
1515 if (dwError != ERROR_SUCCESS)
1516 goto Done;
1517
1518 /* Store the new security descriptor */
1519 dwError = ScmWriteSecurityDescriptor(hServiceKey,
1520 lpService->pSecurityDescriptor);
1521
1522 RegFlushKey(hServiceKey);
1523
1524Done:
1525 if (hServiceKey != NULL)
1526 RegCloseKey(hServiceKey);
1527
1528 /* Unlock service database */
1529 if (bDatabaseLocked == TRUE)
1531
1532 if (hToken != NULL)
1533 NtClose(hToken);
1534
1535 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError);
1536
1537 return dwError;
1538}
1539
1540
1541/* Function 6 */
1542DWORD
1543WINAPI
1545 SC_RPC_HANDLE hService,
1546 LPSERVICE_STATUS lpServiceStatus)
1547{
1548 PSERVICE_HANDLE hSvc;
1549 PSERVICE lpService;
1550
1551 DPRINT("RQueryServiceStatus() called\n");
1552
1553 if (ScmShutdown)
1555
1556 hSvc = ScmGetServiceFromHandle(hService);
1557 if (hSvc == NULL)
1558 {
1559 DPRINT1("Invalid service handle\n");
1560 return ERROR_INVALID_HANDLE;
1561 }
1562
1565 {
1566 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1567 return ERROR_ACCESS_DENIED;
1568 }
1569
1570 lpService = hSvc->ServiceEntry;
1571 if (lpService == NULL)
1572 {
1573 DPRINT("lpService == NULL\n");
1574 return ERROR_INVALID_HANDLE;
1575 }
1576
1577 /* Lock the service database shared */
1579
1580 /* Return service status information */
1581 RtlCopyMemory(lpServiceStatus,
1582 &lpService->Status,
1583 sizeof(SERVICE_STATUS));
1584
1585 /* Unlock the service database */
1587
1588 return ERROR_SUCCESS;
1589}
1590
1591
1592static BOOL
1594{
1595 switch (dwCurrentState)
1596 {
1597 case SERVICE_STOPPED:
1600 case SERVICE_RUNNING:
1603 case SERVICE_PAUSED:
1604 return TRUE;
1605
1606 default:
1607 return FALSE;
1608 }
1609}
1610
1611static
1612DWORD
1613WINAPI
1615{
1616 PSERVICE lpService = (PSERVICE)pParam;
1617 WCHAR szLogBuffer[80];
1618 LPCWSTR lpLogStrings[2];
1619
1620 /* Check if we are about to stop this service */
1621 if (lpService->lpImage->dwImageRunCount == 1)
1622 {
1623 /* Stop the dispatcher thread.
1624 * We must not send a control message while holding the database lock, otherwise it can cause timeouts
1625 * We are sure that the service won't be deleted in the meantime because we still have a reference to it. */
1626 DPRINT("Stopping the dispatcher thread for service %S\n", lpService->lpServiceName);
1628 L"",
1630 (SERVICE_STATUS_HANDLE)lpService);
1631 }
1632
1633 /* Lock the service database exclusively */
1635
1636 DPRINT("Service %S image count:%d\n", lpService->lpServiceName, lpService->lpImage->dwImageRunCount);
1637
1638 /* Decrement the image run counter */
1639 lpService->lpImage->dwImageRunCount--;
1640
1641 /* If we just stopped the last running service... */
1642 if (lpService->lpImage->dwImageRunCount == 0)
1643 {
1644 /* Remove the service image */
1645 DPRINT("Removing service image for %S\n", lpService->lpServiceName);
1646 ScmRemoveServiceImage(lpService->lpImage);
1647 lpService->lpImage = NULL;
1648 }
1649
1650 /* Report the results of the status change here */
1651 if (lpService->Status.dwWin32ExitCode != ERROR_SUCCESS)
1652 {
1653 /* Log a failed service stop */
1654 StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer),
1655 L"%lu", lpService->Status.dwWin32ExitCode);
1656 lpLogStrings[0] = lpService->lpDisplayName;
1657 lpLogStrings[1] = szLogBuffer;
1658
1661 ARRAYSIZE(lpLogStrings),
1662 lpLogStrings);
1663 }
1664 else
1665 {
1666 /* Log a successful service status change */
1667 LoadStringW(GetModuleHandle(NULL), IDS_SERVICE_STOPPED, szLogBuffer, ARRAYSIZE(szLogBuffer));
1668 lpLogStrings[0] = lpService->lpDisplayName;
1669 lpLogStrings[1] = szLogBuffer;
1670
1673 ARRAYSIZE(lpLogStrings),
1674 lpLogStrings);
1675 }
1676
1677 /* Remove the reference that was added when the service started */
1678 DPRINT("Service %S has %d references while stoping\n", lpService->lpServiceName, lpService->RefCount);
1679 ScmDereferenceService(lpService);
1680
1681 /* Unlock the service database */
1683
1684 return 0;
1685}
1686
1687/* Function 7 */
1688DWORD
1689WINAPI
1692 LPSERVICE_STATUS lpServiceStatus)
1693{
1694 PSERVICE lpService;
1695 DWORD dwPreviousState;
1696 DWORD dwPreviousType;
1697 LPCWSTR lpLogStrings[2];
1698 WCHAR szLogBuffer[80];
1699 UINT uID;
1700
1701 DPRINT("RSetServiceStatus() called\n");
1702 DPRINT("hServiceStatus = %lu\n", hServiceStatus);
1703 DPRINT("dwServiceType = 0x%lx\n", lpServiceStatus->dwServiceType);
1704 DPRINT("dwCurrentState = %lu\n", lpServiceStatus->dwCurrentState);
1705 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus->dwControlsAccepted);
1706 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus->dwWin32ExitCode);
1707 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus->dwServiceSpecificExitCode);
1708 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus->dwCheckPoint);
1709 DPRINT("dwWaitHint = %lu\n", lpServiceStatus->dwWaitHint);
1710
1711 if (hServiceStatus == 0)
1712 {
1713 DPRINT("hServiceStatus == NULL\n");
1714 return ERROR_INVALID_HANDLE;
1715 }
1716
1717 lpService = (PSERVICE)hServiceStatus;
1718
1719 /* Check current state */
1720 if (!ScmIsValidServiceState(lpServiceStatus->dwCurrentState))
1721 {
1722 DPRINT("Invalid service state\n");
1723 return ERROR_INVALID_DATA;
1724 }
1725
1726 /* Check service type */
1727 if (!(lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
1728 (lpServiceStatus->dwServiceType & SERVICE_DRIVER))
1729 {
1730 DPRINT("Invalid service type\n");
1731 return ERROR_INVALID_DATA;
1732 }
1733
1734 /* Check accepted controls */
1735 if (lpServiceStatus->dwControlsAccepted & ~0xFF)
1736 {
1737 DPRINT("Invalid controls accepted\n");
1738 return ERROR_INVALID_DATA;
1739 }
1740
1741 /* Set the wait hint and check point only if the service is in a pending state,
1742 otherwise they should be 0 */
1743 if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED ||
1744 lpServiceStatus->dwCurrentState == SERVICE_PAUSED ||
1745 lpServiceStatus->dwCurrentState == SERVICE_RUNNING)
1746 {
1747 lpServiceStatus->dwWaitHint = 0;
1748 lpServiceStatus->dwCheckPoint = 0;
1749 }
1750
1751 /* Lock the service database exclusively */
1753
1754 /* Save the current service state */
1755 dwPreviousState = lpService->Status.dwCurrentState;
1756
1757 /* Save the current service type */
1758 dwPreviousType = lpService->Status.dwServiceType;
1759
1760 /* Update the service status */
1761 RtlCopyMemory(&lpService->Status,
1762 lpServiceStatus,
1763 sizeof(SERVICE_STATUS));
1764
1765 /* Restore the previous service type */
1766 lpService->Status.dwServiceType = dwPreviousType;
1767
1768 DPRINT("Service %S changed state %d to %d\n", lpService->lpServiceName, dwPreviousState, lpServiceStatus->dwCurrentState);
1769
1770 if (lpServiceStatus->dwCurrentState != SERVICE_STOPPED &&
1771 dwPreviousState == SERVICE_STOPPED)
1772 {
1773 /* Keep a reference on all non stopped services */
1774 ScmReferenceService(lpService);
1775 DPRINT("Service %S has %d references after starting\n", lpService->lpServiceName, lpService->RefCount);
1776 }
1777
1778 /* Check if the service just stopped */
1779 if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED &&
1780 dwPreviousState != SERVICE_STOPPED)
1781 {
1782 HANDLE hStopThread;
1783 DWORD dwStopThreadId;
1784 DPRINT("Service %S, currentstate: %d, prev: %d\n", lpService->lpServiceName, lpServiceStatus->dwCurrentState, dwPreviousState);
1785
1786 /*
1787 * The service just changed its status to stopped.
1788 * Create a thread that will complete the stop sequence.
1789 * This thread will remove the reference that was added when the service started.
1790 * This will ensure that the service will remain valid as long as this reference is still held.
1791 */
1792 hStopThread = CreateThread(NULL,
1793 0,
1795 (LPVOID)lpService,
1796 0,
1797 &dwStopThreadId);
1798 if (hStopThread == NULL)
1799 {
1800 DPRINT1("Failed to create thread to complete service stop\n");
1801 /* We can't leave without releasing the reference.
1802 * We also can't remove it without holding the lock. */
1803 ScmDereferenceService(lpService);
1804 DPRINT1("Service %S has %d references after stop\n", lpService->lpServiceName, lpService->RefCount);
1805 }
1806 else
1807 {
1808 CloseHandle(hStopThread);
1809 }
1810 }
1811
1812 /* Unlock the service database */
1814
1815 /* Don't log any events here regarding a service stop as it can become invalid at any time */
1816
1817 if (lpServiceStatus->dwCurrentState != dwPreviousState &&
1818 (lpServiceStatus->dwCurrentState == SERVICE_RUNNING ||
1819 lpServiceStatus->dwCurrentState == SERVICE_PAUSED))
1820 {
1821 /* Log a successful service status change */
1822 switch(lpServiceStatus->dwCurrentState)
1823 {
1824 case SERVICE_RUNNING:
1825 uID = IDS_SERVICE_RUNNING;
1826 break;
1827
1828 case SERVICE_PAUSED:
1829 uID = IDS_SERVICE_PAUSED;
1830 break;
1831 }
1832
1833 LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer));
1834 lpLogStrings[0] = lpService->lpDisplayName;
1835 lpLogStrings[1] = szLogBuffer;
1836
1839 2,
1840 lpLogStrings);
1841 }
1842
1843 DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
1844 DPRINT("RSetServiceStatus() done\n");
1845
1846 return ERROR_SUCCESS;
1847}
1848
1849
1850/* Function 8 */
1851DWORD
1852WINAPI
1855{
1856 DPRINT("RUnlockServiceDatabase(%p)\n", Lock);
1858}
1859
1860
1861/* Function 9 */
1862DWORD
1863WINAPI
1865 SVCCTL_HANDLEW lpMachineName,
1866 DWORD BootAcceptable)
1867{
1868 DPRINT("RNotifyBootConfigStatus(%p %lu)\n",
1869 lpMachineName, BootAcceptable);
1870
1871 if (BootAcceptable)
1872 return ScmAcceptBoot();
1873
1874 return ScmRunLastKnownGood();
1875}
1876
1877
1878/* Function 10 */
1879DWORD
1880WINAPI
1884 int bSetBitsOn,
1885 int bUpdateImmediately,
1886 wchar_t *lpString)
1887{
1888 PSERVICE pService;
1889
1890 DPRINT("RI_ScSetServiceBitsW(%p %lx %d %d %S)\n",
1891 hServiceStatus, dwServiceBits, bSetBitsOn,
1892 bUpdateImmediately, lpString);
1893
1894 if (ScmShutdown)
1896
1897 if (lpString != NULL)
1899
1900 if (hServiceStatus == 0)
1901 {
1902 DPRINT("hServiceStatus == NULL\n");
1903 return ERROR_INVALID_HANDLE;
1904 }
1905
1906 // FIXME: Validate the status handle
1907 pService = (PSERVICE)hServiceStatus;
1908
1909 if (bSetBitsOn)
1910 {
1911 DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
1912 DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
1913 pService->dwServiceBits |= dwServiceBits;
1915 DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
1916 DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
1917 }
1918 else
1919 {
1920 DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
1921 DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
1922 pService->dwServiceBits &= ~dwServiceBits;
1923 g_dwServiceBits &= ~dwServiceBits;
1924 DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
1925 DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
1926 }
1927
1928 return ERROR_SUCCESS;
1929}
1930
1931
1932/* Function 11 */
1933DWORD
1934WINAPI
1936 SC_RPC_HANDLE hService,
1937 DWORD dwServiceType,
1938 DWORD dwStartType,
1939 DWORD dwErrorControl,
1940 LPWSTR lpBinaryPathName,
1941 LPWSTR lpLoadOrderGroup,
1942 LPDWORD lpdwTagId,
1943 LPBYTE lpDependencies,
1944 DWORD dwDependSize,
1945 LPWSTR lpServiceStartName,
1946 LPBYTE lpPassword,
1947 DWORD dwPwSize,
1949{
1950 DWORD dwError = ERROR_SUCCESS;
1951 PSERVICE_HANDLE hSvc;
1952 PSERVICE lpService = NULL;
1953 HKEY hServiceKey = NULL;
1954 LPWSTR lpDisplayNameW = NULL;
1955 LPWSTR lpImagePathW = NULL;
1956 LPWSTR lpClearTextPassword = NULL;
1957
1958 DPRINT("RChangeServiceConfigW() called\n");
1959 DPRINT("dwServiceType = 0x%lx\n", dwServiceType);
1960 DPRINT("dwStartType = %lu\n", dwStartType);
1961 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
1962 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
1963 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
1964 DPRINT("lpServiceStartName = %S\n", lpServiceStartName);
1965 DPRINT("lpPassword = %p\n", lpPassword);
1966 DPRINT("dwPwSite = %lu\n", dwPwSize);
1967 DPRINT("lpDisplayName = %S\n", lpDisplayName);
1968
1969 if (ScmShutdown)
1971
1972 hSvc = ScmGetServiceFromHandle(hService);
1973 if (hSvc == NULL)
1974 {
1975 DPRINT1("Invalid service handle\n");
1976 return ERROR_INVALID_HANDLE;
1977 }
1978
1981 {
1982 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1983 return ERROR_ACCESS_DENIED;
1984 }
1985
1986 /* Check for invalid service type value */
1987 if ((dwServiceType != SERVICE_NO_CHANGE) &&
1988 (dwServiceType != SERVICE_KERNEL_DRIVER) &&
1989 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) &&
1992 {
1994 }
1995
1996 /* Check for invalid start type value */
1997 if ((dwStartType != SERVICE_NO_CHANGE) &&
1998 (dwStartType != SERVICE_BOOT_START) &&
1999 (dwStartType != SERVICE_SYSTEM_START) &&
2000 (dwStartType != SERVICE_AUTO_START) &&
2001 (dwStartType != SERVICE_DEMAND_START) &&
2002 (dwStartType != SERVICE_DISABLED))
2003 {
2005 }
2006
2007 /* Only drivers can be boot start or system start services */
2008 if ((dwStartType == SERVICE_BOOT_START) ||
2009 (dwStartType == SERVICE_SYSTEM_START))
2010 {
2011 if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
2012 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
2014 }
2015
2016 /* Check for invalid error control value */
2017 if ((dwErrorControl != SERVICE_NO_CHANGE) &&
2018 (dwErrorControl != SERVICE_ERROR_IGNORE) &&
2019 (dwErrorControl != SERVICE_ERROR_NORMAL) &&
2020 (dwErrorControl != SERVICE_ERROR_SEVERE) &&
2021 (dwErrorControl != SERVICE_ERROR_CRITICAL))
2022 {
2024 }
2025
2026 if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup))
2027 {
2029 }
2030
2031 lpService = hSvc->ServiceEntry;
2032 if (lpService == NULL)
2033 {
2034 DPRINT("lpService == NULL\n");
2035 return ERROR_INVALID_HANDLE;
2036 }
2037
2038 /* Lock the service database exclusively */
2040
2041 if (lpService->bDeleted)
2042 {
2043 DPRINT("Service has already been marked for delete\n");
2045 goto done;
2046 }
2047
2048 /* Open the service key */
2049 dwError = ScmOpenServiceKey(lpService->szServiceName,
2051 &hServiceKey);
2052 if (dwError != ERROR_SUCCESS)
2053 goto done;
2054
2055 /* Write service data to the registry */
2056
2057 /* Set the display name */
2058 if (lpDisplayName != NULL && *lpDisplayName != 0)
2059 {
2060 RegSetValueExW(hServiceKey,
2061 L"DisplayName",
2062 0,
2063 REG_SZ,
2065 (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR)));
2066
2067 /* Update the display name */
2068 lpDisplayNameW = HeapAlloc(GetProcessHeap(),
2070 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
2071 if (lpDisplayNameW == NULL)
2072 {
2073 dwError = ERROR_NOT_ENOUGH_MEMORY;
2074 goto done;
2075 }
2076
2077 wcscpy(lpDisplayNameW, lpDisplayName);
2078 if (lpService->lpDisplayName != lpService->lpServiceName)
2079 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
2080
2081 lpService->lpDisplayName = lpDisplayNameW;
2082 }
2083
2084 if (dwServiceType != SERVICE_NO_CHANGE)
2085 {
2086 /* Set the service type */
2087 dwError = RegSetValueExW(hServiceKey,
2088 L"Type",
2089 0,
2090 REG_DWORD,
2091 (LPBYTE)&dwServiceType,
2092 sizeof(DWORD));
2093 if (dwError != ERROR_SUCCESS)
2094 goto done;
2095
2096 lpService->Status.dwServiceType = dwServiceType;
2097 }
2098
2099 if (dwStartType != SERVICE_NO_CHANGE)
2100 {
2101 /* Set the start value */
2102 dwError = RegSetValueExW(hServiceKey,
2103 L"Start",
2104 0,
2105 REG_DWORD,
2106 (LPBYTE)&dwStartType,
2107 sizeof(DWORD));
2108 if (dwError != ERROR_SUCCESS)
2109 goto done;
2110
2111 lpService->dwStartType = dwStartType;
2112 }
2113
2114 if (dwErrorControl != SERVICE_NO_CHANGE)
2115 {
2116 /* Set the error control value */
2117 dwError = RegSetValueExW(hServiceKey,
2118 L"ErrorControl",
2119 0,
2120 REG_DWORD,
2121 (LPBYTE)&dwErrorControl,
2122 sizeof(DWORD));
2123 if (dwError != ERROR_SUCCESS)
2124 goto done;
2125
2126 lpService->dwErrorControl = dwErrorControl;
2127 }
2128
2129 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
2130 {
2131 /* Set the image path */
2132 lpImagePathW = lpBinaryPathName;
2133
2134 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
2135 {
2136 dwError = ScmCanonDriverImagePath(lpService->dwStartType,
2137 lpBinaryPathName,
2138 &lpImagePathW);
2139
2140 if (dwError != ERROR_SUCCESS)
2141 goto done;
2142 }
2143
2144 dwError = RegSetValueExW(hServiceKey,
2145 L"ImagePath",
2146 0,
2148 (LPBYTE)lpImagePathW,
2149 (DWORD)((wcslen(lpImagePathW) + 1) * sizeof(WCHAR)));
2150
2151 if (lpImagePathW != lpBinaryPathName)
2152 HeapFree(GetProcessHeap(), 0, lpImagePathW);
2153
2154 if (dwError != ERROR_SUCCESS)
2155 goto done;
2156 }
2157
2158 /* Set the group name */
2159 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
2160 {
2161 dwError = RegSetValueExW(hServiceKey,
2162 L"Group",
2163 0,
2164 REG_SZ,
2165 (LPBYTE)lpLoadOrderGroup,
2166 (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)));
2167 if (dwError != ERROR_SUCCESS)
2168 goto done;
2169
2170 dwError = ScmSetServiceGroup(lpService,
2171 lpLoadOrderGroup);
2172 if (dwError != ERROR_SUCCESS)
2173 goto done;
2174 }
2175
2176 /* Set the tag */
2177 if (lpdwTagId != NULL)
2178 {
2179 dwError = ScmAssignNewTag(lpService);
2180 if (dwError != ERROR_SUCCESS)
2181 goto done;
2182
2183 dwError = RegSetValueExW(hServiceKey,
2184 L"Tag",
2185 0,
2186 REG_DWORD,
2187 (LPBYTE)&lpService->dwTag,
2188 sizeof(DWORD));
2189 if (dwError != ERROR_SUCCESS)
2190 goto done;
2191
2192 *lpdwTagId = lpService->dwTag;
2193 }
2194
2195 /* Write dependencies */
2196 if (lpDependencies != NULL && *lpDependencies != 0)
2197 {
2198 dwError = ScmWriteDependencies(hServiceKey,
2199 (LPWSTR)lpDependencies,
2200 dwDependSize);
2201 if (dwError != ERROR_SUCCESS)
2202 goto done;
2203 }
2204
2205 /* Start name and password are only used by Win32 services */
2206 if (lpService->Status.dwServiceType & SERVICE_WIN32)
2207 {
2208 /* Write service start name */
2209 if (lpServiceStartName != NULL && *lpServiceStartName != 0)
2210 {
2211 dwError = RegSetValueExW(hServiceKey,
2212 L"ObjectName",
2213 0,
2214 REG_SZ,
2215 (LPBYTE)lpServiceStartName,
2216 (DWORD)((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR)));
2217 if (dwError != ERROR_SUCCESS)
2218 goto done;
2219 }
2220
2221 if (lpPassword != NULL)
2222 {
2223 if (*(LPWSTR)lpPassword != 0)
2224 {
2225 /* Decrypt the password */
2226 dwError = ScmDecryptPassword(hService,
2227 lpPassword,
2228 dwPwSize,
2229 &lpClearTextPassword);
2230 if (dwError != ERROR_SUCCESS)
2231 {
2232 DPRINT1("ScmDecryptPassword failed (Error %lu)\n", dwError);
2233 goto done;
2234 }
2235 DPRINT("Clear text password: %S\n", lpClearTextPassword);
2236
2237 /* Write the password */
2238 dwError = ScmSetServicePassword(lpService->szServiceName,
2239 lpClearTextPassword);
2240 if (dwError != ERROR_SUCCESS)
2241 {
2242 DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError);
2243 goto done;
2244 }
2245 }
2246 else
2247 {
2248 /* Delete the password */
2249 dwError = ScmSetServicePassword(lpService->szServiceName,
2250 NULL);
2251 if (dwError == ERROR_FILE_NOT_FOUND)
2252 dwError = ERROR_SUCCESS;
2253
2254 if (dwError != ERROR_SUCCESS)
2255 {
2256 DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError);
2257 goto done;
2258 }
2259 }
2260 }
2261 }
2262
2263done:
2264 if (lpClearTextPassword != NULL)
2265 {
2266 /* Wipe and release the password buffer */
2267 SecureZeroMemory(lpClearTextPassword,
2268 (wcslen(lpClearTextPassword) + 1) * sizeof(WCHAR));
2269 HeapFree(GetProcessHeap(), 0, lpClearTextPassword);
2270 }
2271
2272 if (hServiceKey != NULL)
2273 RegCloseKey(hServiceKey);
2274
2275 /* Unlock the service database */
2277
2278 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError);
2279
2280 return dwError;
2281}
2282
2283
2284/* Function 12 */
2285DWORD
2286WINAPI
2289 LPCWSTR lpServiceName,
2291 DWORD dwDesiredAccess,
2292 DWORD dwServiceType,
2293 DWORD dwStartType,
2294 DWORD dwErrorControl,
2295 LPCWSTR lpBinaryPathName,
2296 LPCWSTR lpLoadOrderGroup,
2297 LPDWORD lpdwTagId,
2298 LPBYTE lpDependencies,
2299 DWORD dwDependSize,
2300 LPCWSTR lpServiceStartName,
2301 LPBYTE lpPassword,
2302 DWORD dwPwSize,
2303 LPSC_RPC_HANDLE lpServiceHandle)
2304{
2305 PMANAGER_HANDLE hManager;
2306 DWORD dwError = ERROR_SUCCESS;
2307 PSERVICE lpService = NULL;
2308 SC_HANDLE hServiceHandle = NULL;
2309 LPWSTR lpImagePath = NULL;
2310 LPWSTR lpClearTextPassword = NULL;
2311 HKEY hServiceKey = NULL;
2312 LPWSTR lpObjectName;
2313
2314 DPRINT("RCreateServiceW() called\n");
2315 DPRINT("lpServiceName = %S\n", lpServiceName);
2316 DPRINT("lpDisplayName = %S\n", lpDisplayName);
2317 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
2318 DPRINT("dwServiceType = 0x%lx\n", dwServiceType);
2319 DPRINT("dwStartType = %lu\n", dwStartType);
2320 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
2321 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
2322 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
2323 DPRINT("lpdwTagId = %p\n", lpdwTagId);
2324
2325 if (ScmShutdown)
2327
2329 if (hManager == NULL)
2330 {
2331 DPRINT1("Invalid service manager handle\n");
2332 return ERROR_INVALID_HANDLE;
2333 }
2334
2335 /* Check access rights */
2338 {
2339 DPRINT("Insufficient access rights! 0x%lx\n",
2340 hManager->Handle.DesiredAccess);
2341 return ERROR_ACCESS_DENIED;
2342 }
2343
2344 if (*lpServiceName == 0)
2345 return ERROR_INVALID_NAME;
2346
2347 if (*lpBinaryPathName == 0)
2349
2350 /* Check for invalid service type value */
2351 if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
2352 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) &&
2355 {
2357 }
2358
2359 /* Check for invalid start type value */
2360 if ((dwStartType != SERVICE_BOOT_START) &&
2361 (dwStartType != SERVICE_SYSTEM_START) &&
2362 (dwStartType != SERVICE_AUTO_START) &&
2363 (dwStartType != SERVICE_DEMAND_START) &&
2364 (dwStartType != SERVICE_DISABLED))
2365 {
2367 }
2368
2369 /* Only drivers can be boot start or system start services */
2370 if ((dwStartType == SERVICE_BOOT_START) ||
2371 (dwStartType == SERVICE_SYSTEM_START))
2372 {
2373 if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
2374 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
2375 {
2377 }
2378 }
2379
2380 /* Check for invalid error control value */
2381 if ((dwErrorControl != SERVICE_ERROR_IGNORE) &&
2382 (dwErrorControl != SERVICE_ERROR_NORMAL) &&
2383 (dwErrorControl != SERVICE_ERROR_SEVERE) &&
2384 (dwErrorControl != SERVICE_ERROR_CRITICAL))
2385 {
2387 }
2388
2389 if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
2390 (lpServiceStartName))
2391 {
2392 /* We allow LocalSystem to run interactive. */
2393 if (_wcsicmp(lpServiceStartName, L"LocalSystem"))
2394 {
2396 }
2397 }
2398
2399 if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup))
2400 {
2402 }
2403
2404 /* Lock the service database exclusively */
2406
2407 lpService = ScmGetServiceEntryByName(lpServiceName);
2408 if (lpService)
2409 {
2410 /* Unlock the service database */
2412
2413 /* Check if it is marked for deletion */
2414 if (lpService->bDeleted)
2416
2417 /* Return service-exists error */
2418 return ERROR_SERVICE_EXISTS;
2419 }
2420
2421 if (lpDisplayName != NULL &&
2423 {
2424 /* Unlock the service database */
2426
2428 }
2429
2430 if (dwServiceType & SERVICE_DRIVER)
2431 {
2432 dwError = ScmCanonDriverImagePath(dwStartType,
2433 lpBinaryPathName,
2434 &lpImagePath);
2435 if (dwError != ERROR_SUCCESS)
2436 goto done;
2437 }
2438 else
2439 {
2440 if (dwStartType == SERVICE_BOOT_START ||
2441 dwStartType == SERVICE_SYSTEM_START)
2442 {
2443 /* Unlock the service database */
2445
2447 }
2448 }
2449
2450 /* Allocate a new service entry */
2451 dwError = ScmCreateNewServiceRecord(lpServiceName,
2452 &lpService,
2453 dwServiceType,
2454 dwStartType);
2455 if (dwError != ERROR_SUCCESS)
2456 goto done;
2457
2458 /* Fill the new service entry */
2459 lpService->dwErrorControl = dwErrorControl;
2460
2461 /* Fill the display name */
2462 if (lpDisplayName != NULL &&
2463 *lpDisplayName != 0 &&
2464 _wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
2465 {
2466 lpService->lpDisplayName = HeapAlloc(GetProcessHeap(),
2468 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
2469 if (lpService->lpDisplayName == NULL)
2470 {
2471 dwError = ERROR_NOT_ENOUGH_MEMORY;
2472 goto done;
2473 }
2474 wcscpy(lpService->lpDisplayName, lpDisplayName);
2475 }
2476
2477 /* Assign the service to a group */
2478 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
2479 {
2480 dwError = ScmSetServiceGroup(lpService,
2481 lpLoadOrderGroup);
2482 if (dwError != ERROR_SUCCESS)
2483 goto done;
2484 }
2485
2486 /* Assign a new tag */
2487 if (lpdwTagId != NULL)
2488 {
2489 dwError = ScmAssignNewTag(lpService);
2490 if (dwError != ERROR_SUCCESS)
2491 goto done;
2492 }
2493
2494 /* Assign the default security descriptor */
2495 if (dwServiceType & SERVICE_WIN32)
2496 {
2497 dwError = ScmCreateDefaultServiceSD(&lpService->pSecurityDescriptor);
2498 if (dwError != ERROR_SUCCESS)
2499 goto done;
2500 }
2501
2502 /* Write service data to the registry */
2503 /* Create the service key */
2504 dwError = ScmCreateServiceKey(lpServiceName,
2505 KEY_WRITE,
2506 &hServiceKey);
2507 if (dwError != ERROR_SUCCESS)
2508 goto done;
2509
2510 /* Set the display name */
2511 if (lpDisplayName != NULL && *lpDisplayName != 0)
2512 {
2513 RegSetValueExW(hServiceKey,
2514 L"DisplayName",
2515 0,
2516 REG_SZ,
2518 (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR)));
2519 }
2520
2521 /* Set the service type */
2522 dwError = RegSetValueExW(hServiceKey,
2523 L"Type",
2524 0,
2525 REG_DWORD,
2526 (LPBYTE)&dwServiceType,
2527 sizeof(DWORD));
2528 if (dwError != ERROR_SUCCESS)
2529 goto done;
2530
2531 /* Set the start value */
2532 dwError = RegSetValueExW(hServiceKey,
2533 L"Start",
2534 0,
2535 REG_DWORD,
2536 (LPBYTE)&dwStartType,
2537 sizeof(DWORD));
2538 if (dwError != ERROR_SUCCESS)
2539 goto done;
2540
2541 /* Set the error control value */
2542 dwError = RegSetValueExW(hServiceKey,
2543 L"ErrorControl",
2544 0,
2545 REG_DWORD,
2546 (LPBYTE)&dwErrorControl,
2547 sizeof(DWORD));
2548 if (dwError != ERROR_SUCCESS)
2549 goto done;
2550
2551 /* Set the image path */
2552 if (dwServiceType & SERVICE_WIN32)
2553 {
2554 dwError = RegSetValueExW(hServiceKey,
2555 L"ImagePath",
2556 0,
2558 (LPBYTE)lpBinaryPathName,
2559 (DWORD)((wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR)));
2560 if (dwError != ERROR_SUCCESS)
2561 goto done;
2562 }
2563 else if (dwServiceType & SERVICE_DRIVER)
2564 {
2565 dwError = RegSetValueExW(hServiceKey,
2566 L"ImagePath",
2567 0,
2569 (LPBYTE)lpImagePath,
2570 (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR)));
2571 if (dwError != ERROR_SUCCESS)
2572 goto done;
2573 }
2574
2575 /* Set the group name */
2576 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
2577 {
2578 dwError = RegSetValueExW(hServiceKey,
2579 L"Group",
2580 0,
2581 REG_SZ,
2582 (LPBYTE)lpLoadOrderGroup,
2583 (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)));
2584 if (dwError != ERROR_SUCCESS)
2585 goto done;
2586 }
2587
2588 /* Set the service tag */
2589 if (lpdwTagId != NULL)
2590 {
2591 dwError = RegSetValueExW(hServiceKey,
2592 L"Tag",
2593 0,
2594 REG_DWORD,
2595 (LPBYTE)&lpService->dwTag,
2596 sizeof(DWORD));
2597 if (dwError != ERROR_SUCCESS)
2598 goto done;
2599 }
2600
2601 /* Write dependencies */
2602 if (lpDependencies != NULL && *lpDependencies != 0)
2603 {
2604 dwError = ScmWriteDependencies(hServiceKey,
2605 (LPCWSTR)lpDependencies,
2606 dwDependSize);
2607 if (dwError != ERROR_SUCCESS)
2608 goto done;
2609 }
2610
2611 /* Start name and password are only used by Win32 services */
2612 if (dwServiceType & SERVICE_WIN32)
2613 {
2614 /* Write service start name */
2615 lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem";
2616 dwError = RegSetValueExW(hServiceKey,
2617 L"ObjectName",
2618 0,
2619 REG_SZ,
2620 (LPBYTE)lpObjectName,
2621 (DWORD)((wcslen(lpObjectName) + 1) * sizeof(WCHAR)));
2622 if (dwError != ERROR_SUCCESS)
2623 goto done;
2624
2625 if (lpPassword != NULL && *(LPWSTR)lpPassword != 0)
2626 {
2627 /* Decrypt the password */
2629 lpPassword,
2630 dwPwSize,
2631 &lpClearTextPassword);
2632 if (dwError != ERROR_SUCCESS)
2633 goto done;
2634
2635 /* Write the password */
2636 dwError = ScmSetServicePassword(lpServiceName,
2637 lpClearTextPassword);
2638 if (dwError != ERROR_SUCCESS)
2639 goto done;
2640 }
2641
2642 /* Write the security descriptor */
2643 dwError = ScmWriteSecurityDescriptor(hServiceKey,
2644 lpService->pSecurityDescriptor);
2645 if (dwError != ERROR_SUCCESS)
2646 goto done;
2647 }
2648
2649 dwError = ScmCreateServiceHandle(lpService,
2650 &hServiceHandle);
2651 if (dwError != ERROR_SUCCESS)
2652 goto done;
2653
2654 dwError = ScmCheckAccess(hServiceHandle,
2655 dwDesiredAccess);
2656 if (dwError != ERROR_SUCCESS)
2657 goto done;
2658
2659 ScmReferenceService(lpService);
2660
2661 /* Get the service tag (if Win32) */
2662 ScmGenerateServiceTag(lpService);
2663
2664 DPRINT("CreateService - lpService->RefCount %u\n", lpService->RefCount);
2665
2666done:
2667 /* Unlock the service database */
2669
2670 if (hServiceKey != NULL)
2671 RegCloseKey(hServiceKey);
2672
2673 if (lpClearTextPassword != NULL)
2674 {
2675 /* Wipe and release the password buffer */
2676 SecureZeroMemory(lpClearTextPassword,
2677 (wcslen(lpClearTextPassword) + 1) * sizeof(WCHAR));
2678 HeapFree(GetProcessHeap(), 0, lpClearTextPassword);
2679 }
2680
2681 if (dwError == ERROR_SUCCESS)
2682 {
2683 DPRINT("hService %p\n", hServiceHandle);
2684 *lpServiceHandle = (SC_RPC_HANDLE)hServiceHandle;
2685
2686 if (lpdwTagId != NULL)
2687 *lpdwTagId = lpService->dwTag;
2688 }
2689 else
2690 {
2691 if (lpService != NULL &&
2692 lpService->lpServiceName != NULL)
2693 {
2694 /* Release the display name buffer */
2695 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
2696 }
2697
2698 if (hServiceHandle)
2699 {
2700 /* Remove the service handle */
2701 HeapFree(GetProcessHeap(), 0, hServiceHandle);
2702 }
2703
2704 if (lpService != NULL)
2705 {
2706 /* FIXME: remove the service entry */
2707 }
2708 }
2709
2710 if (lpImagePath != NULL)
2711 HeapFree(GetProcessHeap(), 0, lpImagePath);
2712
2713 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError);
2714
2715 return dwError;
2716}
2717
2718
2719/* Function 13 */
2720DWORD
2721WINAPI
2723 SC_RPC_HANDLE hService,
2724 DWORD dwServiceState,
2725 LPBYTE lpServices,
2728 LPBOUNDED_DWORD_256K lpServicesReturned)
2729{
2730 DWORD dwError = ERROR_SUCCESS;
2731 DWORD dwServicesReturned = 0;
2732 DWORD dwServiceCount;
2734 PSERVICE_HANDLE hSvc;
2735 PSERVICE lpService = NULL;
2736 PSERVICE *lpServicesArray = NULL;
2737 LPENUM_SERVICE_STATUSW lpServicesPtr = NULL;
2738 LPWSTR lpStr;
2739
2740 *pcbBytesNeeded = 0;
2741 *lpServicesReturned = 0;
2742
2743 DPRINT("REnumDependentServicesW() called\n");
2744
2745 hSvc = ScmGetServiceFromHandle(hService);
2746 if (hSvc == NULL)
2747 {
2748 DPRINT1("Invalid service handle\n");
2749 return ERROR_INVALID_HANDLE;
2750 }
2751
2752 lpService = hSvc->ServiceEntry;
2753
2754 /* Check access rights */
2757 {
2758 DPRINT("Insufficient access rights! 0x%lx\n",
2759 hSvc->Handle.DesiredAccess);
2760 return ERROR_ACCESS_DENIED;
2761 }
2762
2763 /* Open the Services Reg key */
2765 L"System\\CurrentControlSet\\Services",
2766 0,
2767 KEY_READ,
2768 &hServicesKey);
2769 if (dwError != ERROR_SUCCESS)
2770 return dwError;
2771
2772 /* First determine the bytes needed and get the number of dependent services */
2774 lpService,
2775 dwServiceState,
2776 NULL,
2778 &dwServicesReturned);
2779 if (dwError != ERROR_SUCCESS)
2780 goto Done;
2781
2782 /* If buffer size is less than the bytes needed or pointer is null */
2783 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
2784 {
2785 dwError = ERROR_MORE_DATA;
2786 goto Done;
2787 }
2788
2789 /* Allocate memory for array of service pointers */
2790 lpServicesArray = HeapAlloc(GetProcessHeap(),
2792 (dwServicesReturned + 1) * sizeof(PSERVICE));
2793 if (!lpServicesArray)
2794 {
2795 DPRINT1("Could not allocate buffer\n");
2796 dwError = ERROR_NOT_ENOUGH_MEMORY;
2797 goto Done;
2798 }
2799
2800 dwServicesReturned = 0;
2801 *pcbBytesNeeded = 0;
2802
2804 lpService,
2805 dwServiceState,
2806 lpServicesArray,
2808 &dwServicesReturned);
2809 if (dwError != ERROR_SUCCESS)
2810 {
2811 goto Done;
2812 }
2813
2814 lpServicesPtr = (LPENUM_SERVICE_STATUSW)lpServices;
2815 lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW)));
2816
2817 /* Copy EnumDepenedentService to Buffer */
2818 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
2819 {
2820 lpService = lpServicesArray[dwServiceCount];
2821
2822 /* Copy status info */
2823 memcpy(&lpServicesPtr->ServiceStatus,
2824 &lpService->Status,
2825 sizeof(SERVICE_STATUS));
2826
2827 /* Copy display name */
2828 wcscpy(lpStr, lpService->lpDisplayName);
2829 lpServicesPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
2830 lpStr += (wcslen(lpService->lpDisplayName) + 1);
2831
2832 /* Copy service name */
2833 wcscpy(lpStr, lpService->lpServiceName);
2834 lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
2835 lpStr += (wcslen(lpService->lpServiceName) + 1);
2836
2837 lpServicesPtr++;
2838 }
2839
2840 *lpServicesReturned = dwServicesReturned;
2841
2842Done:
2843 if (lpServicesArray != NULL)
2844 HeapFree(GetProcessHeap(), 0, lpServicesArray);
2845
2847
2848 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError);
2849
2850 return dwError;
2851}
2852
2853
2854/* Function 14 */
2855DWORD
2856WINAPI
2859 DWORD dwServiceType,
2860 DWORD dwServiceState,
2862 DWORD dwBufSize,
2864 LPBOUNDED_DWORD_256K lpServicesReturned,
2865 LPBOUNDED_DWORD_256K lpResumeHandle)
2866{
2867 /* Enumerate all the services, not regarding of their group */
2869 dwServiceType,
2870 dwServiceState,
2871 lpBuffer,
2872 dwBufSize,
2874 lpServicesReturned,
2875 lpResumeHandle,
2876 NULL);
2877}
2878
2879
2880/* Function 15 */
2881DWORD
2882WINAPI
2884 LPWSTR lpMachineName,
2885 LPWSTR lpDatabaseName,
2886 DWORD dwDesiredAccess,
2887 LPSC_RPC_HANDLE lpScHandle)
2888{
2889 DWORD dwError;
2890 SC_HANDLE hHandle;
2891
2892 DPRINT("ROpenSCManagerW() called\n");
2893 DPRINT("lpMachineName = %p\n", lpMachineName);
2894 DPRINT("lpMachineName: %S\n", lpMachineName);
2895 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
2896 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
2897 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
2898
2899 if (ScmShutdown)
2901
2902 if (!lpScHandle)
2904
2905 dwError = ScmCreateManagerHandle(lpDatabaseName,
2906 &hHandle);
2907 if (dwError != ERROR_SUCCESS)
2908 {
2909 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
2910 return dwError;
2911 }
2912
2913 /* Check the desired access */
2914 dwError = ScmCheckAccess(hHandle,
2915 dwDesiredAccess | SC_MANAGER_CONNECT);
2916 if (dwError != ERROR_SUCCESS)
2917 {
2918 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError);
2919 HeapFree(GetProcessHeap(), 0, hHandle);
2920 return dwError;
2921 }
2922
2923 *lpScHandle = (SC_RPC_HANDLE)hHandle;
2924 DPRINT("*hScm = %p\n", *lpScHandle);
2925
2926 DPRINT("ROpenSCManagerW() done\n");
2927
2928 return ERROR_SUCCESS;
2929}
2930
2931
2932/* Function 16 */
2933DWORD
2934WINAPI
2937 LPWSTR lpServiceName,
2938 DWORD dwDesiredAccess,
2939 LPSC_RPC_HANDLE lpServiceHandle)
2940{
2941 PSERVICE lpService;
2942 PMANAGER_HANDLE hManager;
2943 SC_HANDLE hHandle;
2944 DWORD dwError = ERROR_SUCCESS;
2945
2946 DPRINT("ROpenServiceW() called\n");
2947 DPRINT("hSCManager = %p\n", hSCManager);
2948 DPRINT("lpServiceName = %p\n", lpServiceName);
2949 DPRINT("lpServiceName: %S\n", lpServiceName);
2950 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
2951
2952 if (ScmShutdown)
2954
2956 if (hManager == NULL)
2957 {
2958 DPRINT1("Invalid service manager handle\n");
2959 return ERROR_INVALID_HANDLE;
2960 }
2961
2962 if (!lpServiceHandle)
2964
2965 if (!lpServiceName)
2966 return ERROR_INVALID_ADDRESS;
2967
2968 /* Lock the service database exclusive */
2970
2971 /* Get service database entry */
2972 lpService = ScmGetServiceEntryByName(lpServiceName);
2973 if (lpService == NULL)
2974 {
2975 DPRINT("Could not find service\n");
2977 goto Done;
2978 }
2979
2980 /* Create a service handle */
2981 dwError = ScmCreateServiceHandle(lpService,
2982 &hHandle);
2983 if (dwError != ERROR_SUCCESS)
2984 {
2985 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
2986 goto Done;
2987 }
2988
2989 /* Check the desired access */
2990 dwError = ScmCheckAccess(hHandle,
2991 dwDesiredAccess);
2992 if (dwError != ERROR_SUCCESS)
2993 {
2994 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError);
2995 HeapFree(GetProcessHeap(), 0, hHandle);
2996 goto Done;
2997 }
2998
2999 ScmReferenceService(lpService);
3000 DPRINT("OpenService %S - lpService->RefCount %u\n", lpService->lpServiceName, lpService->RefCount);
3001
3002 *lpServiceHandle = (SC_RPC_HANDLE)hHandle;
3003 DPRINT("*hService = %p\n", *lpServiceHandle);
3004
3005Done:
3006 /* Unlock the service database */
3008
3009 DPRINT("ROpenServiceW() done\n");
3010
3011 return dwError;
3012}
3013
3014
3015/* Function 17 */
3016DWORD
3017WINAPI
3019 SC_RPC_HANDLE hService,
3020 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
3023{
3024 LPQUERY_SERVICE_CONFIGW lpServiceConfig = (LPQUERY_SERVICE_CONFIGW)lpBuf;
3025 DWORD dwError = ERROR_SUCCESS;
3026 PSERVICE_HANDLE hSvc;
3027 PSERVICE lpService = NULL;
3028 HKEY hServiceKey = NULL;
3029 LPWSTR lpImagePath = NULL;
3030 LPWSTR lpServiceStartName = NULL;
3031 LPWSTR lpDependencies = NULL;
3032 DWORD dwDependenciesLength = 0;
3033 DWORD dwRequiredSize;
3034 LPWSTR lpStr;
3035
3036 DPRINT("RQueryServiceConfigW() called\n");
3037
3038 if (ScmShutdown)
3040
3041 hSvc = ScmGetServiceFromHandle(hService);
3042 if (hSvc == NULL)
3043 {
3044 DPRINT1("Invalid service handle\n");
3045 return ERROR_INVALID_HANDLE;
3046 }
3047
3050 {
3051 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
3052 return ERROR_ACCESS_DENIED;
3053 }
3054
3055 lpService = hSvc->ServiceEntry;
3056 if (lpService == NULL)
3057 {
3058 DPRINT("lpService == NULL\n");
3059 return ERROR_INVALID_HANDLE;
3060 }
3061
3062 /* Lock the service database shared */
3064
3065 dwError = ScmOpenServiceKey(lpService->lpServiceName,
3066 KEY_READ,
3067 &hServiceKey);
3068 if (dwError != ERROR_SUCCESS)
3069 goto Done;
3070
3071 /* Read the image path */
3072 dwError = ScmReadString(hServiceKey,
3073 L"ImagePath",
3074 &lpImagePath);
3075 if (dwError != ERROR_SUCCESS)
3076 goto Done;
3077
3078 /* Read the service start name */
3079 ScmReadString(hServiceKey,
3080 L"ObjectName",
3081 &lpServiceStartName);
3082
3083 /* Read the dependencies */
3084 ScmReadDependencies(hServiceKey,
3085 &lpDependencies,
3086 &dwDependenciesLength);
3087
3088 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
3089
3090 if (lpImagePath != NULL)
3091 dwRequiredSize += (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
3092 else
3093 dwRequiredSize += 2 * sizeof(WCHAR);
3094
3095 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
3096 dwRequiredSize += (DWORD)((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
3097 else
3098 dwRequiredSize += 2 * sizeof(WCHAR);
3099
3100 if (lpDependencies != NULL)
3101 dwRequiredSize += dwDependenciesLength * sizeof(WCHAR);
3102 else
3103 dwRequiredSize += 2 * sizeof(WCHAR);
3104
3105 if (lpServiceStartName != NULL)
3106 dwRequiredSize += (DWORD)((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
3107 else
3108 dwRequiredSize += 2 * sizeof(WCHAR);
3109
3110 if (lpService->lpDisplayName != NULL)
3111 dwRequiredSize += (DWORD)((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
3112 else
3113 dwRequiredSize += 2 * sizeof(WCHAR);
3114
3115 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
3116 {
3117 dwError = ERROR_INSUFFICIENT_BUFFER;
3118 }
3119 else
3120 {
3121 lpServiceConfig->dwServiceType = lpService->Status.dwServiceType;
3122 lpServiceConfig->dwStartType = lpService->dwStartType;
3123 lpServiceConfig->dwErrorControl = lpService->dwErrorControl;
3124 lpServiceConfig->dwTagId = lpService->dwTag;
3125
3126 lpStr = (LPWSTR)(lpServiceConfig + 1);
3127
3128 /* Append the image path */
3129 if (lpImagePath != NULL)
3130 {
3131 wcscpy(lpStr, lpImagePath);
3132 }
3133 else
3134 {
3135 *lpStr = 0;
3136 }
3137
3138 lpServiceConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3139 lpStr += (wcslen(lpStr) + 1);
3140
3141 /* Append the group name */
3142 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
3143 {
3144 wcscpy(lpStr, lpService->lpGroup->lpGroupName);
3145 }
3146 else
3147 {
3148 *lpStr = 0;
3149 }
3150
3151 lpServiceConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3152 lpStr += (wcslen(lpStr) + 1);
3153
3154 /* Append Dependencies */
3155 if (lpDependencies != NULL)
3156 {
3157 memcpy(lpStr,
3158 lpDependencies,
3159 dwDependenciesLength * sizeof(WCHAR));
3160 }
3161 else
3162 {
3163 *lpStr = 0;
3164 }
3165
3166 lpServiceConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3167 if (lpDependencies != NULL)
3168 lpStr += dwDependenciesLength;
3169 else
3170 lpStr += (wcslen(lpStr) + 1);
3171
3172 /* Append the service start name */
3173 if (lpServiceStartName != NULL)
3174 {
3175 wcscpy(lpStr, lpServiceStartName);
3176 }
3177 else
3178 {
3179 *lpStr = 0;
3180 }
3181
3182 lpServiceConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3183 lpStr += (wcslen(lpStr) + 1);
3184
3185 /* Append the display name */
3186 if (lpService->lpDisplayName != NULL)
3187 {
3188 wcscpy(lpStr, lpService->lpDisplayName);
3189 }
3190 else
3191 {
3192 *lpStr = 0;
3193 }
3194
3195 lpServiceConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3196 }
3197
3198 if (pcbBytesNeeded != NULL)
3199 *pcbBytesNeeded = dwRequiredSize;
3200
3201Done:
3202 /* Unlock the service database */
3204
3205 if (lpImagePath != NULL)
3206 HeapFree(GetProcessHeap(), 0, lpImagePath);
3207
3208 if (lpServiceStartName != NULL)
3209 HeapFree(GetProcessHeap(), 0, lpServiceStartName);
3210
3211 if (lpDependencies != NULL)
3212 HeapFree(GetProcessHeap(), 0, lpDependencies);
3213
3214 if (hServiceKey != NULL)
3215 RegCloseKey(hServiceKey);
3216
3217 DPRINT("RQueryServiceConfigW() done\n");
3218
3219 return dwError;
3220}
3221
3222
3223/* Function 18 */
3224DWORD
3225WINAPI
3228 LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
3231{
3233 PMANAGER_HANDLE hMgr;
3234 DWORD dwRequiredSize;
3235
3236 if (!lpLockStatus || !pcbBytesNeeded)
3238
3240 if (hMgr == NULL)
3241 {
3242 DPRINT1("Invalid service manager handle\n");
3243 return ERROR_INVALID_HANDLE;
3244 }
3245
3248 {
3249 DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess);
3250 return ERROR_ACCESS_DENIED;
3251 }
3252
3253 /* FIXME: we need to compute instead the real length of the owner name */
3254 dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSW) + sizeof(WCHAR);
3255 *pcbBytesNeeded = dwRequiredSize;
3256
3257 if (cbBufSize < dwRequiredSize)
3259
3260 ScmQueryServiceLockStatusW(lpLockStatus);
3261
3262 return ERROR_SUCCESS;
3263}
3264
3265
3266/* Function 19 */
3267DWORD
3268WINAPI
3270 SC_RPC_HANDLE hService,
3271 DWORD argc,
3273{
3274 DWORD dwError = ERROR_SUCCESS;
3275 PSERVICE_HANDLE hSvc;
3276 PSERVICE lpService = NULL;
3277
3278#ifndef NDEBUG
3279 DWORD i;
3280
3281 DPRINT("RStartServiceW(%p %lu %p) called\n", hService, argc, argv);
3282 DPRINT(" argc: %lu\n", argc);
3283 if (argv != NULL)
3284 {
3285 for (i = 0; i < argc; i++)
3286 {
3287 DPRINT(" argv[%lu]: %S\n", i, argv[i].StringPtr);
3288 }
3289 }
3290#endif
3291
3292 if (ScmShutdown)
3294
3295 hSvc = ScmGetServiceFromHandle(hService);
3296 if (hSvc == NULL)
3297 {
3298 DPRINT1("Invalid service handle\n");
3299 return ERROR_INVALID_HANDLE;
3300 }
3301
3304 {
3305 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
3306 return ERROR_ACCESS_DENIED;
3307 }
3308
3309 lpService = hSvc->ServiceEntry;
3310 if (lpService == NULL)
3311 {
3312 DPRINT("lpService == NULL\n");
3313 return ERROR_INVALID_HANDLE;
3314 }
3315
3316 if (lpService->dwStartType == SERVICE_DISABLED)
3318
3319 if (lpService->bDeleted)
3321
3322 /* Start the service */
3323 dwError = ScmStartService(lpService, argc, (PCWSTR*)argv);
3324
3325 return dwError;
3326}
3327
3328
3329/* Function 20 */
3330DWORD
3331WINAPI
3334 LPCWSTR lpServiceName,
3336 DWORD *lpcchBuffer)
3337{
3338 // PMANAGER_HANDLE hManager;
3339 PSERVICE lpService;
3340 LPCWSTR lpSvcDisplayName;
3342 DWORD dwError;
3343
3344 DPRINT("RGetServiceDisplayNameW() called\n");
3345 DPRINT("hSCManager = %p\n", hSCManager);
3346 DPRINT("lpServiceName: %S\n", lpServiceName);
3347 DPRINT("lpDisplayName: %p\n", lpDisplayName);
3348 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
3349
3350#if 0
3351 hManager = (PMANAGER_HANDLE)hSCManager;
3352 if (hManager->Handle.Tag != MANAGER_TAG)
3353 {
3354 DPRINT("Invalid manager handle\n");
3355 return ERROR_INVALID_HANDLE;
3356 }
3357#endif
3358
3359 /* Get service database entry */
3360 lpService = ScmGetServiceEntryByName(lpServiceName);
3361 if (lpService == NULL)
3362 {
3363 DPRINT("Could not find service\n");
3365 }
3366
3367 if (lpService->lpDisplayName)
3368 lpSvcDisplayName = lpService->lpDisplayName;
3369 else
3370 lpSvcDisplayName = lpService->lpServiceName;
3371
3372 dwLength = (DWORD)wcslen(lpSvcDisplayName);
3373
3374 if (*lpcchBuffer > dwLength)
3375 {
3376 if (lpDisplayName != NULL)
3377 wcscpy(lpDisplayName, lpSvcDisplayName);
3378
3379 dwError = ERROR_SUCCESS;
3380 }
3381 else
3382 {
3383 dwError = ERROR_INSUFFICIENT_BUFFER;
3384 }
3385
3386 *lpcchBuffer = dwLength;
3387
3388 return dwError;
3389}
3390
3391
3392/* Function 21 */
3393DWORD
3394WINAPI
3398 LPWSTR lpServiceName,
3399 DWORD *lpcchBuffer)
3400{
3401 // PMANAGER_HANDLE hManager;
3402 PSERVICE lpService;
3404 DWORD dwError;
3405
3406 DPRINT("RGetServiceKeyNameW() called\n");
3407 DPRINT("hSCManager = %p\n", hSCManager);
3408 DPRINT("lpDisplayName: %S\n", lpDisplayName);
3409 DPRINT("lpServiceName: %p\n", lpServiceName);
3410 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
3411
3412#if 0
3413 hManager = (PMANAGER_HANDLE)hSCManager;
3414 if (hManager->Handle.Tag != MANAGER_TAG)
3415 {
3416 DPRINT("Invalid manager handle\n");
3417 return ERROR_INVALID_HANDLE;
3418 }
3419#endif
3420
3421 /* Get service database entry */
3423 if (lpService == NULL)
3424 {
3425 DPRINT("Could not find service\n");
3427 }
3428
3429 dwLength = (DWORD)wcslen(lpService->lpServiceName);
3430
3431 if (*lpcchBuffer > dwLength)
3432 {
3433 if (lpServiceName != NULL)
3434 wcscpy(lpServiceName, lpService->lpServiceName);
3435
3436 dwError = ERROR_SUCCESS;
3437 }
3438 else
3439 {
3440 dwError = ERROR_INSUFFICIENT_BUFFER;
3441 }
3442
3443 *lpcchBuffer = dwLength;
3444
3445 return dwError;
3446}
3447
3448
3449/* Function 22 */
3450DWORD
3451WINAPI
3455 int bSetBitsOn,
3456 int bUpdateImmediately,
3457 char *lpString)
3458{
3459 if (ScmShutdown)
3461
3462 if (lpString != NULL)
3464
3467 bSetBitsOn,
3468 bUpdateImmediately,
3469 NULL);
3470}
3471
3472
3473/* Function 23 */
3474DWORD
3475WINAPI
3477 SC_RPC_HANDLE hService,
3478 DWORD dwServiceType,
3479 DWORD dwStartType,
3480 DWORD dwErrorControl,
3481 LPSTR lpBinaryPathName,
3482 LPSTR lpLoadOrderGroup,
3483 LPDWORD lpdwTagId,
3484 LPBYTE lpDependencies,
3485 DWORD dwDependSize,
3486 LPSTR lpServiceStartName,
3487 LPBYTE lpPassword,
3488 DWORD dwPwSize,
3490{
3491 DWORD dwError = ERROR_SUCCESS;
3492 LPWSTR lpBinaryPathNameW = NULL;
3493 LPWSTR lpLoadOrderGroupW = NULL;
3494 LPWSTR lpDependenciesW = NULL;
3495 LPWSTR lpServiceStartNameW = NULL;
3496 LPWSTR lpDisplayNameW = NULL;
3497 DWORD dwDependenciesLength = 0;
3498 SIZE_T cchLength;
3499 int len;
3500 LPCSTR lpStr;
3501
3502 if (lpBinaryPathName)
3503 {
3504 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
3505 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3506 if (!lpBinaryPathNameW)
3507 {
3509 goto cleanup;
3510 }
3511 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
3512 }
3513
3514 if (lpLoadOrderGroup)
3515 {
3516 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
3517 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3518 if (!lpLoadOrderGroupW)
3519 {
3521 goto cleanup;
3522 }
3523 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
3524 }
3525
3526 if (lpDependencies)
3527 {
3528 lpStr = (LPCSTR)lpDependencies;
3529 while (*lpStr)
3530 {
3531 cchLength = strlen(lpStr) + 1;
3532 dwDependenciesLength += (DWORD)cchLength;
3533 lpStr = lpStr + cchLength;
3534 }
3535 dwDependenciesLength++;
3536
3537 lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR));
3538 if (!lpDependenciesW)
3539 {
3541 goto cleanup;
3542 }
3543 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
3544 }
3545
3546 if (lpServiceStartName)
3547 {
3548 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
3549 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3550 if (!lpServiceStartNameW)
3551 {
3553 goto cleanup;
3554 }
3555 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
3556 }
3557
3558 if (lpDisplayName)
3559 {
3561 lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3562 if (!lpDisplayNameW)
3563 {
3565 goto cleanup;
3566 }
3567 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
3568 }
3569
3570 dwError = RChangeServiceConfigW(hService,
3571 dwServiceType,
3572 dwStartType,
3573 dwErrorControl,
3574 lpBinaryPathNameW,
3575 lpLoadOrderGroupW,
3576 lpdwTagId,
3577 (LPBYTE)lpDependenciesW,
3578 dwDependenciesLength,
3579 lpServiceStartNameW,
3580 lpPassword,
3581 dwPwSize,
3582 lpDisplayNameW);
3583
3584cleanup:
3585 if (lpBinaryPathNameW != NULL)
3586 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
3587
3588 if (lpLoadOrderGroupW != NULL)
3589 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
3590
3591 if (lpDependenciesW != NULL)
3592 HeapFree(GetProcessHeap(), 0, lpDependenciesW);
3593
3594 if (lpServiceStartNameW != NULL)
3595 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
3596
3597 if (lpDisplayNameW != NULL)
3598 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
3599
3600 return dwError;
3601}
3602
3603
3604/* Function 24 */
3605DWORD
3606WINAPI
3609 LPSTR lpServiceName,
3611 DWORD dwDesiredAccess,
3612 DWORD dwServiceType,
3613 DWORD dwStartType,
3614 DWORD dwErrorControl,
3615 LPSTR lpBinaryPathName,
3616 LPSTR lpLoadOrderGroup,
3617 LPDWORD lpdwTagId,
3618 LPBYTE lpDependencies,
3619 DWORD dwDependSize,
3620 LPSTR lpServiceStartName,
3621 LPBYTE lpPassword,
3622 DWORD dwPwSize,
3623 LPSC_RPC_HANDLE lpServiceHandle)
3624{
3625 DWORD dwError = ERROR_SUCCESS;
3626 LPWSTR lpServiceNameW = NULL;
3627 LPWSTR lpDisplayNameW = NULL;
3628 LPWSTR lpBinaryPathNameW = NULL;
3629 LPWSTR lpLoadOrderGroupW = NULL;
3630 LPWSTR lpDependenciesW = NULL;
3631 LPWSTR lpServiceStartNameW = NULL;
3632 DWORD dwDependenciesLength = 0;
3633 SIZE_T cchLength;
3634 int len;
3635 LPCSTR lpStr;
3636
3637 if (lpServiceName)
3638 {
3639 len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
3640 lpServiceNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3641 if (!lpServiceNameW)
3642 {
3644 goto cleanup;
3645 }
3646 MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len);
3647 }
3648
3649 if (lpDisplayName)
3650 {
3652 lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3653 if (!lpDisplayNameW)
3654 {
3656 goto cleanup;
3657 }
3658 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
3659 }
3660
3661 if (lpBinaryPathName)
3662 {
3663 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
3664 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3665 if (!lpBinaryPathNameW)
3666 {
3668 goto cleanup;
3669 }
3670 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
3671 }
3672
3673 if (lpLoadOrderGroup)
3674 {
3675 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
3676 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3677 if (!lpLoadOrderGroupW)
3678 {
3680 goto cleanup;
3681 }
3682 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
3683 }
3684
3685 if (lpDependencies)
3686 {
3687 lpStr = (LPCSTR)lpDependencies;
3688 while (*lpStr)
3689 {
3690 cchLength = strlen(lpStr) + 1;
3691 dwDependenciesLength += (DWORD)cchLength;
3692 lpStr = lpStr + cchLength;
3693 }
3694 dwDependenciesLength++;
3695
3696 lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR));
3697 if (!lpDependenciesW)
3698 {
3700 goto cleanup;
3701 }
3702 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
3703 }
3704
3705 if (lpServiceStartName)
3706 {
3707 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
3708 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3709 if (!lpServiceStartNameW)
3710 {
3712 goto cleanup;
3713 }
3714 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
3715 }
3716
3717 dwError = RCreateServiceW(hSCManager,
3718 lpServiceNameW,
3719 lpDisplayNameW,
3720 dwDesiredAccess,
3721 dwServiceType,
3722 dwStartType,
3723 dwErrorControl,
3724 lpBinaryPathNameW,
3725 lpLoadOrderGroupW,
3726 lpdwTagId,
3727 (LPBYTE)lpDependenciesW,
3728 dwDependenciesLength,
3729 lpServiceStartNameW,
3730 lpPassword,
3731 dwPwSize,
3732 lpServiceHandle);
3733
3734cleanup:
3735 if (lpServiceNameW !=NULL)
3736 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
3737
3738 if (lpDisplayNameW != NULL)
3739 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
3740
3741 if (lpBinaryPathNameW != NULL)
3742 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
3743
3744 if (lpLoadOrderGroupW != NULL)
3745 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
3746
3747 if (lpDependenciesW != NULL)
3748 HeapFree(GetProcessHeap(), 0, lpDependenciesW);
3749
3750 if (lpServiceStartNameW != NULL)
3751 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
3752
3753 return dwError;
3754}
3755
3756
3757/* Function 25 */
3758DWORD
3759WINAPI
3761 SC_RPC_HANDLE hService,
3762 DWORD dwServiceState,
3763 LPBYTE lpServices,
3766 LPBOUNDED_DWORD_256K lpServicesReturned)
3767{
3768 DWORD dwError = ERROR_SUCCESS;
3769 DWORD dwServicesReturned = 0;
3770 DWORD dwServiceCount;
3772 PSERVICE_HANDLE hSvc;
3773 PSERVICE lpService = NULL;
3774 PSERVICE *lpServicesArray = NULL;
3775 LPENUM_SERVICE_STATUSA lpServicesPtr = NULL;
3776 LPSTR lpStr;
3777
3778 *pcbBytesNeeded = 0;
3779 *lpServicesReturned = 0;
3780
3781 DPRINT("REnumDependentServicesA() called\n");
3782
3783 hSvc = ScmGetServiceFromHandle(hService);
3784 if (hSvc == NULL)
3785 {
3786 DPRINT1("Invalid service handle\n");
3787 return ERROR_INVALID_HANDLE;
3788 }
3789
3790 lpService = hSvc->ServiceEntry;
3791
3792 /* Check access rights */
3795 {
3796 DPRINT("Insufficient access rights! 0x%lx\n",
3797 hSvc->Handle.DesiredAccess);
3798 return ERROR_ACCESS_DENIED;
3799 }
3800
3801 /* Open the Services Reg key */
3803 L"System\\CurrentControlSet\\Services",
3804 0,
3805 KEY_READ,
3806 &hServicesKey);
3807
3808 if (dwError != ERROR_SUCCESS)
3809 return dwError;
3810
3811 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3812 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3813 are the same for both. Verified in WINXP. */
3814
3815 /* First determine the bytes needed and get the number of dependent services*/
3817 lpService,
3818 dwServiceState,
3819 NULL,
3821 &dwServicesReturned);
3822 if (dwError != ERROR_SUCCESS)
3823 goto Done;
3824
3825 /* If buffer size is less than the bytes needed or pointer is null*/
3826 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
3827 {
3828 dwError = ERROR_MORE_DATA;
3829 goto Done;
3830 }
3831
3832 /* Allocate memory for array of service pointers */
3833 lpServicesArray = HeapAlloc(GetProcessHeap(),
3835 (dwServicesReturned + 1) * sizeof(PSERVICE));
3836 if (!lpServicesArray)
3837 {
3838 DPRINT("Could not allocate buffer\n");
3839 dwError = ERROR_NOT_ENOUGH_MEMORY;
3840 goto Done;
3841 }
3842
3843 dwServicesReturned = 0;
3844 *pcbBytesNeeded = 0;
3845
3847 lpService,
3848 dwServiceState,
3849 lpServicesArray,
3851 &dwServicesReturned);
3852 if (dwError != ERROR_SUCCESS)
3853 {
3854 goto Done;
3855 }
3856
3857 lpServicesPtr = (LPENUM_SERVICE_STATUSA)lpServices;
3858 lpStr = (LPSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSA)));
3859
3860 /* Copy EnumDepenedentService to Buffer */
3861 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
3862 {
3863 lpService = lpServicesArray[dwServiceCount];
3864
3865 /* Copy the status info */
3866 memcpy(&lpServicesPtr->ServiceStatus,
3867 &lpService->Status,
3868 sizeof(SERVICE_STATUS));
3869
3870 /* Copy display name */
3872 0,
3873 lpService->lpDisplayName,
3874 -1,
3875 lpStr,
3876 (int)wcslen(lpService->lpDisplayName),
3877 0,
3878 0);
3879 lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
3880 lpStr += strlen(lpStr) + 1;
3881
3882 /* Copy service name */
3884 0,
3885 lpService->lpServiceName,
3886 -1,
3887 lpStr,
3888 (int)wcslen(lpService->lpServiceName),
3889 0,
3890 0);
3891 lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
3892 lpStr += strlen(lpStr) + 1;
3893
3894 lpServicesPtr++;
3895 }
3896
3897 *lpServicesReturned = dwServicesReturned;
3898
3899Done:
3900 if (lpServicesArray)
3901 HeapFree(GetProcessHeap(), 0, lpServicesArray);
3902
3904
3905 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError);
3906
3907 return dwError;
3908}
3909
3910
3911/* Function 26 */
3912DWORD
3913WINAPI
3916 DWORD dwServiceType,
3917 DWORD dwServiceState,
3919 DWORD dwBufSize,
3921 LPBOUNDED_DWORD_256K lpServicesReturned,
3922 LPBOUNDED_DWORD_256K lpResumeHandle)
3923{
3924 LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL;
3925 LPENUM_SERVICE_STATUSW lpStatusPtrIncrW;
3926 LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL;
3927 LPWSTR lpStringPtrW;
3928 LPSTR lpStringPtrA;
3929 DWORD dwError;
3930 DWORD dwServiceCount;
3931
3932 DPRINT("REnumServicesStatusA() called\n");
3933
3934 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
3935 {
3936 return ERROR_INVALID_ADDRESS;
3937 }
3938
3939 if ((dwBufSize > 0) && (lpBuffer))
3940 {
3941 lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize);
3942 if (!lpStatusPtrW)
3943 {
3944 DPRINT("Failed to allocate buffer\n");
3946 }
3947 }
3948
3950 dwServiceType,
3951 dwServiceState,
3952 (LPBYTE)lpStatusPtrW,
3953 dwBufSize,
3955 lpServicesReturned,
3956 lpResumeHandle);
3957
3958 /* if no services were returned then we are Done */
3959 if (*lpServicesReturned == 0)
3960 goto Done;
3961
3962 lpStatusPtrIncrW = lpStatusPtrW;
3963 lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer;
3964 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
3965 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA));
3966 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW +
3967 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW));
3968
3969 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
3970 {
3971 /* Copy the service name */
3973 0,
3974 lpStringPtrW,
3975 -1,
3976 lpStringPtrA,
3977 (int)wcslen(lpStringPtrW),
3978 0,
3979 0);
3980
3981 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
3982 lpStringPtrA += wcslen(lpStringPtrW) + 1;
3983 lpStringPtrW += wcslen(lpStringPtrW) + 1;
3984
3985 /* Copy the display name */
3987 0,
3988 lpStringPtrW,
3989 -1,
3990 lpStringPtrA,
3991 (int)wcslen(lpStringPtrW),
3992 0,
3993 0);
3994
3995 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
3996 lpStringPtrA += wcslen(lpStringPtrW) + 1;
3997 lpStringPtrW += wcslen(lpStringPtrW) + 1;
3998
3999 /* Copy the status information */
4000 memcpy(&lpStatusPtrA->ServiceStatus,
4001 &lpStatusPtrIncrW->ServiceStatus,
4002 sizeof(SERVICE_STATUS));
4003
4004 lpStatusPtrIncrW++;
4005 lpStatusPtrA++;
4006 }
4007
4008Done:
4009 if (lpStatusPtrW)
4010 HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
4011
4012 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError);
4013
4014 return dwError;
4015}
4016
4017
4018/* Function 27 */
4019DWORD
4020WINAPI
4022 LPSTR lpMachineName,
4023 LPSTR lpDatabaseName,
4024 DWORD dwDesiredAccess,
4025 LPSC_RPC_HANDLE lpScHandle)
4026{
4028 UNICODE_STRING DatabaseName;
4029 DWORD dwError;
4030
4031 DPRINT("ROpenSCManagerA() called\n");
4032
4033 if (lpMachineName)
4035 lpMachineName);
4036
4037 if (lpDatabaseName)
4039 lpDatabaseName);
4040
4041 dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL,
4042 lpDatabaseName ? DatabaseName.Buffer : NULL,
4043 dwDesiredAccess,
4044 lpScHandle);
4045
4046 if (lpMachineName)
4048
4049 if (lpDatabaseName)
4050 RtlFreeUnicodeString(&DatabaseName);
4051
4052 return dwError;
4053}
4054
4055
4056/* Function 28 */
4057DWORD
4058WINAPI
4061 LPSTR lpServiceName,
4062 DWORD dwDesiredAccess,
4063 LPSC_RPC_HANDLE lpServiceHandle)
4064{
4066 DWORD dwError;
4067
4068 DPRINT("ROpenServiceA() called\n");
4069
4070 if (lpServiceName)
4072 lpServiceName);
4073
4074 dwError = ROpenServiceW(hSCManager,
4075 lpServiceName ? ServiceName.Buffer : NULL,
4076 dwDesiredAccess,
4077 lpServiceHandle);
4078
4079 if (lpServiceName)
4081
4082 return dwError;
4083}
4084
4085
4086/* Function 29 */
4087DWORD
4088WINAPI
4090 SC_RPC_HANDLE hService,
4091 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4094{
4095 LPQUERY_SERVICE_CONFIGA lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)lpBuf;
4096 DWORD dwError = ERROR_SUCCESS;
4097 PSERVICE_HANDLE hSvc;
4098 PSERVICE lpService = NULL;
4099 HKEY hServiceKey = NULL;
4100 LPWSTR lpImagePath = NULL;
4101 LPWSTR lpServiceStartName = NULL;
4102 LPWSTR lpDependencies = NULL;
4103 DWORD dwDependenciesLength = 0;
4104 DWORD dwRequiredSize;
4105 LPSTR lpStr;
4106
4107 DPRINT("RQueryServiceConfigA() called\n");
4108
4109 if (ScmShutdown)
4111
4112 hSvc = ScmGetServiceFromHandle(hService);
4113 if (hSvc == NULL)
4114 {
4115 DPRINT1("Invalid service handle\n");
4116 return ERROR_INVALID_HANDLE;
4117 }
4118
4121 {
4122 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
4123 return ERROR_ACCESS_DENIED;
4124 }
4125
4126 lpService = hSvc->ServiceEntry;
4127 if (lpService == NULL)
4128 {
4129 DPRINT("lpService == NULL\n");
4130 return ERROR_INVALID_HANDLE;
4131 }
4132
4133 /* Lock the service database shared */
4135
4136 dwError = ScmOpenServiceKey(lpService->lpServiceName,
4137 KEY_READ,
4138 &hServiceKey);
4139 if (dwError != ERROR_SUCCESS)
4140 goto Done;
4141
4142 /* Read the image path */
4143 dwError = ScmReadString(hServiceKey,
4144 L"ImagePath",
4145 &lpImagePath);
4146 if (dwError != ERROR_SUCCESS)
4147 goto Done;
4148
4149 /* Read the service start name */
4150 ScmReadString(hServiceKey,
4151 L"ObjectName",
4152 &lpServiceStartName);
4153
4154 /* Read the dependencies */
4155 ScmReadDependencies(hServiceKey,
4156 &lpDependencies,
4157 &dwDependenciesLength);
4158
4159 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGA);
4160
4161 if (lpImagePath != NULL)
4162 dwRequiredSize += (DWORD)(wcslen(lpImagePath) + 1);
4163 else
4164 dwRequiredSize += 2 * sizeof(CHAR);
4165
4166 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
4167 dwRequiredSize += (DWORD)(wcslen(lpService->lpGroup->lpGroupName) + 1);
4168 else
4169 dwRequiredSize += 2 * sizeof(CHAR);
4170
4171 /* Add Dependencies length */
4172 if (lpDependencies != NULL)
4173 dwRequiredSize += dwDependenciesLength;
4174 else
4175 dwRequiredSize += 2 * sizeof(CHAR);
4176
4177 if (lpServiceStartName != NULL)
4178 dwRequiredSize += (DWORD)(wcslen(lpServiceStartName) + 1);
4179 else
4180 dwRequiredSize += 2 * sizeof(CHAR);
4181
4182 if (lpService->lpDisplayName != NULL)
4183 dwRequiredSize += (DWORD)(wcslen(lpService->lpDisplayName) + 1);
4184 else
4185 dwRequiredSize += 2 * sizeof(CHAR);
4186
4187 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
4188 {
4189 dwError = ERROR_INSUFFICIENT_BUFFER;
4190 }
4191 else
4192 {
4193 lpServiceConfig->dwServiceType = lpService->Status.dwServiceType;
4194 lpServiceConfig->dwStartType = lpService->dwStartType;
4195 lpServiceConfig->dwErrorControl = lpService->dwErrorControl;
4196 lpServiceConfig->dwTagId = lpService->dwTag;
4197
4198 lpStr = (LPSTR)(lpServiceConfig + 1);
4199
4200 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4201 Verified in WINXP */
4202
4203 if (lpImagePath)
4204 {
4206 0,
4207 lpImagePath,
4208 -1,
4209 lpStr,
4210 (int)(wcslen(lpImagePath) + 1),
4211 0,
4212 0);
4213 }
4214 else
4215 {
4216 *lpStr = 0;
4217 }
4218
4219 lpServiceConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4220 lpStr += (strlen((LPSTR)lpStr) + 1);
4221
4222 if (lpService->lpGroup && lpService->lpGroup->lpGroupName)
4223 {
4225 0,
4226 lpService->lpGroup->lpGroupName,
4227 -1,
4228 lpStr,
4229 (int)(wcslen(lpService->lpGroup->lpGroupName) + 1),
4230 0,
4231 0);
4232 }
4233 else
4234 {
4235 *lpStr = 0;
4236 }
4237
4238 lpServiceConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4239 lpStr += (strlen(lpStr) + 1);
4240
4241 /* Append Dependencies */
4242 if (lpDependencies)
4243 {
4245 0,
4246 lpDependencies,
4247 dwDependenciesLength,
4248 lpStr,
4249 dwDependenciesLength,
4250 0,
4251 0);
4252 }
4253 else
4254 {
4255 *lpStr = 0;
4256 }
4257
4258 lpServiceConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4259 if (lpDependencies)
4260 lpStr += dwDependenciesLength;
4261 else
4262 lpStr += (strlen(lpStr) + 1);
4263
4264 if (lpServiceStartName)
4265 {
4267 0,
4268 lpServiceStartName,
4269 -1,
4270 lpStr,
4271 (int)(wcslen(lpServiceStartName) + 1),
4272 0,
4273 0);
4274 }
4275 else
4276 {
4277 *lpStr = 0;
4278 }
4279
4280 lpServiceConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4281 lpStr += (strlen(lpStr) + 1);
4282
4283 if (lpService->lpDisplayName)
4284 {
4286 0,
4287 lpService->lpDisplayName,
4288 -1,
4289 lpStr,
4290 (int)(wcslen(lpService->lpDisplayName) + 1),
4291 0,
4292 0);
4293 }
4294 else
4295 {
4296 *lpStr = 0;
4297 }
4298
4299 lpServiceConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4300 }
4301
4302 if (pcbBytesNeeded != NULL)
4303 *pcbBytesNeeded = dwRequiredSize;
4304
4305Done:
4306 /* Unlock the service database */
4308
4309 if (lpImagePath != NULL)
4310 HeapFree(GetProcessHeap(), 0, lpImagePath);
4311
4312 if (lpServiceStartName != NULL)
4313 HeapFree(GetProcessHeap(), 0, lpServiceStartName);
4314
4315 if (lpDependencies != NULL)
4316 HeapFree(GetProcessHeap(), 0, lpDependencies);
4317
4318 if (hServiceKey != NULL)
4319 RegCloseKey(hServiceKey);
4320
4321 DPRINT("RQueryServiceConfigA() done\n");
4322
4323 return dwError;
4324}
4325
4326
4327/* Function 30 */
4328DWORD
4329WINAPI
4332 LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
4335{
4337 PMANAGER_HANDLE hMgr;
4338 DWORD dwRequiredSize;
4339
4340 if (!lpLockStatus || !pcbBytesNeeded)
4342
4344 if (hMgr == NULL)
4345 {
4346 DPRINT1("Invalid service manager handle\n");
4347 return ERROR_INVALID_HANDLE;
4348 }
4349
4352 {
4353 DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess);
4354 return ERROR_ACCESS_DENIED;
4355 }
4356
4357 /* FIXME: we need to compute instead the real length of the owner name */
4358 dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSA) + sizeof(CHAR);
4359 *pcbBytesNeeded = dwRequiredSize;
4360
4361 if (cbBufSize < dwRequiredSize)
4363
4364 ScmQueryServiceLockStatusA(lpLockStatus);
4365
4366 return ERROR_SUCCESS;
4367}
4368
4369
4370/* Function 31 */
4371DWORD
4372WINAPI
4374 SC_RPC_HANDLE hService,
4375 DWORD argc,
4377{
4378 DWORD dwError = ERROR_SUCCESS;
4379 PSERVICE_HANDLE hSvc;
4380 PSERVICE lpService = NULL;
4381 PWSTR* pVector = NULL;
4382 DWORD i;
4384
4385 DPRINT("RStartServiceA() called\n");
4386
4387 if (ScmShutdown)
4389
4390 hSvc = ScmGetServiceFromHandle(hService);
4391 if (hSvc == NULL)
4392 {
4393 DPRINT1("Invalid service handle\n");
4394 return ERROR_INVALID_HANDLE;
4395 }
4396
4399 {
4400 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
4401 return ERROR_ACCESS_DENIED;
4402 }
4403
4404 lpService = hSvc->ServiceEntry;
4405 if (lpService == NULL)
4406 {
4407 DPRINT("lpService == NULL\n");
4408 return ERROR_INVALID_HANDLE;
4409 }
4410
4411 if (lpService->dwStartType == SERVICE_DISABLED)
4413
4414 if (lpService->bDeleted)
4416
4417 /* Build a Unicode argument vector */
4418 if (argc > 0)
4419 {
4420 pVector = HeapAlloc(GetProcessHeap(),
4422 argc * sizeof(PWSTR));
4423 if (!pVector)
4425
4426 for (i = 0; i < argc; i++)
4427 {
4429 0,
4430 argv[i].StringPtr,
4431 -1,
4432 NULL,
4433 0);
4434
4435 pVector[i] = HeapAlloc(GetProcessHeap(),
4437 dwLength * sizeof(WCHAR));
4438 if (!pVector[i])
4439 {
4440 dwError = ERROR_NOT_ENOUGH_MEMORY;
4441 goto done;
4442 }
4443
4445 0,
4446 argv[i].StringPtr,
4447 -1,
4448 pVector[i],
4449 dwLength);
4450 }
4451 }
4452
4453 /* Start the service */
4454 dwError = ScmStartService(lpService, argc, (PCWSTR*)pVector);
4455
4456done:
4457 /* Free the Unicode argument vector */
4458 if (pVector)
4459 {
4460 for (i = 0; i < argc; i++)
4461 {
4462 if (pVector[i])
4463 HeapFree(GetProcessHeap(), 0, pVector[i]);
4464 }
4465 HeapFree(GetProcessHeap(), 0, pVector);
4466 }
4467
4468 return dwError;
4469}
4470
4471
4472/* Function 32 */
4473DWORD
4474WINAPI
4477 LPCSTR lpServiceName,
4479 LPBOUNDED_DWORD_4K lpcchBuffer)
4480{
4481 // PMANAGER_HANDLE hManager;
4482 PSERVICE lpService = NULL;
4483 LPCWSTR lpSvcDisplayName;
4484 LPWSTR lpServiceNameW;
4486
4487 DPRINT("RGetServiceDisplayNameA() called\n");
4488 DPRINT("hSCManager = %p\n", hSCManager);
4489 DPRINT("lpServiceName: %s\n", lpServiceName);
4490 DPRINT("lpDisplayName: %p\n", lpDisplayName);
4491 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
4492
4493#if 0
4494 hManager = (PMANAGER_HANDLE)hSCManager;
4495 if (hManager->Handle.Tag != MANAGER_TAG)
4496 {
4497 DPRINT("Invalid manager handle\n");
4498 return ERROR_INVALID_HANDLE;
4499 }
4500#endif
4501
4502 /* Get service database entry */
4503 if (lpServiceName != NULL)
4504 {
4505 dwLength = (DWORD)(strlen(lpServiceName) + 1);
4506 lpServiceNameW = HeapAlloc(GetProcessHeap(),
4508 dwLength * sizeof(WCHAR));
4509 if (!lpServiceNameW)
4511
4513 0,
4514 lpServiceName,
4515 -1,
4516 lpServiceNameW,
4517 dwLength);
4518
4519 lpService = ScmGetServiceEntryByName(lpServiceNameW);
4520
4521 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
4522 }
4523
4524 if (lpService == NULL)
4525 {
4526 DPRINT("Could not find service\n");
4528 }
4529
4530 if (lpService->lpDisplayName)
4531 lpSvcDisplayName = lpService->lpDisplayName;
4532 else
4533 lpSvcDisplayName = lpService->lpServiceName;
4534
4535 /*
4536 * NOTE: On Windows the comparison on *lpcchBuffer is made against
4537 * the number of (wide) characters of the UNICODE display name, and
4538 * not against the number of bytes needed to store the ANSI string.
4539 */
4540 dwLength = (DWORD)wcslen(lpSvcDisplayName);
4541
4542 if (*lpcchBuffer > dwLength)
4543 {
4544 if (lpDisplayName != NULL &&
4546 0,
4547 lpSvcDisplayName,
4548 -1,
4550 (int)*lpcchBuffer,
4551 NULL,
4552 NULL) == 0)
4553 {
4554 /*
4555 * But then, if *lpcchBuffer was greater than the number of
4556 * (wide) characters of the UNICODE display name, yet smaller
4557 * than the number of bytes needed due to the possible presence
4558 * of DBCS characters, the *exact* number of bytes is returned
4559 * (without the NULL terminator).
4560 */
4562 0,
4563 lpSvcDisplayName,
4564 (int)dwLength,
4565 NULL,
4566 0,
4567 NULL,
4568 NULL);
4569 *lpDisplayName = 0;
4570 *lpcchBuffer = dwLength;
4572 }
4573
4574 /*
4575 * NOTE: On Windows, RGetServiceDisplayNameA() does not update
4576 * *lpcchBuffer on success, contrary to RGetServiceDisplayNameW().
4577 */
4578 return ERROR_SUCCESS;
4579 }
4580 else
4581 {
4582 /*
4583 * NOTE: On Windows, if *lpcchBuffer is smaller than the number of
4584 * (wide) characters of the UNICODE display name, only an upper
4585 * estimation is returned by doubling the string length, to account
4586 * for the presence of any possible DBCS characters.
4587 */
4588 *lpcchBuffer = dwLength * sizeof(WCHAR);
4590 }
4591}
4592
4593
4594/* Function 33 */
4595DWORD
4596WINAPI
4600 LPSTR lpServiceName,
4601 LPBOUNDED_DWORD_4K lpcchBuffer)
4602{
4603 // PMANAGER_HANDLE hManager;
4604 PSERVICE lpService;
4605 LPWSTR lpDisplayNameW;
4607
4608 DPRINT("RGetServiceKeyNameA() called\n");
4609 DPRINT("hSCManager = %p\n", hSCManager);
4610 DPRINT("lpDisplayName: %s\n", lpDisplayName);
4611 DPRINT("lpServiceName: %p\n", lpServiceName);
4612 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
4613
4614#if 0
4615 hManager = (PMANAGER_HANDLE)hSCManager;
4616 if (hManager->Handle.Tag != MANAGER_TAG)
4617 {
4618 DPRINT("Invalid manager handle\n");
4619 return ERROR_INVALID_HANDLE;
4620 }
4621#endif
4622
4623 /* Get service database entry */
4624
4626 lpDisplayNameW = HeapAlloc(GetProcessHeap(),
4628 dwLength * sizeof(WCHAR));
4629 if (!lpDisplayNameW)
4631
4633 0,
4635 -1,
4636 lpDisplayNameW,
4637 dwLength);
4638
4639 lpService = ScmGetServiceEntryByDisplayName(lpDisplayNameW);
4640
4641 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
4642
4643 if (lpService == NULL)
4644 {
4645 DPRINT("Could not find service\n");
4647 }
4648
4649 /*
4650 * NOTE: On Windows the comparison on *lpcchBuffer is made against
4651 * the number of (wide) characters of the UNICODE service name, and
4652 * not against the number of bytes needed to store the ANSI string.
4653 */
4654 dwLength = (DWORD)wcslen(lpService->lpServiceName);
4655
4656 if (*lpcchBuffer > dwLength)
4657 {
4658 if (lpServiceName != NULL &&
4660 0,
4661 lpService->lpServiceName,
4662 -1,
4663 lpServiceName,
4664 (int)*lpcchBuffer,
4665 NULL,
4666 NULL) == 0)
4667 {
4668 /*
4669 * But then, if *lpcchBuffer was greater than the number of
4670 * (wide) characters of the UNICODE service name, yet smaller
4671 * than the number of bytes needed due to the possible presence
4672 * of DBCS characters, the *exact* number of bytes is returned
4673 * (without the NULL terminator).
4674 */
4676 0,
4677 lpService->lpServiceName,
4678 (int)dwLength,
4679 NULL,
4680 0,
4681 NULL,
4682 NULL);
4683 *lpServiceName = 0;
4684 *lpcchBuffer = dwLength;
4686 }
4687
4688 /*
4689 * NOTE: On Windows, RGetServiceKeyNameA() does not update
4690 * *lpcchBuffer on success, contrary to RGetServiceKeyNameW().
4691 */
4692 return ERROR_SUCCESS;
4693 }
4694 else
4695 {
4696 /*
4697 * NOTE: On Windows, if *lpcchBuffer is smaller than the number of
4698 * (wide) characters of the UNICODE service name, only an upper
4699 * estimation is returned by doubling the string length, to account
4700 * for the presence of any possible DBCS characters.
4701 */
4702 *lpcchBuffer = dwLength * sizeof(WCHAR);
4704 }
4705}
4706
4707
4708/* Function 34 */
4709DWORD
4710WINAPI
4713 LPWSTR lpLoadOrderGroup,
4714 LPDWORD lpState)
4715{
4716 PMANAGER_HANDLE hManager;
4717 PSERVICE_GROUP pServiceGroup;
4718 DWORD dwError = ERROR_SUCCESS;
4719
4720 DPRINT("RI_ScGetCurrentGroupStateW() called\n");
4721
4722 if (ScmShutdown)
4724
4726 if (hManager == NULL)
4727 {
4728 DPRINT1("Invalid service manager handle\n");
4729 return ERROR_INVALID_HANDLE;
4730 }
4731
4732 /* Check for SC_MANAGER_ENUMERATE_SERVICE access right */
4735 {
4736 DPRINT("Insufficient access rights! 0x%lx\n",
4737 hManager->Handle.DesiredAccess);
4738 return ERROR_ACCESS_DENIED;
4739 }
4740
4741 /* Lock the service database shared */
4743
4744 /* Get the group list entry */
4745 pServiceGroup = ScmGetServiceGroupByName(lpLoadOrderGroup);
4746 if (pServiceGroup == NULL)
4747 {
4749 goto done;
4750 }
4751
4752 /* FIXME: Return the group state */
4753 *lpState = 0;
4754
4755done:
4756 /* Unlock the service database */
4758
4759 DPRINT("RI_ScGetCurrentGroupStateW() done (Error %lu)\n", dwError);
4760
4761 return dwError;
4762}
4763
4764
4765/* Function 35 */
4766DWORD
4767WINAPI
4770 DWORD dwServiceType,
4771 DWORD dwServiceState,
4775 LPBOUNDED_DWORD_256K lpServicesReturned,
4776 LPBOUNDED_DWORD_256K lpResumeIndex,
4777 LPCWSTR pszGroupName)
4778{
4779 PMANAGER_HANDLE hManager;
4780 PSERVICE lpService;
4781 DWORD dwError = ERROR_SUCCESS;
4782 PLIST_ENTRY ServiceEntry;
4783 PSERVICE CurrentService;
4784 DWORD dwState;
4785 DWORD dwRequiredSize;
4786 DWORD dwServiceCount;
4787 DWORD dwSize;
4788 DWORD dwLastResumeCount = 0;
4789 LPENUM_SERVICE_STATUSW lpStatusPtr;
4790 LPWSTR lpStringPtr;
4791
4792 DPRINT("REnumServiceGroupW() called\n");
4793
4794 if (ScmShutdown)
4796
4798 if (hManager == NULL)
4799 {
4800 DPRINT1("Invalid service manager handle\n");
4801 return ERROR_INVALID_HANDLE;
4802 }
4803
4804 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
4805 {
4806 return ERROR_INVALID_ADDRESS;
4807 }
4808
4809 *pcbBytesNeeded = 0;
4810 *lpServicesReturned = 0;
4811
4812 if ((dwServiceType == 0) ||
4813 ((dwServiceType & ~SERVICE_TYPE_ALL) != 0))
4814 {
4815 DPRINT("Invalid Service Type\n");
4817 }
4818
4819 if ((dwServiceState == 0) ||
4820 ((dwServiceState & ~SERVICE_STATE_ALL) != 0))
4821 {
4822 DPRINT("Invalid Service State\n");
4824 }
4825
4826 /* Check access rights */
4829 {
4830 DPRINT("Insufficient access rights! 0x%lx\n",
4831 hManager->Handle.DesiredAccess);
4832 return ERROR_ACCESS_DENIED;
4833 }
4834
4835 if (lpResumeIndex)
4836 dwLastResumeCount = *lpResumeIndex;
4837
4838 /* Lock the service database shared */
4840
4841 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
4842 if (lpService == NULL)
4843 {
4844 dwError = ERROR_SUCCESS;
4845 goto Done;
4846 }
4847
4848 dwRequiredSize = 0;
4849 dwServiceCount = 0;
4850
4851 for (ServiceEntry = &lpService->ServiceListEntry;
4852 ServiceEntry != &ServiceListHead;
4853 ServiceEntry = ServiceEntry->Flink)
4854 {
4855 CurrentService = CONTAINING_RECORD(ServiceEntry,
4856 SERVICE,
4857 ServiceListEntry);
4858
4859 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
4860 continue;
4861
4862 dwState = SERVICE_ACTIVE;
4863 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
4864 dwState = SERVICE_INACTIVE;
4865
4866 if ((dwState & dwServiceState) == 0)
4867 continue;
4868
4869 if (pszGroupName)
4870 {
4871 if (*pszGroupName == 0)
4872 {
4873 if (CurrentService->lpGroup != NULL)
4874 continue;
4875 }
4876 else
4877 {
4878 if ((CurrentService->lpGroup == NULL) ||
4879 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
4880 continue;
4881 }
4882 }
4883
4884 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
4885 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
4886 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
4887
4888 if (dwRequiredSize + dwSize > cbBufSize)
4889 {
4890 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
4891 break;
4892 }
4893
4894 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
4895 dwRequiredSize += dwSize;
4896 dwServiceCount++;
4897 dwLastResumeCount = CurrentService->dwResumeCount;
4898 }
4899
4900 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
4901 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
4902
4903 for (;
4904 ServiceEntry != &ServiceListHead;
4905 ServiceEntry = ServiceEntry->Flink)
4906 {
4907 CurrentService = CONTAINING_RECORD(ServiceEntry,
4908 SERVICE,
4909 ServiceListEntry);
4910
4911 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
4912 continue;
4913
4914 dwState = SERVICE_ACTIVE;
4915 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
4916 dwState = SERVICE_INACTIVE;
4917
4918 if ((dwState & dwServiceState) == 0)
4919 continue;
4920
4921 if (pszGroupName)
4922 {
4923 if (*pszGroupName == 0)
4924 {
4925 if (CurrentService->lpGroup != NULL)
4926 continue;
4927 }
4928 else
4929 {
4930 if ((CurrentService->lpGroup == NULL) ||
4931 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
4932 continue;
4933 }
4934 }
4935
4936 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
4937 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
4938 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
4939
4940 dwError = ERROR_MORE_DATA;
4941 }
4942
4943 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
4944
4945 if (lpResumeIndex)
4946 *lpResumeIndex = dwLastResumeCount;
4947
4948 *lpServicesReturned = dwServiceCount;
4949 *pcbBytesNeeded = dwRequiredSize;
4950
4951 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer;
4952 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
4953 dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
4954
4955 dwRequiredSize = 0;
4956 for (ServiceEntry = &lpService->ServiceListEntry;
4957 ServiceEntry != &ServiceListHead;
4958 ServiceEntry = ServiceEntry->Flink)
4959 {
4960 CurrentService = CONTAINING_RECORD(ServiceEntry,
4961 SERVICE,
4962 ServiceListEntry);
4963
4964 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
4965 continue;
4966
4967 dwState = SERVICE_ACTIVE;
4968 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
4969 dwState = SERVICE_INACTIVE;
4970
4971 if ((dwState & dwServiceState) == 0)
4972 continue;
4973
4974 if (pszGroupName)
4975 {
4976 if (*pszGroupName == 0)
4977 {
4978 if (CurrentService->lpGroup != NULL)
4979 continue;
4980 }
4981 else
4982 {
4983 if ((CurrentService->lpGroup == NULL) ||
4984 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
4985 continue;
4986 }
4987 }
4988
4989 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
4990 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
4991 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
4992
4993 if (dwRequiredSize + dwSize > cbBufSize)
4994 break;
4995
4996 /* Copy the service name */
4997 wcscpy(lpStringPtr, CurrentService->lpServiceName);
4998 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
4999 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
5000
5001 /* Copy the display name */
5002 wcscpy(lpStringPtr, CurrentService->lpDisplayName);
5003 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
5004 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
5005
5006 /* Copy the status information */
5007 memcpy(&lpStatusPtr->ServiceStatus,
5008 &CurrentService->Status,
5009 sizeof(SERVICE_STATUS));
5010
5011 lpStatusPtr++;
5012 dwRequiredSize += dwSize;
5013 }
5014
5015 if (dwError == ERROR_SUCCESS)
5016 {
5017 *pcbBytesNeeded = 0;
5018 if (lpResumeIndex) *lpResumeIndex = 0;
5019 }
5020
5021Done:
5022 /* Unlock the service database */
5024
5025 DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError);
5026
5027 return dwError;
5028}
5029
5030
5031/* Function 36 */
5032DWORD
5033WINAPI
5035 SC_RPC_HANDLE hService,
5037{
5038 SC_RPC_CONFIG_INFOW InfoW = { 0 };
5039 DWORD dwRet, dwLength;
5040 PVOID ptr = NULL;
5041
5042 DPRINT("RChangeServiceConfig2A() called\n");
5043 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
5044
5045 if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
5046 (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
5047 {
5048 return ERROR_INVALID_LEVEL;
5049 }
5050
5051 InfoW.dwInfoLevel = Info.dwInfoLevel;
5052
5054 {
5055 LPSERVICE_DESCRIPTIONW lpServiceDescriptionW;
5056 LPSERVICE_DESCRIPTIONA lpServiceDescriptionA;
5057
5058 lpServiceDescriptionA = Info.psd;
5059
5060 if (lpServiceDescriptionA &&
5061 lpServiceDescriptionA->lpDescription)
5062 {
5063 dwLength = (DWORD)((strlen(lpServiceDescriptionA->lpDescription) + 1) * sizeof(WCHAR));
5064
5065 lpServiceDescriptionW = HeapAlloc(GetProcessHeap(),
5067 dwLength + sizeof(SERVICE_DESCRIPTIONW));
5068 if (!lpServiceDescriptionW)
5069 {
5071 }
5072
5073 lpServiceDescriptionW->lpDescription = (LPWSTR)(lpServiceDescriptionW + 1);
5074
5076 0,
5077 lpServiceDescriptionA->lpDescription,
5078 -1,
5079 lpServiceDescriptionW->lpDescription,
5080 dwLength);
5081
5082 ptr = lpServiceDescriptionW;
5083 InfoW.psd = lpServiceDescriptionW;
5084 }
5085 }
5086 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5087 {
5088 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW;
5089 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA;
5090 DWORD dwRebootLen = 0;
5091 DWORD dwCommandLen = 0;
5092 DWORD dwActionArrayLen = 0;
5093 LPWSTR lpStr = NULL;
5094
5095 lpServiceFailureActionsA = Info.psfa;
5096
5097 if (lpServiceFailureActionsA)
5098 {
5099 /*
5100 * The following code is inspired by the
5101 * SERVICE_CONFIG_FAILURE_ACTIONS case of
5102 * the RQueryServiceConfig2W function.
5103 */
5104
5105 /* Retrieve the needed length for the two data strings */
5106 if (lpServiceFailureActionsA->lpRebootMsg)
5107 {
5108 dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR));
5109 }
5110 if (lpServiceFailureActionsA->lpCommand)
5111 {
5112 dwCommandLen = (DWORD)((strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR));
5113 }
5114
5115 /*
5116 * Retrieve the size of the lpsaActions array if needed.
5117 * We will copy the lpsaActions array only if there is at
5118 * least one action AND that the original array is valid.
5119 */
5120 if (lpServiceFailureActionsA->cActions > 0 && lpServiceFailureActionsA->lpsaActions)
5121 {
5122 dwActionArrayLen = lpServiceFailureActionsA->cActions * sizeof(SC_ACTION);
5123 }
5124
5125 /* Compute the total length for the UNICODE structure, including data */
5127 dwActionArrayLen + dwRebootLen + dwCommandLen;
5128
5129 /* Allocate the structure */
5130 lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(),
5132 dwLength);
5133 if (!lpServiceFailureActionsW)
5134 {
5136 }
5137
5138 /* Copy the members */
5139 lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod;
5140 lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions;
5141
5142 /* Copy the lpsaActions array if needed */
5143 if (dwActionArrayLen > 0)
5144 {
5145 /* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */
5146 lpServiceFailureActionsW->lpsaActions = (LPSC_ACTION)((ULONG_PTR)(lpServiceFailureActionsW + 1));
5147
5148 /* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */
5149 RtlCopyMemory(lpServiceFailureActionsW->lpsaActions,
5150 lpServiceFailureActionsA->lpsaActions,
5151 dwActionArrayLen);
5152 }
5153 else
5154 {
5155 /* No lpsaActions array */
5156 lpServiceFailureActionsW->lpsaActions = NULL;
5157 }
5158 /* The data strings are stored just after the lpsaActions array */
5159 lpStr = (LPWSTR)((ULONG_PTR)(lpServiceFailureActionsW + 1) + dwActionArrayLen);
5160
5161 /*
5162 * Convert the data strings to UNICODE
5163 */
5164
5165 lpServiceFailureActionsW->lpRebootMsg = NULL;
5166 lpServiceFailureActionsW->lpCommand = NULL;
5167
5168 if (dwRebootLen)
5169 {
5170 /* lpRebootMsg points just after the lpsaActions array */
5171 lpServiceFailureActionsW->lpRebootMsg = lpStr;
5172
5174 0,
5175 lpServiceFailureActionsA->lpRebootMsg,
5176 -1,
5177 lpServiceFailureActionsW->lpRebootMsg,
5178 dwRebootLen);
5179
5180 lpStr += dwRebootLen / sizeof(WCHAR);
5181 }
5182
5183 if (dwCommandLen)
5184 {
5185 /* lpRebootMsg points just after the lpRebootMsg data string */
5186 lpServiceFailureActionsW->lpCommand = lpStr;
5187
5189 0,
5190 lpServiceFailureActionsA->lpCommand,
5191 -1,
5192 lpServiceFailureActionsW->lpCommand,
5193 dwCommandLen);
5194 }
5195
5196 /* Set the pointers */
5197 ptr = lpServiceFailureActionsW;
5198 InfoW.psfa = lpServiceFailureActionsW;
5199 }
5200 }
5201
5202 dwRet = RChangeServiceConfig2W(hService, InfoW);
5203
5205
5206 return dwRet;
5207}
5208
5209
5210static DWORD
5212 LPSERVICE_FAILURE_ACTIONSW lpFailureActions)
5213{
5214 LPSERVICE_FAILURE_ACTIONSW lpReadBuffer = NULL;
5215 LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer = NULL;
5216 DWORD dwRequiredSize = 0;
5217 DWORD dwType = 0;
5218 DWORD dwError;
5219
5220 /* There is nothing to be done if we have no failure actions */
5221 if (lpFailureActions == NULL)
5222 return ERROR_SUCCESS;
5223
5224 /*
5225 * 1- Retrieve the original value of FailureActions.
5226 */
5227
5228 /* Query value length */
5229 dwError = RegQueryValueExW(hServiceKey,
5230 L"FailureActions",
5231 NULL,
5232 &dwType,
5233 NULL,
5234 &dwRequiredSize);
5235 if (dwError != ERROR_SUCCESS &&
5236 dwError != ERROR_MORE_DATA &&
5237 dwError != ERROR_FILE_NOT_FOUND)
5238 {
5239 return dwError;
5240 }
5241
5242 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
5243 : sizeof(SERVICE_FAILURE_ACTIONSW);
5244
5245 /* Initialize the read buffer */
5246 lpReadBuffer = HeapAlloc(GetProcessHeap(),
5248 dwRequiredSize);
5249 if (lpReadBuffer == NULL)
5251
5252 /* Now we can fill the read buffer */
5253 if (dwError != ERROR_FILE_NOT_FOUND &&
5254 dwType == REG_BINARY)
5255 {
5256 dwError = RegQueryValueExW(hServiceKey,
5257 L"FailureActions",
5258 NULL,
5259 NULL,
5260 (LPBYTE)lpReadBuffer,
5261 &dwRequiredSize);
5262 if (dwError != ERROR_SUCCESS &&
5263 dwError != ERROR_FILE_NOT_FOUND)
5264 goto done;
5265
5266 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW))
5267 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
5268 }
5269 else
5270 {
5271 /*
5272 * The value of the error doesn't really matter, the only
5273 * important thing is that it must be != ERROR_SUCCESS.
5274 */
5275 dwError = ERROR_INVALID_DATA;
5276 }
5277
5278 if (dwError == ERROR_SUCCESS)
5279 {
5280 lpReadBuffer->cActions = min(lpReadBuffer->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION));
5281 lpReadBuffer->lpsaActions = (lpReadBuffer->cActions > 0 ? (LPSC_ACTION)(lpReadBuffer + 1) : NULL);
5282 }
5283 else
5284 {
5285 lpReadBuffer->dwResetPeriod = 0;
5286 lpReadBuffer->cActions = 0;
5287 lpReadBuffer->lpsaActions = NULL;
5288 }
5289
5290 lpReadBuffer->lpRebootMsg = NULL;
5291 lpReadBuffer->lpCommand = NULL;
5292
5293 /*
5294 * 2- Initialize the new value to set.
5295 */
5296
5297 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
5298
5299 if (lpFailureActions->lpsaActions == NULL)
5300 {
5301 /*
5302 * lpFailureActions->cActions is ignored.
5303 * Therefore we use the original values
5304 * of cActions and lpsaActions.
5305 */
5306 dwRequiredSize += lpReadBuffer->cActions * sizeof(SC_ACTION);
5307 }
5308 else
5309 {
5310 /*
5311 * The reset period and array of failure actions
5312 * are deleted if lpFailureActions->cActions == 0 .
5313 */
5314 dwRequiredSize += lpFailureActions->cActions * sizeof(SC_ACTION);
5315 }
5316
5317 lpWriteBuffer = HeapAlloc(GetProcessHeap(),
5319 dwRequiredSize);
5320 if (lpWriteBuffer == NULL)
5321 {
5322 dwError = ERROR_NOT_ENOUGH_MEMORY;
5323 goto done;
5324 }
5325
5326 /* Clean the pointers as they have no meaning when the structure is stored in the registry */
5327 lpWriteBuffer->lpRebootMsg = NULL;
5328 lpWriteBuffer->lpCommand = NULL;
5329 lpWriteBuffer->lpsaActions = NULL;
5330
5331 /* Set the members */
5332 if (lpFailureActions->lpsaActions == NULL)
5333 {
5334 /*
5335 * lpFailureActions->dwResetPeriod and lpFailureActions->cActions are ignored.
5336 * Therefore we use the original values of dwResetPeriod, cActions and lpsaActions.
5337 */
5338 lpWriteBuffer->dwResetPeriod = lpReadBuffer->dwResetPeriod;
5339 lpWriteBuffer->cActions = lpReadBuffer->cActions;
5340
5341 if (lpReadBuffer->lpsaActions != NULL)
5342 {
5343 memmove(lpWriteBuffer + 1,
5344 lpReadBuffer->lpsaActions,
5345 lpReadBuffer->cActions * sizeof(SC_ACTION));
5346 }
5347 }
5348 else
5349 {
5350 if (lpFailureActions->cActions > 0)
5351 {
5352 lpWriteBuffer->dwResetPeriod = lpFailureActions->dwResetPeriod;
5353 lpWriteBuffer->cActions = lpFailureActions->cActions;
5354
5355 memmove(lpWriteBuffer + 1,
5356 lpFailureActions->lpsaActions,
5357 lpFailureActions->cActions * sizeof(SC_ACTION));
5358 }
5359 else
5360 {
5361 /* The reset period and array of failure actions are deleted */
5362 lpWriteBuffer->dwResetPeriod = 0;
5363 lpWriteBuffer->cActions = 0;
5364 }
5365 }
5366
5367 /* Save the new failure actions into the registry */
5368 dwError = RegSetValueExW(hServiceKey,
5369 L"FailureActions",
5370 0,
5371 REG_BINARY,
5372 (LPBYTE)lpWriteBuffer,
5373 dwRequiredSize);
5374
5375 /* We modify the strings only in case of success.*/
5376 if (dwError == ERROR_SUCCESS)
5377 {
5378 /* Modify the Reboot Message value, if specified */
5379 if (lpFailureActions->lpRebootMsg != NULL)
5380 {
5381 /* If the Reboot Message is "" then we delete it */
5382 if (*lpFailureActions->lpRebootMsg == 0)
5383 {
5384 DPRINT("Delete Reboot Message value\n");
5385 RegDeleteValueW(hServiceKey, L"RebootMessage");
5386 }
5387 else
5388 {
5389 DPRINT("Setting Reboot Message value %S\n", lpFailureActions->lpRebootMsg);
5390 RegSetValueExW(hServiceKey,
5391 L"RebootMessage",
5392 0,
5393 REG_SZ,
5394 (LPBYTE)lpFailureActions->lpRebootMsg,
5395 (DWORD)((wcslen(lpFailureActions->lpRebootMsg) + 1) * sizeof(WCHAR)));
5396 }
5397 }
5398
5399 /* Modify the Failure Command value, if specified */
5400 if (lpFailureActions->lpCommand != NULL)
5401 {
5402 /* If the FailureCommand string is an empty string, delete the value */
5403 if (*lpFailureActions->lpCommand == 0)
5404 {
5405 DPRINT("Delete Failure Command value\n");
5406 RegDeleteValueW(hServiceKey, L"FailureCommand");
5407 }
5408 else
5409 {
5410 DPRINT("Setting Failure Command value %S\n", lpFailureActions->lpCommand);
5411 RegSetValueExW(hServiceKey,
5412 L"FailureCommand",
5413 0,
5414 REG_SZ,
5415 (LPBYTE)lpFailureActions->lpCommand,
5416 (DWORD)((wcslen(lpFailureActions->lpCommand) + 1) * sizeof(WCHAR)));
5417 }
5418 }
5419 }
5420
5421done:
5422 if (lpWriteBuffer != NULL)
5423 HeapFree(GetProcessHeap(), 0, lpWriteBuffer);
5424
5425 if (lpReadBuffer != NULL)
5426 HeapFree(GetProcessHeap(), 0, lpReadBuffer);
5427
5428 return dwError;
5429}
5430
5431
5432/* Function 37 */
5433DWORD
5434WINAPI
5436 SC_RPC_HANDLE hService,
5438{
5439 DWORD dwError = ERROR_SUCCESS;
5440 PSERVICE_HANDLE hSvc;
5441 PSERVICE lpService = NULL;
5442 HKEY hServiceKey = NULL;
5444
5445 DPRINT("RChangeServiceConfig2W() called\n");
5446 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
5447
5448 if (ScmShutdown)
5450
5451 if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
5452 (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
5453 {
5454 return ERROR_INVALID_LEVEL;
5455 }
5456
5457 hSvc = ScmGetServiceFromHandle(hService);
5458 if (hSvc == NULL)
5459 {
5460 DPRINT("Invalid service handle\n");
5461 return ERROR_INVALID_HANDLE;
5462 }
5463
5464 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5466
5467 /* Check the access rights */
5470 {
5471 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
5472 return ERROR_ACCESS_DENIED;
5473 }
5474
5475 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5476 {
5477 /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */
5478
5479 }
5480
5481 lpService = hSvc->ServiceEntry;
5482 if (lpService == NULL)
5483 {
5484 DPRINT("lpService == NULL\n");
5485 return ERROR_INVALID_HANDLE;
5486 }
5487
5488 /* Failure actions can only be set for Win32 services, not for drivers */
5489 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5490 {
5491 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
5493 }
5494
5495 /* Lock the service database exclusively */
5497
5498 if (lpService->bDeleted)
5499 {
5500 DPRINT("Service has already been marked for delete\n");
5502 goto done;
5503 }
5504
5505 /* Open the service key */
5506 dwError = ScmOpenServiceKey(lpService->szServiceName,
5508 &hServiceKey);
5509 if (dwError != ERROR_SUCCESS)
5510 goto done;
5511
5512 if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
5513 {
5514 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd;
5515
5516 /* Modify the service description, if specified */
5517 if (lpServiceDescription != NULL &&
5518 lpServiceDescription->lpDescription != NULL)
5519 {
5520 /* If the description is "" then we delete it */
5521 if (*lpServiceDescription->lpDescription == 0)
5522 {
5523 DPRINT("Delete service description\n");
5524 dwError = RegDeleteValueW(hServiceKey, L"Description");
5525
5526 if (dwError == ERROR_FILE_NOT_FOUND)
5527 dwError = ERROR_SUCCESS;
5528 }
5529 else
5530 {
5531 DPRINT("Setting service description value %S\n", lpServiceDescription->lpDescription);
5532 dwError = RegSetValueExW(hServiceKey,
5533 L"Description",
5534 0,
5535 REG_SZ,
5536 (LPBYTE)lpServiceDescription->lpDescription,
5537 (DWORD)((wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR)));
5538 }
5539 }
5540 else
5541 {
5542 dwError = ERROR_SUCCESS;
5543 }
5544 }
5545 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5546 {
5547 dwError = ScmSetFailureActions(hServiceKey,
5549 }
5550
5551done:
5552 if (hServiceKey != NULL)
5553 RegCloseKey(hServiceKey);
5554
5555 /* Unlock the service database */
5557
5558 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError);
5559
5560 return dwError;
5561}
5562
5563
5564/* Function 38 */
5565DWORD
5566WINAPI
5568 SC_RPC_HANDLE hService,
5573{
5574 DWORD dwError = ERROR_SUCCESS;
5575 PSERVICE_HANDLE hSvc;
5576 PSERVICE lpService = NULL;
5577 HKEY hServiceKey = NULL;
5578 DWORD dwRequiredSize = 0;
5579 DWORD dwType = 0;
5580 LPWSTR lpDescriptionW = NULL;
5581 LPWSTR lpRebootMessageW = NULL;
5582 LPWSTR lpFailureCommandW = NULL;
5583
5584 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
5586
5587 if (!lpBuffer)
5588 return ERROR_INVALID_ADDRESS;
5589
5590 if (ScmShutdown)
5592
5595 {
5596 return ERROR_INVALID_LEVEL;
5597 }
5598
5599 hSvc = ScmGetServiceFromHandle(hService);
5600 if (hSvc == NULL)
5601 {
5602 DPRINT1("Invalid service handle\n");
5603 return ERROR_INVALID_HANDLE;
5604 }
5605
5608 {
5609 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
5610 return ERROR_ACCESS_DENIED;
5611 }
5612
5613 lpService = hSvc->ServiceEntry;
5614 if (lpService == NULL)
5615 {
5616 DPRINT("lpService == NULL\n");
5617 return ERROR_INVALID_HANDLE;
5618 }
5619
5620 /* Lock the service database shared */
5622
5623 dwError = ScmOpenServiceKey(lpService->lpServiceName,
5624 KEY_READ,
5625 &hServiceKey);
5626 if (dwError != ERROR_SUCCESS)
5627 goto done;
5628
5630 {
5632 LPSTR lpStr;
5633
5634 dwError = ScmReadString(hServiceKey,
5635 L"Description",
5636 &lpDescriptionW);
5637 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
5638 goto done;
5639
5641 if (dwError == ERROR_SUCCESS)
5642 *pcbBytesNeeded += (DWORD)((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR));
5643
5645 {
5646 dwError = ERROR_INSUFFICIENT_BUFFER;
5647 goto done;
5648 }
5649
5650 if (dwError == ERROR_SUCCESS)
5651 {
5652 lpStr = (LPSTR)(lpServiceDescription + 1);
5653
5655 0,
5656 lpDescriptionW,
5657 -1,
5658 lpStr,
5659 (int)wcslen(lpDescriptionW),
5660 NULL,
5661 NULL);
5662 lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
5663 }
5664 else
5665 {
5666 lpServiceDescription->lpDescription = NULL;
5667 dwError = ERROR_SUCCESS;
5668 }
5669 }
5671 {
5673 LPSTR lpStr = NULL;
5674
5675 /* Query value length */
5676 dwError = RegQueryValueExW(hServiceKey,
5677 L"FailureActions",
5678 NULL,
5679 &dwType,
5680 NULL,
5681 &dwRequiredSize);
5682 if (dwError != ERROR_SUCCESS &&
5683 dwError != ERROR_MORE_DATA &&
5684 dwError != ERROR_FILE_NOT_FOUND)
5685 {
5686 goto done;
5687 }
5688
5689 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize)
5690 : sizeof(SERVICE_FAILURE_ACTIONSA);
5691
5692 /* Get the strings */
5693 ScmReadString(hServiceKey,
5694 L"FailureCommand",
5695 &lpFailureCommandW);
5696
5697 ScmReadString(hServiceKey,
5698 L"RebootMessage",
5699 &lpRebootMessageW);
5700
5701 if (lpRebootMessageW)
5702 dwRequiredSize += (DWORD)((wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR));
5703
5704 if (lpFailureCommandW)
5705 dwRequiredSize += (DWORD)((wcslen(lpFailureCommandW) + 1) * sizeof(WCHAR));
5706
5707 if (cbBufSize < dwRequiredSize)
5708 {
5709 *pcbBytesNeeded = dwRequiredSize;
5710 dwError = ERROR_INSUFFICIENT_BUFFER;
5711 goto done;
5712 }
5713
5714 /* Now we can fill the buffer */
5715 if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY)
5716 {
5717 dwError = RegQueryValueExW(hServiceKey,
5718 L"FailureActions",
5719 NULL,
5720 NULL,
5721 (LPBYTE)lpFailureActions,
5722 &dwRequiredSize);
5723 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
5724 goto done;
5725
5726 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSA))
5727 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSA);
5728 }
5729 else
5730 {
5731 /*
5732 * The value of the error doesn't really matter, the only
5733 * important thing is that it must be != ERROR_SUCCESS .
5734 */
5735 dwError = ERROR_INVALID_DATA;
5736 }
5737
5738 if (dwError == ERROR_SUCCESS)
5739 {
5740 lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSA)) / sizeof(SC_ACTION));
5741
5742 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5743 lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSA) : NULL);
5744
5745 lpStr = (LPSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION));
5746 }
5747 else
5748 {
5749 lpFailureActions->dwResetPeriod = 0;
5750 lpFailureActions->cActions = 0;
5751 lpFailureActions->lpsaActions = NULL;
5752 lpStr = (LPSTR)(lpFailureActions + 1);
5753 }
5754
5755 lpFailureActions->lpRebootMsg = NULL;
5756 lpFailureActions->lpCommand = NULL;
5757
5758 if (lpRebootMessageW)
5759 {
5761 0,
5762 lpRebootMessageW,
5763 -1,
5764 lpStr,
5765 (int)wcslen(lpRebootMessageW),
5766 NULL,
5767 NULL);
5768 lpFailureActions->lpRebootMsg = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
5769 lpStr += strlen(lpStr) + 1;
5770 }
5771
5772 if (lpFailureCommandW)
5773 {
5775 0,
5776 lpFailureCommandW,
5777 -1,
5778 lpStr,
5779 (int)wcslen(lpFailureCommandW),
5780 NULL,
5781 NULL);
5782 lpFailureActions->lpCommand = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
5783 /* lpStr += strlen(lpStr) + 1; */
5784 }
5785
5786 dwError = ERROR_SUCCESS;
5787 }
5788
5789done:
5790 /* Unlock the service database */
5792
5793 if (lpDescriptionW != NULL)
5794 HeapFree(GetProcessHeap(), 0, lpDescriptionW);
5795
5796 if (lpRebootMessageW != NULL)
5797 HeapFree(GetProcessHeap(), 0, lpRebootMessageW);
5798
5799 if (lpFailureCommandW != NULL)
5800 HeapFree(GetProcessHeap(), 0, lpFailureCommandW);
5801
5802 if (hServiceKey != NULL)
5803 RegCloseKey(hServiceKey);
5804
5805 DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError);
5806
5807 return dwError;
5808}
5809
5810
5811/* Function 39 */
5812DWORD
5813WINAPI
5815 SC_RPC_HANDLE hService,
5820{
5821 DWORD dwError = ERROR_SUCCESS;
5822 PSERVICE_HANDLE hSvc;
5823 PSERVICE lpService = NULL;
5824 HKEY hServiceKey = NULL;
5825 DWORD dwRequiredSize = 0;
5826 DWORD dwType = 0;
5827 LPWSTR lpDescription = NULL;
5828 LPWSTR lpRebootMessage = NULL;
5829 LPWSTR lpFailureCommand = NULL;
5830
5831 DPRINT("RQueryServiceConfig2W() called\n");
5832
5833 if (!lpBuffer)
5834 return ERROR_INVALID_ADDRESS;
5835
5836 if (ScmShutdown)
5838
5841 {
5842 return ERROR_INVALID_LEVEL;
5843 }
5844
5845 hSvc = ScmGetServiceFromHandle(hService);
5846 if (hSvc == NULL)
5847 {
5848 DPRINT1("Invalid service handle\n");
5849 return ERROR_INVALID_HANDLE;
5850 }
5851
5854 {
5855 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
5856 return ERROR_ACCESS_DENIED;
5857 }
5858
5859 lpService = hSvc->ServiceEntry;
5860 if (lpService == NULL)
5861 {
5862 DPRINT("lpService == NULL\n");
5863 return ERROR_INVALID_HANDLE;
5864 }
5865
5866 /* Lock the service database shared */
5868
5869 dwError = ScmOpenServiceKey(lpService->lpServiceName,
5870 KEY_READ,
5871 &hServiceKey);
5872 if (dwError != ERROR_SUCCESS)
5873 goto done;
5874
5876 {
5878 LPWSTR lpStr;
5879
5880 dwError = ScmReadString(hServiceKey,
5881 L"Description",
5882 &lpDescription);
5883 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
5884 goto done;
5885
5887 if (dwError == ERROR_SUCCESS)
5888 *pcbBytesNeeded += (DWORD)((wcslen(lpDescription) + 1) * sizeof(WCHAR));
5889
5891 {
5892 dwError = ERROR_INSUFFICIENT_BUFFER;
5893 goto done;
5894 }
5895
5896 if (dwError == ERROR_SUCCESS)
5897 {
5898 lpStr = (LPWSTR)(lpServiceDescription + 1);
5899 wcscpy(lpStr, lpDescription);
5900 lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
5901 }
5902 else
5903 {
5904 lpServiceDescription->lpDescription = NULL;
5905 dwError = ERROR_SUCCESS;
5906 }
5907 }
5909 {
5911 LPWSTR lpStr = NULL;
5912
5913 /* Query value length */
5914 dwError = RegQueryValueExW(hServiceKey,
5915 L"FailureActions",
5916 NULL,
5917 &dwType,
5918 NULL,
5919 &dwRequiredSize);
5920 if (dwError != ERROR_SUCCESS &&
5921 dwError != ERROR_MORE_DATA &&
5922 dwError != ERROR_FILE_NOT_FOUND)
5923 {
5924 goto done;
5925 }
5926
5927 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
5928 : sizeof(SERVICE_FAILURE_ACTIONSW);
5929
5930 /* Get the strings */
5931 ScmReadString(hServiceKey,
5932 L"FailureCommand",
5933 &lpFailureCommand);
5934
5935 ScmReadString(hServiceKey,
5936 L"RebootMessage",
5937 &lpRebootMessage);
5938
5939 if (lpRebootMessage)
5940 dwRequiredSize += (DWORD)((wcslen(lpRebootMessage) + 1) * sizeof(WCHAR));
5941
5942 if (lpFailureCommand)
5943 dwRequiredSize += (DWORD)((wcslen(lpFailureCommand) + 1) * sizeof(WCHAR));
5944
5945 if (cbBufSize < dwRequiredSize)
5946 {
5947 *pcbBytesNeeded = dwRequiredSize;
5948 dwError = ERROR_INSUFFICIENT_BUFFER;
5949 goto done;
5950 }
5951
5952 /* Now we can fill the buffer */
5953 if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY)
5954 {
5955 dwError = RegQueryValueExW(hServiceKey,
5956 L"FailureActions",
5957 NULL,
5958 NULL,
5959 (LPBYTE)lpFailureActions,
5960 &dwRequiredSize);
5961 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
5962 goto done;
5963
5964 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW))
5965 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
5966 }
5967 else
5968 {
5969 /*
5970 * The value of the error doesn't really matter, the only
5971 * important thing is that it must be != ERROR_SUCCESS .
5972 */
5973 dwError = ERROR_INVALID_DATA;
5974 }
5975
5976 if (dwError == ERROR_SUCCESS)
5977 {
5978 lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION));
5979
5980 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5981 lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSW) : NULL);
5982
5983 lpStr = (LPWSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION));
5984 }
5985 else
5986 {
5987 lpFailureActions->dwResetPeriod = 0;
5988 lpFailureActions->cActions = 0;
5989 lpFailureActions->lpsaActions = NULL;
5990 lpStr = (LPWSTR)(lpFailureActions + 1);
5991 }
5992
5993 lpFailureActions->lpRebootMsg = NULL;
5994 lpFailureActions->lpCommand = NULL;
5995
5996 if (lpRebootMessage)
5997 {
5998 wcscpy(lpStr, lpRebootMessage);
5999 lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
6000 lpStr += wcslen(lpStr) + 1;
6001 }
6002
6003 if (lpFailureCommand)
6004 {
6005 wcscpy(lpStr, lpFailureCommand);
6006 lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
6007 /* lpStr += wcslen(lpStr) + 1; */
6008 }
6009
6010 dwError = ERROR_SUCCESS;
6011 }
6012
6013done:
6014 /* Unlock the service database */
6016
6017 if (lpDescription != NULL)
6018 HeapFree(GetProcessHeap(), 0, lpDescription);
6019
6020 if (lpRebootMessage != NULL)
6021 HeapFree(GetProcessHeap(), 0, lpRebootMessage);
6022
6023 if (lpFailureCommand != NULL)
6024 HeapFree(GetProcessHeap(), 0, lpFailureCommand);
6025
6026 if (hServiceKey != NULL)
6027 RegCloseKey(hServiceKey);
6028
6029 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
6030
6031 return dwError;
6032}
6033
6034
6035/* Function 40 */
6036DWORD
6037WINAPI
6039 SC_RPC_HANDLE hService,
6040 SC_STATUS_TYPE InfoLevel,
6044{
6045 LPSERVICE_STATUS_PROCESS lpStatus;
6046 PSERVICE_HANDLE hSvc;
6047 PSERVICE lpService;
6048
6049 DPRINT("RQueryServiceStatusEx() called\n");
6050
6051 if (ScmShutdown)
6053
6054 if (InfoLevel != SC_STATUS_PROCESS_INFO)
6055 return ERROR_INVALID_LEVEL;
6056
6058
6059 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
6061
6062 hSvc = ScmGetServiceFromHandle(hService);
6063 if (hSvc == NULL)
6064 {
6065 DPRINT1("Invalid service handle\n");
6066 return ERROR_INVALID_HANDLE;
6067 }
6068
6071 {
6072 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
6073 return ERROR_ACCESS_DENIED;
6074 }
6075
6076 lpService = hSvc->ServiceEntry;
6077 if (lpService == NULL)
6078 {
6079 DPRINT("lpService == NULL\n");
6080 return ERROR_INVALID_HANDLE;
6081 }
6082
6083 /* Lock the service database shared */
6085
6087
6088 /* Return service status information */
6089 RtlCopyMemory(lpStatus,
6090 &lpService->Status,
6091 sizeof(SERVICE_STATUS));
6092
6093 /* Copy the service process ID */
6094 if ((lpService->Status.dwCurrentState == SERVICE_STOPPED) || (lpService->lpImage == NULL))
6095 lpStatus->dwProcessId = 0;
6096 else
6097 lpStatus->dwProcessId = lpService->lpImage->dwProcessId;
6098
6099 lpStatus->dwServiceFlags = 0; /* FIXME */
6100
6101 /* Unlock the service database */
6103
6104 return ERROR_SUCCESS;
6105}
6106
6107
6108/* Function 41 */
6109DWORD
6110WINAPI
6113 SC_ENUM_TYPE InfoLevel,
6114 DWORD dwServiceType,
6115 DWORD dwServiceState,
6119 LPBOUNDED_DWORD_256K lpServicesReturned,
6120 LPBOUNDED_DWORD_256K lpResumeIndex,
6121 LPCSTR pszGroupName)
6122{
6123 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL;
6124 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW;
6125 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL;
6126 LPWSTR lpStringPtrW;
6127 LPSTR lpStringPtrA;
6128 LPWSTR pszGroupNameW = NULL;
6129 DWORD dwError;
6130 DWORD dwServiceCount;
6131
6132 DPRINT("REnumServicesStatusExA() called\n");
6133
6134 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
6135 {
6136 return ERROR_INVALID_ADDRESS;
6137 }
6138
6139 if (pszGroupName)
6140 {
6141 pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR));
6142 if (!pszGroupNameW)
6143 {
6144 DPRINT("Failed to allocate buffer\n");
6145 dwError = ERROR_NOT_ENOUGH_MEMORY;
6146 goto Done;
6147 }
6148
6150 0,
6151 pszGroupName,
6152 -1,
6153 pszGroupNameW,
6154 (int)(strlen(pszGroupName) + 1));
6155 }
6156
6157 if ((cbBufSize > 0) && (lpBuffer))
6158 {
6160 if (!lpStatusPtrW)
6161 {
6162 DPRINT("Failed to allocate buffer\n");
6163 dwError = ERROR_NOT_ENOUGH_MEMORY;
6164 goto Done;
6165 }
6166 }
6167
6169 InfoLevel,
6170 dwServiceType,
6171 dwServiceState,
6172 (LPBYTE)lpStatusPtrW,
6173 cbBufSize,
6175 lpServicesReturned,
6176 lpResumeIndex,
6177 pszGroupNameW);
6178
6179 /* if no services were returned then we are Done */
6180 if (*lpServicesReturned == 0)
6181 goto Done;
6182
6183 lpStatusPtrIncrW = lpStatusPtrW;
6185 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
6186 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA));
6187 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW +
6188 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
6189
6190 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
6191 {
6192 /* Copy the service name */
6194 0,
6195 lpStringPtrW,
6196 -1,
6197 lpStringPtrA,
6198 (int)wcslen(lpStringPtrW),
6199 0,
6200 0);
6201
6202 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
6203 lpStringPtrA += wcslen(lpStringPtrW) + 1;
6204 lpStringPtrW += wcslen(lpStringPtrW) + 1;
6205
6206 /* Copy the display name */
6208 0,
6209 lpStringPtrW,
6210 -1,
6211 lpStringPtrA,
6212 (int)wcslen(lpStringPtrW),
6213 0,
6214 0);
6215
6216 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
6217 lpStringPtrA += wcslen(lpStringPtrW) + 1;
6218 lpStringPtrW += wcslen(lpStringPtrW) + 1;
6219
6220 /* Copy the status information */
6221 memcpy(&lpStatusPtrA->ServiceStatusProcess,
6222 &lpStatusPtrIncrW->ServiceStatusProcess,
6223 sizeof(SERVICE_STATUS));
6224
6225 /* Copy the service process ID */
6226 lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrIncrW->ServiceStatusProcess.dwProcessId;
6227
6228 lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
6229
6230 lpStatusPtrIncrW++;
6231 lpStatusPtrA++;
6232 }
6233
6234Done:
6235 if (pszGroupNameW)
6236 HeapFree(GetProcessHeap(), 0, pszGroupNameW);
6237
6238 if (lpStatusPtrW)
6239 HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
6240
6241 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError);
6242
6243 return dwError;
6244}
6245
6246
6247/* Function 42 */
6248DWORD
6249WINAPI
6252 SC_ENUM_TYPE InfoLevel,
6253 DWORD dwServiceType,
6254 DWORD dwServiceState,
6258 LPBOUNDED_DWORD_256K lpServicesReturned,
6259 LPBOUNDED_DWORD_256K lpResumeIndex,
6260 LPCWSTR pszGroupName)
6261{
6262 PMANAGER_HANDLE hManager;
6263 PSERVICE lpService;
6264 DWORD dwError = ERROR_SUCCESS;
6265 PLIST_ENTRY ServiceEntry;
6266 PSERVICE CurrentService;
6267 DWORD dwState;
6268 DWORD dwRequiredSize;
6269 DWORD dwServiceCount;
6270 DWORD dwSize;
6271 DWORD dwLastResumeCount = 0;
6273 LPWSTR lpStringPtr;
6274
6275 DPRINT("REnumServicesStatusExW() called\n");
6276
6277 if (ScmShutdown)
6279
6280 if (InfoLevel != SC_ENUM_PROCESS_INFO)
6281 return ERROR_INVALID_LEVEL;
6282
6284 if (hManager == NULL)
6285 {
6286 DPRINT1("Invalid service manager handle\n");
6287 return ERROR_INVALID_HANDLE;
6288 }
6289
6290 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
6291 {
6292 return ERROR_INVALID_ADDRESS;
6293 }
6294
6295 *pcbBytesNeeded = 0;
6296 *lpServicesReturned = 0;
6297
6298 if ((dwServiceType == 0) ||
6299 ((dwServiceType & ~SERVICE_TYPE_ALL) != 0))
6300 {
6301 DPRINT("Invalid Service Type\n");
6303 }
6304
6305 if ((dwServiceState == 0) ||
6306 ((dwServiceState & ~SERVICE_STATE_ALL) != 0))
6307 {
6308 DPRINT("Invalid Service State\n");
6310 }
6311
6312 /* Check access rights */
6315 {
6316 DPRINT("Insufficient access rights 0x%lx\n",
6317 hManager->Handle.DesiredAccess);
6318 return ERROR_ACCESS_DENIED;
6319 }
6320
6321 if (lpResumeIndex)
6322 dwLastResumeCount = *lpResumeIndex;
6323
6324 /* Lock the service database shared */
6326
6327 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
6328 if (lpService == NULL)
6329 {
6330 dwError = ERROR_SUCCESS;
6331 goto Done;
6332 }
6333
6334 dwRequiredSize = 0;
6335 dwServiceCount = 0;
6336
6337 for (ServiceEntry = &lpService->ServiceListEntry;
6338 ServiceEntry != &ServiceListHead;
6339 ServiceEntry = ServiceEntry->Flink)
6340 {
6341 CurrentService = CONTAINING_RECORD(ServiceEntry,
6342 SERVICE,
6343 ServiceListEntry);
6344
6345 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
6346 continue;
6347
6348 dwState = SERVICE_ACTIVE;
6349 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
6350 dwState = SERVICE_INACTIVE;
6351
6352 if ((dwState & dwServiceState) == 0)
6353 continue;
6354
6355 if (pszGroupName)
6356 {
6357 if (*pszGroupName == 0)
6358 {
6359 if (CurrentService->lpGroup != NULL)
6360 continue;
6361 }
6362 else
6363 {
6364 if ((CurrentService->lpGroup == NULL) ||
6365 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
6366 continue;
6367 }
6368 }
6369
6371 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
6372 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
6373
6374 if (dwRequiredSize + dwSize <= cbBufSize)
6375 {
6376 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
6377 dwRequiredSize += dwSize;
6378 dwServiceCount++;
6379 dwLastResumeCount = CurrentService->dwResumeCount;
6380 }
6381 else
6382 {
6383 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
6384 break;
6385 }
6386
6387 }
6388
6389 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
6390 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
6391
6392 for (;
6393 ServiceEntry != &ServiceListHead;
6394 ServiceEntry = ServiceEntry->Flink)
6395 {
6396 CurrentService = CONTAINING_RECORD(ServiceEntry,
6397 SERVICE,
6398 ServiceListEntry);
6399
6400 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
6401 continue;
6402
6403 dwState = SERVICE_ACTIVE;
6404 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
6405 dwState = SERVICE_INACTIVE;
6406
6407 if ((dwState & dwServiceState) == 0)
6408 continue;
6409
6410 if (pszGroupName)
6411 {
6412 if (*pszGroupName == 0)
6413 {
6414 if (CurrentService->lpGroup != NULL)
6415 continue;
6416 }
6417 else
6418 {
6419 if ((CurrentService->lpGroup == NULL) ||
6420 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
6421 continue;
6422 }
6423 }
6424
6425 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
6426 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
6427 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
6428
6429 dwError = ERROR_MORE_DATA;
6430 }
6431
6432 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
6433
6434 if (lpResumeIndex)
6435 *lpResumeIndex = dwLastResumeCount;
6436
6437 *lpServicesReturned = dwServiceCount;
6438 *pcbBytesNeeded = dwRequiredSize;
6439
6440 /* If there was no services that matched */
6441 if ((!dwServiceCount) && (dwError != ERROR_MORE_DATA))
6442 {
6444 goto Done;
6445 }
6446
6448 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
6449 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
6450
6451 dwRequiredSize = 0;
6452 for (ServiceEntry = &lpService->ServiceListEntry;
6453 ServiceEntry != &ServiceListHead;
6454 ServiceEntry = ServiceEntry->Flink)
6455 {
6456 CurrentService = CONTAINING_RECORD(ServiceEntry,
6457 SERVICE,
6458 ServiceListEntry);
6459
6460 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
6461 continue;
6462
6463 dwState = SERVICE_ACTIVE;
6464 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
6465 dwState = SERVICE_INACTIVE;
6466
6467 if ((dwState & dwServiceState) == 0)
6468 continue;
6469
6470 if (pszGroupName)
6471 {
6472 if (*pszGroupName == 0)
6473 {
6474 if (CurrentService->lpGroup != NULL)
6475 continue;
6476 }
6477 else
6478 {
6479 if ((CurrentService->lpGroup == NULL) ||
6480 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
6481 continue;
6482 }
6483 }
6484
6486 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
6487 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
6488
6489 if (dwRequiredSize + dwSize <= cbBufSize)
6490 {
6491 /* Copy the service name */
6492 wcscpy(lpStringPtr,
6493 CurrentService->lpServiceName);
6494 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
6495 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
6496
6497 /* Copy the display name */
6498 wcscpy(lpStringPtr,
6499 CurrentService->lpDisplayName);
6500 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
6501 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
6502
6503 /* Copy the status information */
6504 memcpy(&lpStatusPtr->ServiceStatusProcess,
6505 &CurrentService->Status,
6506 sizeof(SERVICE_STATUS));
6507
6508 /* Copy the service process ID */
6509 if ((CurrentService->Status.dwCurrentState == SERVICE_STOPPED) || (CurrentService->lpImage == NULL))
6510 lpStatusPtr->ServiceStatusProcess.dwProcessId = 0;
6511 else
6512 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->lpImage->dwProcessId;
6513
6514 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
6515
6516 lpStatusPtr++;
6517 dwRequiredSize += dwSize;
6518 }
6519 else
6520 {
6521 break;
6522 }
6523 }
6524
6525 if (dwError == 0)
6526 {
6527 *pcbBytesNeeded = 0;
6528 if (lpResumeIndex)
6529 *lpResumeIndex = 0;
6530 }
6531
6532Done:
6533 /* Unlock the service database */
6535
6536 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError);
6537
6538 return dwError;
6539}
6540
6541
6542/* Function 43 */
6543DWORD
6544WINAPI
6546 handle_t BindingHandle) /* FIXME */
6547{
6550}
6551
6552
6553/* Function 44 */
6554DWORD
6555WINAPI
6558 LPSTR lpServiceName,
6560 DWORD dwDesiredAccess,
6561 DWORD dwServiceType,
6562 DWORD dwStartType,
6563 DWORD dwErrorControl,
6564 LPSTR lpBinaryPathName,
6565 LPSTR lpLoadOrderGroup,
6566 LPDWORD lpdwTagId,
6567 LPBYTE lpDependencies,
6568 DWORD dwDependSize,
6569 LPSTR lpServiceStartName,
6570 LPBYTE lpPassword,
6571 DWORD dwPwSize,
6572 LPSC_RPC_HANDLE lpServiceHandle)
6573{
6576}
6577
6578
6579/* Function 45 */
6580DWORD
6581WINAPI
6584 LPWSTR lpServiceName,
6586 DWORD dwDesiredAccess,
6587 DWORD dwServiceType,
6588 DWORD dwStartType,
6589 DWORD dwErrorControl,
6590 LPWSTR lpBinaryPathName,
6591 LPWSTR lpLoadOrderGroup,
6592 LPDWORD lpdwTagId,
6593 LPBYTE lpDependencies,
6594 DWORD dwDependSize,
6595 LPWSTR lpServiceStartName,
6596 LPBYTE lpPassword,
6597 DWORD dwPwSize,
6598 LPSC_RPC_HANDLE lpServiceHandle)
6599{
6602}
6603
6604
6605/* Function 46 */
6606DWORD
6607WINAPI
6613{
6614 PMANAGER_HANDLE hManager;
6615
6616 /* Validate handle */
6618 if (hManager == NULL)
6619 {
6620 return ERROR_INVALID_HANDLE;
6621 }
6622
6623 /* FIXME: should check whether client is local */
6624
6625 /* Check access rights */
6628 {
6629 return ERROR_ACCESS_DENIED;
6630 }
6631
6632 /* Check parameters */
6633 if (lpInParams == NULL || lpOutParams == NULL)
6634 {
6636 }
6637
6638 /* Check info level */
6640 {
6641 return ERROR_RETRY;
6642 }
6643
6644 /* Call internal helper */
6645 return ScmGetServiceNameFromTag(*lpInParams, lpOutParams);
6646}
6647
6648
6649/* Function 47 */
6650DWORD
6651WINAPI
6653 SC_RPC_HANDLE hService,
6654 SC_RPC_NOTIFY_PARAMS NotifyParams,
6655 GUID *pClientProcessGuid,
6656 GUID *pSCMProcessGuid,
6657 PBOOL pfCreateRemoteQueue,
6658 LPSC_NOTIFY_RPC_HANDLE phNotify)
6659{
6662}
6663
6664
6665/* Function 48 */
6666DWORD
6667WINAPI
6669 SC_NOTIFY_RPC_HANDLE hNotify,
6670 PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams)
6671{
6674}
6675
6676
6677/* Function 49 */
6678DWORD
6679WINAPI
6681 LPSC_NOTIFY_RPC_HANDLE phNotify,
6682 PBOOL pfApcFired)
6683{
6686}
6687
6688
6689/* Function 50 */
6690DWORD
6691WINAPI
6693 SC_RPC_HANDLE hService,
6694 DWORD dwControl,
6696{
6699}
6700
6701
6702/* Function 51 */
6703DWORD
6704WINAPI
6706 SC_RPC_HANDLE hService,
6707 DWORD dwControl,
6709{
6712}
6713
6714
6715/* Function 52 */
6716DWORD
6717WINAPI
6719 handle_t BindingHandle) /* FIXME */
6720{
6723}
6724
6725
6726/* Function 53 */
6727DWORD
6728WINAPI
6731 _In_ LPWSTR pszServiceName,
6732 _Out_ RPC_SERVICE_STATUS_HANDLE *phServiceStatus)
6733{
6734 PMANAGER_HANDLE hManager;
6735 PSERVICE pService;
6736
6737 DPRINT("RI_ScValidatePnPService(%p %S %p)\n", hSCManager, pszServiceName, phServiceStatus);
6738
6739 /* Validate handle */
6741 if (hManager == NULL)
6742 {
6743 DPRINT1("Invalid handle\n");
6744 return ERROR_INVALID_HANDLE;
6745 }
6746
6747 /* FIXME: should check whether client is local */
6748
6749 /* Check access rights */
6752 {
6753 DPRINT1("No SC_MANAGER_CONNECT access\n");
6754 return ERROR_ACCESS_DENIED;
6755 }
6756
6757 pService = ScmGetServiceEntryByName(pszServiceName);
6758 DPRINT("pService: %p\n", pService);
6759 if (pService == NULL)
6761
6762 *phServiceStatus = (RPC_SERVICE_STATUS_HANDLE)pService;
6763
6764 return ERROR_SUCCESS;
6765}
6766
6767
6768/* Function 54 */
6769DWORD
6770WINAPI
6772 handle_t BindingHandle) /* FIXME */
6773{
6776}
6777
6778
6779/* Function 55 */
6780DWORD
6781WINAPI
6783 handle_t BindingHandle) /* FIXME */
6784{
6787}
6788
6789
6791{
6793}
6794
6795
6797{
6799}
6800
6801
6803{
6804 /* Close the handle */
6805 RCloseServiceHandle(&hSCObject);
6806}
6807
6808
6810{
6811 /* Unlock the database */
6813}
6814
6815
6817{
6818}
6819
6820/* EOF */
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
unsigned char BOOLEAN
static int argc
Definition: ServiceArgs.c:12
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
WCHAR SourceName[256]
Definition: arping.c:28
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
static WCHAR ServiceName[]
Definition: browser.c:19
DWORD dwServiceBits
Definition: srvsvc.c:40
static HANDLE hServicesKey
Definition: devinst.c:21
#define CHAR(Char)
DWORD ScmReadString(HKEY hServiceKey, LPCWSTR lpValueName, LPWSTR *lpValue)
Definition: config.c:270
DWORD ScmDecryptPassword(_In_ PVOID ContextHandle, _In_ PBYTE pPassword, _In_ DWORD dwPasswordSize, _Out_ PWSTR *pClearTextPassword)
Definition: config.c:708
DWORD ScmOpenServiceKey(LPWSTR lpServiceName, REGSAM samDesired, PHKEY phKey)
Definition: config.c:42
DWORD ScmWriteSecurityDescriptor(_In_ HKEY hServiceKey, _In_ PSECURITY_DESCRIPTOR pSecurityDescriptor)
Definition: config.c:530
DWORD ScmSetServicePassword(IN PCWSTR pszServiceName, IN PCWSTR pszPassword)
Definition: config.c:469
DWORD ScmWriteDependencies(HKEY hServiceKey, LPCWSTR lpDependencies, DWORD dwDependenciesLength)
Definition: config.c:117
DWORD ScmReadDependencies(HKEY hServiceKey, LPWSTR *lpDependencies, DWORD *lpdwDependenciesLength)
Definition: config.c:349
DWORD ScmMarkServiceForDelete(PSERVICE pService)
Definition: config.c:223
DWORD ScmCreateServiceKey(LPCWSTR lpServiceName, REGSAM samDesired, PHKEY phKey)
Definition: config.c:72
DWORD ScmControlService(_In_ HANDLE hControlPipe, _In_ PCWSTR pServiceName, _In_ DWORD dwControl, _In_ SERVICE_STATUS_HANDLE hServiceStatus)
Definition: database.c:1569
PSERVICE ScmGetServiceEntryByResumeCount(DWORD dwResumeCount)
Definition: database.c:715
VOID ScmRemoveServiceImage(PSERVICE_IMAGE pServiceImage)
Definition: database.c:622
VOID ScmUnlockDatabase(VOID)
Definition: database.c:2328
DWORD ScmGenerateServiceTag(PSERVICE lpServiceRecord)
Definition: database.c:744
DWORD ScmGetServiceNameFromTag(IN PTAG_INFO_NAME_FROM_TAG_IN_PARAMS InParams, OUT PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS *OutParams)
Definition: database.c:183
DWORD ScmReferenceService(PSERVICE lpService)
Definition: database.c:931
DWORD ScmStartService(PSERVICE Service, DWORD argc, const PCWSTR *argv)
Definition: database.c:2024
BOOL ScmLockDatabaseExclusive(VOID)
Definition: database.c:2314
DWORD ScmDereferenceService(PSERVICE lpService)
Definition: database.c:939
DWORD ScmCreateNewServiceRecord(LPCWSTR lpServiceName, PSERVICE *lpServiceRecord, DWORD dwServiceType, DWORD dwStartType)
Definition: database.c:767
PSERVICE ScmGetServiceEntryByName(LPCWSTR lpServiceName)
Definition: database.c:657
BOOL ScmLockDatabaseShared(VOID)
Definition: database.c:2321
LIST_ENTRY ServiceListHead
Definition: database.c:29
PSERVICE ScmGetServiceEntryByDisplayName(LPCWSTR lpDisplayName)
Definition: database.c:686
DWORD ScmControlDriver(PSERVICE lpService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: driver.c:335
VOID ScmQueryServiceLockStatusW(OUT LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus)
Definition: lock.c:127
VOID ScmQueryServiceLockStatusA(OUT LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus)
Definition: lock.c:159
DWORD ScmAcquireServiceStartLock(IN BOOL IsServiceController, OUT LPSC_RPC_LOCK lpLock)
Definition: lock.c:31
DWORD ScmReleaseServiceStartLock(IN OUT LPSC_RPC_LOCK lpLock)
Definition: lock.c:82
#define IDS_SERVICE_PAUSE
Definition: resource.h:5
#define IDS_SERVICE_PAUSED
Definition: resource.h:9
#define IDS_SERVICE_STOP
Definition: resource.h:4
#define IDS_SERVICE_RUNNING
Definition: resource.h:7
#define IDS_SERVICE_STOPPED
Definition: resource.h:8
#define IDS_SERVICE_RESUME
Definition: resource.h:6
DWORD WINAPI RCloseServiceHandle(LPSC_RPC_HANDLE hSCObject)
Definition: rpcserver.c:935
DWORD WINAPI RChangeServiceConfig2W(SC_RPC_HANDLE hService, SC_RPC_CONFIG_INFOW Info)
Definition: rpcserver.c:5435
DWORD WINAPI RDeleteService(SC_RPC_HANDLE hService)
Definition: rpcserver.c:1240
static PSERVICE_HANDLE ScmGetServiceFromHandle(SC_RPC_HANDLE Handle)
Definition: rpcserver.c:222
DWORD WINAPI RQueryServiceLockStatusW(SC_RPC_HANDLE hSCManager, LPBYTE lpBuf, DWORD cbBufSize, LPBOUNDED_DWORD_4K pcbBytesNeeded)
Definition: rpcserver.c:3226
DWORD ScmCanonDriverImagePath(DWORD dwStartType, const wchar_t *lpServiceName, wchar_t **lpCanonName)
Definition: rpcserver.c:642
DWORD WINAPI RQueryServiceObjectSecurity(SC_RPC_HANDLE hService, SECURITY_INFORMATION dwSecurityInformation, LPBYTE lpSecurityDescriptor, DWORD cbBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded)
Definition: rpcserver.c:1326
static DWORD ScmCreateServiceHandle(PSERVICE lpServiceEntry, SC_HANDLE *Handle)
Definition: rpcserver.c:180
DWORD WINAPI RChangeServiceConfig2A(SC_RPC_HANDLE hService, SC_RPC_CONFIG_INFOA Info)
Definition: rpcserver.c:5034
struct _MANAGER_HANDLE * PMANAGER_HANDLE
DWORD WINAPI ROpenSCManagerW(LPWSTR lpMachineName, LPWSTR lpDatabaseName, DWORD dwDesiredAccess, LPSC_RPC_HANDLE lpScHandle)
Definition: rpcserver.c:2883
#define SC_MANAGER_WRITE
Definition: rpcserver.c:55
#define MANAGER_TAG
Definition: rpcserver.c:25
DWORD WINAPI RNotifyBootConfigStatus(SVCCTL_HANDLEW lpMachineName, DWORD BootAcceptable)
Definition: rpcserver.c:1864
#define SERVICE_EXECUTE
Definition: rpcserver.c:79
struct _SCMGR_HANDLE SCMGR_HANDLE
#define SC_MANAGER_EXECUTE
Definition: rpcserver.c:60
#define SERVICE_TAG
Definition: rpcserver.c:26
struct _SERVICE_HANDLE SERVICE_HANDLE
DWORD WINAPI RStartServiceW(SC_RPC_HANDLE hService, DWORD argc, LPSTRING_PTRSW argv)
Definition: rpcserver.c:3269
struct _SERVICE_HANDLE * PSERVICE_HANDLE
DWORD WINAPI RGetServiceKeyNameA(SC_RPC_HANDLE hSCManager, LPCSTR lpDisplayName, LPSTR lpServiceName, LPBOUNDED_DWORD_4K lpcchBuffer)
Definition: rpcserver.c:4597
#define INVALID_TAG
Definition: rpcserver.c:27
DWORD WINAPI RCreateServiceW(SC_RPC_HANDLE hSCManager, LPCWSTR lpServiceName, LPCWSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName, LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPBYTE lpDependencies, DWORD dwDependSize, LPCWSTR lpServiceStartName, LPBYTE lpPassword, DWORD dwPwSize, LPSC_RPC_HANDLE lpServiceHandle)
Definition: rpcserver.c:2287
DWORD WINAPI RUnlockServiceDatabase(LPSC_RPC_LOCK Lock)
Definition: rpcserver.c:1853
static BOOL ScmIsValidServiceState(DWORD dwCurrentState)
Definition: rpcserver.c:1593
DWORD WINAPI ROpenServiceW(SC_RPC_HANDLE hSCManager, LPWSTR lpServiceName, DWORD dwDesiredAccess, LPSC_RPC_HANDLE lpServiceHandle)
Definition: rpcserver.c:2935
static DWORD ScmCheckAccess(SC_HANDLE Handle, DWORD dwDesiredAccess)
Definition: rpcserver.c:242
DWORD WINAPI RChangeServiceConfigW(SC_RPC_HANDLE hService, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPWSTR lpBinaryPathName, LPWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPBYTE lpDependencies, DWORD dwDependSize, LPWSTR lpServiceStartName, LPBYTE lpPassword, DWORD dwPwSize, LPWSTR lpDisplayName)
Definition: rpcserver.c:1935
DWORD WINAPI RControlServiceExA(SC_RPC_HANDLE hService, DWORD dwControl, DWORD dwInfoLevel)
Definition: rpcserver.c:6692
DWORD WINAPI REnumServicesStatusA(SC_RPC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, LPBYTE lpBuffer, DWORD dwBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned, LPBOUNDED_DWORD_256K lpResumeHandle)
Definition: rpcserver.c:3914
DWORD g_dwServiceBits
Definition: rpcserver.c:102
DWORD WINAPI RLockServiceDatabase(SC_RPC_HANDLE hSCManager, LPSC_RPC_LOCK lpLock)
Definition: rpcserver.c:1298
DWORD WINAPI RQueryServiceConfig2A(SC_RPC_HANDLE hService, DWORD dwInfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPBOUNDED_DWORD_8K pcbBytesNeeded)
Definition: rpcserver.c:5567
DWORD WINAPI RQueryServiceStatus(SC_RPC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: rpcserver.c:1544
DWORD WINAPI RNotifyServiceStatusChange(SC_RPC_HANDLE hService, SC_RPC_NOTIFY_PARAMS NotifyParams, GUID *pClientProcessGuid, GUID *pSCMProcessGuid, PBOOL pfCreateRemoteQueue, LPSC_NOTIFY_RPC_HANDLE phNotify)
Definition: rpcserver.c:6652
DWORD WINAPI ROpenServiceA(SC_RPC_HANDLE hSCManager, LPSTR lpServiceName, DWORD dwDesiredAccess, LPSC_RPC_HANDLE lpServiceHandle)
Definition: rpcserver.c:4059
DWORD WINAPI RStartServiceA(SC_RPC_HANDLE hService, DWORD argc, LPSTRING_PTRSA argv)
Definition: rpcserver.c:4373
DWORD WINAPI RSendPnPMessage(handle_t BindingHandle)
Definition: rpcserver.c:6718
DWORD WINAPI RGetServiceDisplayNameW(SC_RPC_HANDLE hSCManager, LPCWSTR lpServiceName, LPWSTR lpDisplayName, DWORD *lpcchBuffer)
Definition: rpcserver.c:3332
DWORD WINAPI RQueryServiceLockStatusA(SC_RPC_HANDLE hSCManager, LPBYTE lpBuf, DWORD cbBufSize, LPBOUNDED_DWORD_4K pcbBytesNeeded)
Definition: rpcserver.c:4330
DWORD WINAPI RControlServiceExW(SC_RPC_HANDLE hService, DWORD dwControl, DWORD dwInfoLevel)
Definition: rpcserver.c:6705
DWORD WINAPI RGetServiceKeyNameW(SC_RPC_HANDLE hSCManager, LPCWSTR lpDisplayName, LPWSTR lpServiceName, DWORD *lpcchBuffer)
Definition: rpcserver.c:3395
void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject)
Definition: rpcserver.c:6802
void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify)
Definition: rpcserver.c:6816
DWORD WINAPI RGetNotifyResults(SC_NOTIFY_RPC_HANDLE hNotify, PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams)
Definition: rpcserver.c:6668
DWORD WINAPI RControlService(SC_RPC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: rpcserver.c:1005
static GENERIC_MAPPING ScmServiceMapping
Definition: rpcserver.c:97
#define SC_MANAGER_READ
Definition: rpcserver.c:50
static DWORD ScmSetFailureActions(HKEY hServiceKey, LPSERVICE_FAILURE_ACTIONSW lpFailureActions)
Definition: rpcserver.c:5211
DWORD WINAPI RCreateServiceA(SC_RPC_HANDLE hSCManager, LPSTR lpServiceName, LPSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPSTR lpBinaryPathName, LPSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPBYTE lpDependencies, DWORD dwDependSize, LPSTR lpServiceStartName, LPBYTE lpPassword, DWORD dwPwSize, LPSC_RPC_HANDLE lpServiceHandle)
Definition: rpcserver.c:3607
DWORD WINAPI REnumServiceGroupW(SC_RPC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, LPBYTE lpBuffer, DWORD cbBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned, LPBOUNDED_DWORD_256K lpResumeIndex, LPCWSTR pszGroupName)
Definition: rpcserver.c:4768
#define SERVICE_READ
Definition: rpcserver.c:68
DWORD WINAPI RQueryServiceStatusEx(SC_RPC_HANDLE hService, SC_STATUS_TYPE InfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPBOUNDED_DWORD_8K pcbBytesNeeded)
Definition: rpcserver.c:6038
DWORD ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
Definition: rpcserver.c:403
#define SERVICE_WRITE
Definition: rpcserver.c:75
DWORD WINAPI RI_ScQueryServiceTagInfo(SC_RPC_HANDLE hSCManager, TAG_INFO_LEVEL dwInfoLevel, PTAG_INFO_NAME_FROM_TAG_IN_PARAMS *lpInParams, PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS *lpOutParams)
Definition: rpcserver.c:6608
static GENERIC_MAPPING ScmManagerMapping
Definition: rpcserver.c:91
DWORD ScmAssignNewTag(PSERVICE lpService)
Definition: rpcserver.c:272
DWORD WINAPI RQueryServiceConfigW(SC_RPC_HANDLE hService, LPBYTE lpBuf, DWORD cbBufSize, LPBOUNDED_DWORD_8K pcbBytesNeeded)
Definition: rpcserver.c:3018
VOID ScmStartRpcServer(VOID)
Definition: rpcserver.c:107
DWORD WINAPI RQueryServiceConfig2W(SC_RPC_HANDLE hService, DWORD dwInfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPBOUNDED_DWORD_8K pcbBytesNeeded)
Definition: rpcserver.c:5814
DWORD WINAPI RSendTSMessage(handle_t BindingHandle)
Definition: rpcserver.c:6545
static DWORD WINAPI ScmStopThread(PVOID pParam)
Definition: rpcserver.c:1614
DWORD WINAPI RCloseNotifyHandle(LPSC_NOTIFY_RPC_HANDLE phNotify, PBOOL pfApcFired)
Definition: rpcserver.c:6680
#define TAG_ARRAY_SIZE
Definition: rpcserver.c:86
DWORD Int_EnumDependentServicesW(HKEY hServicesKey, PSERVICE lpService, DWORD dwServiceState, PSERVICE *lpServices, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned)
Definition: rpcserver.c:782
DWORD WINAPI RI_ScValidatePnPService(_In_ SC_RPC_HANDLE hSCManager, _In_ LPWSTR pszServiceName, _Out_ RPC_SERVICE_STATUS_HANDLE *phServiceStatus)
Definition: rpcserver.c:6729
DWORD WINAPI RI_ScSetServiceBitsA(RPC_SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwServiceBits, int bSetBitsOn, int bUpdateImmediately, char *lpString)
Definition: rpcserver.c:3452
DWORD WINAPI REnumServicesStatusExA(SC_RPC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType, DWORD dwServiceState, LPBYTE lpBuffer, DWORD cbBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned, LPBOUNDED_DWORD_256K lpResumeIndex, LPCSTR pszGroupName)
Definition: rpcserver.c:6111
DWORD WINAPI REnumDependentServicesW(SC_RPC_HANDLE hService, DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned)
Definition: rpcserver.c:2722
DWORD WINAPI RGetServiceDisplayNameA(SC_RPC_HANDLE hSCManager, LPCSTR lpServiceName, LPSTR lpDisplayName, LPBOUNDED_DWORD_4K lpcchBuffer)
Definition: rpcserver.c:4475
DWORD WINAPI RCreateServiceWOW64W(handle_t BindingHandle, LPWSTR lpServiceName, LPWSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPWSTR lpBinaryPathName, LPWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPBYTE lpDependencies, DWORD dwDependSize, LPWSTR lpServiceStartName, LPBYTE lpPassword, DWORD dwPwSize, LPSC_RPC_HANDLE lpServiceHandle)
Definition: rpcserver.c:6582
static DWORD ScmCreateManagerHandle(LPWSTR lpDatabaseName, SC_HANDLE *Handle)
Definition: rpcserver.c:144
DWORD WINAPI RFunction55(handle_t BindingHandle)
Definition: rpcserver.c:6782
DWORD WINAPI RI_ScGetCurrentGroupStateW(SC_RPC_HANDLE hSCManager, LPWSTR lpLoadOrderGroup, LPDWORD lpState)
Definition: rpcserver.c:4711
DWORD WINAPI ROpenSCManagerA(LPSTR lpMachineName, LPSTR lpDatabaseName, DWORD dwDesiredAccess, LPSC_RPC_HANDLE lpScHandle)
Definition: rpcserver.c:4021
DWORD WINAPI RSetServiceObjectSecurity(SC_RPC_HANDLE hService, DWORD dwSecurityInformation, LPBYTE lpSecurityDescriptor, DWORD dwSecurityDescriptorSize)
Definition: rpcserver.c:1410
DWORD WINAPI RChangeServiceConfigA(SC_RPC_HANDLE hService, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPSTR lpBinaryPathName, LPSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPBYTE lpDependencies, DWORD dwDependSize, LPSTR lpServiceStartName, LPBYTE lpPassword, DWORD dwPwSize, LPSTR lpDisplayName)
Definition: rpcserver.c:3476
DWORD WINAPI RQueryServiceConfigA(SC_RPC_HANDLE hService, LPBYTE lpBuf, DWORD cbBufSize, LPBOUNDED_DWORD_8K pcbBytesNeeded)
Definition: rpcserver.c:4089
void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock)
Definition: rpcserver.c:6809
DWORD WINAPI REnumDependentServicesA(SC_RPC_HANDLE hService, DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned)
Definition: rpcserver.c:3760
struct _MANAGER_HANDLE MANAGER_HANDLE
DWORD WINAPI REnumServicesStatusExW(SC_RPC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType, DWORD dwServiceState, LPBYTE lpBuffer, DWORD cbBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned, LPBOUNDED_DWORD_256K lpResumeIndex, LPCWSTR pszGroupName)
Definition: rpcserver.c:6250
DWORD WINAPI RI_ScSetServiceBitsW(RPC_SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwServiceBits, int bSetBitsOn, int bUpdateImmediately, wchar_t *lpString)
Definition: rpcserver.c:1881
DWORD WINAPI ROpenServiceStatusHandle(handle_t BindingHandle)
Definition: rpcserver.c:6771
static PMANAGER_HANDLE ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle)
Definition: rpcserver.c:202
DWORD WINAPI RSetServiceStatus(RPC_SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: rpcserver.c:1690
DWORD WINAPI REnumServicesStatusW(SC_RPC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, LPBYTE lpBuffer, DWORD dwBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned, LPBOUNDED_DWORD_256K lpResumeHandle)
Definition: rpcserver.c:2857
DWORD WINAPI RCreateServiceWOW64A(handle_t BindingHandle, LPSTR lpServiceName, LPSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPSTR lpBinaryPathName, LPSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPBYTE lpDependencies, DWORD dwDependSize, LPSTR lpServiceStartName, LPBYTE lpPassword, DWORD dwPwSize, LPSC_RPC_HANDLE lpServiceHandle)
Definition: rpcserver.c:6556
DWORD ScmCreateDefaultServiceSD(PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
Definition: security.c:320
BOOL ScmShutdown
Definition: services.c:29
VOID ScmLogEvent(DWORD dwEventId, WORD wType, WORD wStrings, LPCWSTR *lpStrings)
Definition: services.c:174
struct _SERVICE * PSERVICE
#define UNIMPLEMENTED
Definition: debug.h:118
#define RegCloseKey(hKey)
Definition: registry.h:49
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
DWORD ScmRunLastKnownGood(VOID)
Definition: controlset.c:402
DWORD ScmAcceptBoot(VOID)
Definition: controlset.c:336
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:175
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NO_ERROR
Definition: dderror.h:5
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define BufferSize
Definition: mmc.h:75
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegFlushKey(HKEY hKey)
Definition: reg.c:2951
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2330
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3662
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
static const WCHAR SystemRoot[]
Definition: reg.c:38
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_ADDRESS
Definition: compat.h:106
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define ERROR_INVALID_NAME
Definition: compat.h:103
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static DWORD DWORD * dwLength
Definition: fusion.c:86
static void cleanup(void)
Definition: main.c:1335
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
#define ULONG_PTR
Definition: config.h:101
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
FxAutoRegKey hKey
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
PSERVICE_GROUP ScmGetServiceGroupByName(_In_ LPCWSTR lpGroupName)
Definition: groupdb.c:26
DWORD ScmSetServiceGroup(PSERVICE lpService, LPCWSTR lpGroupName)
Definition: groupdb.c:61
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define ASSERT(a)
Definition: mode.c:44
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
#define argv
Definition: mplay32.c:18
DWORD SECURITY_INFORMATION
Definition: ms-dtyp.idl:311
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI RtlSetSecurityObject(_In_ SECURITY_INFORMATION SecurityInformation, _In_ PSECURITY_DESCRIPTOR ModificationDescriptor, _Out_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, _In_ PGENERIC_MAPPING GenericMapping, _In_ HANDLE Token)
_In_opt_ PSID Group
Definition: rtlfuncs.h:1658
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1609
NTSYSAPI NTSTATUS NTAPI RtlQuerySecurityObject(_In_ PSECURITY_DESCRIPTOR ObjectDescriptor, _In_ SECURITY_INFORMATION SecurityInformation, _Out_ PSECURITY_DESCRIPTOR ResultantDescriptor, _In_ ULONG DescriptorLength, _Out_ PULONG ReturnLength)
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
NTSYSAPI VOID NTAPI RtlMapGenericMask(PACCESS_MASK AccessMask, PGENERIC_MAPPING GenericMapping)
NTSYSAPI BOOLEAN NTAPI RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
Definition: sd.c:1054
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
NTSYSAPI BOOLEAN NTAPI RtlAreAllAccessesGranted(ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess)
#define EVENT_SERVICE_CONTROL_SUCCESS
Definition: netevent.h:432
#define EVENT_SERVICE_EXIT_FAILED
Definition: netevent.h:436
#define EVENT_SERVICE_STATUS_SUCCESS
Definition: netevent.h:450
#define SYMBOLIC_LINK_QUERY
Definition: nt_native.h:1265
#define WRITE_DAC
Definition: nt_native.h:59
#define REG_BINARY
Definition: nt_native.h:1496
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define ACCESS_SYSTEM_SECURITY
Definition: nt_native.h:77
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define DELETE
Definition: nt_native.h:57
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define KEY_WRITE
Definition: nt_native.h:1031
#define READ_CONTROL
Definition: nt_native.h:58
#define WRITE_OWNER
Definition: nt_native.h:60
#define DWORD
Definition: nt_native.h:44
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define UNICODE_NULL
#define UNICODE_STRING_MAX_BYTES
NTSTATUS NTAPI NtOpenThreadToken(_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _Out_ PHANDLE TokenHandle)
Opens a token that is tied to a thread handle.
Definition: token.c:2474
#define STATUS_BAD_DESCRIPTOR_FORMAT
Definition: ntstatus.h:467
#define L(x)
Definition: ntvdm.h:50
DWORD * PDWORD
Definition: pedump.c:68
unsigned short USHORT
Definition: pedump.c:61
static WCHAR CanonName[NI_MAXHOST]
Definition: ping.c:69
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
RPC_STATUS WINAPI RpcRevertToSelf(void)
Definition: rpc_binding.c:1463
RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
Definition: rpc_binding.c:1056
RPC_STATUS WINAPI RpcServerListen(UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait)
Definition: rpc_server.c:1520
RPC_STATUS WINAPI RpcServerRegisterIf(RPC_IF_HANDLE IfSpec, UUID *MgrTypeUuid, RPC_MGR_EPV *MgrEpv)
Definition: rpc_server.c:1116
RPC_STATUS WINAPI RpcServerUseProtseqEpW(RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor)
Definition: rpc_server.c:927
#define RPC_S_OK
Definition: rpcnterr.h:22
SC_HANDLE hSCManager
Definition: sc.c:12
#define REG_DWORD
Definition: sdbapi.c:596
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define midl_user_free
Definition: rpc.h:45
#define __RPC_FAR
Definition: rpc.h:56
long RPC_STATUS
Definition: rpc.h:52
#define __RPC_USER
Definition: rpc.h:65
#define midl_user_allocate
Definition: rpc.h:44
_In_ DWORD _Out_ PDWORD _In_opt_ PCSTR MachineName
Definition: setupapi.h:1293
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:73
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
SERVICE_STATUS ServiceStatus
Definition: winsvc.h:127
SERVICE_STATUS ServiceStatus
Definition: winsvc.h:132
LPWSTR lpDisplayName
Definition: winsvc.h:131
LPWSTR lpServiceName
Definition: winsvc.h:130
SERVICE_STATUS_PROCESS ServiceStatusProcess
Definition: winsvc.h:137
SERVICE_STATUS_PROCESS ServiceStatusProcess
Definition: winsvc.h:142
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
SCMGR_HANDLE Handle
Definition: rpcserver.c:38
WCHAR DatabaseName[1]
Definition: rpcserver.c:39
LPWSTR lpBinaryPathName
Definition: winsvc.h:159
DWORD DesiredAccess
Definition: rpcserver.c:32
LPSERVICE_DESCRIPTIONW psd
Definition: svcctl.idl:200
LPSERVICE_FAILURE_ACTIONSW psfa
Definition: svcctl.idl:201
LPWSTR lpDescription
Definition: winsvc.h:196
SC_ACTION * lpsaActions
Definition: winsvc.h:213
SC_ACTION * lpsaActions
Definition: winsvc.h:220
WCHAR szGroupName[1]
Definition: services.h:42
LPWSTR lpGroupName
Definition: services.h:35
SCMGR_HANDLE Handle
Definition: rpcserver.c:45
PSERVICE ServiceEntry
Definition: rpcserver.c:46
HANDLE hControlPipe
Definition: services.h:53
DWORD dwProcessId
Definition: services.h:55
DWORD dwImageRunCount
Definition: services.h:51
DWORD dwServiceType
Definition: winsvc.h:99
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwControlsAccepted
Definition: winsvc.h:101
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwCurrentState
Definition: winsvc.h:100
DWORD dwCheckPoint
Definition: winsvc.h:104
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
BOOL bDeleted
Definition: services.h:68
DWORD dwServiceBits
Definition: services.h:77
PSERVICE_GROUP lpGroup
Definition: services.h:66
PSECURITY_DESCRIPTOR pSecurityDescriptor
Definition: services.h:82
DWORD dwErrorControl
Definition: services.h:74
LPWSTR lpDisplayName
Definition: services.h:65
LIST_ENTRY ServiceListEntry
Definition: services.h:63
DWORD dwResumeCount
Definition: services.h:69
SERVICE_STATUS Status
Definition: services.h:72
DWORD dwStartType
Definition: services.h:73
WCHAR szServiceName[1]
Definition: services.h:86
LONG RefCount
Definition: services.h:70
DWORD dwTag
Definition: services.h:75
PSERVICE_IMAGE lpImage
Definition: services.h:67
LPWSTR lpServiceName
Definition: services.h:64
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define max(a, b)
Definition: svc.c:63
BOUNDED_DWORD_256K * LPBOUNDED_DWORD_256K
Definition: svcctl.idl:32
BOUNDED_DWORD_8K * LPBOUNDED_DWORD_8K
Definition: svcctl.idl:30
BOUNDED_DWORD_4K * LPBOUNDED_DWORD_4K
Definition: svcctl.idl:28
ULONG_PTR RPC_SERVICE_STATUS_HANDLE
Definition: svcctl.idl:20
LPWSTR SVCCTL_HANDLEW
Definition: svcctl.idl:19
PVOID SC_RPC_HANDLE
Definition: svcctl.idl:21
enum _TAG_INFO_LEVEL TAG_INFO_LEVEL
@ TagInfoLevelNameFromTag
Definition: svcctl.idl:300
_In_ ULONG _Out_ HANDLE * BindingHandle
Definition: tdikrnl.h:1147
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
SERVICE_STATUS_HANDLE hServiceStatus
Definition: main.c:10
#define SecureZeroMemory
Definition: winbase.h:1713
_In_ LPCSTR _Out_writes_to_opt_ cchDisplayName LPSTR lpDisplayName
Definition: winbase.h:2790
#define GetModuleHandle
Definition: winbase.h:3827
BOOL * PBOOL
Definition: windef.h:161
#define WINAPI
Definition: msvc.h:6
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
#define ERROR_SERVICE_MARKED_FOR_DELETE
Definition: winerror.h:623
#define ERROR_SERVICE_NOT_ACTIVE
Definition: winerror.h:613
#define ERROR_INVALID_ENVIRONMENT
Definition: winerror.h:1112
#define ERROR_GEN_FAILURE
Definition: winerror.h:134
#define ERROR_SERVICE_DOES_NOT_EXIST
Definition: winerror.h:611
#define ERROR_RETRY
Definition: winerror.h:740
#define ERROR_DUPLICATE_SERVICE_NAME
Definition: winerror.h:629
#define ERROR_SERVICE_EXISTS
Definition: winerror.h:624
#define ERROR_DEPENDENT_SERVICES_RUNNING
Definition: winerror.h:602
#define ERROR_SERVICE_DISABLED
Definition: winerror.h:609
#define ERROR_CANNOT_DETECT_DRIVER_FAILURE
Definition: winerror.h:631
#define ERROR_INVALID_SERVICE_CONTROL
Definition: winerror.h:603
#define ERROR_SHUTDOWN_IN_PROGRESS
Definition: winerror.h:651
#define ERROR_DATABASE_DOES_NOT_EXIST
Definition: winerror.h:616
#define ERROR_SERVICE_CANNOT_ACCEPT_CTRL
Definition: winerror.h:612
#define ERROR_INVALID_DATA
Definition: winerror.h:116
#define ERROR_NOT_FOUND
Definition: winerror.h:690
#define EVENTLOG_ERROR_TYPE
Definition: winnt_old.h:2834
#define EVENTLOG_INFORMATION_TYPE
Definition: winnt_old.h:2836
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define SERVICE_ACCEPT_PARAMCHANGE
Definition: winsvc.h:31
#define SERVICE_START
Definition: winsvc.h:57
#define SERVICE_CONTROL_PARAMCHANGE
Definition: winsvc.h:41
struct _QUERY_SERVICE_CONFIGW * LPQUERY_SERVICE_CONFIGW
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_STATE_ALL
Definition: winsvc.h:52
struct _QUERY_SERVICE_LOCK_STATUSW QUERY_SERVICE_LOCK_STATUSW
struct _SERVICE_DESCRIPTIONA SERVICE_DESCRIPTIONA
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
struct _ENUM_SERVICE_STATUS_PROCESSA ENUM_SERVICE_STATUS_PROCESSA
_In_ DWORD _In_ DWORD _Out_ LPDWORD pcbBytesNeeded
Definition: winsvc.h:425
struct _SERVICE_FAILURE_ACTIONSW SERVICE_FAILURE_ACTIONSW
#define SERVICE_CONTROL_NETBINDREMOVE
Definition: winsvc.h:43
#define SERVICE_QUERY_STATUS
Definition: winsvc.h:55
struct _QUERY_SERVICE_LOCK_STATUSA * LPQUERY_SERVICE_LOCK_STATUSA
struct _QUERY_SERVICE_LOCK_STATUSA QUERY_SERVICE_LOCK_STATUSA
#define SERVICE_CONTROL_NETBINDADD
Definition: winsvc.h:42
#define SC_MANAGER_LOCK
Definition: winsvc.h:17
#define SERVICE_USER_DEFINED_CONTROL
Definition: winsvc.h:61
#define SC_MANAGER_QUERY_LOCK_STATUS
Definition: winsvc.h:18
@ SC_STATUS_PROCESS_INFO
Definition: winsvc.h:119
_In_ DWORD _In_ DWORD cbBufSize
Definition: winsvc.h:424
struct _ENUM_SERVICE_STATUS_PROCESSW * LPENUM_SERVICE_STATUS_PROCESSW
#define SERVICE_CONFIG_DESCRIPTION
Definition: winsvc.h:65
#define SERVICE_ALL_ACCESS
Definition: winsvc.h:62
#define SERVICE_ACTIVE
Definition: winsvc.h:50
struct _SERVICE_DESCRIPTIONW SERVICE_DESCRIPTIONW
#define SC_MANAGER_ENUMERATE_SERVICE
Definition: winsvc.h:16
struct _SC_ACTION SC_ACTION
struct _ENUM_SERVICE_STATUS_PROCESSA * LPENUM_SERVICE_STATUS_PROCESSA
#define SC_MANAGER_CREATE_SERVICE
Definition: winsvc.h:15
#define SC_MANAGER_CONNECT
Definition: winsvc.h:14
struct _QUERY_SERVICE_CONFIGW QUERY_SERVICE_CONFIGW
#define SERVICE_NO_CHANGE
Definition: winsvc.h:20
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define SERVICE_CHANGE_CONFIG
Definition: winsvc.h:54
#define SERVICES_FAILED_DATABASEW
Definition: winsvc.h:10
struct _SERVICE_DESCRIPTIONW * LPSERVICE_DESCRIPTIONW
#define SERVICE_PAUSED
Definition: winsvc.h:27
struct _ENUM_SERVICE_STATUSW ENUM_SERVICE_STATUSW
struct _ENUM_SERVICE_STATUS_PROCESSW ENUM_SERVICE_STATUS_PROCESSW
struct _SERVICE_STATUS SERVICE_STATUS
struct _SERVICE_FAILURE_ACTIONSA * LPSERVICE_FAILURE_ACTIONSA
#define SERVICE_CONTROL_NETBINDDISABLE
Definition: winsvc.h:45
_In_ DWORD dwInfoLevel
Definition: winsvc.h:422
struct _SC_ACTION * LPSC_ACTION
#define SERVICE_PAUSE_CONTINUE
Definition: winsvc.h:59
enum _SC_STATUS_TYPE SC_STATUS_TYPE
struct _QUERY_SERVICE_CONFIGA * LPQUERY_SERVICE_CONFIGA
#define SERVICE_CONTROL_NETBINDENABLE
Definition: winsvc.h:44
#define SERVICE_INTERROGATE
Definition: winsvc.h:60
#define SERVICE_STOP
Definition: winsvc.h:58
struct _SERVICE_DESCRIPTIONA * LPSERVICE_DESCRIPTIONA
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_CONTINUE
Definition: winsvc.h:38
struct _QUERY_SERVICE_LOCK_STATUSW * LPQUERY_SERVICE_LOCK_STATUSW
struct _ENUM_SERVICE_STATUSW * LPENUM_SERVICE_STATUSW
#define SERVICE_ACCEPT_PAUSE_CONTINUE
Definition: winsvc.h:29
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
struct _SERVICE_STATUS_PROCESS * LPSERVICE_STATUS_PROCESS
struct _SERVICE_FAILURE_ACTIONSA SERVICE_FAILURE_ACTIONSA
#define SERVICE_INACTIVE
Definition: winsvc.h:51
#define SERVICES_ACTIVE_DATABASEW
Definition: winsvc.h:8
#define SERVICE_PAUSE_PENDING
Definition: winsvc.h:26
#define SERVICE_CONFIG_FAILURE_ACTIONS
Definition: winsvc.h:66
@ SC_ENUM_PROCESS_INFO
Definition: winsvc.h:122
#define SERVICE_ACCEPT_NETBINDCHANGE
Definition: winsvc.h:32
#define SERVICE_CONTROL_PAUSE
Definition: winsvc.h:37
struct _SERVICE_FAILURE_ACTIONSW * LPSERVICE_FAILURE_ACTIONSW
struct _SERVICE_STATUS_PROCESS SERVICE_STATUS_PROCESS
#define SERVICE_CONTROL_INTERROGATE
Definition: winsvc.h:39
struct _ENUM_SERVICE_STATUSA ENUM_SERVICE_STATUSA
#define SC_MANAGER_ALL_ACCESS
Definition: winsvc.h:13
struct _ENUM_SERVICE_STATUSA * LPENUM_SERVICE_STATUSA
#define SERVICE_QUERY_CONFIG
Definition: winsvc.h:53
enum _SC_ENUM_TYPE SC_ENUM_TYPE
Definition: service.c:43
struct _QUERY_SERVICE_CONFIGA QUERY_SERVICE_CONFIGA
#define SERVICE_CONTINUE_PENDING
Definition: winsvc.h:25
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define SERVICE_TYPE_ALL
Definition: cmtypes.h:969
#define SERVICE_DEMAND_START
Definition: cmtypes.h:978
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:953
#define SERVICE_WIN32_SHARE_PROCESS
Definition: cmtypes.h:963
#define SERVICE_ERROR_SEVERE
Definition: cmtypes.h:983
#define SERVICE_INTERACTIVE_PROCESS
Definition: cmtypes.h:967
#define SERVICE_DISABLED
Definition: cmtypes.h:979
#define SERVICE_AUTO_START
Definition: cmtypes.h:977
#define SERVICE_BOOT_START
Definition: cmtypes.h:975
#define SERVICE_ERROR_CRITICAL
Definition: cmtypes.h:984
#define SERVICE_DRIVER
Definition: cmtypes.h:958
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:962
#define SERVICE_SYSTEM_START
Definition: cmtypes.h:976
#define SERVICE_FILE_SYSTEM_DRIVER
Definition: cmtypes.h:954
#define SERVICE_ERROR_IGNORE
Definition: cmtypes.h:981
#define SERVICE_WIN32
Definition: cmtypes.h:964
#define SERVICE_ERROR_NORMAL
Definition: cmtypes.h:982
_In_ ULONG RequiredAccess
Definition: iofuncs.h:2223
#define DACL_SECURITY_INFORMATION
Definition: setypes.h:125
#define OWNER_SECURITY_INFORMATION
Definition: setypes.h:123
#define GROUP_SECURITY_INFORMATION
Definition: setypes.h:124
#define SACL_SECURITY_INFORMATION
Definition: setypes.h:126
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292
#define NtCurrentThread()