ReactOS 0.4.15-dev-7788-g1ad9096
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/* Internal recursive function */
781/* Need to search for every dependency on every service */
782static DWORD
784 PSERVICE lpService,
785 DWORD dwServiceState,
786 PSERVICE *lpServices,
788 LPDWORD lpServicesReturned)
789{
790 DWORD dwError = ERROR_SUCCESS;
791 WCHAR szNameBuf[MAX_PATH];
792 WCHAR szValueBuf[MAX_PATH];
793 WCHAR *lpszNameBuf = szNameBuf;
794 WCHAR *lpszValueBuf = szValueBuf;
796 DWORD dwNumSubKeys;
797 DWORD dwIteration;
798 PSERVICE lpCurrentService;
799 HKEY hServiceEnumKey;
800 DWORD dwCurrentServiceState = SERVICE_ACTIVE;
801 DWORD dwDependServiceStrPtr = 0;
802 DWORD dwRequiredSize = 0;
803
804 /* Get the number of service keys */
806 NULL,
807 NULL,
808 NULL,
809 &dwNumSubKeys,
810 NULL,
811 NULL,
812 NULL,
813 NULL,
814 NULL,
815 NULL,
816 NULL);
817 if (dwError != ERROR_SUCCESS)
818 {
819 DPRINT("ERROR! Unable to get number of services keys\n");
820 return dwError;
821 }
822
823 /* Iterate the service keys to see if another service depends on the this service */
824 for (dwIteration = 0; dwIteration < dwNumSubKeys; dwIteration++)
825 {
827 dwError = RegEnumKeyExW(hServicesKey,
828 dwIteration,
829 lpszNameBuf,
830 &dwSize,
831 NULL,
832 NULL,
833 NULL,
834 NULL);
835 if (dwError != ERROR_SUCCESS)
836 return dwError;
837
838 /* Open the Service key */
839 dwError = RegOpenKeyExW(hServicesKey,
840 lpszNameBuf,
841 0,
842 KEY_READ,
843 &hServiceEnumKey);
844 if (dwError != ERROR_SUCCESS)
845 return dwError;
846
847 dwSize = MAX_PATH * sizeof(WCHAR);
848
849 /* Check for the DependOnService Value */
850 dwError = RegQueryValueExW(hServiceEnumKey,
851 L"DependOnService",
852 NULL,
853 NULL,
854 (LPBYTE)lpszValueBuf,
855 &dwSize);
856
857 /* FIXME: Handle load order. */
858
859 /* If the service found has a DependOnService value */
860 if (dwError == ERROR_SUCCESS)
861 {
862 dwDependServiceStrPtr = 0;
863
864 /* Can be more than one Dependencies in the DependOnService string */
865 while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0)
866 {
867 if (_wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0)
868 {
869 /* Get the current enumed service pointer */
870 lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf);
871
872 /* Check for valid Service */
873 if (!lpCurrentService)
874 {
875 /* This should never happen! */
876 DPRINT("This should not happen at this point, report to Developer\n");
877 return ERROR_NOT_FOUND;
878 }
879
880 /* Determine state the service is in */
881 if (lpCurrentService->Status.dwCurrentState == SERVICE_STOPPED)
882 dwCurrentServiceState = SERVICE_INACTIVE;
883
884 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
885 if ((dwCurrentServiceState == dwServiceState) ||
886 (dwServiceState == SERVICE_STATE_ALL))
887 {
888 /* Calculate the required size */
889 dwRequiredSize += sizeof(SERVICE_STATUS);
890 dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR));
891 dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
892
893 /* Add the size for service name and display name pointers */
894 dwRequiredSize += (2 * sizeof(PVOID));
895
896 /* increase the BytesNeeded size */
897 *pcbBytesNeeded = *pcbBytesNeeded + dwRequiredSize;
898
899 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
900 comes first */
901
902 /* Recursive call to check for its dependencies */
904 lpCurrentService,
905 dwServiceState,
906 lpServices,
908 lpServicesReturned);
909
910 /* If the lpServices is valid set the service pointer */
911 if (lpServices)
912 lpServices[*lpServicesReturned] = lpCurrentService;
913
914 *lpServicesReturned = *lpServicesReturned + 1;
915 }
916 }
917
918 dwDependServiceStrPtr += (DWORD)(wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1);
919 }
920 }
921 else if (*pcbBytesNeeded)
922 {
923 dwError = ERROR_SUCCESS;
924 }
925
926 RegCloseKey(hServiceEnumKey);
927 }
928
929 return dwError;
930}
931
932
933/* Function 0 */
934DWORD
935WINAPI
937 LPSC_RPC_HANDLE hSCObject)
938{
939 PMANAGER_HANDLE hManager;
940 PSERVICE_HANDLE hService;
941 PSERVICE lpService;
943 DWORD dwError;
945 DWORD dwServicesReturned = 0;
946
947 DPRINT("RCloseServiceHandle() called\n");
948
949 DPRINT("hSCObject = %p\n", *hSCObject);
950
951 if (*hSCObject == 0)
953
954 hManager = ScmGetServiceManagerFromHandle(*hSCObject);
955 hService = ScmGetServiceFromHandle(*hSCObject);
956
957 if (hManager != NULL)
958 {
959 DPRINT("Found manager handle\n");
960
961 /* Make sure we don't access stale memory if someone tries to use this handle again. */
962 hManager->Handle.Tag = INVALID_TAG;
963
964 HeapFree(GetProcessHeap(), 0, hManager);
965 hManager = NULL;
966
967 *hSCObject = NULL;
968
969 DPRINT("RCloseServiceHandle() done\n");
970 return ERROR_SUCCESS;
971 }
972 else if (hService != NULL)
973 {
974 DPRINT("Found service handle\n");
975
976 /* Lock the service database exclusively */
978
979 /* Get the pointer to the service record */
980 lpService = hService->ServiceEntry;
981
982 /* Make sure we don't access stale memory if someone tries to use this handle again. */
983 hService->Handle.Tag = INVALID_TAG;
984
985 /* Free the handle */
986 HeapFree(GetProcessHeap(), 0, hService);
987 hService = NULL;
988
989 ASSERT(lpService->dwRefCount > 0);
990
991 lpService->dwRefCount--;
992 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
993 lpService->dwRefCount);
994
995 if (lpService->dwRefCount == 0)
996 {
997 /* If this service has been marked for deletion */
998 if (lpService->bDeleted &&
1000 {
1001 /* Open the Services Reg key */
1003 L"System\\CurrentControlSet\\Services",
1004 0,
1006 &hServicesKey);
1007 if (dwError != ERROR_SUCCESS)
1008 {
1009 DPRINT("Failed to open services key\n");
1011 return dwError;
1012 }
1013
1014 /* Call the internal function with NULL, just to get bytes we need */
1016 lpService,
1018 NULL,
1020 &dwServicesReturned);
1021
1022 /* If pcbBytesNeeded returned a value then there are services running that are dependent on this service */
1023 if (pcbBytesNeeded)
1024 {
1025 DPRINT("Deletion failed due to running dependencies\n");
1028 return ERROR_SUCCESS;
1029 }
1030
1031 /* There are no references and no running dependencies,
1032 it is now safe to delete the service */
1033
1034 /* Delete the Service Key */
1035 dwError = ScmDeleteRegKey(hServicesKey,
1036 lpService->lpServiceName);
1037
1039
1040 if (dwError != ERROR_SUCCESS)
1041 {
1042 DPRINT("Failed to Delete the Service Registry key\n");
1044 return dwError;
1045 }
1046
1047 /* Delete the Service */
1048 ScmDeleteServiceRecord(lpService);
1049 }
1050 }
1051
1053
1054 *hSCObject = NULL;
1055
1056 DPRINT("RCloseServiceHandle() done\n");
1057 return ERROR_SUCCESS;
1058 }
1059
1060 DPRINT("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
1061
1062 return ERROR_INVALID_HANDLE;
1063}
1064
1065
1066/* Function 1 */
1067DWORD
1068WINAPI
1070 SC_RPC_HANDLE hService,
1071 DWORD dwControl,
1072 LPSERVICE_STATUS lpServiceStatus)
1073{
1074 PSERVICE_HANDLE hSvc;
1075 PSERVICE lpService;
1077 DWORD dwError = ERROR_SUCCESS;
1079 DWORD dwServicesReturned = 0;
1080 DWORD dwControlsAccepted;
1081 DWORD dwCurrentState;
1083 LPCWSTR lpLogStrings[2];
1084 WCHAR szLogBuffer[80];
1085 UINT uID;
1086
1087 DPRINT("RControlService() called\n");
1088
1089 if (ScmShutdown)
1091
1092 /* Check the service handle */
1093 hSvc = ScmGetServiceFromHandle(hService);
1094 if (hSvc == NULL)
1095 {
1096 DPRINT1("Invalid service handle\n");
1097 return ERROR_INVALID_HANDLE;
1098 }
1099
1100 /* Check the service entry point */
1101 lpService = hSvc->ServiceEntry;
1102 if (lpService == NULL)
1103 {
1104 DPRINT1("lpService == NULL\n");
1105 return ERROR_INVALID_HANDLE;
1106 }
1107
1108 /* Check access rights */
1109 switch (dwControl)
1110 {
1113 break;
1114
1123 break;
1124
1127 break;
1128
1129 default:
1130 if (dwControl >= 128 && dwControl <= 255)
1132 else
1134 break;
1135 }
1136
1139 return ERROR_ACCESS_DENIED;
1140
1141 /* Return the current service status information */
1142 RtlCopyMemory(lpServiceStatus,
1143 &lpService->Status,
1144 sizeof(SERVICE_STATUS));
1145
1146 if (dwControl == SERVICE_CONTROL_STOP)
1147 {
1148 /* Check if the service has dependencies running as windows
1149 doesn't stop a service that does */
1150
1151 /* Open the Services Reg key */
1153 L"System\\CurrentControlSet\\Services",
1154 0,
1155 KEY_READ,
1156 &hServicesKey);
1157 if (dwError != ERROR_SUCCESS)
1158 {
1159 DPRINT("Failed to open services key\n");
1160 return dwError;
1161 }
1162
1163 /* Call the internal function with NULL, just to get bytes we need */
1165 lpService,
1167 NULL,
1169 &dwServicesReturned);
1170
1172
1173 /* If pcbBytesNeeded is not zero then there are services running that
1174 are dependent on this service */
1175 if (pcbBytesNeeded != 0)
1176 {
1177 DPRINT("Service has running dependencies. Failed to stop service\n");
1179 }
1180 }
1181
1182 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
1183 {
1184 /* Send control code to the driver */
1185 dwError = ScmControlDriver(lpService,
1186 dwControl,
1187 lpServiceStatus);
1188 }
1189 else
1190 {
1191 dwControlsAccepted = lpService->Status.dwControlsAccepted;
1192 dwCurrentState = lpService->Status.dwCurrentState;
1193
1194 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
1195 if (lpService->lpImage == NULL || dwCurrentState == SERVICE_STOPPED)
1197
1198 /* Check the current state before sending a control request */
1199 switch (dwCurrentState)
1200 {
1202 case SERVICE_STOPPED:
1204
1206 switch (dwControl)
1207 {
1209 break;
1210
1212 RtlCopyMemory(lpServiceStatus,
1213 &lpService->Status,
1214 sizeof(SERVICE_STATUS));
1215 return ERROR_SUCCESS;
1216
1217 default:
1219 }
1220 break;
1221 }
1222
1223 /* Check if the control code is acceptable to the service */
1224 switch (dwControl)
1225 {
1227 if ((dwControlsAccepted & SERVICE_ACCEPT_STOP) == 0)
1229 break;
1230
1233 if ((dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) == 0)
1235 break;
1236
1238 if ((dwControlsAccepted & SERVICE_ACCEPT_PARAMCHANGE) == 0)
1240 break;
1241
1246 if ((dwControlsAccepted & SERVICE_ACCEPT_NETBINDCHANGE) == 0)
1248 break;
1249 }
1250
1251 /* Send control code to the service */
1252 dwError = ScmControlService(lpService->lpImage->hControlPipe,
1253 lpService->lpServiceName,
1254 (SERVICE_STATUS_HANDLE)lpService,
1255 dwControl);
1256
1257 /* Return service status information */
1258 RtlCopyMemory(lpServiceStatus,
1259 &lpService->Status,
1260 sizeof(SERVICE_STATUS));
1261 }
1262
1263 if (dwError == ERROR_SUCCESS)
1264 {
1265 if (dwControl == SERVICE_CONTROL_STOP ||
1266 dwControl == SERVICE_CONTROL_PAUSE ||
1267 dwControl == SERVICE_CONTROL_CONTINUE)
1268 {
1269 /* Log a successful send control */
1270
1271 switch (dwControl)
1272 {
1274 uID = IDS_SERVICE_STOP;
1275 break;
1276
1278 uID = IDS_SERVICE_PAUSE;
1279 break;
1280
1282 uID = IDS_SERVICE_RESUME;
1283 break;
1284 }
1285 LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer));
1286
1287 lpLogStrings[0] = lpService->lpDisplayName;
1288 lpLogStrings[1] = szLogBuffer;
1289
1292 2,
1293 lpLogStrings);
1294 }
1295 }
1296
1297 return dwError;
1298}
1299
1300
1301/* Function 2 */
1302DWORD
1303WINAPI
1305 SC_RPC_HANDLE hService)
1306{
1307 PSERVICE_HANDLE hSvc;
1308 PSERVICE lpService;
1309 DWORD dwError;
1310
1311 DPRINT("RDeleteService() called\n");
1312
1313 if (ScmShutdown)
1315
1316 hSvc = ScmGetServiceFromHandle(hService);
1317 if (hSvc == NULL)
1318 {
1319 DPRINT1("Invalid service handle\n");
1320 return ERROR_INVALID_HANDLE;
1321 }
1322
1324 DELETE))
1325 return ERROR_ACCESS_DENIED;
1326
1327 lpService = hSvc->ServiceEntry;
1328 if (lpService == NULL)
1329 {
1330 DPRINT("lpService == NULL\n");
1331 return ERROR_INVALID_HANDLE;
1332 }
1333
1334 /* Lock the service database exclusively */
1336
1337 if (lpService->bDeleted)
1338 {
1339 DPRINT("Service has already been marked for delete\n");
1341 goto Done;
1342 }
1343
1344 /* Mark service for delete */
1345 lpService->bDeleted = TRUE;
1346
1347 dwError = ScmMarkServiceForDelete(lpService);
1348
1349Done:
1350 /* Unlock the service database */
1352
1353 DPRINT("RDeleteService() done\n");
1354
1355 return dwError;
1356}
1357
1358
1359/* Function 3 */
1360DWORD
1361WINAPI
1364 LPSC_RPC_LOCK lpLock)
1365{
1366 PMANAGER_HANDLE hMgr;
1367
1368 DPRINT("RLockServiceDatabase() called\n");
1369
1370 *lpLock = NULL;
1371
1373 if (hMgr == NULL)
1374 {
1375 DPRINT1("Invalid service manager handle\n");
1376 return ERROR_INVALID_HANDLE;
1377 }
1378
1381 return ERROR_ACCESS_DENIED;
1382
1383 return ScmAcquireServiceStartLock(FALSE, lpLock);
1384}
1385
1386
1387/* Function 4 */
1388DWORD
1389WINAPI
1391 SC_RPC_HANDLE hService,
1392 SECURITY_INFORMATION dwSecurityInformation,
1393 LPBYTE lpSecurityDescriptor,
1396{
1397 PSERVICE_HANDLE hSvc;
1398 PSERVICE lpService;
1399 ULONG DesiredAccess = 0;
1401 DWORD dwBytesNeeded;
1402 DWORD dwError;
1403
1404 DPRINT("RQueryServiceObjectSecurity() called\n");
1405
1406 hSvc = ScmGetServiceFromHandle(hService);
1407 if (hSvc == NULL)
1408 {
1409 DPRINT1("Invalid service handle\n");
1410 return ERROR_INVALID_HANDLE;
1411 }
1412
1413 if (dwSecurityInformation & (DACL_SECURITY_INFORMATION |
1417
1418 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
1420
1423 {
1424 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1425 return ERROR_ACCESS_DENIED;
1426 }
1427
1428 lpService = hSvc->ServiceEntry;
1429 if (lpService == NULL)
1430 {
1431 DPRINT("lpService == NULL\n");
1432 return ERROR_INVALID_HANDLE;
1433 }
1434
1435 /* Lock the service database */
1437
1438 /* Retrieve the security descriptor */
1440 dwSecurityInformation,
1441 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
1442 cbBufSize,
1443 &dwBytesNeeded);
1444
1445 /* Unlock the service database */
1447
1448 if (NT_SUCCESS(Status))
1449 {
1450 *pcbBytesNeeded = dwBytesNeeded;
1451 dwError = STATUS_SUCCESS;
1452 }
1453 else if (Status == STATUS_BUFFER_TOO_SMALL)
1454 {
1455 *pcbBytesNeeded = dwBytesNeeded;
1456 dwError = ERROR_INSUFFICIENT_BUFFER;
1457 }
1459 {
1460 dwError = ERROR_GEN_FAILURE;
1461 }
1462 else
1463 {
1464 dwError = RtlNtStatusToDosError(Status);
1465 }
1466
1467 return dwError;
1468}
1469
1470
1471/* Function 5 */
1472DWORD
1473WINAPI
1475 SC_RPC_HANDLE hService,
1476 DWORD dwSecurityInformation,
1477 LPBYTE lpSecurityDescriptor,
1478 DWORD dwSecurityDescriptorSize)
1479{
1480 PSERVICE_HANDLE hSvc;
1481 PSERVICE lpService;
1483 HANDLE hToken = NULL;
1484 HKEY hServiceKey = NULL;
1485 BOOL bDatabaseLocked = FALSE;
1487 DWORD dwError;
1488
1489 DPRINT("RSetServiceObjectSecurity() called\n");
1490
1491 hSvc = ScmGetServiceFromHandle(hService);
1492 if (hSvc == NULL)
1493 {
1494 DPRINT1("Invalid service handle\n");
1495 return ERROR_INVALID_HANDLE;
1496 }
1497
1498 if (dwSecurityInformation == 0 ||
1499 dwSecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
1501 {
1503 }
1504
1505 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
1507
1508 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
1510
1511 if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
1513
1514 if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
1516
1517 if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
1518 (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
1519 {
1521 }
1522
1523 if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
1524 (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
1525 {
1527 }
1528
1531 {
1532 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1533 return ERROR_ACCESS_DENIED;
1534 }
1535
1536 lpService = hSvc->ServiceEntry;
1537 if (lpService == NULL)
1538 {
1539 DPRINT1("lpService == NULL\n");
1540 return ERROR_INVALID_HANDLE;
1541 }
1542
1543 if (lpService->bDeleted)
1545
1546#if 0
1548
1550 8,
1551 TRUE,
1552 &hToken);
1553 if (!NT_SUCCESS(Status))
1555
1557#endif
1558
1559 /* Build the new security descriptor */
1560 Status = RtlSetSecurityObject(dwSecurityInformation,
1561 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
1562 &lpService->pSecurityDescriptor,
1564 hToken);
1565 if (!NT_SUCCESS(Status))
1566 {
1567 dwError = RtlNtStatusToDosError(Status);
1568 goto Done;
1569 }
1570
1571 /* Lock the service database exclusive */
1573 bDatabaseLocked = TRUE;
1574
1575 /* Open the service key */
1576 dwError = ScmOpenServiceKey(lpService->lpServiceName,
1578 &hServiceKey);
1579 if (dwError != ERROR_SUCCESS)
1580 goto Done;
1581
1582 /* Store the new security descriptor */
1583 dwError = ScmWriteSecurityDescriptor(hServiceKey,
1584 lpService->pSecurityDescriptor);
1585
1586 RegFlushKey(hServiceKey);
1587
1588Done:
1589 if (hServiceKey != NULL)
1590 RegCloseKey(hServiceKey);
1591
1592 /* Unlock service database */
1593 if (bDatabaseLocked == TRUE)
1595
1596 if (hToken != NULL)
1597 NtClose(hToken);
1598
1599 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError);
1600
1601 return dwError;
1602}
1603
1604
1605/* Function 6 */
1606DWORD
1607WINAPI
1609 SC_RPC_HANDLE hService,
1610 LPSERVICE_STATUS lpServiceStatus)
1611{
1612 PSERVICE_HANDLE hSvc;
1613 PSERVICE lpService;
1614
1615 DPRINT("RQueryServiceStatus() called\n");
1616
1617 if (ScmShutdown)
1619
1620 hSvc = ScmGetServiceFromHandle(hService);
1621 if (hSvc == NULL)
1622 {
1623 DPRINT1("Invalid service handle\n");
1624 return ERROR_INVALID_HANDLE;
1625 }
1626
1629 {
1630 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1631 return ERROR_ACCESS_DENIED;
1632 }
1633
1634 lpService = hSvc->ServiceEntry;
1635 if (lpService == NULL)
1636 {
1637 DPRINT("lpService == NULL\n");
1638 return ERROR_INVALID_HANDLE;
1639 }
1640
1641 /* Lock the service database shared */
1643
1644 /* Return service status information */
1645 RtlCopyMemory(lpServiceStatus,
1646 &lpService->Status,
1647 sizeof(SERVICE_STATUS));
1648
1649 /* Unlock the service database */
1651
1652 return ERROR_SUCCESS;
1653}
1654
1655
1656static BOOL
1658{
1659 switch (dwCurrentState)
1660 {
1661 case SERVICE_STOPPED:
1664 case SERVICE_RUNNING:
1667 case SERVICE_PAUSED:
1668 return TRUE;
1669
1670 default:
1671 return FALSE;
1672 }
1673}
1674
1675
1676/* Function 7 */
1677DWORD
1678WINAPI
1681 LPSERVICE_STATUS lpServiceStatus)
1682{
1683 PSERVICE lpService;
1684 DWORD dwPreviousState;
1685 DWORD dwPreviousType;
1686 LPCWSTR lpLogStrings[2];
1687 WCHAR szLogBuffer[80];
1688 UINT uID;
1689
1690 DPRINT("RSetServiceStatus() called\n");
1691 DPRINT("hServiceStatus = %lu\n", hServiceStatus);
1692 DPRINT("dwServiceType = 0x%lx\n", lpServiceStatus->dwServiceType);
1693 DPRINT("dwCurrentState = %lu\n", lpServiceStatus->dwCurrentState);
1694 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus->dwControlsAccepted);
1695 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus->dwWin32ExitCode);
1696 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus->dwServiceSpecificExitCode);
1697 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus->dwCheckPoint);
1698 DPRINT("dwWaitHint = %lu\n", lpServiceStatus->dwWaitHint);
1699
1700 if (hServiceStatus == 0)
1701 {
1702 DPRINT("hServiceStatus == NULL\n");
1703 return ERROR_INVALID_HANDLE;
1704 }
1705
1706 lpService = (PSERVICE)hServiceStatus;
1707
1708 /* Check current state */
1709 if (!ScmIsValidServiceState(lpServiceStatus->dwCurrentState))
1710 {
1711 DPRINT("Invalid service state\n");
1712 return ERROR_INVALID_DATA;
1713 }
1714
1715 /* Check service type */
1716 if (!(lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
1717 (lpServiceStatus->dwServiceType & SERVICE_DRIVER))
1718 {
1719 DPRINT("Invalid service type\n");
1720 return ERROR_INVALID_DATA;
1721 }
1722
1723 /* Check accepted controls */
1724 if (lpServiceStatus->dwControlsAccepted & ~0xFF)
1725 {
1726 DPRINT("Invalid controls accepted\n");
1727 return ERROR_INVALID_DATA;
1728 }
1729
1730 /* Set the wait hint and check point only if the service is in a pending state,
1731 otherwise they should be 0 */
1732 if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED ||
1733 lpServiceStatus->dwCurrentState == SERVICE_PAUSED ||
1734 lpServiceStatus->dwCurrentState == SERVICE_RUNNING)
1735 {
1736 lpServiceStatus->dwWaitHint = 0;
1737 lpServiceStatus->dwCheckPoint = 0;
1738 }
1739
1740 /* Lock the service database exclusively */
1742
1743 /* Save the current service state */
1744 dwPreviousState = lpService->Status.dwCurrentState;
1745
1746 /* Save the current service type */
1747 dwPreviousType = lpService->Status.dwServiceType;
1748
1749 /* Update the service status */
1750 RtlCopyMemory(&lpService->Status,
1751 lpServiceStatus,
1752 sizeof(SERVICE_STATUS));
1753
1754 /* Restore the previous service type */
1755 lpService->Status.dwServiceType = dwPreviousType;
1756
1757 /* Dereference a stopped service */
1758 if ((lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
1759 (lpServiceStatus->dwCurrentState == SERVICE_STOPPED))
1760 {
1761 /* Decrement the image run counter */
1762 lpService->lpImage->dwImageRunCount--;
1763
1764 /* If we just stopped the last running service... */
1765 if (lpService->lpImage->dwImageRunCount == 0)
1766 {
1767 /* Stop the dispatcher thread */
1769 L"",
1770 (SERVICE_STATUS_HANDLE)lpService,
1772
1773 /* Remove the service image */
1774 ScmRemoveServiceImage(lpService->lpImage);
1775 lpService->lpImage = NULL;
1776 }
1777 }
1778
1779 /* Unlock the service database */
1781
1782 if ((lpServiceStatus->dwCurrentState == SERVICE_STOPPED) &&
1783 (dwPreviousState != SERVICE_STOPPED) &&
1784 (lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS))
1785 {
1786 /* Log a failed service stop */
1787 StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer),
1788 L"%lu", lpServiceStatus->dwWin32ExitCode);
1789 lpLogStrings[0] = lpService->lpDisplayName;
1790 lpLogStrings[1] = szLogBuffer;
1791
1794 2,
1795 lpLogStrings);
1796 }
1797 else if (lpServiceStatus->dwCurrentState != dwPreviousState &&
1798 (lpServiceStatus->dwCurrentState == SERVICE_STOPPED ||
1799 lpServiceStatus->dwCurrentState == SERVICE_RUNNING ||
1800 lpServiceStatus->dwCurrentState == SERVICE_PAUSED))
1801 {
1802 /* Log a successful service status change */
1803 switch(lpServiceStatus->dwCurrentState)
1804 {
1805 case SERVICE_STOPPED:
1806 uID = IDS_SERVICE_STOPPED;
1807 break;
1808
1809 case SERVICE_RUNNING:
1810 uID = IDS_SERVICE_RUNNING;
1811 break;
1812
1813 case SERVICE_PAUSED:
1814 uID = IDS_SERVICE_PAUSED;
1815 break;
1816 }
1817
1818 LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer));
1819 lpLogStrings[0] = lpService->lpDisplayName;
1820 lpLogStrings[1] = szLogBuffer;
1821
1824 2,
1825 lpLogStrings);
1826 }
1827
1828 DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
1829 DPRINT("RSetServiceStatus() done\n");
1830
1831 return ERROR_SUCCESS;
1832}
1833
1834
1835/* Function 8 */
1836DWORD
1837WINAPI
1840{
1841 DPRINT("RUnlockServiceDatabase(%p)\n", Lock);
1843}
1844
1845
1846/* Function 9 */
1847DWORD
1848WINAPI
1850 SVCCTL_HANDLEW lpMachineName,
1851 DWORD BootAcceptable)
1852{
1853 DPRINT("RNotifyBootConfigStatus(%p %lu)\n",
1854 lpMachineName, BootAcceptable);
1855
1856 if (BootAcceptable)
1857 return ScmAcceptBoot();
1858
1859 return ScmRunLastKnownGood();
1860}
1861
1862
1863/* Function 10 */
1864DWORD
1865WINAPI
1869 int bSetBitsOn,
1870 int bUpdateImmediately,
1871 wchar_t *lpString)
1872{
1873 PSERVICE pService;
1874
1875 DPRINT("RI_ScSetServiceBitsW(%p %lx %d %d %S)\n",
1876 hServiceStatus, dwServiceBits, bSetBitsOn,
1877 bUpdateImmediately, lpString);
1878
1879 if (ScmShutdown)
1881
1882 if (lpString != NULL)
1884
1885 if (hServiceStatus == 0)
1886 {
1887 DPRINT("hServiceStatus == NULL\n");
1888 return ERROR_INVALID_HANDLE;
1889 }
1890
1891 // FIXME: Validate the status handle
1892 pService = (PSERVICE)hServiceStatus;
1893
1894 if (bSetBitsOn)
1895 {
1896 DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
1897 DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
1898 pService->dwServiceBits |= dwServiceBits;
1900 DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
1901 DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
1902 }
1903 else
1904 {
1905 DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
1906 DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
1907 pService->dwServiceBits &= ~dwServiceBits;
1908 g_dwServiceBits &= ~dwServiceBits;
1909 DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
1910 DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
1911 }
1912
1913 return ERROR_SUCCESS;
1914}
1915
1916
1917/* Function 11 */
1918DWORD
1919WINAPI
1921 SC_RPC_HANDLE hService,
1922 DWORD dwServiceType,
1923 DWORD dwStartType,
1924 DWORD dwErrorControl,
1925 LPWSTR lpBinaryPathName,
1926 LPWSTR lpLoadOrderGroup,
1927 LPDWORD lpdwTagId,
1928 LPBYTE lpDependencies,
1929 DWORD dwDependSize,
1930 LPWSTR lpServiceStartName,
1931 LPBYTE lpPassword,
1932 DWORD dwPwSize,
1934{
1935 DWORD dwError = ERROR_SUCCESS;
1936 PSERVICE_HANDLE hSvc;
1937 PSERVICE lpService = NULL;
1938 HKEY hServiceKey = NULL;
1939 LPWSTR lpDisplayNameW = NULL;
1940 LPWSTR lpImagePathW = NULL;
1941 LPWSTR lpClearTextPassword = NULL;
1942
1943 DPRINT("RChangeServiceConfigW() called\n");
1944 DPRINT("dwServiceType = 0x%lx\n", dwServiceType);
1945 DPRINT("dwStartType = %lu\n", dwStartType);
1946 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
1947 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
1948 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
1949 DPRINT("lpServiceStartName = %S\n", lpServiceStartName);
1950 DPRINT("lpPassword = %p\n", lpPassword);
1951 DPRINT("dwPwSite = %lu\n", dwPwSize);
1952 DPRINT("lpDisplayName = %S\n", lpDisplayName);
1953
1954 if (ScmShutdown)
1956
1957 hSvc = ScmGetServiceFromHandle(hService);
1958 if (hSvc == NULL)
1959 {
1960 DPRINT1("Invalid service handle\n");
1961 return ERROR_INVALID_HANDLE;
1962 }
1963
1966 {
1967 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1968 return ERROR_ACCESS_DENIED;
1969 }
1970
1971 /* Check for invalid service type value */
1972 if ((dwServiceType != SERVICE_NO_CHANGE) &&
1973 (dwServiceType != SERVICE_KERNEL_DRIVER) &&
1974 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) &&
1977 {
1979 }
1980
1981 /* Check for invalid start type value */
1982 if ((dwStartType != SERVICE_NO_CHANGE) &&
1983 (dwStartType != SERVICE_BOOT_START) &&
1984 (dwStartType != SERVICE_SYSTEM_START) &&
1985 (dwStartType != SERVICE_AUTO_START) &&
1986 (dwStartType != SERVICE_DEMAND_START) &&
1987 (dwStartType != SERVICE_DISABLED))
1988 {
1990 }
1991
1992 /* Only drivers can be boot start or system start services */
1993 if ((dwStartType == SERVICE_BOOT_START) ||
1994 (dwStartType == SERVICE_SYSTEM_START))
1995 {
1996 if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
1997 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
1999 }
2000
2001 /* Check for invalid error control value */
2002 if ((dwErrorControl != SERVICE_NO_CHANGE) &&
2003 (dwErrorControl != SERVICE_ERROR_IGNORE) &&
2004 (dwErrorControl != SERVICE_ERROR_NORMAL) &&
2005 (dwErrorControl != SERVICE_ERROR_SEVERE) &&
2006 (dwErrorControl != SERVICE_ERROR_CRITICAL))
2007 {
2009 }
2010
2011 if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup))
2012 {
2014 }
2015
2016 lpService = hSvc->ServiceEntry;
2017 if (lpService == NULL)
2018 {
2019 DPRINT("lpService == NULL\n");
2020 return ERROR_INVALID_HANDLE;
2021 }
2022
2023 /* Lock the service database exclusively */
2025
2026 if (lpService->bDeleted)
2027 {
2028 DPRINT("Service has already been marked for delete\n");
2030 goto done;
2031 }
2032
2033 /* Open the service key */
2034 dwError = ScmOpenServiceKey(lpService->szServiceName,
2036 &hServiceKey);
2037 if (dwError != ERROR_SUCCESS)
2038 goto done;
2039
2040 /* Write service data to the registry */
2041
2042 /* Set the display name */
2043 if (lpDisplayName != NULL && *lpDisplayName != 0)
2044 {
2045 RegSetValueExW(hServiceKey,
2046 L"DisplayName",
2047 0,
2048 REG_SZ,
2050 (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR)));
2051
2052 /* Update the display name */
2053 lpDisplayNameW = HeapAlloc(GetProcessHeap(),
2055 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
2056 if (lpDisplayNameW == NULL)
2057 {
2058 dwError = ERROR_NOT_ENOUGH_MEMORY;
2059 goto done;
2060 }
2061
2062 wcscpy(lpDisplayNameW, lpDisplayName);
2063 if (lpService->lpDisplayName != lpService->lpServiceName)
2064 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
2065
2066 lpService->lpDisplayName = lpDisplayNameW;
2067 }
2068
2069 if (dwServiceType != SERVICE_NO_CHANGE)
2070 {
2071 /* Set the service type */
2072 dwError = RegSetValueExW(hServiceKey,
2073 L"Type",
2074 0,
2075 REG_DWORD,
2076 (LPBYTE)&dwServiceType,
2077 sizeof(DWORD));
2078 if (dwError != ERROR_SUCCESS)
2079 goto done;
2080
2081 lpService->Status.dwServiceType = dwServiceType;
2082 }
2083
2084 if (dwStartType != SERVICE_NO_CHANGE)
2085 {
2086 /* Set the start value */
2087 dwError = RegSetValueExW(hServiceKey,
2088 L"Start",
2089 0,
2090 REG_DWORD,
2091 (LPBYTE)&dwStartType,
2092 sizeof(DWORD));
2093 if (dwError != ERROR_SUCCESS)
2094 goto done;
2095
2096 lpService->dwStartType = dwStartType;
2097 }
2098
2099 if (dwErrorControl != SERVICE_NO_CHANGE)
2100 {
2101 /* Set the error control value */
2102 dwError = RegSetValueExW(hServiceKey,
2103 L"ErrorControl",
2104 0,
2105 REG_DWORD,
2106 (LPBYTE)&dwErrorControl,
2107 sizeof(DWORD));
2108 if (dwError != ERROR_SUCCESS)
2109 goto done;
2110
2111 lpService->dwErrorControl = dwErrorControl;
2112 }
2113
2114 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
2115 {
2116 /* Set the image path */
2117 lpImagePathW = lpBinaryPathName;
2118
2119 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
2120 {
2121 dwError = ScmCanonDriverImagePath(lpService->dwStartType,
2122 lpBinaryPathName,
2123 &lpImagePathW);
2124
2125 if (dwError != ERROR_SUCCESS)
2126 goto done;
2127 }
2128
2129 dwError = RegSetValueExW(hServiceKey,
2130 L"ImagePath",
2131 0,
2133 (LPBYTE)lpImagePathW,
2134 (DWORD)((wcslen(lpImagePathW) + 1) * sizeof(WCHAR)));
2135
2136 if (lpImagePathW != lpBinaryPathName)
2137 HeapFree(GetProcessHeap(), 0, lpImagePathW);
2138
2139 if (dwError != ERROR_SUCCESS)
2140 goto done;
2141 }
2142
2143 /* Set the group name */
2144 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
2145 {
2146 dwError = RegSetValueExW(hServiceKey,
2147 L"Group",
2148 0,
2149 REG_SZ,
2150 (LPBYTE)lpLoadOrderGroup,
2151 (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)));
2152 if (dwError != ERROR_SUCCESS)
2153 goto done;
2154
2155 dwError = ScmSetServiceGroup(lpService,
2156 lpLoadOrderGroup);
2157 if (dwError != ERROR_SUCCESS)
2158 goto done;
2159 }
2160
2161 /* Set the tag */
2162 if (lpdwTagId != NULL)
2163 {
2164 dwError = ScmAssignNewTag(lpService);
2165 if (dwError != ERROR_SUCCESS)
2166 goto done;
2167
2168 dwError = RegSetValueExW(hServiceKey,
2169 L"Tag",
2170 0,
2171 REG_DWORD,
2172 (LPBYTE)&lpService->dwTag,
2173 sizeof(DWORD));
2174 if (dwError != ERROR_SUCCESS)
2175 goto done;
2176
2177 *lpdwTagId = lpService->dwTag;
2178 }
2179
2180 /* Write dependencies */
2181 if (lpDependencies != NULL && *lpDependencies != 0)
2182 {
2183 dwError = ScmWriteDependencies(hServiceKey,
2184 (LPWSTR)lpDependencies,
2185 dwDependSize);
2186 if (dwError != ERROR_SUCCESS)
2187 goto done;
2188 }
2189
2190 /* Start name and password are only used by Win32 services */
2191 if (lpService->Status.dwServiceType & SERVICE_WIN32)
2192 {
2193 /* Write service start name */
2194 if (lpServiceStartName != NULL && *lpServiceStartName != 0)
2195 {
2196 dwError = RegSetValueExW(hServiceKey,
2197 L"ObjectName",
2198 0,
2199 REG_SZ,
2200 (LPBYTE)lpServiceStartName,
2201 (DWORD)((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR)));
2202 if (dwError != ERROR_SUCCESS)
2203 goto done;
2204 }
2205
2206 if (lpPassword != NULL)
2207 {
2208 if (*(LPWSTR)lpPassword != 0)
2209 {
2210 /* Decrypt the password */
2211 dwError = ScmDecryptPassword(hService,
2212 lpPassword,
2213 dwPwSize,
2214 &lpClearTextPassword);
2215 if (dwError != ERROR_SUCCESS)
2216 {
2217 DPRINT1("ScmDecryptPassword failed (Error %lu)\n", dwError);
2218 goto done;
2219 }
2220 DPRINT1("Clear text password: %S\n", lpClearTextPassword);
2221
2222 /* Write the password */
2223 dwError = ScmSetServicePassword(lpService->szServiceName,
2224 lpClearTextPassword);
2225 if (dwError != ERROR_SUCCESS)
2226 {
2227 DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError);
2228 goto done;
2229 }
2230 }
2231 else
2232 {
2233 /* Delete the password */
2234 dwError = ScmSetServicePassword(lpService->szServiceName,
2235 NULL);
2236 if (dwError == ERROR_FILE_NOT_FOUND)
2237 dwError = ERROR_SUCCESS;
2238
2239 if (dwError != ERROR_SUCCESS)
2240 {
2241 DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError);
2242 goto done;
2243 }
2244 }
2245 }
2246 }
2247
2248done:
2249 if (lpClearTextPassword != NULL)
2250 {
2251 /* Wipe and release the password buffer */
2252 SecureZeroMemory(lpClearTextPassword,
2253 (wcslen(lpClearTextPassword) + 1) * sizeof(WCHAR));
2254 HeapFree(GetProcessHeap(), 0, lpClearTextPassword);
2255 }
2256
2257 if (hServiceKey != NULL)
2258 RegCloseKey(hServiceKey);
2259
2260 /* Unlock the service database */
2262
2263 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError);
2264
2265 return dwError;
2266}
2267
2268
2269/* Function 12 */
2270DWORD
2271WINAPI
2274 LPCWSTR lpServiceName,
2276 DWORD dwDesiredAccess,
2277 DWORD dwServiceType,
2278 DWORD dwStartType,
2279 DWORD dwErrorControl,
2280 LPCWSTR lpBinaryPathName,
2281 LPCWSTR lpLoadOrderGroup,
2282 LPDWORD lpdwTagId,
2283 LPBYTE lpDependencies,
2284 DWORD dwDependSize,
2285 LPCWSTR lpServiceStartName,
2286 LPBYTE lpPassword,
2287 DWORD dwPwSize,
2288 LPSC_RPC_HANDLE lpServiceHandle)
2289{
2290 PMANAGER_HANDLE hManager;
2291 DWORD dwError = ERROR_SUCCESS;
2292 PSERVICE lpService = NULL;
2293 SC_HANDLE hServiceHandle = NULL;
2294 LPWSTR lpImagePath = NULL;
2295 LPWSTR lpClearTextPassword = NULL;
2296 HKEY hServiceKey = NULL;
2297 LPWSTR lpObjectName;
2298
2299 DPRINT("RCreateServiceW() called\n");
2300 DPRINT("lpServiceName = %S\n", lpServiceName);
2301 DPRINT("lpDisplayName = %S\n", lpDisplayName);
2302 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
2303 DPRINT("dwServiceType = 0x%lx\n", dwServiceType);
2304 DPRINT("dwStartType = %lu\n", dwStartType);
2305 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
2306 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
2307 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
2308 DPRINT("lpdwTagId = %p\n", lpdwTagId);
2309
2310 if (ScmShutdown)
2312
2314 if (hManager == NULL)
2315 {
2316 DPRINT1("Invalid service manager handle\n");
2317 return ERROR_INVALID_HANDLE;
2318 }
2319
2320 /* Check access rights */
2323 {
2324 DPRINT("Insufficient access rights! 0x%lx\n",
2325 hManager->Handle.DesiredAccess);
2326 return ERROR_ACCESS_DENIED;
2327 }
2328
2329 if (*lpServiceName == 0)
2330 return ERROR_INVALID_NAME;
2331
2332 if (*lpBinaryPathName == 0)
2334
2335 /* Check for invalid service type value */
2336 if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
2337 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) &&
2340 {
2342 }
2343
2344 /* Check for invalid start type value */
2345 if ((dwStartType != SERVICE_BOOT_START) &&
2346 (dwStartType != SERVICE_SYSTEM_START) &&
2347 (dwStartType != SERVICE_AUTO_START) &&
2348 (dwStartType != SERVICE_DEMAND_START) &&
2349 (dwStartType != SERVICE_DISABLED))
2350 {
2352 }
2353
2354 /* Only drivers can be boot start or system start services */
2355 if ((dwStartType == SERVICE_BOOT_START) ||
2356 (dwStartType == SERVICE_SYSTEM_START))
2357 {
2358 if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
2359 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
2360 {
2362 }
2363 }
2364
2365 /* Check for invalid error control value */
2366 if ((dwErrorControl != SERVICE_ERROR_IGNORE) &&
2367 (dwErrorControl != SERVICE_ERROR_NORMAL) &&
2368 (dwErrorControl != SERVICE_ERROR_SEVERE) &&
2369 (dwErrorControl != SERVICE_ERROR_CRITICAL))
2370 {
2372 }
2373
2374 if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
2375 (lpServiceStartName))
2376 {
2377 /* We allow LocalSystem to run interactive. */
2378 if (wcsicmp(lpServiceStartName, L"LocalSystem"))
2379 {
2381 }
2382 }
2383
2384 if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup))
2385 {
2387 }
2388
2389 /* Lock the service database exclusively */
2391
2392 lpService = ScmGetServiceEntryByName(lpServiceName);
2393 if (lpService)
2394 {
2395 /* Unlock the service database */
2397
2398 /* Check if it is marked for deletion */
2399 if (lpService->bDeleted)
2401
2402 /* Return service-exists error */
2403 return ERROR_SERVICE_EXISTS;
2404 }
2405
2406 if (lpDisplayName != NULL &&
2408 {
2409 /* Unlock the service database */
2411
2413 }
2414
2415 if (dwServiceType & SERVICE_DRIVER)
2416 {
2417 dwError = ScmCanonDriverImagePath(dwStartType,
2418 lpBinaryPathName,
2419 &lpImagePath);
2420 if (dwError != ERROR_SUCCESS)
2421 goto done;
2422 }
2423 else
2424 {
2425 if (dwStartType == SERVICE_BOOT_START ||
2426 dwStartType == SERVICE_SYSTEM_START)
2427 {
2428 /* Unlock the service database */
2430
2432 }
2433 }
2434
2435 /* Allocate a new service entry */
2436 dwError = ScmCreateNewServiceRecord(lpServiceName,
2437 &lpService,
2438 dwServiceType,
2439 dwStartType);
2440 if (dwError != ERROR_SUCCESS)
2441 goto done;
2442
2443 /* Fill the new service entry */
2444 lpService->dwErrorControl = dwErrorControl;
2445
2446 /* Fill the display name */
2447 if (lpDisplayName != NULL &&
2448 *lpDisplayName != 0 &&
2449 _wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
2450 {
2451 lpService->lpDisplayName = HeapAlloc(GetProcessHeap(),
2453 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
2454 if (lpService->lpDisplayName == NULL)
2455 {
2456 dwError = ERROR_NOT_ENOUGH_MEMORY;
2457 goto done;
2458 }
2459 wcscpy(lpService->lpDisplayName, lpDisplayName);
2460 }
2461
2462 /* Assign the service to a group */
2463 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
2464 {
2465 dwError = ScmSetServiceGroup(lpService,
2466 lpLoadOrderGroup);
2467 if (dwError != ERROR_SUCCESS)
2468 goto done;
2469 }
2470
2471 /* Assign a new tag */
2472 if (lpdwTagId != NULL)
2473 {
2474 dwError = ScmAssignNewTag(lpService);
2475 if (dwError != ERROR_SUCCESS)
2476 goto done;
2477 }
2478
2479 /* Assign the default security descriptor */
2480 if (dwServiceType & SERVICE_WIN32)
2481 {
2482 dwError = ScmCreateDefaultServiceSD(&lpService->pSecurityDescriptor);
2483 if (dwError != ERROR_SUCCESS)
2484 goto done;
2485 }
2486
2487 /* Write service data to the registry */
2488 /* Create the service key */
2489 dwError = ScmCreateServiceKey(lpServiceName,
2490 KEY_WRITE,
2491 &hServiceKey);
2492 if (dwError != ERROR_SUCCESS)
2493 goto done;
2494
2495 /* Set the display name */
2496 if (lpDisplayName != NULL && *lpDisplayName != 0)
2497 {
2498 RegSetValueExW(hServiceKey,
2499 L"DisplayName",
2500 0,
2501 REG_SZ,
2503 (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR)));
2504 }
2505
2506 /* Set the service type */
2507 dwError = RegSetValueExW(hServiceKey,
2508 L"Type",
2509 0,
2510 REG_DWORD,
2511 (LPBYTE)&dwServiceType,
2512 sizeof(DWORD));
2513 if (dwError != ERROR_SUCCESS)
2514 goto done;
2515
2516 /* Set the start value */
2517 dwError = RegSetValueExW(hServiceKey,
2518 L"Start",
2519 0,
2520 REG_DWORD,
2521 (LPBYTE)&dwStartType,
2522 sizeof(DWORD));
2523 if (dwError != ERROR_SUCCESS)
2524 goto done;
2525
2526 /* Set the error control value */
2527 dwError = RegSetValueExW(hServiceKey,
2528 L"ErrorControl",
2529 0,
2530 REG_DWORD,
2531 (LPBYTE)&dwErrorControl,
2532 sizeof(DWORD));
2533 if (dwError != ERROR_SUCCESS)
2534 goto done;
2535
2536 /* Set the image path */
2537 if (dwServiceType & SERVICE_WIN32)
2538 {
2539 dwError = RegSetValueExW(hServiceKey,
2540 L"ImagePath",
2541 0,
2543 (LPBYTE)lpBinaryPathName,
2544 (DWORD)((wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR)));
2545 if (dwError != ERROR_SUCCESS)
2546 goto done;
2547 }
2548 else if (dwServiceType & SERVICE_DRIVER)
2549 {
2550 dwError = RegSetValueExW(hServiceKey,
2551 L"ImagePath",
2552 0,
2554 (LPBYTE)lpImagePath,
2555 (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR)));
2556 if (dwError != ERROR_SUCCESS)
2557 goto done;
2558 }
2559
2560 /* Set the group name */
2561 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
2562 {
2563 dwError = RegSetValueExW(hServiceKey,
2564 L"Group",
2565 0,
2566 REG_SZ,
2567 (LPBYTE)lpLoadOrderGroup,
2568 (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)));
2569 if (dwError != ERROR_SUCCESS)
2570 goto done;
2571 }
2572
2573 /* Set the service tag */
2574 if (lpdwTagId != NULL)
2575 {
2576 dwError = RegSetValueExW(hServiceKey,
2577 L"Tag",
2578 0,
2579 REG_DWORD,
2580 (LPBYTE)&lpService->dwTag,
2581 sizeof(DWORD));
2582 if (dwError != ERROR_SUCCESS)
2583 goto done;
2584 }
2585
2586 /* Write dependencies */
2587 if (lpDependencies != NULL && *lpDependencies != 0)
2588 {
2589 dwError = ScmWriteDependencies(hServiceKey,
2590 (LPCWSTR)lpDependencies,
2591 dwDependSize);
2592 if (dwError != ERROR_SUCCESS)
2593 goto done;
2594 }
2595
2596 /* Start name and password are only used by Win32 services */
2597 if (dwServiceType & SERVICE_WIN32)
2598 {
2599 /* Write service start name */
2600 lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem";
2601 dwError = RegSetValueExW(hServiceKey,
2602 L"ObjectName",
2603 0,
2604 REG_SZ,
2605 (LPBYTE)lpObjectName,
2606 (DWORD)((wcslen(lpObjectName) + 1) * sizeof(WCHAR)));
2607 if (dwError != ERROR_SUCCESS)
2608 goto done;
2609
2610 if (lpPassword != NULL && *(LPWSTR)lpPassword != 0)
2611 {
2612 /* Decrypt the password */
2614 lpPassword,
2615 dwPwSize,
2616 &lpClearTextPassword);
2617 if (dwError != ERROR_SUCCESS)
2618 goto done;
2619
2620 /* Write the password */
2621 dwError = ScmSetServicePassword(lpServiceName,
2622 lpClearTextPassword);
2623 if (dwError != ERROR_SUCCESS)
2624 goto done;
2625 }
2626
2627 /* Write the security descriptor */
2628 dwError = ScmWriteSecurityDescriptor(hServiceKey,
2629 lpService->pSecurityDescriptor);
2630 if (dwError != ERROR_SUCCESS)
2631 goto done;
2632 }
2633
2634 dwError = ScmCreateServiceHandle(lpService,
2635 &hServiceHandle);
2636 if (dwError != ERROR_SUCCESS)
2637 goto done;
2638
2639 dwError = ScmCheckAccess(hServiceHandle,
2640 dwDesiredAccess);
2641 if (dwError != ERROR_SUCCESS)
2642 goto done;
2643
2644 lpService->dwRefCount = 1;
2645
2646 /* Get the service tag (if Win32) */
2647 ScmGenerateServiceTag(lpService);
2648
2649 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount);
2650
2651done:
2652 /* Unlock the service database */
2654
2655 if (hServiceKey != NULL)
2656 RegCloseKey(hServiceKey);
2657
2658 if (lpClearTextPassword != NULL)
2659 {
2660 /* Wipe and release the password buffer */
2661 SecureZeroMemory(lpClearTextPassword,
2662 (wcslen(lpClearTextPassword) + 1) * sizeof(WCHAR));
2663 HeapFree(GetProcessHeap(), 0, lpClearTextPassword);
2664 }
2665
2666 if (dwError == ERROR_SUCCESS)
2667 {
2668 DPRINT("hService %p\n", hServiceHandle);
2669 *lpServiceHandle = (SC_RPC_HANDLE)hServiceHandle;
2670
2671 if (lpdwTagId != NULL)
2672 *lpdwTagId = lpService->dwTag;
2673 }
2674 else
2675 {
2676 if (lpService != NULL &&
2677 lpService->lpServiceName != NULL)
2678 {
2679 /* Release the display name buffer */
2680 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
2681 }
2682
2683 if (hServiceHandle)
2684 {
2685 /* Remove the service handle */
2686 HeapFree(GetProcessHeap(), 0, hServiceHandle);
2687 }
2688
2689 if (lpService != NULL)
2690 {
2691 /* FIXME: remove the service entry */
2692 }
2693 }
2694
2695 if (lpImagePath != NULL)
2696 HeapFree(GetProcessHeap(), 0, lpImagePath);
2697
2698 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError);
2699
2700 return dwError;
2701}
2702
2703
2704/* Function 13 */
2705DWORD
2706WINAPI
2708 SC_RPC_HANDLE hService,
2709 DWORD dwServiceState,
2710 LPBYTE lpServices,
2713 LPBOUNDED_DWORD_256K lpServicesReturned)
2714{
2715 DWORD dwError = ERROR_SUCCESS;
2716 DWORD dwServicesReturned = 0;
2717 DWORD dwServiceCount;
2719 PSERVICE_HANDLE hSvc;
2720 PSERVICE lpService = NULL;
2721 PSERVICE *lpServicesArray = NULL;
2722 LPENUM_SERVICE_STATUSW lpServicesPtr = NULL;
2723 LPWSTR lpStr;
2724
2725 *pcbBytesNeeded = 0;
2726 *lpServicesReturned = 0;
2727
2728 DPRINT("REnumDependentServicesW() called\n");
2729
2730 hSvc = ScmGetServiceFromHandle(hService);
2731 if (hSvc == NULL)
2732 {
2733 DPRINT1("Invalid service handle\n");
2734 return ERROR_INVALID_HANDLE;
2735 }
2736
2737 lpService = hSvc->ServiceEntry;
2738
2739 /* Check access rights */
2742 {
2743 DPRINT("Insufficient access rights! 0x%lx\n",
2744 hSvc->Handle.DesiredAccess);
2745 return ERROR_ACCESS_DENIED;
2746 }
2747
2748 /* Open the Services Reg key */
2750 L"System\\CurrentControlSet\\Services",
2751 0,
2752 KEY_READ,
2753 &hServicesKey);
2754 if (dwError != ERROR_SUCCESS)
2755 return dwError;
2756
2757 /* First determine the bytes needed and get the number of dependent services */
2759 lpService,
2760 dwServiceState,
2761 NULL,
2763 &dwServicesReturned);
2764 if (dwError != ERROR_SUCCESS)
2765 goto Done;
2766
2767 /* If buffer size is less than the bytes needed or pointer is null */
2768 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
2769 {
2770 dwError = ERROR_MORE_DATA;
2771 goto Done;
2772 }
2773
2774 /* Allocate memory for array of service pointers */
2775 lpServicesArray = HeapAlloc(GetProcessHeap(),
2777 (dwServicesReturned + 1) * sizeof(PSERVICE));
2778 if (!lpServicesArray)
2779 {
2780 DPRINT1("Could not allocate buffer\n");
2781 dwError = ERROR_NOT_ENOUGH_MEMORY;
2782 goto Done;
2783 }
2784
2785 dwServicesReturned = 0;
2786 *pcbBytesNeeded = 0;
2787
2789 lpService,
2790 dwServiceState,
2791 lpServicesArray,
2793 &dwServicesReturned);
2794 if (dwError != ERROR_SUCCESS)
2795 {
2796 goto Done;
2797 }
2798
2799 lpServicesPtr = (LPENUM_SERVICE_STATUSW)lpServices;
2800 lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW)));
2801
2802 /* Copy EnumDepenedentService to Buffer */
2803 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
2804 {
2805 lpService = lpServicesArray[dwServiceCount];
2806
2807 /* Copy status info */
2808 memcpy(&lpServicesPtr->ServiceStatus,
2809 &lpService->Status,
2810 sizeof(SERVICE_STATUS));
2811
2812 /* Copy display name */
2813 wcscpy(lpStr, lpService->lpDisplayName);
2814 lpServicesPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
2815 lpStr += (wcslen(lpService->lpDisplayName) + 1);
2816
2817 /* Copy service name */
2818 wcscpy(lpStr, lpService->lpServiceName);
2819 lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
2820 lpStr += (wcslen(lpService->lpServiceName) + 1);
2821
2822 lpServicesPtr++;
2823 }
2824
2825 *lpServicesReturned = dwServicesReturned;
2826
2827Done:
2828 if (lpServicesArray != NULL)
2829 HeapFree(GetProcessHeap(), 0, lpServicesArray);
2830
2832
2833 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError);
2834
2835 return dwError;
2836}
2837
2838
2839/* Function 14 */
2840DWORD
2841WINAPI
2844 DWORD dwServiceType,
2845 DWORD dwServiceState,
2847 DWORD dwBufSize,
2849 LPBOUNDED_DWORD_256K lpServicesReturned,
2850 LPBOUNDED_DWORD_256K lpResumeHandle)
2851{
2852 /* Enumerate all the services, not regarding of their group */
2854 dwServiceType,
2855 dwServiceState,
2856 lpBuffer,
2857 dwBufSize,
2859 lpServicesReturned,
2860 lpResumeHandle,
2861 NULL);
2862}
2863
2864
2865/* Function 15 */
2866DWORD
2867WINAPI
2869 LPWSTR lpMachineName,
2870 LPWSTR lpDatabaseName,
2871 DWORD dwDesiredAccess,
2872 LPSC_RPC_HANDLE lpScHandle)
2873{
2874 DWORD dwError;
2875 SC_HANDLE hHandle;
2876
2877 DPRINT("ROpenSCManagerW() called\n");
2878 DPRINT("lpMachineName = %p\n", lpMachineName);
2879 DPRINT("lpMachineName: %S\n", lpMachineName);
2880 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
2881 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
2882 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
2883
2884 if (ScmShutdown)
2886
2887 if (!lpScHandle)
2889
2890 dwError = ScmCreateManagerHandle(lpDatabaseName,
2891 &hHandle);
2892 if (dwError != ERROR_SUCCESS)
2893 {
2894 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
2895 return dwError;
2896 }
2897
2898 /* Check the desired access */
2899 dwError = ScmCheckAccess(hHandle,
2900 dwDesiredAccess | SC_MANAGER_CONNECT);
2901 if (dwError != ERROR_SUCCESS)
2902 {
2903 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError);
2904 HeapFree(GetProcessHeap(), 0, hHandle);
2905 return dwError;
2906 }
2907
2908 *lpScHandle = (SC_RPC_HANDLE)hHandle;
2909 DPRINT("*hScm = %p\n", *lpScHandle);
2910
2911 DPRINT("ROpenSCManagerW() done\n");
2912
2913 return ERROR_SUCCESS;
2914}
2915
2916
2917/* Function 16 */
2918DWORD
2919WINAPI
2922 LPWSTR lpServiceName,
2923 DWORD dwDesiredAccess,
2924 LPSC_RPC_HANDLE lpServiceHandle)
2925{
2926 PSERVICE lpService;
2927 PMANAGER_HANDLE hManager;
2928 SC_HANDLE hHandle;
2929 DWORD dwError = ERROR_SUCCESS;
2930
2931 DPRINT("ROpenServiceW() called\n");
2932 DPRINT("hSCManager = %p\n", hSCManager);
2933 DPRINT("lpServiceName = %p\n", lpServiceName);
2934 DPRINT("lpServiceName: %S\n", lpServiceName);
2935 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
2936
2937 if (ScmShutdown)
2939
2941 if (hManager == NULL)
2942 {
2943 DPRINT1("Invalid service manager handle\n");
2944 return ERROR_INVALID_HANDLE;
2945 }
2946
2947 if (!lpServiceHandle)
2949
2950 if (!lpServiceName)
2951 return ERROR_INVALID_ADDRESS;
2952
2953 /* Lock the service database exclusive */
2955
2956 /* Get service database entry */
2957 lpService = ScmGetServiceEntryByName(lpServiceName);
2958 if (lpService == NULL)
2959 {
2960 DPRINT("Could not find service\n");
2962 goto Done;
2963 }
2964
2965 /* Create a service handle */
2966 dwError = ScmCreateServiceHandle(lpService,
2967 &hHandle);
2968 if (dwError != ERROR_SUCCESS)
2969 {
2970 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
2971 goto Done;
2972 }
2973
2974 /* Check the desired access */
2975 dwError = ScmCheckAccess(hHandle,
2976 dwDesiredAccess);
2977 if (dwError != ERROR_SUCCESS)
2978 {
2979 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError);
2980 HeapFree(GetProcessHeap(), 0, hHandle);
2981 goto Done;
2982 }
2983
2984 lpService->dwRefCount++;
2985 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService->dwRefCount);
2986
2987 *lpServiceHandle = (SC_RPC_HANDLE)hHandle;
2988 DPRINT("*hService = %p\n", *lpServiceHandle);
2989
2990Done:
2991 /* Unlock the service database */
2993
2994 DPRINT("ROpenServiceW() done\n");
2995
2996 return dwError;
2997}
2998
2999
3000/* Function 17 */
3001DWORD
3002WINAPI
3004 SC_RPC_HANDLE hService,
3005 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
3008{
3009 LPQUERY_SERVICE_CONFIGW lpServiceConfig = (LPQUERY_SERVICE_CONFIGW)lpBuf;
3010 DWORD dwError = ERROR_SUCCESS;
3011 PSERVICE_HANDLE hSvc;
3012 PSERVICE lpService = NULL;
3013 HKEY hServiceKey = NULL;
3014 LPWSTR lpImagePath = NULL;
3015 LPWSTR lpServiceStartName = NULL;
3016 LPWSTR lpDependencies = NULL;
3017 DWORD dwDependenciesLength = 0;
3018 DWORD dwRequiredSize;
3019 LPWSTR lpStr;
3020
3021 DPRINT("RQueryServiceConfigW() called\n");
3022
3023 if (ScmShutdown)
3025
3026 hSvc = ScmGetServiceFromHandle(hService);
3027 if (hSvc == NULL)
3028 {
3029 DPRINT1("Invalid service handle\n");
3030 return ERROR_INVALID_HANDLE;
3031 }
3032
3035 {
3036 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
3037 return ERROR_ACCESS_DENIED;
3038 }
3039
3040 lpService = hSvc->ServiceEntry;
3041 if (lpService == NULL)
3042 {
3043 DPRINT("lpService == NULL\n");
3044 return ERROR_INVALID_HANDLE;
3045 }
3046
3047 /* Lock the service database shared */
3049
3050 dwError = ScmOpenServiceKey(lpService->lpServiceName,
3051 KEY_READ,
3052 &hServiceKey);
3053 if (dwError != ERROR_SUCCESS)
3054 goto Done;
3055
3056 /* Read the image path */
3057 dwError = ScmReadString(hServiceKey,
3058 L"ImagePath",
3059 &lpImagePath);
3060 if (dwError != ERROR_SUCCESS)
3061 goto Done;
3062
3063 /* Read the service start name */
3064 ScmReadString(hServiceKey,
3065 L"ObjectName",
3066 &lpServiceStartName);
3067
3068 /* Read the dependencies */
3069 ScmReadDependencies(hServiceKey,
3070 &lpDependencies,
3071 &dwDependenciesLength);
3072
3073 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
3074
3075 if (lpImagePath != NULL)
3076 dwRequiredSize += (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
3077 else
3078 dwRequiredSize += 2 * sizeof(WCHAR);
3079
3080 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
3081 dwRequiredSize += (DWORD)((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
3082 else
3083 dwRequiredSize += 2 * sizeof(WCHAR);
3084
3085 if (lpDependencies != NULL)
3086 dwRequiredSize += dwDependenciesLength * sizeof(WCHAR);
3087 else
3088 dwRequiredSize += 2 * sizeof(WCHAR);
3089
3090 if (lpServiceStartName != NULL)
3091 dwRequiredSize += (DWORD)((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
3092 else
3093 dwRequiredSize += 2 * sizeof(WCHAR);
3094
3095 if (lpService->lpDisplayName != NULL)
3096 dwRequiredSize += (DWORD)((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
3097 else
3098 dwRequiredSize += 2 * sizeof(WCHAR);
3099
3100 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
3101 {
3102 dwError = ERROR_INSUFFICIENT_BUFFER;
3103 }
3104 else
3105 {
3106 lpServiceConfig->dwServiceType = lpService->Status.dwServiceType;
3107 lpServiceConfig->dwStartType = lpService->dwStartType;
3108 lpServiceConfig->dwErrorControl = lpService->dwErrorControl;
3109 lpServiceConfig->dwTagId = lpService->dwTag;
3110
3111 lpStr = (LPWSTR)(lpServiceConfig + 1);
3112
3113 /* Append the image path */
3114 if (lpImagePath != NULL)
3115 {
3116 wcscpy(lpStr, lpImagePath);
3117 }
3118 else
3119 {
3120 *lpStr = 0;
3121 }
3122
3123 lpServiceConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3124 lpStr += (wcslen(lpStr) + 1);
3125
3126 /* Append the group name */
3127 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
3128 {
3129 wcscpy(lpStr, lpService->lpGroup->lpGroupName);
3130 }
3131 else
3132 {
3133 *lpStr = 0;
3134 }
3135
3136 lpServiceConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3137 lpStr += (wcslen(lpStr) + 1);
3138
3139 /* Append Dependencies */
3140 if (lpDependencies != NULL)
3141 {
3142 memcpy(lpStr,
3143 lpDependencies,
3144 dwDependenciesLength * sizeof(WCHAR));
3145 }
3146 else
3147 {
3148 *lpStr = 0;
3149 }
3150
3151 lpServiceConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3152 if (lpDependencies != NULL)
3153 lpStr += dwDependenciesLength;
3154 else
3155 lpStr += (wcslen(lpStr) + 1);
3156
3157 /* Append the service start name */
3158 if (lpServiceStartName != NULL)
3159 {
3160 wcscpy(lpStr, lpServiceStartName);
3161 }
3162 else
3163 {
3164 *lpStr = 0;
3165 }
3166
3167 lpServiceConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3168 lpStr += (wcslen(lpStr) + 1);
3169
3170 /* Append the display name */
3171 if (lpService->lpDisplayName != NULL)
3172 {
3173 wcscpy(lpStr, lpService->lpDisplayName);
3174 }
3175 else
3176 {
3177 *lpStr = 0;
3178 }
3179
3180 lpServiceConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
3181 }
3182
3183 if (pcbBytesNeeded != NULL)
3184 *pcbBytesNeeded = dwRequiredSize;
3185
3186Done:
3187 /* Unlock the service database */
3189
3190 if (lpImagePath != NULL)
3191 HeapFree(GetProcessHeap(), 0, lpImagePath);
3192
3193 if (lpServiceStartName != NULL)
3194 HeapFree(GetProcessHeap(), 0, lpServiceStartName);
3195
3196 if (lpDependencies != NULL)
3197 HeapFree(GetProcessHeap(), 0, lpDependencies);
3198
3199 if (hServiceKey != NULL)
3200 RegCloseKey(hServiceKey);
3201
3202 DPRINT("RQueryServiceConfigW() done\n");
3203
3204 return dwError;
3205}
3206
3207
3208/* Function 18 */
3209DWORD
3210WINAPI
3213 LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
3216{
3218 PMANAGER_HANDLE hMgr;
3219 DWORD dwRequiredSize;
3220
3221 if (!lpLockStatus || !pcbBytesNeeded)
3223
3225 if (hMgr == NULL)
3226 {
3227 DPRINT1("Invalid service manager handle\n");
3228 return ERROR_INVALID_HANDLE;
3229 }
3230
3233 {
3234 DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess);
3235 return ERROR_ACCESS_DENIED;
3236 }
3237
3238 /* FIXME: we need to compute instead the real length of the owner name */
3239 dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSW) + sizeof(WCHAR);
3240 *pcbBytesNeeded = dwRequiredSize;
3241
3242 if (cbBufSize < dwRequiredSize)
3244
3245 ScmQueryServiceLockStatusW(lpLockStatus);
3246
3247 return ERROR_SUCCESS;
3248}
3249
3250
3251/* Function 19 */
3252DWORD
3253WINAPI
3255 SC_RPC_HANDLE hService,
3256 DWORD argc,
3258{
3259 DWORD dwError = ERROR_SUCCESS;
3260 PSERVICE_HANDLE hSvc;
3261 PSERVICE lpService = NULL;
3262
3263#ifndef NDEBUG
3264 DWORD i;
3265
3266 DPRINT("RStartServiceW(%p %lu %p) called\n", hService, argc, argv);
3267 DPRINT(" argc: %lu\n", argc);
3268 if (argv != NULL)
3269 {
3270 for (i = 0; i < argc; i++)
3271 {
3272 DPRINT(" argv[%lu]: %S\n", i, argv[i].StringPtr);
3273 }
3274 }
3275#endif
3276
3277 if (ScmShutdown)
3279
3280 hSvc = ScmGetServiceFromHandle(hService);
3281 if (hSvc == NULL)
3282 {
3283 DPRINT1("Invalid service handle\n");
3284 return ERROR_INVALID_HANDLE;
3285 }
3286
3289 {
3290 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
3291 return ERROR_ACCESS_DENIED;
3292 }
3293
3294 lpService = hSvc->ServiceEntry;
3295 if (lpService == NULL)
3296 {
3297 DPRINT("lpService == NULL\n");
3298 return ERROR_INVALID_HANDLE;
3299 }
3300
3301 if (lpService->dwStartType == SERVICE_DISABLED)
3303
3304 if (lpService->bDeleted)
3306
3307 /* Start the service */
3308 dwError = ScmStartService(lpService, argc, (LPWSTR*)argv);
3309
3310 return dwError;
3311}
3312
3313
3314/* Function 20 */
3315DWORD
3316WINAPI
3319 LPCWSTR lpServiceName,
3321 DWORD *lpcchBuffer)
3322{
3323 // PMANAGER_HANDLE hManager;
3324 PSERVICE lpService;
3325 LPCWSTR lpSvcDisplayName;
3327 DWORD dwError;
3328
3329 DPRINT("RGetServiceDisplayNameW() called\n");
3330 DPRINT("hSCManager = %p\n", hSCManager);
3331 DPRINT("lpServiceName: %S\n", lpServiceName);
3332 DPRINT("lpDisplayName: %p\n", lpDisplayName);
3333 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
3334
3335#if 0
3336 hManager = (PMANAGER_HANDLE)hSCManager;
3337 if (hManager->Handle.Tag != MANAGER_TAG)
3338 {
3339 DPRINT("Invalid manager handle\n");
3340 return ERROR_INVALID_HANDLE;
3341 }
3342#endif
3343
3344 /* Get service database entry */
3345 lpService = ScmGetServiceEntryByName(lpServiceName);
3346 if (lpService == NULL)
3347 {
3348 DPRINT("Could not find service\n");
3350 }
3351
3352 if (lpService->lpDisplayName)
3353 lpSvcDisplayName = lpService->lpDisplayName;
3354 else
3355 lpSvcDisplayName = lpService->lpServiceName;
3356
3357 dwLength = (DWORD)wcslen(lpSvcDisplayName);
3358
3359 if (*lpcchBuffer > dwLength)
3360 {
3361 if (lpDisplayName != NULL)
3362 wcscpy(lpDisplayName, lpSvcDisplayName);
3363
3364 dwError = ERROR_SUCCESS;
3365 }
3366 else
3367 {
3368 dwError = ERROR_INSUFFICIENT_BUFFER;
3369 }
3370
3371 *lpcchBuffer = dwLength;
3372
3373 return dwError;
3374}
3375
3376
3377/* Function 21 */
3378DWORD
3379WINAPI
3383 LPWSTR lpServiceName,
3384 DWORD *lpcchBuffer)
3385{
3386 // PMANAGER_HANDLE hManager;
3387 PSERVICE lpService;
3389 DWORD dwError;
3390
3391 DPRINT("RGetServiceKeyNameW() called\n");
3392 DPRINT("hSCManager = %p\n", hSCManager);
3393 DPRINT("lpDisplayName: %S\n", lpDisplayName);
3394 DPRINT("lpServiceName: %p\n", lpServiceName);
3395 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
3396
3397#if 0
3398 hManager = (PMANAGER_HANDLE)hSCManager;
3399 if (hManager->Handle.Tag != MANAGER_TAG)
3400 {
3401 DPRINT("Invalid manager handle\n");
3402 return ERROR_INVALID_HANDLE;
3403 }
3404#endif
3405
3406 /* Get service database entry */
3408 if (lpService == NULL)
3409 {
3410 DPRINT("Could not find service\n");
3412 }
3413
3414 dwLength = (DWORD)wcslen(lpService->lpServiceName);
3415
3416 if (*lpcchBuffer > dwLength)
3417 {
3418 if (lpServiceName != NULL)
3419 wcscpy(lpServiceName, lpService->lpServiceName);
3420
3421 dwError = ERROR_SUCCESS;
3422 }
3423 else
3424 {
3425 dwError = ERROR_INSUFFICIENT_BUFFER;
3426 }
3427
3428 *lpcchBuffer = dwLength;
3429
3430 return dwError;
3431}
3432
3433
3434/* Function 22 */
3435DWORD
3436WINAPI
3440 int bSetBitsOn,
3441 int bUpdateImmediately,
3442 char *lpString)
3443{
3444 if (ScmShutdown)
3446
3447 if (lpString != NULL)
3449
3452 bSetBitsOn,
3453 bUpdateImmediately,
3454 NULL);
3455}
3456
3457
3458/* Function 23 */
3459DWORD
3460WINAPI
3462 SC_RPC_HANDLE hService,
3463 DWORD dwServiceType,
3464 DWORD dwStartType,
3465 DWORD dwErrorControl,
3466 LPSTR lpBinaryPathName,
3467 LPSTR lpLoadOrderGroup,
3468 LPDWORD lpdwTagId,
3469 LPBYTE lpDependencies,
3470 DWORD dwDependSize,
3471 LPSTR lpServiceStartName,
3472 LPBYTE lpPassword,
3473 DWORD dwPwSize,
3475{
3476 DWORD dwError = ERROR_SUCCESS;
3477 LPWSTR lpBinaryPathNameW = NULL;
3478 LPWSTR lpLoadOrderGroupW = NULL;
3479 LPWSTR lpDependenciesW = NULL;
3480 LPWSTR lpServiceStartNameW = NULL;
3481 LPWSTR lpDisplayNameW = NULL;
3482 DWORD dwDependenciesLength = 0;
3483 SIZE_T cchLength;
3484 int len;
3485 LPCSTR lpStr;
3486
3487 if (lpBinaryPathName)
3488 {
3489 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
3490 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3491 if (!lpBinaryPathNameW)
3492 {
3494 goto cleanup;
3495 }
3496 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
3497 }
3498
3499 if (lpLoadOrderGroup)
3500 {
3501 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
3502 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3503 if (!lpLoadOrderGroupW)
3504 {
3506 goto cleanup;
3507 }
3508 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
3509 }
3510
3511 if (lpDependencies)
3512 {
3513 lpStr = (LPCSTR)lpDependencies;
3514 while (*lpStr)
3515 {
3516 cchLength = strlen(lpStr) + 1;
3517 dwDependenciesLength += (DWORD)cchLength;
3518 lpStr = lpStr + cchLength;
3519 }
3520 dwDependenciesLength++;
3521
3522 lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR));
3523 if (!lpDependenciesW)
3524 {
3526 goto cleanup;
3527 }
3528 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
3529 }
3530
3531 if (lpServiceStartName)
3532 {
3533 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
3534 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3535 if (!lpServiceStartNameW)
3536 {
3538 goto cleanup;
3539 }
3540 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
3541 }
3542
3543 if (lpDisplayName)
3544 {
3546 lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3547 if (!lpDisplayNameW)
3548 {
3550 goto cleanup;
3551 }
3552 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
3553 }
3554
3555 dwError = RChangeServiceConfigW(hService,
3556 dwServiceType,
3557 dwStartType,
3558 dwErrorControl,
3559 lpBinaryPathNameW,
3560 lpLoadOrderGroupW,
3561 lpdwTagId,
3562 (LPBYTE)lpDependenciesW,
3563 dwDependenciesLength,
3564 lpServiceStartNameW,
3565 lpPassword,
3566 dwPwSize,
3567 lpDisplayNameW);
3568
3569cleanup:
3570 if (lpBinaryPathNameW != NULL)
3571 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
3572
3573 if (lpLoadOrderGroupW != NULL)
3574 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
3575
3576 if (lpDependenciesW != NULL)
3577 HeapFree(GetProcessHeap(), 0, lpDependenciesW);
3578
3579 if (lpServiceStartNameW != NULL)
3580 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
3581
3582 if (lpDisplayNameW != NULL)
3583 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
3584
3585 return dwError;
3586}
3587
3588
3589/* Function 24 */
3590DWORD
3591WINAPI
3594 LPSTR lpServiceName,
3596 DWORD dwDesiredAccess,
3597 DWORD dwServiceType,
3598 DWORD dwStartType,
3599 DWORD dwErrorControl,
3600 LPSTR lpBinaryPathName,
3601 LPSTR lpLoadOrderGroup,
3602 LPDWORD lpdwTagId,
3603 LPBYTE lpDependencies,
3604 DWORD dwDependSize,
3605 LPSTR lpServiceStartName,
3606 LPBYTE lpPassword,
3607 DWORD dwPwSize,
3608 LPSC_RPC_HANDLE lpServiceHandle)
3609{
3610 DWORD dwError = ERROR_SUCCESS;
3611 LPWSTR lpServiceNameW = NULL;
3612 LPWSTR lpDisplayNameW = NULL;
3613 LPWSTR lpBinaryPathNameW = NULL;
3614 LPWSTR lpLoadOrderGroupW = NULL;
3615 LPWSTR lpDependenciesW = NULL;
3616 LPWSTR lpServiceStartNameW = NULL;
3617 DWORD dwDependenciesLength = 0;
3618 SIZE_T cchLength;
3619 int len;
3620 LPCSTR lpStr;
3621
3622 if (lpServiceName)
3623 {
3624 len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
3625 lpServiceNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3626 if (!lpServiceNameW)
3627 {
3629 goto cleanup;
3630 }
3631 MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len);
3632 }
3633
3634 if (lpDisplayName)
3635 {
3637 lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3638 if (!lpDisplayNameW)
3639 {
3641 goto cleanup;
3642 }
3643 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
3644 }
3645
3646 if (lpBinaryPathName)
3647 {
3648 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
3649 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3650 if (!lpBinaryPathNameW)
3651 {
3653 goto cleanup;
3654 }
3655 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
3656 }
3657
3658 if (lpLoadOrderGroup)
3659 {
3660 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
3661 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3662 if (!lpLoadOrderGroupW)
3663 {
3665 goto cleanup;
3666 }
3667 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
3668 }
3669
3670 if (lpDependencies)
3671 {
3672 lpStr = (LPCSTR)lpDependencies;
3673 while (*lpStr)
3674 {
3675 cchLength = strlen(lpStr) + 1;
3676 dwDependenciesLength += (DWORD)cchLength;
3677 lpStr = lpStr + cchLength;
3678 }
3679 dwDependenciesLength++;
3680
3681 lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR));
3682 if (!lpDependenciesW)
3683 {
3685 goto cleanup;
3686 }
3687 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
3688 }
3689
3690 if (lpServiceStartName)
3691 {
3692 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
3693 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
3694 if (!lpServiceStartNameW)
3695 {
3697 goto cleanup;
3698 }
3699 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
3700 }
3701
3702 dwError = RCreateServiceW(hSCManager,
3703 lpServiceNameW,
3704 lpDisplayNameW,
3705 dwDesiredAccess,
3706 dwServiceType,
3707 dwStartType,
3708 dwErrorControl,
3709 lpBinaryPathNameW,
3710 lpLoadOrderGroupW,
3711 lpdwTagId,
3712 (LPBYTE)lpDependenciesW,
3713 dwDependenciesLength,
3714 lpServiceStartNameW,
3715 lpPassword,
3716 dwPwSize,
3717 lpServiceHandle);
3718
3719cleanup:
3720 if (lpServiceNameW !=NULL)
3721 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
3722
3723 if (lpDisplayNameW != NULL)
3724 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
3725
3726 if (lpBinaryPathNameW != NULL)
3727 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
3728
3729 if (lpLoadOrderGroupW != NULL)
3730 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
3731
3732 if (lpDependenciesW != NULL)
3733 HeapFree(GetProcessHeap(), 0, lpDependenciesW);
3734
3735 if (lpServiceStartNameW != NULL)
3736 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
3737
3738 return dwError;
3739}
3740
3741
3742/* Function 25 */
3743DWORD
3744WINAPI
3746 SC_RPC_HANDLE hService,
3747 DWORD dwServiceState,
3748 LPBYTE lpServices,
3751 LPBOUNDED_DWORD_256K lpServicesReturned)
3752{
3753 DWORD dwError = ERROR_SUCCESS;
3754 DWORD dwServicesReturned = 0;
3755 DWORD dwServiceCount;
3757 PSERVICE_HANDLE hSvc;
3758 PSERVICE lpService = NULL;
3759 PSERVICE *lpServicesArray = NULL;
3760 LPENUM_SERVICE_STATUSA lpServicesPtr = NULL;
3761 LPSTR lpStr;
3762
3763 *pcbBytesNeeded = 0;
3764 *lpServicesReturned = 0;
3765
3766 DPRINT("REnumDependentServicesA() called\n");
3767
3768 hSvc = ScmGetServiceFromHandle(hService);
3769 if (hSvc == NULL)
3770 {
3771 DPRINT1("Invalid service handle\n");
3772 return ERROR_INVALID_HANDLE;
3773 }
3774
3775 lpService = hSvc->ServiceEntry;
3776
3777 /* Check access rights */
3780 {
3781 DPRINT("Insufficient access rights! 0x%lx\n",
3782 hSvc->Handle.DesiredAccess);
3783 return ERROR_ACCESS_DENIED;
3784 }
3785
3786 /* Open the Services Reg key */
3788 L"System\\CurrentControlSet\\Services",
3789 0,
3790 KEY_READ,
3791 &hServicesKey);
3792
3793 if (dwError != ERROR_SUCCESS)
3794 return dwError;
3795
3796 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3797 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3798 are the same for both. Verified in WINXP. */
3799
3800 /* First determine the bytes needed and get the number of dependent services*/
3802 lpService,
3803 dwServiceState,
3804 NULL,
3806 &dwServicesReturned);
3807 if (dwError != ERROR_SUCCESS)
3808 goto Done;
3809
3810 /* If buffer size is less than the bytes needed or pointer is null*/
3811 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
3812 {
3813 dwError = ERROR_MORE_DATA;
3814 goto Done;
3815 }
3816
3817 /* Allocate memory for array of service pointers */
3818 lpServicesArray = HeapAlloc(GetProcessHeap(),
3820 (dwServicesReturned + 1) * sizeof(PSERVICE));
3821 if (!lpServicesArray)
3822 {
3823 DPRINT("Could not allocate buffer\n");
3824 dwError = ERROR_NOT_ENOUGH_MEMORY;
3825 goto Done;
3826 }
3827
3828 dwServicesReturned = 0;
3829 *pcbBytesNeeded = 0;
3830
3832 lpService,
3833 dwServiceState,
3834 lpServicesArray,
3836 &dwServicesReturned);
3837 if (dwError != ERROR_SUCCESS)
3838 {
3839 goto Done;
3840 }
3841
3842 lpServicesPtr = (LPENUM_SERVICE_STATUSA)lpServices;
3843 lpStr = (LPSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSA)));
3844
3845 /* Copy EnumDepenedentService to Buffer */
3846 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
3847 {
3848 lpService = lpServicesArray[dwServiceCount];
3849
3850 /* Copy the status info */
3851 memcpy(&lpServicesPtr->ServiceStatus,
3852 &lpService->Status,
3853 sizeof(SERVICE_STATUS));
3854
3855 /* Copy display name */
3857 0,
3858 lpService->lpDisplayName,
3859 -1,
3860 lpStr,
3861 (int)wcslen(lpService->lpDisplayName),
3862 0,
3863 0);
3864 lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
3865 lpStr += strlen(lpStr) + 1;
3866
3867 /* Copy service name */
3869 0,
3870 lpService->lpServiceName,
3871 -1,
3872 lpStr,
3873 (int)wcslen(lpService->lpServiceName),
3874 0,
3875 0);
3876 lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
3877 lpStr += strlen(lpStr) + 1;
3878
3879 lpServicesPtr++;
3880 }
3881
3882 *lpServicesReturned = dwServicesReturned;
3883
3884Done:
3885 if (lpServicesArray)
3886 HeapFree(GetProcessHeap(), 0, lpServicesArray);
3887
3889
3890 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError);
3891
3892 return dwError;
3893}
3894
3895
3896/* Function 26 */
3897DWORD
3898WINAPI
3901 DWORD dwServiceType,
3902 DWORD dwServiceState,
3904 DWORD dwBufSize,
3906 LPBOUNDED_DWORD_256K lpServicesReturned,
3907 LPBOUNDED_DWORD_256K lpResumeHandle)
3908{
3909 LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL;
3910 LPENUM_SERVICE_STATUSW lpStatusPtrIncrW;
3911 LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL;
3912 LPWSTR lpStringPtrW;
3913 LPSTR lpStringPtrA;
3914 DWORD dwError;
3915 DWORD dwServiceCount;
3916
3917 DPRINT("REnumServicesStatusA() called\n");
3918
3919 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
3920 {
3921 return ERROR_INVALID_ADDRESS;
3922 }
3923
3924 if ((dwBufSize > 0) && (lpBuffer))
3925 {
3926 lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize);
3927 if (!lpStatusPtrW)
3928 {
3929 DPRINT("Failed to allocate buffer\n");
3931 }
3932 }
3933
3935 dwServiceType,
3936 dwServiceState,
3937 (LPBYTE)lpStatusPtrW,
3938 dwBufSize,
3940 lpServicesReturned,
3941 lpResumeHandle);
3942
3943 /* if no services were returned then we are Done */
3944 if (*lpServicesReturned == 0)
3945 goto Done;
3946
3947 lpStatusPtrIncrW = lpStatusPtrW;
3948 lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer;
3949 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
3950 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA));
3951 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW +
3952 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW));
3953
3954 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
3955 {
3956 /* Copy the service name */
3958 0,
3959 lpStringPtrW,
3960 -1,
3961 lpStringPtrA,
3962 (int)wcslen(lpStringPtrW),
3963 0,
3964 0);
3965
3966 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
3967 lpStringPtrA += wcslen(lpStringPtrW) + 1;
3968 lpStringPtrW += wcslen(lpStringPtrW) + 1;
3969
3970 /* Copy the display name */
3972 0,
3973 lpStringPtrW,
3974 -1,
3975 lpStringPtrA,
3976 (int)wcslen(lpStringPtrW),
3977 0,
3978 0);
3979
3980 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
3981 lpStringPtrA += wcslen(lpStringPtrW) + 1;
3982 lpStringPtrW += wcslen(lpStringPtrW) + 1;
3983
3984 /* Copy the status information */
3985 memcpy(&lpStatusPtrA->ServiceStatus,
3986 &lpStatusPtrIncrW->ServiceStatus,
3987 sizeof(SERVICE_STATUS));
3988
3989 lpStatusPtrIncrW++;
3990 lpStatusPtrA++;
3991 }
3992
3993Done:
3994 if (lpStatusPtrW)
3995 HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
3996
3997 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError);
3998
3999 return dwError;
4000}
4001
4002
4003/* Function 27 */
4004DWORD
4005WINAPI
4007 LPSTR lpMachineName,
4008 LPSTR lpDatabaseName,
4009 DWORD dwDesiredAccess,
4010 LPSC_RPC_HANDLE lpScHandle)
4011{
4013 UNICODE_STRING DatabaseName;
4014 DWORD dwError;
4015
4016 DPRINT("ROpenSCManagerA() called\n");
4017
4018 if (lpMachineName)
4020 lpMachineName);
4021
4022 if (lpDatabaseName)
4024 lpDatabaseName);
4025
4026 dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL,
4027 lpDatabaseName ? DatabaseName.Buffer : NULL,
4028 dwDesiredAccess,
4029 lpScHandle);
4030
4031 if (lpMachineName)
4033
4034 if (lpDatabaseName)
4035 RtlFreeUnicodeString(&DatabaseName);
4036
4037 return dwError;
4038}
4039
4040
4041/* Function 28 */
4042DWORD
4043WINAPI
4046 LPSTR lpServiceName,
4047 DWORD dwDesiredAccess,
4048 LPSC_RPC_HANDLE lpServiceHandle)
4049{
4051 DWORD dwError;
4052
4053 DPRINT("ROpenServiceA() called\n");
4054
4055 if (lpServiceName)
4057 lpServiceName);
4058
4059 dwError = ROpenServiceW(hSCManager,
4060 lpServiceName ? ServiceName.Buffer : NULL,
4061 dwDesiredAccess,
4062 lpServiceHandle);
4063
4064 if (lpServiceName)
4066
4067 return dwError;
4068}
4069
4070
4071/* Function 29 */
4072DWORD
4073WINAPI
4075 SC_RPC_HANDLE hService,
4076 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4079{
4080 LPQUERY_SERVICE_CONFIGA lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)lpBuf;
4081 DWORD dwError = ERROR_SUCCESS;
4082 PSERVICE_HANDLE hSvc;
4083 PSERVICE lpService = NULL;
4084 HKEY hServiceKey = NULL;
4085 LPWSTR lpImagePath = NULL;
4086 LPWSTR lpServiceStartName = NULL;
4087 LPWSTR lpDependencies = NULL;
4088 DWORD dwDependenciesLength = 0;
4089 DWORD dwRequiredSize;
4090 LPSTR lpStr;
4091
4092 DPRINT("RQueryServiceConfigA() called\n");
4093
4094 if (ScmShutdown)
4096
4097 hSvc = ScmGetServiceFromHandle(hService);
4098 if (hSvc == NULL)
4099 {
4100 DPRINT1("Invalid service handle\n");
4101 return ERROR_INVALID_HANDLE;
4102 }
4103
4106 {
4107 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
4108 return ERROR_ACCESS_DENIED;
4109 }
4110
4111 lpService = hSvc->ServiceEntry;
4112 if (lpService == NULL)
4113 {
4114 DPRINT("lpService == NULL\n");
4115 return ERROR_INVALID_HANDLE;
4116 }
4117
4118 /* Lock the service database shared */
4120
4121 dwError = ScmOpenServiceKey(lpService->lpServiceName,
4122 KEY_READ,
4123 &hServiceKey);
4124 if (dwError != ERROR_SUCCESS)
4125 goto Done;
4126
4127 /* Read the image path */
4128 dwError = ScmReadString(hServiceKey,
4129 L"ImagePath",
4130 &lpImagePath);
4131 if (dwError != ERROR_SUCCESS)
4132 goto Done;
4133
4134 /* Read the service start name */
4135 ScmReadString(hServiceKey,
4136 L"ObjectName",
4137 &lpServiceStartName);
4138
4139 /* Read the dependencies */
4140 ScmReadDependencies(hServiceKey,
4141 &lpDependencies,
4142 &dwDependenciesLength);
4143
4144 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGA);
4145
4146 if (lpImagePath != NULL)
4147 dwRequiredSize += (DWORD)(wcslen(lpImagePath) + 1);
4148 else
4149 dwRequiredSize += 2 * sizeof(CHAR);
4150
4151 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
4152 dwRequiredSize += (DWORD)(wcslen(lpService->lpGroup->lpGroupName) + 1);
4153 else
4154 dwRequiredSize += 2 * sizeof(CHAR);
4155
4156 /* Add Dependencies length */
4157 if (lpDependencies != NULL)
4158 dwRequiredSize += dwDependenciesLength;
4159 else
4160 dwRequiredSize += 2 * sizeof(CHAR);
4161
4162 if (lpServiceStartName != NULL)
4163 dwRequiredSize += (DWORD)(wcslen(lpServiceStartName) + 1);
4164 else
4165 dwRequiredSize += 2 * sizeof(CHAR);
4166
4167 if (lpService->lpDisplayName != NULL)
4168 dwRequiredSize += (DWORD)(wcslen(lpService->lpDisplayName) + 1);
4169 else
4170 dwRequiredSize += 2 * sizeof(CHAR);
4171
4172 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
4173 {
4174 dwError = ERROR_INSUFFICIENT_BUFFER;
4175 }
4176 else
4177 {
4178 lpServiceConfig->dwServiceType = lpService->Status.dwServiceType;
4179 lpServiceConfig->dwStartType = lpService->dwStartType;
4180 lpServiceConfig->dwErrorControl = lpService->dwErrorControl;
4181 lpServiceConfig->dwTagId = lpService->dwTag;
4182
4183 lpStr = (LPSTR)(lpServiceConfig + 1);
4184
4185 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4186 Verified in WINXP */
4187
4188 if (lpImagePath)
4189 {
4191 0,
4192 lpImagePath,
4193 -1,
4194 lpStr,
4195 (int)(wcslen(lpImagePath) + 1),
4196 0,
4197 0);
4198 }
4199 else
4200 {
4201 *lpStr = 0;
4202 }
4203
4204 lpServiceConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4205 lpStr += (strlen((LPSTR)lpStr) + 1);
4206
4207 if (lpService->lpGroup && lpService->lpGroup->lpGroupName)
4208 {
4210 0,
4211 lpService->lpGroup->lpGroupName,
4212 -1,
4213 lpStr,
4214 (int)(wcslen(lpService->lpGroup->lpGroupName) + 1),
4215 0,
4216 0);
4217 }
4218 else
4219 {
4220 *lpStr = 0;
4221 }
4222
4223 lpServiceConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4224 lpStr += (strlen(lpStr) + 1);
4225
4226 /* Append Dependencies */
4227 if (lpDependencies)
4228 {
4230 0,
4231 lpDependencies,
4232 dwDependenciesLength,
4233 lpStr,
4234 dwDependenciesLength,
4235 0,
4236 0);
4237 }
4238 else
4239 {
4240 *lpStr = 0;
4241 }
4242
4243 lpServiceConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4244 if (lpDependencies)
4245 lpStr += dwDependenciesLength;
4246 else
4247 lpStr += (strlen(lpStr) + 1);
4248
4249 if (lpServiceStartName)
4250 {
4252 0,
4253 lpServiceStartName,
4254 -1,
4255 lpStr,
4256 (int)(wcslen(lpServiceStartName) + 1),
4257 0,
4258 0);
4259 }
4260 else
4261 {
4262 *lpStr = 0;
4263 }
4264
4265 lpServiceConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4266 lpStr += (strlen(lpStr) + 1);
4267
4268 if (lpService->lpDisplayName)
4269 {
4271 0,
4272 lpService->lpDisplayName,
4273 -1,
4274 lpStr,
4275 (int)(wcslen(lpService->lpDisplayName) + 1),
4276 0,
4277 0);
4278 }
4279 else
4280 {
4281 *lpStr = 0;
4282 }
4283
4284 lpServiceConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
4285 }
4286
4287 if (pcbBytesNeeded != NULL)
4288 *pcbBytesNeeded = dwRequiredSize;
4289
4290Done:
4291 /* Unlock the service database */
4293
4294 if (lpImagePath != NULL)
4295 HeapFree(GetProcessHeap(), 0, lpImagePath);
4296
4297 if (lpServiceStartName != NULL)
4298 HeapFree(GetProcessHeap(), 0, lpServiceStartName);
4299
4300 if (lpDependencies != NULL)
4301 HeapFree(GetProcessHeap(), 0, lpDependencies);
4302
4303 if (hServiceKey != NULL)
4304 RegCloseKey(hServiceKey);
4305
4306 DPRINT("RQueryServiceConfigA() done\n");
4307
4308 return dwError;
4309}
4310
4311
4312/* Function 30 */
4313DWORD
4314WINAPI
4317 LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
4320{
4322 PMANAGER_HANDLE hMgr;
4323 DWORD dwRequiredSize;
4324
4325 if (!lpLockStatus || !pcbBytesNeeded)
4327
4329 if (hMgr == NULL)
4330 {
4331 DPRINT1("Invalid service manager handle\n");
4332 return ERROR_INVALID_HANDLE;
4333 }
4334
4337 {
4338 DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess);
4339 return ERROR_ACCESS_DENIED;
4340 }
4341
4342 /* FIXME: we need to compute instead the real length of the owner name */
4343 dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSA) + sizeof(CHAR);
4344 *pcbBytesNeeded = dwRequiredSize;
4345
4346 if (cbBufSize < dwRequiredSize)
4348
4349 ScmQueryServiceLockStatusA(lpLockStatus);
4350
4351 return ERROR_SUCCESS;
4352}
4353
4354
4355/* Function 31 */
4356DWORD
4357WINAPI
4359 SC_RPC_HANDLE hService,
4360 DWORD argc,
4362{
4363 DWORD dwError = ERROR_SUCCESS;
4364 PSERVICE_HANDLE hSvc;
4365 PSERVICE lpService = NULL;
4366 LPWSTR *lpVector = NULL;
4367 DWORD i;
4369
4370 DPRINT("RStartServiceA() called\n");
4371
4372 if (ScmShutdown)
4374
4375 hSvc = ScmGetServiceFromHandle(hService);
4376 if (hSvc == NULL)
4377 {
4378 DPRINT1("Invalid service handle\n");
4379 return ERROR_INVALID_HANDLE;
4380 }
4381
4384 {
4385 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
4386 return ERROR_ACCESS_DENIED;
4387 }
4388
4389 lpService = hSvc->ServiceEntry;
4390 if (lpService == NULL)
4391 {
4392 DPRINT("lpService == NULL\n");
4393 return ERROR_INVALID_HANDLE;
4394 }
4395
4396 if (lpService->dwStartType == SERVICE_DISABLED)
4398
4399 if (lpService->bDeleted)
4401
4402 /* Build a Unicode argument vector */
4403 if (argc > 0)
4404 {
4405 lpVector = HeapAlloc(GetProcessHeap(),
4407 argc * sizeof(LPWSTR));
4408 if (lpVector == NULL)
4410
4411 for (i = 0; i < argc; i++)
4412 {
4414 0,
4415 ((LPSTR*)argv)[i],
4416 -1,
4417 NULL,
4418 0);
4419
4420 lpVector[i] = HeapAlloc(GetProcessHeap(),
4422 dwLength * sizeof(WCHAR));
4423 if (lpVector[i] == NULL)
4424 {
4425 dwError = ERROR_NOT_ENOUGH_MEMORY;
4426 goto done;
4427 }
4428
4430 0,
4431 ((LPSTR*)argv)[i],
4432 -1,
4433 lpVector[i],
4434 dwLength);
4435 }
4436 }
4437
4438 /* Start the service */
4439 dwError = ScmStartService(lpService, argc, lpVector);
4440
4441done:
4442 /* Free the Unicode argument vector */
4443 if (lpVector != NULL)
4444 {
4445 for (i = 0; i < argc; i++)
4446 {
4447 if (lpVector[i] != NULL)
4448 HeapFree(GetProcessHeap(), 0, lpVector[i]);
4449 }
4450 HeapFree(GetProcessHeap(), 0, lpVector);
4451 }
4452
4453 return dwError;
4454}
4455
4456
4457/* Function 32 */
4458DWORD
4459WINAPI
4462 LPCSTR lpServiceName,
4464 LPBOUNDED_DWORD_4K lpcchBuffer)
4465{
4466 // PMANAGER_HANDLE hManager;
4467 PSERVICE lpService = NULL;
4468 LPCWSTR lpSvcDisplayName;
4469 LPWSTR lpServiceNameW;
4471
4472 DPRINT("RGetServiceDisplayNameA() called\n");
4473 DPRINT("hSCManager = %p\n", hSCManager);
4474 DPRINT("lpServiceName: %s\n", lpServiceName);
4475 DPRINT("lpDisplayName: %p\n", lpDisplayName);
4476 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
4477
4478#if 0
4479 hManager = (PMANAGER_HANDLE)hSCManager;
4480 if (hManager->Handle.Tag != MANAGER_TAG)
4481 {
4482 DPRINT("Invalid manager handle\n");
4483 return ERROR_INVALID_HANDLE;
4484 }
4485#endif
4486
4487 /* Get service database entry */
4488 if (lpServiceName != NULL)
4489 {
4490 dwLength = (DWORD)(strlen(lpServiceName) + 1);
4491 lpServiceNameW = HeapAlloc(GetProcessHeap(),
4493 dwLength * sizeof(WCHAR));
4494 if (!lpServiceNameW)
4496
4498 0,
4499 lpServiceName,
4500 -1,
4501 lpServiceNameW,
4502 dwLength);
4503
4504 lpService = ScmGetServiceEntryByName(lpServiceNameW);
4505
4506 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
4507 }
4508
4509 if (lpService == NULL)
4510 {
4511 DPRINT("Could not find service\n");
4513 }
4514
4515 if (lpService->lpDisplayName)
4516 lpSvcDisplayName = lpService->lpDisplayName;
4517 else
4518 lpSvcDisplayName = lpService->lpServiceName;
4519
4520 /*
4521 * NOTE: On Windows the comparison on *lpcchBuffer is made against
4522 * the number of (wide) characters of the UNICODE display name, and
4523 * not against the number of bytes needed to store the ANSI string.
4524 */
4525 dwLength = (DWORD)wcslen(lpSvcDisplayName);
4526
4527 if (*lpcchBuffer > dwLength)
4528 {
4529 if (lpDisplayName != NULL &&
4531 0,
4532 lpSvcDisplayName,
4533 -1,
4535 (int)*lpcchBuffer,
4536 NULL,
4537 NULL) == 0)
4538 {
4539 /*
4540 * But then, if *lpcchBuffer was greater than the number of
4541 * (wide) characters of the UNICODE display name, yet smaller
4542 * than the number of bytes needed due to the possible presence
4543 * of DBCS characters, the *exact* number of bytes is returned
4544 * (without the NULL terminator).
4545 */
4547 0,
4548 lpSvcDisplayName,
4549 (int)dwLength,
4550 NULL,
4551 0,
4552 NULL,
4553 NULL);
4554 *lpDisplayName = 0;
4555 *lpcchBuffer = dwLength;
4557 }
4558
4559 /*
4560 * NOTE: On Windows, RGetServiceDisplayNameA() does not update
4561 * *lpcchBuffer on success, contrary to RGetServiceDisplayNameW().
4562 */
4563 return ERROR_SUCCESS;
4564 }
4565 else
4566 {
4567 /*
4568 * NOTE: On Windows, if *lpcchBuffer is smaller than the number of
4569 * (wide) characters of the UNICODE display name, only an upper
4570 * estimation is returned by doubling the string length, to account
4571 * for the presence of any possible DBCS characters.
4572 */
4573 *lpcchBuffer = dwLength * sizeof(WCHAR);
4575 }
4576}
4577
4578
4579/* Function 33 */
4580DWORD
4581WINAPI
4585 LPSTR lpServiceName,
4586 LPBOUNDED_DWORD_4K lpcchBuffer)
4587{
4588 // PMANAGER_HANDLE hManager;
4589 PSERVICE lpService;
4590 LPWSTR lpDisplayNameW;
4592
4593 DPRINT("RGetServiceKeyNameA() called\n");
4594 DPRINT("hSCManager = %p\n", hSCManager);
4595 DPRINT("lpDisplayName: %s\n", lpDisplayName);
4596 DPRINT("lpServiceName: %p\n", lpServiceName);
4597 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
4598
4599#if 0
4600 hManager = (PMANAGER_HANDLE)hSCManager;
4601 if (hManager->Handle.Tag != MANAGER_TAG)
4602 {
4603 DPRINT("Invalid manager handle\n");
4604 return ERROR_INVALID_HANDLE;
4605 }
4606#endif
4607
4608 /* Get service database entry */
4609
4611 lpDisplayNameW = HeapAlloc(GetProcessHeap(),
4613 dwLength * sizeof(WCHAR));
4614 if (!lpDisplayNameW)
4616
4618 0,
4620 -1,
4621 lpDisplayNameW,
4622 dwLength);
4623
4624 lpService = ScmGetServiceEntryByDisplayName(lpDisplayNameW);
4625
4626 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
4627
4628 if (lpService == NULL)
4629 {
4630 DPRINT("Could not find service\n");
4632 }
4633
4634 /*
4635 * NOTE: On Windows the comparison on *lpcchBuffer is made against
4636 * the number of (wide) characters of the UNICODE service name, and
4637 * not against the number of bytes needed to store the ANSI string.
4638 */
4639 dwLength = (DWORD)wcslen(lpService->lpServiceName);
4640
4641 if (*lpcchBuffer > dwLength)
4642 {
4643 if (lpServiceName != NULL &&
4645 0,
4646 lpService->lpServiceName,
4647 -1,
4648 lpServiceName,
4649 (int)*lpcchBuffer,
4650 NULL,
4651 NULL) == 0)
4652 {
4653 /*
4654 * But then, if *lpcchBuffer was greater than the number of
4655 * (wide) characters of the UNICODE service name, yet smaller
4656 * than the number of bytes needed due to the possible presence
4657 * of DBCS characters, the *exact* number of bytes is returned
4658 * (without the NULL terminator).
4659 */
4661 0,
4662 lpService->lpServiceName,
4663 (int)dwLength,
4664 NULL,
4665 0,
4666 NULL,
4667 NULL);
4668 *lpServiceName = 0;
4669 *lpcchBuffer = dwLength;
4671 }
4672
4673 /*
4674 * NOTE: On Windows, RGetServiceKeyNameA() does not update
4675 * *lpcchBuffer on success, contrary to RGetServiceKeyNameW().
4676 */
4677 return ERROR_SUCCESS;
4678 }
4679 else
4680 {
4681 /*
4682 * NOTE: On Windows, if *lpcchBuffer is smaller than the number of
4683 * (wide) characters of the UNICODE service name, only an upper
4684 * estimation is returned by doubling the string length, to account
4685 * for the presence of any possible DBCS characters.
4686 */
4687 *lpcchBuffer = dwLength * sizeof(WCHAR);
4689 }
4690}
4691
4692
4693/* Function 34 */
4694DWORD
4695WINAPI
4698 LPWSTR lpLoadOrderGroup,
4699 LPDWORD lpState)
4700{
4701 PMANAGER_HANDLE hManager;
4702 PSERVICE_GROUP pServiceGroup;
4703 DWORD dwError = ERROR_SUCCESS;
4704
4705 DPRINT("RI_ScGetCurrentGroupStateW() called\n");
4706
4707 if (ScmShutdown)
4709
4711 if (hManager == NULL)
4712 {
4713 DPRINT1("Invalid service manager handle\n");
4714 return ERROR_INVALID_HANDLE;
4715 }
4716
4717 /* Check for SC_MANAGER_ENUMERATE_SERVICE access right */
4720 {
4721 DPRINT("Insufficient access rights! 0x%lx\n",
4722 hManager->Handle.DesiredAccess);
4723 return ERROR_ACCESS_DENIED;
4724 }
4725
4726 /* Lock the service database shared */
4728
4729 /* Get the group list entry */
4730 pServiceGroup = ScmGetServiceGroupByName(lpLoadOrderGroup);
4731 if (pServiceGroup == NULL)
4732 {
4734 goto done;
4735 }
4736
4737 /* FIXME: Return the group state */
4738 *lpState = 0;
4739
4740done:
4741 /* Unlock the service database */
4743
4744 DPRINT("RI_ScGetCurrentGroupStateW() done (Error %lu)\n", dwError);
4745
4746 return dwError;
4747}
4748
4749
4750/* Function 35 */
4751DWORD
4752WINAPI
4755 DWORD dwServiceType,
4756 DWORD dwServiceState,
4760 LPBOUNDED_DWORD_256K lpServicesReturned,
4761 LPBOUNDED_DWORD_256K lpResumeIndex,
4762 LPCWSTR pszGroupName)
4763{
4764 PMANAGER_HANDLE hManager;
4765 PSERVICE lpService;
4766 DWORD dwError = ERROR_SUCCESS;
4767 PLIST_ENTRY ServiceEntry;
4768 PSERVICE CurrentService;
4769 DWORD dwState;
4770 DWORD dwRequiredSize;
4771 DWORD dwServiceCount;
4772 DWORD dwSize;
4773 DWORD dwLastResumeCount = 0;
4774 LPENUM_SERVICE_STATUSW lpStatusPtr;
4775 LPWSTR lpStringPtr;
4776
4777 DPRINT("REnumServiceGroupW() called\n");
4778
4779 if (ScmShutdown)
4781
4783 if (hManager == NULL)
4784 {
4785 DPRINT1("Invalid service manager handle\n");
4786 return ERROR_INVALID_HANDLE;
4787 }
4788
4789 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
4790 {
4791 return ERROR_INVALID_ADDRESS;
4792 }
4793
4794 *pcbBytesNeeded = 0;
4795 *lpServicesReturned = 0;
4796
4797 if ((dwServiceType == 0) ||
4798 ((dwServiceType & ~SERVICE_TYPE_ALL) != 0))
4799 {
4800 DPRINT("Invalid Service Type\n");
4802 }
4803
4804 if ((dwServiceState == 0) ||
4805 ((dwServiceState & ~SERVICE_STATE_ALL) != 0))
4806 {
4807 DPRINT("Invalid Service State\n");
4809 }
4810
4811 /* Check access rights */
4814 {
4815 DPRINT("Insufficient access rights! 0x%lx\n",
4816 hManager->Handle.DesiredAccess);
4817 return ERROR_ACCESS_DENIED;
4818 }
4819
4820 if (lpResumeIndex)
4821 dwLastResumeCount = *lpResumeIndex;
4822
4823 /* Lock the service database shared */
4825
4826 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
4827 if (lpService == NULL)
4828 {
4829 dwError = ERROR_SUCCESS;
4830 goto Done;
4831 }
4832
4833 dwRequiredSize = 0;
4834 dwServiceCount = 0;
4835
4836 for (ServiceEntry = &lpService->ServiceListEntry;
4837 ServiceEntry != &ServiceListHead;
4838 ServiceEntry = ServiceEntry->Flink)
4839 {
4840 CurrentService = CONTAINING_RECORD(ServiceEntry,
4841 SERVICE,
4842 ServiceListEntry);
4843
4844 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
4845 continue;
4846
4847 dwState = SERVICE_ACTIVE;
4848 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
4849 dwState = SERVICE_INACTIVE;
4850
4851 if ((dwState & dwServiceState) == 0)
4852 continue;
4853
4854 if (pszGroupName)
4855 {
4856 if (*pszGroupName == 0)
4857 {
4858 if (CurrentService->lpGroup != NULL)
4859 continue;
4860 }
4861 else
4862 {
4863 if ((CurrentService->lpGroup == NULL) ||
4864 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
4865 continue;
4866 }
4867 }
4868
4869 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
4870 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
4871 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
4872
4873 if (dwRequiredSize + dwSize > cbBufSize)
4874 {
4875 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
4876 break;
4877 }
4878
4879 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
4880 dwRequiredSize += dwSize;
4881 dwServiceCount++;
4882 dwLastResumeCount = CurrentService->dwResumeCount;
4883 }
4884
4885 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
4886 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
4887
4888 for (;
4889 ServiceEntry != &ServiceListHead;
4890 ServiceEntry = ServiceEntry->Flink)
4891 {
4892 CurrentService = CONTAINING_RECORD(ServiceEntry,
4893 SERVICE,
4894 ServiceListEntry);
4895
4896 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
4897 continue;
4898
4899 dwState = SERVICE_ACTIVE;
4900 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
4901 dwState = SERVICE_INACTIVE;
4902
4903 if ((dwState & dwServiceState) == 0)
4904 continue;
4905
4906 if (pszGroupName)
4907 {
4908 if (*pszGroupName == 0)
4909 {
4910 if (CurrentService->lpGroup != NULL)
4911 continue;
4912 }
4913 else
4914 {
4915 if ((CurrentService->lpGroup == NULL) ||
4916 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
4917 continue;
4918 }
4919 }
4920
4921 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
4922 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
4923 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
4924
4925 dwError = ERROR_MORE_DATA;
4926 }
4927
4928 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
4929
4930 if (lpResumeIndex)
4931 *lpResumeIndex = dwLastResumeCount;
4932
4933 *lpServicesReturned = dwServiceCount;
4934 *pcbBytesNeeded = dwRequiredSize;
4935
4936 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer;
4937 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
4938 dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
4939
4940 dwRequiredSize = 0;
4941 for (ServiceEntry = &lpService->ServiceListEntry;
4942 ServiceEntry != &ServiceListHead;
4943 ServiceEntry = ServiceEntry->Flink)
4944 {
4945 CurrentService = CONTAINING_RECORD(ServiceEntry,
4946 SERVICE,
4947 ServiceListEntry);
4948
4949 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
4950 continue;
4951
4952 dwState = SERVICE_ACTIVE;
4953 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
4954 dwState = SERVICE_INACTIVE;
4955
4956 if ((dwState & dwServiceState) == 0)
4957 continue;
4958
4959 if (pszGroupName)
4960 {
4961 if (*pszGroupName == 0)
4962 {
4963 if (CurrentService->lpGroup != NULL)
4964 continue;
4965 }
4966 else
4967 {
4968 if ((CurrentService->lpGroup == NULL) ||
4969 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
4970 continue;
4971 }
4972 }
4973
4974 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
4975 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
4976 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
4977
4978 if (dwRequiredSize + dwSize > cbBufSize)
4979 break;
4980
4981 /* Copy the service name */
4982 wcscpy(lpStringPtr, CurrentService->lpServiceName);
4983 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
4984 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
4985
4986 /* Copy the display name */
4987 wcscpy(lpStringPtr, CurrentService->lpDisplayName);
4988 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
4989 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
4990
4991 /* Copy the status information */
4992 memcpy(&lpStatusPtr->ServiceStatus,
4993 &CurrentService->Status,
4994 sizeof(SERVICE_STATUS));
4995
4996 lpStatusPtr++;
4997 dwRequiredSize += dwSize;
4998 }
4999
5000 if (dwError == ERROR_SUCCESS)
5001 {
5002 *pcbBytesNeeded = 0;
5003 if (lpResumeIndex) *lpResumeIndex = 0;
5004 }
5005
5006Done:
5007 /* Unlock the service database */
5009
5010 DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError);
5011
5012 return dwError;
5013}
5014
5015
5016/* Function 36 */
5017DWORD
5018WINAPI
5020 SC_RPC_HANDLE hService,
5022{
5023 SC_RPC_CONFIG_INFOW InfoW = { 0 };
5024 DWORD dwRet, dwLength;
5025 PVOID ptr = NULL;
5026
5027 DPRINT("RChangeServiceConfig2A() called\n");
5028 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
5029
5030 if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
5031 (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
5032 {
5033 return ERROR_INVALID_LEVEL;
5034 }
5035
5036 InfoW.dwInfoLevel = Info.dwInfoLevel;
5037
5039 {
5040 LPSERVICE_DESCRIPTIONW lpServiceDescriptionW;
5041 LPSERVICE_DESCRIPTIONA lpServiceDescriptionA;
5042
5043 lpServiceDescriptionA = Info.psd;
5044
5045 if (lpServiceDescriptionA &&
5046 lpServiceDescriptionA->lpDescription)
5047 {
5048 dwLength = (DWORD)((strlen(lpServiceDescriptionA->lpDescription) + 1) * sizeof(WCHAR));
5049
5050 lpServiceDescriptionW = HeapAlloc(GetProcessHeap(),
5052 dwLength + sizeof(SERVICE_DESCRIPTIONW));
5053 if (!lpServiceDescriptionW)
5054 {
5056 }
5057
5058 lpServiceDescriptionW->lpDescription = (LPWSTR)(lpServiceDescriptionW + 1);
5059
5061 0,
5062 lpServiceDescriptionA->lpDescription,
5063 -1,
5064 lpServiceDescriptionW->lpDescription,
5065 dwLength);
5066
5067 ptr = lpServiceDescriptionW;
5068 InfoW.psd = lpServiceDescriptionW;
5069 }
5070 }
5071 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5072 {
5073 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW;
5074 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA;
5075 DWORD dwRebootLen = 0;
5076 DWORD dwCommandLen = 0;
5077 DWORD dwActionArrayLen = 0;
5078 LPWSTR lpStr = NULL;
5079
5080 lpServiceFailureActionsA = Info.psfa;
5081
5082 if (lpServiceFailureActionsA)
5083 {
5084 /*
5085 * The following code is inspired by the
5086 * SERVICE_CONFIG_FAILURE_ACTIONS case of
5087 * the RQueryServiceConfig2W function.
5088 */
5089
5090 /* Retrieve the needed length for the two data strings */
5091 if (lpServiceFailureActionsA->lpRebootMsg)
5092 {
5093 dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR));
5094 }
5095 if (lpServiceFailureActionsA->lpCommand)
5096 {
5097 dwCommandLen = (DWORD)((strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR));
5098 }
5099
5100 /*
5101 * Retrieve the size of the lpsaActions array if needed.
5102 * We will copy the lpsaActions array only if there is at
5103 * least one action AND that the original array is valid.
5104 */
5105 if (lpServiceFailureActionsA->cActions > 0 && lpServiceFailureActionsA->lpsaActions)
5106 {
5107 dwActionArrayLen = lpServiceFailureActionsA->cActions * sizeof(SC_ACTION);
5108 }
5109
5110 /* Compute the total length for the UNICODE structure, including data */
5112 dwActionArrayLen + dwRebootLen + dwCommandLen;
5113
5114 /* Allocate the structure */
5115 lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(),
5117 dwLength);
5118 if (!lpServiceFailureActionsW)
5119 {
5121 }
5122
5123 /* Copy the members */
5124 lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod;
5125 lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions;
5126
5127 /* Copy the lpsaActions array if needed */
5128 if (dwActionArrayLen > 0)
5129 {
5130 /* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */
5131 lpServiceFailureActionsW->lpsaActions = (LPSC_ACTION)((ULONG_PTR)(lpServiceFailureActionsW + 1));
5132
5133 /* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */
5134 RtlCopyMemory(lpServiceFailureActionsW->lpsaActions,
5135 lpServiceFailureActionsA->lpsaActions,
5136 dwActionArrayLen);
5137 }
5138 else
5139 {
5140 /* No lpsaActions array */
5141 lpServiceFailureActionsW->lpsaActions = NULL;
5142 }
5143 /* The data strings are stored just after the lpsaActions array */
5144 lpStr = (LPWSTR)((ULONG_PTR)(lpServiceFailureActionsW + 1) + dwActionArrayLen);
5145
5146 /*
5147 * Convert the data strings to UNICODE
5148 */
5149
5150 lpServiceFailureActionsW->lpRebootMsg = NULL;
5151 lpServiceFailureActionsW->lpCommand = NULL;
5152
5153 if (dwRebootLen)
5154 {
5155 /* lpRebootMsg points just after the lpsaActions array */
5156 lpServiceFailureActionsW->lpRebootMsg = lpStr;
5157
5159 0,
5160 lpServiceFailureActionsA->lpRebootMsg,
5161 -1,
5162 lpServiceFailureActionsW->lpRebootMsg,
5163 dwRebootLen);
5164
5165 lpStr += dwRebootLen / sizeof(WCHAR);
5166 }
5167
5168 if (dwCommandLen)
5169 {
5170 /* lpRebootMsg points just after the lpRebootMsg data string */
5171 lpServiceFailureActionsW->lpCommand = lpStr;
5172
5174 0,
5175 lpServiceFailureActionsA->lpCommand,
5176 -1,
5177 lpServiceFailureActionsW->lpCommand,
5178 dwCommandLen);
5179 }
5180
5181 /* Set the pointers */
5182 ptr = lpServiceFailureActionsW;
5183 InfoW.psfa = lpServiceFailureActionsW;
5184 }
5185 }
5186
5187 dwRet = RChangeServiceConfig2W(hService, InfoW);
5188
5190
5191 return dwRet;
5192}
5193
5194
5195static DWORD
5197 LPSERVICE_FAILURE_ACTIONSW lpFailureActions)
5198{
5199 LPSERVICE_FAILURE_ACTIONSW lpReadBuffer = NULL;
5200 LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer = NULL;
5201 DWORD dwRequiredSize = 0;
5202 DWORD dwType = 0;
5203 DWORD dwError;
5204
5205 /* There is nothing to be done if we have no failure actions */
5206 if (lpFailureActions == NULL)
5207 return ERROR_SUCCESS;
5208
5209 /*
5210 * 1- Retrieve the original value of FailureActions.
5211 */
5212
5213 /* Query value length */
5214 dwError = RegQueryValueExW(hServiceKey,
5215 L"FailureActions",
5216 NULL,
5217 &dwType,
5218 NULL,
5219 &dwRequiredSize);
5220 if (dwError != ERROR_SUCCESS &&
5221 dwError != ERROR_MORE_DATA &&
5222 dwError != ERROR_FILE_NOT_FOUND)
5223 {
5224 return dwError;
5225 }
5226
5227 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
5228 : sizeof(SERVICE_FAILURE_ACTIONSW);
5229
5230 /* Initialize the read buffer */
5231 lpReadBuffer = HeapAlloc(GetProcessHeap(),
5233 dwRequiredSize);
5234 if (lpReadBuffer == NULL)
5236
5237 /* Now we can fill the read buffer */
5238 if (dwError != ERROR_FILE_NOT_FOUND &&
5239 dwType == REG_BINARY)
5240 {
5241 dwError = RegQueryValueExW(hServiceKey,
5242 L"FailureActions",
5243 NULL,
5244 NULL,
5245 (LPBYTE)lpReadBuffer,
5246 &dwRequiredSize);
5247 if (dwError != ERROR_SUCCESS &&
5248 dwError != ERROR_FILE_NOT_FOUND)
5249 goto done;
5250
5251 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW))
5252 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
5253 }
5254 else
5255 {
5256 /*
5257 * The value of the error doesn't really matter, the only
5258 * important thing is that it must be != ERROR_SUCCESS.
5259 */
5260 dwError = ERROR_INVALID_DATA;
5261 }
5262
5263 if (dwError == ERROR_SUCCESS)
5264 {
5265 lpReadBuffer->cActions = min(lpReadBuffer->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION));
5266 lpReadBuffer->lpsaActions = (lpReadBuffer->cActions > 0 ? (LPSC_ACTION)(lpReadBuffer + 1) : NULL);
5267 }
5268 else
5269 {
5270 lpReadBuffer->dwResetPeriod = 0;
5271 lpReadBuffer->cActions = 0;
5272 lpReadBuffer->lpsaActions = NULL;
5273 }
5274
5275 lpReadBuffer->lpRebootMsg = NULL;
5276 lpReadBuffer->lpCommand = NULL;
5277
5278 /*
5279 * 2- Initialize the new value to set.
5280 */
5281
5282 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
5283
5284 if (lpFailureActions->lpsaActions == NULL)
5285 {
5286 /*
5287 * lpFailureActions->cActions is ignored.
5288 * Therefore we use the original values
5289 * of cActions and lpsaActions.
5290 */
5291 dwRequiredSize += lpReadBuffer->cActions * sizeof(SC_ACTION);
5292 }
5293 else
5294 {
5295 /*
5296 * The reset period and array of failure actions
5297 * are deleted if lpFailureActions->cActions == 0 .
5298 */
5299 dwRequiredSize += lpFailureActions->cActions * sizeof(SC_ACTION);
5300 }
5301
5302 lpWriteBuffer = HeapAlloc(GetProcessHeap(),
5304 dwRequiredSize);
5305 if (lpWriteBuffer == NULL)
5306 {
5307 dwError = ERROR_NOT_ENOUGH_MEMORY;
5308 goto done;
5309 }
5310
5311 /* Clean the pointers as they have no meaning when the structure is stored in the registry */
5312 lpWriteBuffer->lpRebootMsg = NULL;
5313 lpWriteBuffer->lpCommand = NULL;
5314 lpWriteBuffer->lpsaActions = NULL;
5315
5316 /* Set the members */
5317 if (lpFailureActions->lpsaActions == NULL)
5318 {
5319 /*
5320 * lpFailureActions->dwResetPeriod and lpFailureActions->cActions are ignored.
5321 * Therefore we use the original values of dwResetPeriod, cActions and lpsaActions.
5322 */
5323 lpWriteBuffer->dwResetPeriod = lpReadBuffer->dwResetPeriod;
5324 lpWriteBuffer->cActions = lpReadBuffer->cActions;
5325
5326 if (lpReadBuffer->lpsaActions != NULL)
5327 {
5328 memmove(lpWriteBuffer + 1,
5329 lpReadBuffer->lpsaActions,
5330 lpReadBuffer->cActions * sizeof(SC_ACTION));
5331 }
5332 }
5333 else
5334 {
5335 if (lpFailureActions->cActions > 0)
5336 {
5337 lpWriteBuffer->dwResetPeriod = lpFailureActions->dwResetPeriod;
5338 lpWriteBuffer->cActions = lpFailureActions->cActions;
5339
5340 memmove(lpWriteBuffer + 1,
5341 lpFailureActions->lpsaActions,
5342 lpFailureActions->cActions * sizeof(SC_ACTION));
5343 }
5344 else
5345 {
5346 /* The reset period and array of failure actions are deleted */
5347 lpWriteBuffer->dwResetPeriod = 0;
5348 lpWriteBuffer->cActions = 0;
5349 }
5350 }
5351
5352 /* Save the new failure actions into the registry */
5353 dwError = RegSetValueExW(hServiceKey,
5354 L"FailureActions",
5355 0,
5356 REG_BINARY,
5357 (LPBYTE)lpWriteBuffer,
5358 dwRequiredSize);
5359
5360 /* We modify the strings only in case of success.*/
5361 if (dwError == ERROR_SUCCESS)
5362 {
5363 /* Modify the Reboot Message value, if specified */
5364 if (lpFailureActions->lpRebootMsg != NULL)
5365 {
5366 /* If the Reboot Message is "" then we delete it */
5367 if (*lpFailureActions->lpRebootMsg == 0)
5368 {
5369 DPRINT("Delete Reboot Message value\n");
5370 RegDeleteValueW(hServiceKey, L"RebootMessage");
5371 }
5372 else
5373 {
5374 DPRINT("Setting Reboot Message value %S\n", lpFailureActions->lpRebootMsg);
5375 RegSetValueExW(hServiceKey,
5376 L"RebootMessage",
5377 0,
5378 REG_SZ,
5379 (LPBYTE)lpFailureActions->lpRebootMsg,
5380 (DWORD)((wcslen(lpFailureActions->lpRebootMsg) + 1) * sizeof(WCHAR)));
5381 }
5382 }
5383
5384 /* Modify the Failure Command value, if specified */
5385 if (lpFailureActions->lpCommand != NULL)
5386 {
5387 /* If the FailureCommand string is an empty string, delete the value */
5388 if (*lpFailureActions->lpCommand == 0)
5389 {
5390 DPRINT("Delete Failure Command value\n");
5391 RegDeleteValueW(hServiceKey, L"FailureCommand");
5392 }
5393 else
5394 {
5395 DPRINT("Setting Failure Command value %S\n", lpFailureActions->lpCommand);
5396 RegSetValueExW(hServiceKey,
5397 L"FailureCommand",
5398 0,
5399 REG_SZ,
5400 (LPBYTE)lpFailureActions->lpCommand,
5401 (DWORD)((wcslen(lpFailureActions->lpCommand) + 1) * sizeof(WCHAR)));
5402 }
5403 }
5404 }
5405
5406done:
5407 if (lpWriteBuffer != NULL)
5408 HeapFree(GetProcessHeap(), 0, lpWriteBuffer);
5409
5410 if (lpReadBuffer != NULL)
5411 HeapFree(GetProcessHeap(), 0, lpReadBuffer);
5412
5413 return dwError;
5414}
5415
5416
5417/* Function 37 */
5418DWORD
5419WINAPI
5421 SC_RPC_HANDLE hService,
5423{
5424 DWORD dwError = ERROR_SUCCESS;
5425 PSERVICE_HANDLE hSvc;
5426 PSERVICE lpService = NULL;
5427 HKEY hServiceKey = NULL;
5429
5430 DPRINT("RChangeServiceConfig2W() called\n");
5431 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
5432
5433 if (ScmShutdown)
5435
5436 if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
5437 (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
5438 {
5439 return ERROR_INVALID_LEVEL;
5440 }
5441
5442 hSvc = ScmGetServiceFromHandle(hService);
5443 if (hSvc == NULL)
5444 {
5445 DPRINT("Invalid service handle\n");
5446 return ERROR_INVALID_HANDLE;
5447 }
5448
5449 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5451
5452 /* Check the access rights */
5455 {
5456 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
5457 return ERROR_ACCESS_DENIED;
5458 }
5459
5460 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5461 {
5462 /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */
5463
5464 }
5465
5466 lpService = hSvc->ServiceEntry;
5467 if (lpService == NULL)
5468 {
5469 DPRINT("lpService == NULL\n");
5470 return ERROR_INVALID_HANDLE;
5471 }
5472
5473 /* Failure actions can only be set for Win32 services, not for drivers */
5474 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5475 {
5476 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
5478 }
5479
5480 /* Lock the service database exclusively */
5482
5483 if (lpService->bDeleted)
5484 {
5485 DPRINT("Service has already been marked for delete\n");
5487 goto done;
5488 }
5489
5490 /* Open the service key */
5491 dwError = ScmOpenServiceKey(lpService->szServiceName,
5493 &hServiceKey);
5494 if (dwError != ERROR_SUCCESS)
5495 goto done;
5496
5497 if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
5498 {
5499 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd;
5500
5501 /* Modify the service description, if specified */
5502 if (lpServiceDescription != NULL &&
5503 lpServiceDescription->lpDescription != NULL)
5504 {
5505 /* If the description is "" then we delete it */
5506 if (*lpServiceDescription->lpDescription == 0)
5507 {
5508 DPRINT("Delete service description\n");
5509 dwError = RegDeleteValueW(hServiceKey, L"Description");
5510
5511 if (dwError == ERROR_FILE_NOT_FOUND)
5512 dwError = ERROR_SUCCESS;
5513 }
5514 else
5515 {
5516 DPRINT("Setting service description value %S\n", lpServiceDescription->lpDescription);
5517 dwError = RegSetValueExW(hServiceKey,
5518 L"Description",
5519 0,
5520 REG_SZ,
5521 (LPBYTE)lpServiceDescription->lpDescription,
5522 (DWORD)((wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR)));
5523 }
5524 }
5525 else
5526 {
5527 dwError = ERROR_SUCCESS;
5528 }
5529 }
5530 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
5531 {
5532 dwError = ScmSetFailureActions(hServiceKey,
5534 }
5535
5536done:
5537 if (hServiceKey != NULL)
5538 RegCloseKey(hServiceKey);
5539
5540 /* Unlock the service database */
5542
5543 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError);
5544
5545 return dwError;
5546}
5547
5548
5549/* Function 38 */
5550DWORD
5551WINAPI
5553 SC_RPC_HANDLE hService,
5558{
5559 DWORD dwError = ERROR_SUCCESS;
5560 PSERVICE_HANDLE hSvc;
5561 PSERVICE lpService = NULL;
5562 HKEY hServiceKey = NULL;
5563 DWORD dwRequiredSize = 0;
5564 DWORD dwType = 0;
5565 LPWSTR lpDescriptionW = NULL;
5566 LPWSTR lpRebootMessageW = NULL;
5567 LPWSTR lpFailureCommandW = NULL;
5568
5569 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
5571
5572 if (!lpBuffer)
5573 return ERROR_INVALID_ADDRESS;
5574
5575 if (ScmShutdown)
5577
5580 {
5581 return ERROR_INVALID_LEVEL;
5582 }
5583
5584 hSvc = ScmGetServiceFromHandle(hService);
5585 if (hSvc == NULL)
5586 {
5587 DPRINT1("Invalid service handle\n");
5588 return ERROR_INVALID_HANDLE;
5589 }
5590
5593 {
5594 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
5595 return ERROR_ACCESS_DENIED;
5596 }
5597
5598 lpService = hSvc->ServiceEntry;
5599 if (lpService == NULL)
5600 {
5601 DPRINT("lpService == NULL\n");
5602 return ERROR_INVALID_HANDLE;
5603 }
5604
5605 /* Lock the service database shared */
5607
5608 dwError = ScmOpenServiceKey(lpService->lpServiceName,
5609 KEY_READ,
5610 &hServiceKey);
5611 if (dwError != ERROR_SUCCESS)
5612 goto done;
5613
5615 {
5617 LPSTR lpStr;
5618
5619 dwError = ScmReadString(hServiceKey,
5620 L"Description",
5621 &lpDescriptionW);
5622 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
5623 goto done;
5624
5626 if (dwError == ERROR_SUCCESS)
5627 *pcbBytesNeeded += (DWORD)((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR));
5628
5630 {
5631 dwError = ERROR_INSUFFICIENT_BUFFER;
5632 goto done;
5633 }
5634
5635 if (dwError == ERROR_SUCCESS)
5636 {
5637 lpStr = (LPSTR)(lpServiceDescription + 1);
5638
5640 0,
5641 lpDescriptionW,
5642 -1,
5643 lpStr,
5644 (int)wcslen(lpDescriptionW),
5645 NULL,
5646 NULL);
5647 lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
5648 }
5649 else
5650 {
5651 lpServiceDescription->lpDescription = NULL;
5652 dwError = ERROR_SUCCESS;
5653 }
5654 }
5656 {
5658 LPSTR lpStr = NULL;
5659
5660 /* Query value length */
5661 dwError = RegQueryValueExW(hServiceKey,
5662 L"FailureActions",
5663 NULL,
5664 &dwType,
5665 NULL,
5666 &dwRequiredSize);
5667 if (dwError != ERROR_SUCCESS &&
5668 dwError != ERROR_MORE_DATA &&
5669 dwError != ERROR_FILE_NOT_FOUND)
5670 {
5671 goto done;
5672 }
5673
5674 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize)
5675 : sizeof(SERVICE_FAILURE_ACTIONSA);
5676
5677 /* Get the strings */
5678 ScmReadString(hServiceKey,
5679 L"FailureCommand",
5680 &lpFailureCommandW);
5681
5682 ScmReadString(hServiceKey,
5683 L"RebootMessage",
5684 &lpRebootMessageW);
5685
5686 if (lpRebootMessageW)
5687 dwRequiredSize += (DWORD)((wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR));
5688
5689 if (lpFailureCommandW)
5690 dwRequiredSize += (DWORD)((wcslen(lpFailureCommandW) + 1) * sizeof(WCHAR));
5691
5692 if (cbBufSize < dwRequiredSize)
5693 {
5694 *pcbBytesNeeded = dwRequiredSize;
5695 dwError = ERROR_INSUFFICIENT_BUFFER;
5696 goto done;
5697 }
5698
5699 /* Now we can fill the buffer */
5700 if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY)
5701 {
5702 dwError = RegQueryValueExW(hServiceKey,
5703 L"FailureActions",
5704 NULL,
5705 NULL,
5706 (LPBYTE)lpFailureActions,
5707 &dwRequiredSize);
5708 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
5709 goto done;
5710
5711 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSA))
5712 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSA);
5713 }
5714 else
5715 {
5716 /*
5717 * The value of the error doesn't really matter, the only
5718 * important thing is that it must be != ERROR_SUCCESS .
5719 */
5720 dwError = ERROR_INVALID_DATA;
5721 }
5722
5723 if (dwError == ERROR_SUCCESS)
5724 {
5725 lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSA)) / sizeof(SC_ACTION));
5726
5727 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5728 lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSA) : NULL);
5729
5730 lpStr = (LPSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION));
5731 }
5732 else
5733 {
5734 lpFailureActions->dwResetPeriod = 0;
5735 lpFailureActions->cActions = 0;
5736 lpFailureActions->lpsaActions = NULL;
5737 lpStr = (LPSTR)(lpFailureActions + 1);
5738 }
5739
5740 lpFailureActions->lpRebootMsg = NULL;
5741 lpFailureActions->lpCommand = NULL;
5742
5743 if (lpRebootMessageW)
5744 {
5746 0,
5747 lpRebootMessageW,
5748 -1,
5749 lpStr,
5750 (int)wcslen(lpRebootMessageW),
5751 NULL,
5752 NULL);
5753 lpFailureActions->lpRebootMsg = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
5754 lpStr += strlen(lpStr) + 1;
5755 }
5756
5757 if (lpFailureCommandW)
5758 {
5760 0,
5761 lpFailureCommandW,
5762 -1,
5763 lpStr,
5764 (int)wcslen(lpFailureCommandW),
5765 NULL,
5766 NULL);
5767 lpFailureActions->lpCommand = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
5768 /* lpStr += strlen(lpStr) + 1; */
5769 }
5770
5771 dwError = ERROR_SUCCESS;
5772 }
5773
5774done:
5775 /* Unlock the service database */
5777
5778 if (lpDescriptionW != NULL)
5779 HeapFree(GetProcessHeap(), 0, lpDescriptionW);
5780
5781 if (lpRebootMessageW != NULL)
5782 HeapFree(GetProcessHeap(), 0, lpRebootMessageW);
5783
5784 if (lpFailureCommandW != NULL)
5785 HeapFree(GetProcessHeap(), 0, lpFailureCommandW);
5786
5787 if (hServiceKey != NULL)
5788 RegCloseKey(hServiceKey);
5789
5790 DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError);
5791
5792 return dwError;
5793}
5794
5795
5796/* Function 39 */
5797DWORD
5798WINAPI
5800 SC_RPC_HANDLE hService,
5805{
5806 DWORD dwError = ERROR_SUCCESS;
5807 PSERVICE_HANDLE hSvc;
5808 PSERVICE lpService = NULL;
5809 HKEY hServiceKey = NULL;
5810 DWORD dwRequiredSize = 0;
5811 DWORD dwType = 0;
5812 LPWSTR lpDescription = NULL;
5813 LPWSTR lpRebootMessage = NULL;
5814 LPWSTR lpFailureCommand = NULL;
5815
5816 DPRINT("RQueryServiceConfig2W() called\n");
5817
5818 if (!lpBuffer)
5819 return ERROR_INVALID_ADDRESS;
5820
5821 if (ScmShutdown)
5823
5826 {
5827 return ERROR_INVALID_LEVEL;
5828 }
5829
5830 hSvc = ScmGetServiceFromHandle(hService);
5831 if (hSvc == NULL)
5832 {
5833 DPRINT1("Invalid service handle\n");
5834 return ERROR_INVALID_HANDLE;
5835 }
5836
5839 {
5840 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
5841 return ERROR_ACCESS_DENIED;
5842 }
5843
5844 lpService = hSvc->ServiceEntry;
5845 if (lpService == NULL)
5846 {
5847 DPRINT("lpService == NULL\n");
5848 return ERROR_INVALID_HANDLE;
5849 }
5850
5851 /* Lock the service database shared */
5853
5854 dwError = ScmOpenServiceKey(lpService->lpServiceName,
5855 KEY_READ,
5856 &hServiceKey);
5857 if (dwError != ERROR_SUCCESS)
5858 goto done;
5859
5861 {
5863 LPWSTR lpStr;
5864
5865 dwError = ScmReadString(hServiceKey,
5866 L"Description",
5867 &lpDescription);
5868 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
5869 goto done;
5870
5872 if (dwError == ERROR_SUCCESS)
5873 *pcbBytesNeeded += (DWORD)((wcslen(lpDescription) + 1) * sizeof(WCHAR));
5874
5876 {
5877 dwError = ERROR_INSUFFICIENT_BUFFER;
5878 goto done;
5879 }
5880
5881 if (dwError == ERROR_SUCCESS)
5882 {
5883 lpStr = (LPWSTR)(lpServiceDescription + 1);
5884 wcscpy(lpStr, lpDescription);
5885 lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
5886 }
5887 else
5888 {
5889 lpServiceDescription->lpDescription = NULL;
5890 dwError = ERROR_SUCCESS;
5891 }
5892 }
5894 {
5896 LPWSTR lpStr = NULL;
5897
5898 /* Query value length */
5899 dwError = RegQueryValueExW(hServiceKey,
5900 L"FailureActions",
5901 NULL,
5902 &dwType,
5903 NULL,
5904 &dwRequiredSize);
5905 if (dwError != ERROR_SUCCESS &&
5906 dwError != ERROR_MORE_DATA &&
5907 dwError != ERROR_FILE_NOT_FOUND)
5908 {
5909 goto done;
5910 }
5911
5912 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
5913 : sizeof(SERVICE_FAILURE_ACTIONSW);
5914
5915 /* Get the strings */
5916 ScmReadString(hServiceKey,
5917 L"FailureCommand",
5918 &lpFailureCommand);
5919
5920 ScmReadString(hServiceKey,
5921 L"RebootMessage",
5922 &lpRebootMessage);
5923
5924 if (lpRebootMessage)
5925 dwRequiredSize += (DWORD)((wcslen(lpRebootMessage) + 1) * sizeof(WCHAR));
5926
5927 if (lpFailureCommand)
5928 dwRequiredSize += (DWORD)((wcslen(lpFailureCommand) + 1) * sizeof(WCHAR));
5929
5930 if (cbBufSize < dwRequiredSize)
5931 {
5932 *pcbBytesNeeded = dwRequiredSize;
5933 dwError = ERROR_INSUFFICIENT_BUFFER;
5934 goto done;
5935 }
5936
5937 /* Now we can fill the buffer */
5938 if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY)
5939 {
5940 dwError = RegQueryValueExW(hServiceKey,
5941 L"FailureActions",
5942 NULL,
5943 NULL,
5944 (LPBYTE)lpFailureActions,
5945 &dwRequiredSize);
5946 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
5947 goto done;
5948
5949 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW))
5950 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
5951 }
5952 else
5953 {
5954 /*
5955 * The value of the error doesn't really matter, the only
5956 * important thing is that it must be != ERROR_SUCCESS .
5957 */
5958 dwError = ERROR_INVALID_DATA;
5959 }
5960
5961 if (dwError == ERROR_SUCCESS)
5962 {
5963 lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION));
5964
5965 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
5966 lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSW) : NULL);
5967
5968 lpStr = (LPWSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION));
5969 }
5970 else
5971 {
5972 lpFailureActions->dwResetPeriod = 0;
5973 lpFailureActions->cActions = 0;
5974 lpFailureActions->lpsaActions = NULL;
5975 lpStr = (LPWSTR)(lpFailureActions + 1);
5976 }
5977
5978 lpFailureActions->lpRebootMsg = NULL;
5979 lpFailureActions->lpCommand = NULL;
5980
5981 if (lpRebootMessage)
5982 {
5983 wcscpy(lpStr, lpRebootMessage);
5984 lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
5985 lpStr += wcslen(lpStr) + 1;
5986 }
5987
5988 if (lpFailureCommand)
5989 {
5990 wcscpy(lpStr, lpFailureCommand);
5991 lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
5992 /* lpStr += wcslen(lpStr) + 1; */
5993 }
5994
5995 dwError = ERROR_SUCCESS;
5996 }
5997
5998done:
5999 /* Unlock the service database */
6001
6002 if (lpDescription != NULL)
6003 HeapFree(GetProcessHeap(), 0, lpDescription);
6004
6005 if (lpRebootMessage != NULL)
6006 HeapFree(GetProcessHeap(), 0, lpRebootMessage);
6007
6008 if (lpFailureCommand != NULL)
6009 HeapFree(GetProcessHeap(), 0, lpFailureCommand);
6010
6011 if (hServiceKey != NULL)
6012 RegCloseKey(hServiceKey);
6013
6014 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
6015
6016 return dwError;
6017}
6018
6019
6020/* Function 40 */
6021DWORD
6022WINAPI
6024 SC_RPC_HANDLE hService,
6025 SC_STATUS_TYPE InfoLevel,
6029{
6030 LPSERVICE_STATUS_PROCESS lpStatus;
6031 PSERVICE_HANDLE hSvc;
6032 PSERVICE lpService;
6033
6034 DPRINT("RQueryServiceStatusEx() called\n");
6035
6036 if (ScmShutdown)
6038
6039 if (InfoLevel != SC_STATUS_PROCESS_INFO)
6040 return ERROR_INVALID_LEVEL;
6041
6043
6044 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
6046
6047 hSvc = ScmGetServiceFromHandle(hService);
6048 if (hSvc == NULL)
6049 {
6050 DPRINT1("Invalid service handle\n");
6051 return ERROR_INVALID_HANDLE;
6052 }
6053
6056 {
6057 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
6058 return ERROR_ACCESS_DENIED;
6059 }
6060
6061 lpService = hSvc->ServiceEntry;
6062 if (lpService == NULL)
6063 {
6064 DPRINT("lpService == NULL\n");
6065 return ERROR_INVALID_HANDLE;
6066 }
6067
6068 /* Lock the service database shared */
6070
6072
6073 /* Return service status information */
6074 RtlCopyMemory(lpStatus,
6075 &lpService->Status,
6076 sizeof(SERVICE_STATUS));
6077
6078 /* Copy the service process ID */
6079 if ((lpService->Status.dwCurrentState == SERVICE_STOPPED) || (lpService->lpImage == NULL))
6080 lpStatus->dwProcessId = 0;
6081 else
6082 lpStatus->dwProcessId = lpService->lpImage->dwProcessId;
6083
6084 lpStatus->dwServiceFlags = 0; /* FIXME */
6085
6086 /* Unlock the service database */
6088
6089 return ERROR_SUCCESS;
6090}
6091
6092
6093/* Function 41 */
6094DWORD
6095WINAPI
6098 SC_ENUM_TYPE InfoLevel,
6099 DWORD dwServiceType,
6100 DWORD dwServiceState,
6104 LPBOUNDED_DWORD_256K lpServicesReturned,
6105 LPBOUNDED_DWORD_256K lpResumeIndex,
6106 LPCSTR pszGroupName)
6107{
6108 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL;
6109 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW;
6110 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL;
6111 LPWSTR lpStringPtrW;
6112 LPSTR lpStringPtrA;
6113 LPWSTR pszGroupNameW = NULL;
6114 DWORD dwError;
6115 DWORD dwServiceCount;
6116
6117 DPRINT("REnumServicesStatusExA() called\n");
6118
6119 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
6120 {
6121 return ERROR_INVALID_ADDRESS;
6122 }
6123
6124 if (pszGroupName)
6125 {
6126 pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR));
6127 if (!pszGroupNameW)
6128 {
6129 DPRINT("Failed to allocate buffer\n");
6130 dwError = ERROR_NOT_ENOUGH_MEMORY;
6131 goto Done;
6132 }
6133
6135 0,
6136 pszGroupName,
6137 -1,
6138 pszGroupNameW,
6139 (int)(strlen(pszGroupName) + 1));
6140 }
6141
6142 if ((cbBufSize > 0) && (lpBuffer))
6143 {
6145 if (!lpStatusPtrW)
6146 {
6147 DPRINT("Failed to allocate buffer\n");
6148 dwError = ERROR_NOT_ENOUGH_MEMORY;
6149 goto Done;
6150 }
6151 }
6152
6154 InfoLevel,
6155 dwServiceType,
6156 dwServiceState,
6157 (LPBYTE)lpStatusPtrW,
6158 cbBufSize,
6160 lpServicesReturned,
6161 lpResumeIndex,
6162 pszGroupNameW);
6163
6164 /* if no services were returned then we are Done */
6165 if (*lpServicesReturned == 0)
6166 goto Done;
6167
6168 lpStatusPtrIncrW = lpStatusPtrW;
6170 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
6171 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA));
6172 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW +
6173 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
6174
6175 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
6176 {
6177 /* Copy the service name */
6179 0,
6180 lpStringPtrW,
6181 -1,
6182 lpStringPtrA,
6183 (int)wcslen(lpStringPtrW),
6184 0,
6185 0);
6186
6187 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
6188 lpStringPtrA += wcslen(lpStringPtrW) + 1;
6189 lpStringPtrW += wcslen(lpStringPtrW) + 1;
6190
6191 /* Copy the display name */
6193 0,
6194 lpStringPtrW,
6195 -1,
6196 lpStringPtrA,
6197 (int)wcslen(lpStringPtrW),
6198 0,
6199 0);
6200
6201 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
6202 lpStringPtrA += wcslen(lpStringPtrW) + 1;
6203 lpStringPtrW += wcslen(lpStringPtrW) + 1;
6204
6205 /* Copy the status information */
6206 memcpy(&lpStatusPtrA->ServiceStatusProcess,
6207 &lpStatusPtrIncrW->ServiceStatusProcess,
6208 sizeof(SERVICE_STATUS));
6209
6210 /* Copy the service process ID */
6211 lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrIncrW->ServiceStatusProcess.dwProcessId;
6212
6213 lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
6214
6215 lpStatusPtrIncrW++;
6216 lpStatusPtrA++;
6217 }
6218
6219Done:
6220 if (pszGroupNameW)
6221 HeapFree(GetProcessHeap(), 0, pszGroupNameW);
6222
6223 if (lpStatusPtrW)
6224 HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
6225
6226 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError);
6227
6228 return dwError;
6229}
6230
6231
6232/* Function 42 */
6233DWORD
6234WINAPI
6237 SC_ENUM_TYPE InfoLevel,
6238 DWORD dwServiceType,
6239 DWORD dwServiceState,
6243 LPBOUNDED_DWORD_256K lpServicesReturned,
6244 LPBOUNDED_DWORD_256K lpResumeIndex,
6245 LPCWSTR pszGroupName)
6246{
6247 PMANAGER_HANDLE hManager;
6248 PSERVICE lpService;
6249 DWORD dwError = ERROR_SUCCESS;
6250 PLIST_ENTRY ServiceEntry;
6251 PSERVICE CurrentService;
6252 DWORD dwState;
6253 DWORD dwRequiredSize;
6254 DWORD dwServiceCount;
6255 DWORD dwSize;
6256 DWORD dwLastResumeCount = 0;
6258 LPWSTR lpStringPtr;
6259
6260 DPRINT("REnumServicesStatusExW() called\n");
6261
6262 if (ScmShutdown)
6264
6265 if (InfoLevel != SC_ENUM_PROCESS_INFO)
6266 return ERROR_INVALID_LEVEL;
6267
6269 if (hManager == NULL)
6270 {
6271 DPRINT1("Invalid service manager handle\n");
6272 return ERROR_INVALID_HANDLE;
6273 }
6274
6275 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
6276 {
6277 return ERROR_INVALID_ADDRESS;
6278 }
6279
6280 *pcbBytesNeeded = 0;
6281 *lpServicesReturned = 0;
6282
6283 if ((dwServiceType == 0) ||
6284 ((dwServiceType & ~SERVICE_TYPE_ALL) != 0))
6285 {
6286 DPRINT("Invalid Service Type\n");
6288 }
6289
6290 if ((dwServiceState == 0) ||
6291 ((dwServiceState & ~SERVICE_STATE_ALL) != 0))
6292 {
6293 DPRINT("Invalid Service State\n");
6295 }
6296
6297 /* Check access rights */
6300 {
6301 DPRINT("Insufficient access rights 0x%lx\n",
6302 hManager->Handle.DesiredAccess);
6303 return ERROR_ACCESS_DENIED;
6304 }
6305
6306 if (lpResumeIndex)
6307 dwLastResumeCount = *lpResumeIndex;
6308
6309 /* Lock the service database shared */
6311
6312 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
6313 if (lpService == NULL)
6314 {
6315 dwError = ERROR_SUCCESS;
6316 goto Done;
6317 }
6318
6319 dwRequiredSize = 0;
6320 dwServiceCount = 0;
6321
6322 for (ServiceEntry = &lpService->ServiceListEntry;
6323 ServiceEntry != &ServiceListHead;
6324 ServiceEntry = ServiceEntry->Flink)
6325 {
6326 CurrentService = CONTAINING_RECORD(ServiceEntry,
6327 SERVICE,
6328 ServiceListEntry);
6329
6330 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
6331 continue;
6332
6333 dwState = SERVICE_ACTIVE;
6334 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
6335 dwState = SERVICE_INACTIVE;
6336
6337 if ((dwState & dwServiceState) == 0)
6338 continue;
6339
6340 if (pszGroupName)
6341 {
6342 if (*pszGroupName == 0)
6343 {
6344 if (CurrentService->lpGroup != NULL)
6345 continue;
6346 }
6347 else
6348 {
6349 if ((CurrentService->lpGroup == NULL) ||
6350 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
6351 continue;
6352 }
6353 }
6354
6356 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
6357 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
6358
6359 if (dwRequiredSize + dwSize <= cbBufSize)
6360 {
6361 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
6362 dwRequiredSize += dwSize;
6363 dwServiceCount++;
6364 dwLastResumeCount = CurrentService->dwResumeCount;
6365 }
6366 else
6367 {
6368 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
6369 break;
6370 }
6371
6372 }
6373
6374 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
6375 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
6376
6377 for (;
6378 ServiceEntry != &ServiceListHead;
6379 ServiceEntry = ServiceEntry->Flink)
6380 {
6381 CurrentService = CONTAINING_RECORD(ServiceEntry,
6382 SERVICE,
6383 ServiceListEntry);
6384
6385 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
6386 continue;
6387
6388 dwState = SERVICE_ACTIVE;
6389 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
6390 dwState = SERVICE_INACTIVE;
6391
6392 if ((dwState & dwServiceState) == 0)
6393 continue;
6394
6395 if (pszGroupName)
6396 {
6397 if (*pszGroupName == 0)
6398 {
6399 if (CurrentService->lpGroup != NULL)
6400 continue;
6401 }
6402 else
6403 {
6404 if ((CurrentService->lpGroup == NULL) ||
6405 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
6406 continue;
6407 }
6408 }
6409
6410 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
6411 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
6412 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
6413
6414 dwError = ERROR_MORE_DATA;
6415 }
6416
6417 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
6418
6419 if (lpResumeIndex)
6420 *lpResumeIndex = dwLastResumeCount;
6421
6422 *lpServicesReturned = dwServiceCount;
6423 *pcbBytesNeeded = dwRequiredSize;
6424
6425 /* If there was no services that matched */
6426 if ((!dwServiceCount) && (dwError != ERROR_MORE_DATA))
6427 {
6429 goto Done;
6430 }
6431
6433 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
6434 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
6435
6436 dwRequiredSize = 0;
6437 for (ServiceEntry = &lpService->ServiceListEntry;
6438 ServiceEntry != &ServiceListHead;
6439 ServiceEntry = ServiceEntry->Flink)
6440 {
6441 CurrentService = CONTAINING_RECORD(ServiceEntry,
6442 SERVICE,
6443 ServiceListEntry);
6444
6445 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
6446 continue;
6447
6448 dwState = SERVICE_ACTIVE;
6449 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
6450 dwState = SERVICE_INACTIVE;
6451
6452 if ((dwState & dwServiceState) == 0)
6453 continue;
6454
6455 if (pszGroupName)
6456 {
6457 if (*pszGroupName == 0)
6458 {
6459 if (CurrentService->lpGroup != NULL)
6460 continue;
6461 }
6462 else
6463 {
6464 if ((CurrentService->lpGroup == NULL) ||
6465 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
6466 continue;
6467 }
6468 }
6469
6471 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
6472 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
6473
6474 if (dwRequiredSize + dwSize <= cbBufSize)
6475 {
6476 /* Copy the service name */
6477 wcscpy(lpStringPtr,
6478 CurrentService->lpServiceName);
6479 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
6480 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
6481
6482 /* Copy the display name */
6483 wcscpy(lpStringPtr,
6484 CurrentService->lpDisplayName);
6485 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
6486 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
6487
6488 /* Copy the status information */
6489 memcpy(&lpStatusPtr->ServiceStatusProcess,
6490 &CurrentService->Status,
6491 sizeof(SERVICE_STATUS));
6492
6493 /* Copy the service process ID */
6494 if ((CurrentService->Status.dwCurrentState == SERVICE_STOPPED) || (CurrentService->lpImage == NULL))
6495 lpStatusPtr->ServiceStatusProcess.dwProcessId = 0;
6496 else
6497 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->lpImage->dwProcessId;
6498
6499 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
6500
6501 lpStatusPtr++;
6502 dwRequiredSize += dwSize;
6503 }
6504 else
6505 {
6506 break;
6507 }
6508 }
6509
6510 if (dwError == 0)
6511 {
6512 *pcbBytesNeeded = 0;
6513 if (lpResumeIndex)
6514 *lpResumeIndex = 0;
6515 }
6516
6517Done:
6518 /* Unlock the service database */
6520
6521 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError);
6522
6523 return dwError;
6524}
6525
6526
6527/* Function 43 */
6528DWORD
6529WINAPI
6531 handle_t BindingHandle) /* FIXME */
6532{
6535}
6536
6537
6538/* Function 44 */
6539DWORD
6540WINAPI
6543 LPSTR lpServiceName,
6545 DWORD dwDesiredAccess,
6546 DWORD dwServiceType,
6547 DWORD dwStartType,
6548 DWORD dwErrorControl,
6549 LPSTR lpBinaryPathName,
6550 LPSTR lpLoadOrderGroup,
6551 LPDWORD lpdwTagId,
6552 LPBYTE lpDependencies,
6553 DWORD dwDependSize,
6554 LPSTR lpServiceStartName,
6555 LPBYTE lpPassword,
6556 DWORD dwPwSize,
6557 LPSC_RPC_HANDLE lpServiceHandle)
6558{
6561}
6562
6563
6564/* Function 45 */
6565DWORD
6566WINAPI
6569 LPWSTR lpServiceName,
6571 DWORD dwDesiredAccess,
6572 DWORD dwServiceType,
6573 DWORD dwStartType,
6574 DWORD dwErrorControl,
6575 LPWSTR lpBinaryPathName,
6576 LPWSTR lpLoadOrderGroup,
6577 LPDWORD lpdwTagId,
6578 LPBYTE lpDependencies,
6579 DWORD dwDependSize,
6580 LPWSTR lpServiceStartName,
6581 LPBYTE lpPassword,
6582 DWORD dwPwSize,
6583 LPSC_RPC_HANDLE lpServiceHandle)
6584{
6587}
6588
6589
6590/* Function 46 */
6591DWORD
6592WINAPI
6598{
6599 PMANAGER_HANDLE hManager;
6600
6601 /* Validate handle */
6603 if (hManager == NULL)
6604 {
6605 return ERROR_INVALID_HANDLE;
6606 }
6607
6608 /* FIXME: should check whether client is local */
6609
6610 /* Check access rights */
6613 {
6614 return ERROR_ACCESS_DENIED;
6615 }
6616
6617 /* Check parameters */
6618 if (lpInParams == NULL || lpOutParams == NULL)
6619 {
6621 }
6622
6623 /* Check info level */
6625 {
6626 return ERROR_RETRY;
6627 }
6628
6629 /* Call internal helper */
6630 return ScmGetServiceNameFromTag(*lpInParams, lpOutParams);
6631}
6632
6633
6634/* Function 47 */
6635DWORD
6636WINAPI
6638 SC_RPC_HANDLE hService,
6639 SC_RPC_NOTIFY_PARAMS NotifyParams,
6640 GUID *pClientProcessGuid,
6641 GUID *pSCMProcessGuid,
6642 PBOOL pfCreateRemoteQueue,
6643 LPSC_NOTIFY_RPC_HANDLE phNotify)
6644{
6647}
6648
6649
6650/* Function 48 */
6651DWORD
6652WINAPI
6654 SC_NOTIFY_RPC_HANDLE hNotify,
6655 PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams)
6656{
6659}
6660
6661
6662/* Function 49 */
6663DWORD
6664WINAPI
6666 LPSC_NOTIFY_RPC_HANDLE phNotify,
6667 PBOOL pfApcFired)
6668{
6671}
6672
6673
6674/* Function 50 */
6675DWORD
6676WINAPI
6678 SC_RPC_HANDLE hService,
6679 DWORD dwControl,
6681{
6684}
6685
6686
6687/* Function 51 */
6688DWORD
6689WINAPI
6691 SC_RPC_HANDLE hService,
6692 DWORD dwControl,
6694{
6697}
6698
6699
6700/* Function 52 */
6701DWORD
6702WINAPI
6704 handle_t BindingHandle) /* FIXME */
6705{
6708}
6709
6710
6711/* Function 53 */
6712DWORD
6713WINAPI
6716 _In_ LPWSTR pszServiceName,
6717 _Out_ RPC_SERVICE_STATUS_HANDLE *phServiceStatus)
6718{
6719 PMANAGER_HANDLE hManager;
6720 PSERVICE pService;
6721
6722 DPRINT("RI_ScValidatePnPService(%p %S %p)\n", hSCManager, pszServiceName, phServiceStatus);
6723
6724 /* Validate handle */
6726 if (hManager == NULL)
6727 {
6728 DPRINT1("Invalid handle!\n");
6729 return ERROR_INVALID_HANDLE;
6730 }
6731
6732 /* FIXME: should check whether client is local */
6733
6734 /* Check access rights */
6737 {
6738 DPRINT1("No SC_MANAGER_CONNECT access!\n");
6739 return ERROR_ACCESS_DENIED;
6740 }
6741
6742 pService = ScmGetServiceEntryByName(pszServiceName);
6743 DPRINT("pService: %p\n", pService);
6744 if (pService == NULL)
6746
6747 *phServiceStatus = (RPC_SERVICE_STATUS_HANDLE)pService;
6748
6749 return ERROR_SUCCESS;
6750}
6751
6752
6753/* Function 54 */
6754DWORD
6755WINAPI
6757 handle_t BindingHandle) /* FIXME */
6758{
6761}
6762
6763
6764/* Function 55 */
6765DWORD
6766WINAPI
6768 handle_t BindingHandle) /* FIXME */
6769{
6772}
6773
6774
6776{
6778}
6779
6780
6782{
6784}
6785
6786
6788{
6789 /* Close the handle */
6790 RCloseServiceHandle(&hSCObject);
6791}
6792
6793
6795{
6796 /* Unlock the database */
6798}
6799
6800
6802{
6803}
6804
6805/* 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 ScmDeleteRegKey(_In_ HKEY hKey, _In_ PCWSTR pszSubKey)
Definition: config.c:646
DWORD ScmCreateServiceKey(LPCWSTR lpServiceName, REGSAM samDesired, PHKEY phKey)
Definition: config.c:72
PSERVICE ScmGetServiceEntryByResumeCount(DWORD dwResumeCount)
Definition: database.c:715
VOID ScmRemoveServiceImage(PSERVICE_IMAGE pServiceImage)
Definition: database.c:622
VOID ScmUnlockDatabase(VOID)
Definition: database.c:2434
DWORD ScmControlService(HANDLE hControlPipe, PWSTR pServiceName, SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwControl)
Definition: database.c:1314
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
VOID ScmDeleteServiceRecord(PSERVICE lpService)
Definition: database.c:816
BOOL ScmLockDatabaseExclusive(VOID)
Definition: database.c:2420
DWORD ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
Definition: database.c:2131
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:2427
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:936
DWORD WINAPI RChangeServiceConfig2W(SC_RPC_HANDLE hService, SC_RPC_CONFIG_INFOW Info)
Definition: rpcserver.c:5420
DWORD WINAPI RDeleteService(SC_RPC_HANDLE hService)
Definition: rpcserver.c:1304
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:3211
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:1390
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:5019
struct _MANAGER_HANDLE * PMANAGER_HANDLE
DWORD WINAPI ROpenSCManagerW(LPWSTR lpMachineName, LPWSTR lpDatabaseName, DWORD dwDesiredAccess, LPSC_RPC_HANDLE lpScHandle)
Definition: rpcserver.c:2868
#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:1849
#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:3254
struct _SERVICE_HANDLE * PSERVICE_HANDLE
DWORD WINAPI RGetServiceKeyNameA(SC_RPC_HANDLE hSCManager, LPCSTR lpDisplayName, LPSTR lpServiceName, LPBOUNDED_DWORD_4K lpcchBuffer)
Definition: rpcserver.c:4582
#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:2272
static DWORD Int_EnumDependentServicesW(HKEY hServicesKey, PSERVICE lpService, DWORD dwServiceState, PSERVICE *lpServices, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned)
Definition: rpcserver.c:783
DWORD WINAPI RUnlockServiceDatabase(LPSC_RPC_LOCK Lock)
Definition: rpcserver.c:1838
static BOOL ScmIsValidServiceState(DWORD dwCurrentState)
Definition: rpcserver.c:1657
DWORD WINAPI ROpenServiceW(SC_RPC_HANDLE hSCManager, LPWSTR lpServiceName, DWORD dwDesiredAccess, LPSC_RPC_HANDLE lpServiceHandle)
Definition: rpcserver.c:2920
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:1920
DWORD WINAPI RControlServiceExA(SC_RPC_HANDLE hService, DWORD dwControl, DWORD dwInfoLevel)
Definition: rpcserver.c:6677
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:3899
DWORD g_dwServiceBits
Definition: rpcserver.c:102
DWORD WINAPI RLockServiceDatabase(SC_RPC_HANDLE hSCManager, LPSC_RPC_LOCK lpLock)
Definition: rpcserver.c:1362
DWORD WINAPI RQueryServiceConfig2A(SC_RPC_HANDLE hService, DWORD dwInfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPBOUNDED_DWORD_8K pcbBytesNeeded)
Definition: rpcserver.c:5552
DWORD WINAPI RQueryServiceStatus(SC_RPC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: rpcserver.c:1608
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:6637
DWORD WINAPI ROpenServiceA(SC_RPC_HANDLE hSCManager, LPSTR lpServiceName, DWORD dwDesiredAccess, LPSC_RPC_HANDLE lpServiceHandle)
Definition: rpcserver.c:4044
DWORD WINAPI RStartServiceA(SC_RPC_HANDLE hService, DWORD argc, LPSTRING_PTRSA argv)
Definition: rpcserver.c:4358
DWORD WINAPI RSendPnPMessage(handle_t BindingHandle)
Definition: rpcserver.c:6703
DWORD WINAPI RGetServiceDisplayNameW(SC_RPC_HANDLE hSCManager, LPCWSTR lpServiceName, LPWSTR lpDisplayName, DWORD *lpcchBuffer)
Definition: rpcserver.c:3317
DWORD WINAPI RQueryServiceLockStatusA(SC_RPC_HANDLE hSCManager, LPBYTE lpBuf, DWORD cbBufSize, LPBOUNDED_DWORD_4K pcbBytesNeeded)
Definition: rpcserver.c:4315
DWORD WINAPI RControlServiceExW(SC_RPC_HANDLE hService, DWORD dwControl, DWORD dwInfoLevel)
Definition: rpcserver.c:6690
DWORD WINAPI RGetServiceKeyNameW(SC_RPC_HANDLE hSCManager, LPCWSTR lpDisplayName, LPWSTR lpServiceName, DWORD *lpcchBuffer)
Definition: rpcserver.c:3380
void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject)
Definition: rpcserver.c:6787
void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify)
Definition: rpcserver.c:6801
DWORD WINAPI RGetNotifyResults(SC_NOTIFY_RPC_HANDLE hNotify, PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams)
Definition: rpcserver.c:6653
DWORD WINAPI RControlService(SC_RPC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: rpcserver.c:1069
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:5196
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:3592
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:4753
#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:6023
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:6593
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:3003
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:5799
DWORD WINAPI RSendTSMessage(handle_t BindingHandle)
Definition: rpcserver.c:6530
DWORD WINAPI RCloseNotifyHandle(LPSC_NOTIFY_RPC_HANDLE phNotify, PBOOL pfApcFired)
Definition: rpcserver.c:6665
#define TAG_ARRAY_SIZE
Definition: rpcserver.c:86
DWORD WINAPI RI_ScValidatePnPService(_In_ SC_RPC_HANDLE hSCManager, _In_ LPWSTR pszServiceName, _Out_ RPC_SERVICE_STATUS_HANDLE *phServiceStatus)
Definition: rpcserver.c:6714
DWORD WINAPI RI_ScSetServiceBitsA(RPC_SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwServiceBits, int bSetBitsOn, int bUpdateImmediately, char *lpString)
Definition: rpcserver.c:3437
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:6096
DWORD WINAPI REnumDependentServicesW(SC_RPC_HANDLE hService, DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned)
Definition: rpcserver.c:2707
DWORD WINAPI RGetServiceDisplayNameA(SC_RPC_HANDLE hSCManager, LPCSTR lpServiceName, LPSTR lpDisplayName, LPBOUNDED_DWORD_4K lpcchBuffer)
Definition: rpcserver.c:4460
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:6567
static DWORD ScmCreateManagerHandle(LPWSTR lpDatabaseName, SC_HANDLE *Handle)
Definition: rpcserver.c:144
DWORD WINAPI RFunction55(handle_t BindingHandle)
Definition: rpcserver.c:6767
DWORD WINAPI RI_ScGetCurrentGroupStateW(SC_RPC_HANDLE hSCManager, LPWSTR lpLoadOrderGroup, LPDWORD lpState)
Definition: rpcserver.c:4696
DWORD WINAPI ROpenSCManagerA(LPSTR lpMachineName, LPSTR lpDatabaseName, DWORD dwDesiredAccess, LPSC_RPC_HANDLE lpScHandle)
Definition: rpcserver.c:4006
DWORD WINAPI RSetServiceObjectSecurity(SC_RPC_HANDLE hService, DWORD dwSecurityInformation, LPBYTE lpSecurityDescriptor, DWORD dwSecurityDescriptorSize)
Definition: rpcserver.c:1474
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:3461
DWORD WINAPI RQueryServiceConfigA(SC_RPC_HANDLE hService, LPBYTE lpBuf, DWORD cbBufSize, LPBOUNDED_DWORD_8K pcbBytesNeeded)
Definition: rpcserver.c:4074
void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock)
Definition: rpcserver.c:6794
DWORD WINAPI REnumDependentServicesA(SC_RPC_HANDLE hService, DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPBOUNDED_DWORD_256K pcbBytesNeeded, LPBOUNDED_DWORD_256K lpServicesReturned)
Definition: rpcserver.c:3745
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:6235
DWORD WINAPI RI_ScSetServiceBitsW(RPC_SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwServiceBits, int bSetBitsOn, int bUpdateImmediately, wchar_t *lpString)
Definition: rpcserver.c:1866
DWORD WINAPI ROpenServiceStatusHandle(handle_t BindingHandle)
Definition: rpcserver.c:6756
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:1679
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:2842
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:6541
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:115
#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:32
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3362
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:2533
LONG WINAPI RegFlushKey(HKEY hKey)
Definition: reg.c:2980
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:4911
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2361
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:3691
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4132
static const WCHAR SystemRoot[]
Definition: reg.c:38
#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
#define wcsicmp
Definition: compat.h:15
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
#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:1646
_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:1597
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:34
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:71
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:40
LPWSTR lpGroupName
Definition: services.h:33
SCMGR_HANDLE Handle
Definition: rpcserver.c:45
PSERVICE ServiceEntry
Definition: rpcserver.c:46
HANDLE hControlPipe
Definition: services.h:51
DWORD dwProcessId
Definition: services.h:53
DWORD dwImageRunCount
Definition: services.h:49
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:66
DWORD dwServiceBits
Definition: services.h:75
PSERVICE_GROUP lpGroup
Definition: services.h:64
PSECURITY_DESCRIPTOR pSecurityDescriptor
Definition: services.h:80
DWORD dwErrorControl
Definition: services.h:72
LPWSTR lpDisplayName
Definition: services.h:63
LIST_ENTRY ServiceListEntry
Definition: services.h:61
DWORD dwResumeCount
Definition: services.h:67
SERVICE_STATUS Status
Definition: services.h:70
DWORD dwStartType
Definition: services.h:71
WCHAR szServiceName[1]
Definition: services.h:84
DWORD dwTag
Definition: services.h:73
PSERVICE_IMAGE lpImage
Definition: services.h:65
DWORD dwRefCount
Definition: services.h:68
LPWSTR lpServiceName
Definition: services.h:62
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
#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:3762
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()