ReactOS 0.4.16-dev-1292-g1ece139
database.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/database.c
5 * PURPOSE: Database control interface
6 * COPYRIGHT: Copyright 2002-2006 Eric Kohl
7 * Copyright 2006 Hervé Poussineau <hpoussin@reactos.org>
8 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
9 * Gregor Brunmar <gregor.brunmar@home.se>
10 *
11 */
12
13/* INCLUDES *****************************************************************/
14
15#include "services.h"
16
17#include <winbase_undoc.h>
18#include <userenv.h>
19#include <strsafe.h>
20
21#define NDEBUG
22#include <debug.h>
23
24
25/* GLOBALS *******************************************************************/
26
29
31static DWORD ResumeCount = 1;
33static DWORD ServiceTag = 0;
34
35/* The critical section synchronizes service control requests */
37static DWORD PipeTimeout = 30000; /* 30 Seconds */
38
39
40/* FUNCTIONS *****************************************************************/
41
42static
43BOOL
45 _In_ PSERVICE_IMAGE pServiceImage)
46{
47 return (wcsstr(pServiceImage->pszImagePath, L"\\system32\\lsass.exe") != NULL);
48}
49
50
51static DWORD
53 _In_ PSERVICE_IMAGE pServiceImage,
55{
56 WCHAR szControlPipeName[MAX_PATH + 1];
57 SECURITY_ATTRIBUTES SecurityAttributes;
58 HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
59 DWORD dwServiceCurrent = 1;
60 DWORD dwKeyDisposition;
61 DWORD dwKeySize;
62 DWORD dwError;
63
64 /* Get the service number */
66 {
67 /* TODO: Create registry entry with correct write access */
69 L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent",
70 0,
71 NULL,
74 NULL,
75 &hServiceCurrentKey,
76 &dwKeyDisposition);
77 if (dwError != ERROR_SUCCESS)
78 {
79 DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
80 return dwError;
81 }
82
83 if (dwKeyDisposition == REG_OPENED_EXISTING_KEY)
84 {
85 dwKeySize = sizeof(DWORD);
86 dwError = RegQueryValueExW(hServiceCurrentKey,
87 L"",
88 0,
89 NULL,
90 (BYTE*)&dwServiceCurrent,
91 &dwKeySize);
92 if (dwError != ERROR_SUCCESS)
93 {
94 RegCloseKey(hServiceCurrentKey);
95 DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
96 return dwError;
97 }
98
99 dwServiceCurrent++;
100 }
101
102 dwError = RegSetValueExW(hServiceCurrentKey,
103 L"",
104 0,
105 REG_DWORD,
106 (BYTE*)&dwServiceCurrent,
107 sizeof(dwServiceCurrent));
108
109 RegCloseKey(hServiceCurrentKey);
110
111 if (dwError != ERROR_SUCCESS)
112 {
113 DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
114 return dwError;
115 }
116 }
117 else
118 {
119 dwServiceCurrent = 0;
120 }
121
122 /* Create '\\.\pipe\net\NtControlPipeXXX' instance */
123 StringCchPrintfW(szControlPipeName, ARRAYSIZE(szControlPipeName),
124 L"\\\\.\\pipe\\net\\NtControlPipe%lu", dwServiceCurrent);
125
126 DPRINT("PipeName: %S\n", szControlPipeName);
127
128 SecurityAttributes.nLength = sizeof(SecurityAttributes);
129 SecurityAttributes.lpSecurityDescriptor = pPipeSD;
130 SecurityAttributes.bInheritHandle = FALSE;
131
132 pServiceImage->hControlPipe = CreateNamedPipeW(szControlPipeName,
135 100,
136 8000,
137 4,
139 &SecurityAttributes);
140 DPRINT("CreateNamedPipeW(%S) done\n", szControlPipeName);
141 if (pServiceImage->hControlPipe == INVALID_HANDLE_VALUE)
142 {
143 DPRINT1("Failed to create control pipe\n");
144 return GetLastError();
145 }
146
147 return ERROR_SUCCESS;
148}
149
150
151static PSERVICE_IMAGE
153{
154 PLIST_ENTRY ImageEntry;
155 PSERVICE_IMAGE CurrentImage;
156
157 DPRINT("ScmGetServiceImageByImagePath(%S) called\n", lpImagePath);
158
159 ImageEntry = ImageListHead.Flink;
160 while (ImageEntry != &ImageListHead)
161 {
162 CurrentImage = CONTAINING_RECORD(ImageEntry,
164 ImageListEntry);
165 if (_wcsicmp(CurrentImage->pszImagePath, lpImagePath) == 0)
166 {
167 DPRINT("Found image: '%S'\n", CurrentImage->pszImagePath);
168 return CurrentImage;
169 }
170
171 ImageEntry = ImageEntry->Flink;
172 }
173
174 DPRINT("Couldn't find a matching image\n");
175
176 return NULL;
177
178}
179
180
181DWORD
184{
185 PLIST_ENTRY ServiceEntry;
186 PSERVICE CurrentService;
187 PSERVICE_IMAGE CurrentImage;
189 DWORD dwError;
190
191 /* Lock the database */
193
194 /* Find the matching service */
195 ServiceEntry = ServiceListHead.Flink;
196 while (ServiceEntry != &ServiceListHead)
197 {
198 CurrentService = CONTAINING_RECORD(ServiceEntry,
199 SERVICE,
200 ServiceListEntry);
201
202 /* We must match the tag */
203 if (CurrentService->dwServiceTag == InParams->dwTag &&
204 CurrentService->lpImage != NULL)
205 {
206 CurrentImage = CurrentService->lpImage;
207 /* And matching the PID */
208 if (CurrentImage->dwProcessId == InParams->dwPid)
209 {
210 break;
211 }
212 }
213
214 ServiceEntry = ServiceEntry->Flink;
215 }
216
217 /* No match! */
218 if (ServiceEntry == &ServiceListHead)
219 {
220 dwError = ERROR_RETRY;
221 goto Cleanup;
222 }
223
224 /* Allocate the output buffer */
226 if (OutBuffer == NULL)
227 {
228 dwError = ERROR_NOT_ENOUGH_MEMORY;
229 goto Cleanup;
230 }
231
232 /* And the buffer for the name */
233 OutBuffer->pszName = MIDL_user_allocate(wcslen(CurrentService->lpServiceName) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
234 if (OutBuffer->pszName == NULL)
235 {
236 dwError = ERROR_NOT_ENOUGH_MEMORY;
237 goto Cleanup;
238 }
239
240 /* Fill in output data */
241 wcscpy(OutBuffer->pszName, CurrentService->lpServiceName);
242 OutBuffer->TagType = TagTypeService;
243
244 /* And return */
245 *OutParams = OutBuffer;
246 dwError = ERROR_SUCCESS;
247
248Cleanup:
249
250 /* Unlock database */
252
253 /* If failure, free allocated memory */
254 if (dwError != ERROR_SUCCESS)
255 {
256 if (OutBuffer != NULL)
257 {
259 }
260 }
261
262 /* Return error/success */
263 return dwError;
264}
265
266
267static
268BOOL
270 _In_ PCWSTR pszAccountName1,
271 _In_ PCWSTR pszAccountName2)
272{
273 if (pszAccountName1 == NULL &&
274 pszAccountName2 == NULL)
275 return TRUE;
276
277 if (pszAccountName1 == NULL &&
278 pszAccountName2 != NULL &&
279 _wcsicmp(pszAccountName2, L"LocalSystem") == 0)
280 return TRUE;
281
282 if (pszAccountName1 != NULL &&
283 pszAccountName2 == NULL &&
284 _wcsicmp(pszAccountName1, L"LocalSystem") == 0)
285 return TRUE;
286
287 if (pszAccountName1 != NULL &&
288 pszAccountName2 != NULL &&
289 _wcsicmp(pszAccountName1, pszAccountName2) == 0)
290 return TRUE;
291
292 return FALSE;
293}
294
295
296static
297BOOL
299 _In_ PCWSTR pszAccountName)
300{
301 if (pszAccountName == NULL ||
302 _wcsicmp(pszAccountName, L"LocalSystem") == 0)
303 return TRUE;
304
305 return FALSE;
306}
307
308
309static
310BOOL
312 _In_ HANDLE hToken,
314{
315 PTOKEN_PRIVILEGES pTokenPrivileges = NULL;
317 BOOL bRet = FALSE;
318
319 DPRINT("ScmEnableBackupRestorePrivileges(%p %d)\n", hToken, bEnable);
320
321 dwSize = sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES);
322 pTokenPrivileges = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
323 if (pTokenPrivileges == NULL)
324 {
325 DPRINT1("Failed to allocate privilege buffer\n");
326 goto done;
327 }
328
329 pTokenPrivileges->PrivilegeCount = 2;
330 pTokenPrivileges->Privileges[0].Luid.LowPart = SE_BACKUP_PRIVILEGE;
331 pTokenPrivileges->Privileges[0].Luid.HighPart = 0;
332 pTokenPrivileges->Privileges[0].Attributes = (bEnable ? SE_PRIVILEGE_ENABLED : 0);
333 pTokenPrivileges->Privileges[1].Luid.LowPart = SE_RESTORE_PRIVILEGE;
334 pTokenPrivileges->Privileges[1].Luid.HighPart = 0;
335 pTokenPrivileges->Privileges[1].Attributes = (bEnable ? SE_PRIVILEGE_ENABLED : 0);
336
337 bRet = AdjustTokenPrivileges(hToken, FALSE, pTokenPrivileges, 0, NULL, NULL);
338 if (!bRet)
339 {
340 DPRINT1("AdjustTokenPrivileges() failed with error %lu\n", GetLastError());
341 }
343 {
344 DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
345 bRet = FALSE;
346 }
347
348done:
349 if (pTokenPrivileges != NULL)
350 HeapFree(GetProcessHeap(), 0, pTokenPrivileges);
351
352 return bRet;
353}
354
355
356static
357DWORD
359 IN PSERVICE pService,
360 IN PSERVICE_IMAGE pImage)
361{
362 PROFILEINFOW ProfileInfo;
363 PWSTR pszUserName = NULL;
364 PWSTR pszDomainName = NULL;
365 PWSTR pszPassword = NULL;
366 PWSTR ptr;
367 DWORD dwError = ERROR_SUCCESS;
368
369 DPRINT("ScmLogonService(%p %p)\n", pService, pImage);
370 DPRINT("Service %S\n", pService->lpServiceName);
371
372 if (ScmIsLocalSystemAccount(pImage->pszAccountName) || ScmLiveSetup || ScmSetupInProgress)
373 return ERROR_SUCCESS;
374
375 /* Get the user and domain names */
376 ptr = wcschr(pImage->pszAccountName, L'\\');
377 if (ptr != NULL)
378 {
379 *ptr = L'\0';
380 pszUserName = ptr + 1;
381 pszDomainName = pImage->pszAccountName;
382 }
383 else
384 {
385 // ERROR_INVALID_SERVICE_ACCOUNT
386 pszUserName = pImage->pszAccountName;
387 pszDomainName = NULL;
388 }
389
390 /* Build the service 'password' */
391 pszPassword = HeapAlloc(GetProcessHeap(),
393 (wcslen(pService->lpServiceName) + 5) * sizeof(WCHAR));
394 if (pszPassword == NULL)
395 {
396 dwError = ERROR_NOT_ENOUGH_MEMORY;
397 goto done;
398 }
399
400 wcscpy(pszPassword, L"_SC_");
401 wcscat(pszPassword, pService->lpServiceName);
402
403 DPRINT("Domain: %S User: %S Password: %S\n", pszDomainName, pszUserName, pszPassword);
404
405 /* Do the service logon */
406 if (!LogonUserW(pszUserName,
407 pszDomainName,
408 pszPassword,
411 &pImage->hToken))
412 {
413 dwError = GetLastError();
414 DPRINT1("LogonUserW() failed (Error %lu)\n", dwError);
415
416 /* Normalize the returned error */
418 goto done;
419 }
420
421 /* Load the user profile; the per-user environment variables are thus correctly initialized */
422 ZeroMemory(&ProfileInfo, sizeof(ProfileInfo));
423 ProfileInfo.dwSize = sizeof(ProfileInfo);
424 ProfileInfo.dwFlags = PI_NOUI;
425 ProfileInfo.lpUserName = pszUserName;
426 // ProfileInfo.lpProfilePath = NULL;
427 // ProfileInfo.lpDefaultPath = NULL;
428 // ProfileInfo.lpServerName = NULL;
429 // ProfileInfo.lpPolicyPath = NULL;
430 // ProfileInfo.hProfile = NULL;
431
432 ScmEnableBackupRestorePrivileges(pImage->hToken, TRUE);
433 if (!LoadUserProfileW(pImage->hToken, &ProfileInfo))
434 dwError = GetLastError();
436
437 if (dwError != ERROR_SUCCESS)
438 {
439 DPRINT1("LoadUserProfileW() failed (Error %lu)\n", dwError);
440 goto done;
441 }
442
443 pImage->hProfile = ProfileInfo.hProfile;
444
445done:
446 if (pszPassword != NULL)
447 HeapFree(GetProcessHeap(), 0, pszPassword);
448
449 if (ptr != NULL)
450 *ptr = L'\\';
451
452 return dwError;
453}
454
455
456static DWORD
458{
460 UNICODE_STRING ImagePath;
462 PSERVICE_IMAGE pServiceImage = NULL;
464 DWORD dwError = ERROR_SUCCESS;
465 DWORD dwRecordSize;
467 BOOL bSecurityService;
468
469 DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService);
470
471 RtlInitUnicodeString(&ImagePath, NULL);
473
474 /* Get service data */
476 sizeof(QueryTable));
477
478 QueryTable[0].Name = L"ImagePath";
480 QueryTable[0].EntryContext = &ImagePath;
481 QueryTable[1].Name = L"ObjectName";
484
486 pService->lpServiceName,
488 NULL,
489 NULL);
490 if (!NT_SUCCESS(Status))
491 {
492 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
494 }
495
496 DPRINT("ImagePath: '%wZ'\n", &ImagePath);
497 DPRINT("ObjectName: '%wZ'\n", &ObjectName);
498
499 pServiceImage = ScmGetServiceImageByImagePath(ImagePath.Buffer);
500 if (pServiceImage == NULL)
501 {
502 dwRecordSize = sizeof(SERVICE_IMAGE) +
503 ImagePath.Length + sizeof(WCHAR) +
504 ((ObjectName.Length != 0) ? (ObjectName.Length + sizeof(WCHAR)) : 0);
505
506 /* Create a new service image */
507 pServiceImage = HeapAlloc(GetProcessHeap(),
509 dwRecordSize);
510 if (pServiceImage == NULL)
511 {
512 dwError = ERROR_NOT_ENOUGH_MEMORY;
513 goto done;
514 }
515
516 pServiceImage->dwImageRunCount = 1;
517 pServiceImage->hControlPipe = INVALID_HANDLE_VALUE;
518 pServiceImage->hProcess = INVALID_HANDLE_VALUE;
519
520 pString = (PWSTR)((INT_PTR)pServiceImage + sizeof(SERVICE_IMAGE));
521
522 /* Set the image path */
523 pServiceImage->pszImagePath = pString;
524 wcscpy(pServiceImage->pszImagePath,
525 ImagePath.Buffer);
526
527 /* Set the account name */
528 if (ObjectName.Length > 0)
529 {
530 pString = pString + wcslen(pString) + 1;
531
532 pServiceImage->pszAccountName = pString;
533 wcscpy(pServiceImage->pszAccountName,
534 ObjectName.Buffer);
535 }
536
537 /* Service logon */
538 dwError = ScmLogonService(pService, pServiceImage);
539 if (dwError != ERROR_SUCCESS)
540 {
541 DPRINT1("ScmLogonService() failed (Error %lu)\n", dwError);
542
543 /* Release the service image */
544 HeapFree(GetProcessHeap(), 0, pServiceImage);
545
546 goto done;
547 }
548
549 bSecurityService = ScmIsSecurityService(pServiceImage);
550
551 /* Create the control pipe */
552 dwError = ScmCreateNewControlPipe(pServiceImage,
553 bSecurityService);
554 if (dwError != ERROR_SUCCESS)
555 {
556 DPRINT1("ScmCreateNewControlPipe() failed (Error %lu)\n", dwError);
557
558 /* Unload the user profile */
559 if (pServiceImage->hProfile != NULL)
560 {
562 UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
564 }
565
566 /* Close the logon token */
567 if (pServiceImage->hToken != NULL)
568 CloseHandle(pServiceImage->hToken);
569
570 /* Release the service image */
571 HeapFree(GetProcessHeap(), 0, pServiceImage);
572
573 goto done;
574 }
575
576 if (bSecurityService)
577 {
579 }
580
581 /* FIXME: Add more initialization code here */
582
583
584 /* Append service record */
586 &pServiceImage->ImageListEntry);
587 }
588 else
589 {
590// if ((lpService->Status.dwServiceType & SERVICE_WIN32_SHARE_PROCESS) == 0)
591
592 /* Fail if services in an image use different accounts */
593 if (!ScmIsSameServiceAccount(pServiceImage->pszAccountName, ObjectName.Buffer))
594 {
596 goto done;
597 }
598
599 /* Increment the run counter */
600 pServiceImage->dwImageRunCount++;
601 }
602
603 DPRINT("pServiceImage->pszImagePath: %S\n", pServiceImage->pszImagePath);
604 DPRINT("pServiceImage->pszAccountName: %S\n", pServiceImage->pszAccountName);
605 DPRINT("pServiceImage->dwImageRunCount: %lu\n", pServiceImage->dwImageRunCount);
606
607 /* Link the service image to the service */
608 pService->lpImage = pServiceImage;
609
610done:
612 RtlFreeUnicodeString(&ImagePath);
613
614 DPRINT("ScmCreateOrReferenceServiceImage() done (Error: %lu)\n", dwError);
615
616 return dwError;
617}
618
619
620VOID
622{
623 DPRINT1("ScmRemoveServiceImage() called\n");
624
625 /* FIXME: Terminate the process */
626
627 /* Remove the service image from the list */
628 RemoveEntryList(&pServiceImage->ImageListEntry);
629
630 /* Close the process handle */
631 if (pServiceImage->hProcess != INVALID_HANDLE_VALUE)
632 CloseHandle(pServiceImage->hProcess);
633
634 /* Close the control pipe */
635 if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE)
636 CloseHandle(pServiceImage->hControlPipe);
637
638 /* Unload the user profile */
639 if (pServiceImage->hProfile != NULL)
640 {
642 UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
644 }
645
646 /* Close the logon token */
647 if (pServiceImage->hToken != NULL)
648 CloseHandle(pServiceImage->hToken);
649
650 /* Release the service image */
651 HeapFree(GetProcessHeap(), 0, pServiceImage);
652}
653
654
657{
658 PLIST_ENTRY ServiceEntry;
659 PSERVICE CurrentService;
660
661 DPRINT("ScmGetServiceEntryByName() called\n");
662
663 ServiceEntry = ServiceListHead.Flink;
664 while (ServiceEntry != &ServiceListHead)
665 {
666 CurrentService = CONTAINING_RECORD(ServiceEntry,
667 SERVICE,
668 ServiceListEntry);
669 if (_wcsicmp(CurrentService->lpServiceName, lpServiceName) == 0)
670 {
671 DPRINT("Found service: '%S'\n", CurrentService->lpServiceName);
672 return CurrentService;
673 }
674
675 ServiceEntry = ServiceEntry->Flink;
676 }
677
678 DPRINT("Couldn't find a matching service\n");
679
680 return NULL;
681}
682
683
686{
687 PLIST_ENTRY ServiceEntry;
688 PSERVICE CurrentService;
689
690 DPRINT("ScmGetServiceEntryByDisplayName() called\n");
691
692 ServiceEntry = ServiceListHead.Flink;
693 while (ServiceEntry != &ServiceListHead)
694 {
695 CurrentService = CONTAINING_RECORD(ServiceEntry,
696 SERVICE,
697 ServiceListEntry);
698 if (_wcsicmp(CurrentService->lpDisplayName, lpDisplayName) == 0)
699 {
700 DPRINT("Found service: '%S'\n", CurrentService->lpDisplayName);
701 return CurrentService;
702 }
703
704 ServiceEntry = ServiceEntry->Flink;
705 }
706
707 DPRINT("Couldn't find a matching service\n");
708
709 return NULL;
710}
711
712
715{
716 PLIST_ENTRY ServiceEntry;
717 PSERVICE CurrentService;
718
719 DPRINT("ScmGetServiceEntryByResumeCount() called\n");
720
721 ServiceEntry = ServiceListHead.Flink;
722 while (ServiceEntry != &ServiceListHead)
723 {
724 CurrentService = CONTAINING_RECORD(ServiceEntry,
725 SERVICE,
726 ServiceListEntry);
727 if (CurrentService->dwResumeCount > dwResumeCount)
728 {
729 DPRINT("Found service: '%S'\n", CurrentService->lpDisplayName);
730 return CurrentService;
731 }
732
733 ServiceEntry = ServiceEntry->Flink;
734 }
735
736 DPRINT("Couldn't find a matching service\n");
737
738 return NULL;
739}
740
741
742DWORD
744{
745 /* Check for an overflow */
746 if (ServiceTag == -1)
747 {
748 return ERROR_INVALID_DATA;
749 }
750
751 /* This is only valid for Win32 services */
752 if (!(lpServiceRecord->Status.dwServiceType & SERVICE_WIN32))
753 {
755 }
756
757 /* Increment the tag counter and set it */
758 ServiceTag = ServiceTag % 0xFFFFFFFF + 1;
759 lpServiceRecord->dwServiceTag = ServiceTag;
760
761 return ERROR_SUCCESS;
762}
763
764
765DWORD
767 PSERVICE *lpServiceRecord,
768 DWORD dwServiceType,
769 DWORD dwStartType)
770{
771 PSERVICE lpService = NULL;
772
773 DPRINT("Service: '%S'\n", lpServiceName);
774
775 /* Allocate service entry */
776 lpService = HeapAlloc(GetProcessHeap(),
778 FIELD_OFFSET(SERVICE, szServiceName[wcslen(lpServiceName) + 1]));
779 if (lpService == NULL)
781
782 *lpServiceRecord = lpService;
783
784 /* Copy service name */
785 wcscpy(lpService->szServiceName, lpServiceName);
786 lpService->lpServiceName = lpService->szServiceName;
787 lpService->lpDisplayName = lpService->lpServiceName;
788
789 /* Set the start type */
790 lpService->dwStartType = dwStartType;
791
792 /* Set the resume count */
793 lpService->dwResumeCount = ResumeCount++;
794
795 /* Append service record */
797 &lpService->ServiceListEntry);
798
799 /* Initialize the service status */
800 lpService->Status.dwServiceType = dwServiceType;
802 lpService->Status.dwControlsAccepted = 0;
803 lpService->Status.dwWin32ExitCode =
805 lpService->Status.dwServiceSpecificExitCode = 0;
806 lpService->Status.dwCheckPoint = 0;
807 lpService->Status.dwWaitHint =
808 (dwServiceType & SERVICE_DRIVER) ? 0 : 2000; /* 2 seconds */
809
810 return ERROR_SUCCESS;
811}
812
813
814VOID
816{
817 DPRINT("Deleting Service %S\n", lpService->lpServiceName);
818
819 /* Delete the display name */
820 if (lpService->lpDisplayName != NULL &&
821 lpService->lpDisplayName != lpService->lpServiceName)
822 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
823
824 /* Dereference the service image */
825 if (lpService->lpImage)
826 {
827 lpService->lpImage->dwImageRunCount--;
828
829 if (lpService->lpImage->dwImageRunCount == 0)
830 {
831 ScmRemoveServiceImage(lpService->lpImage);
832 lpService->lpImage = NULL;
833 }
834 }
835
836 /* Decrement the group reference counter */
837 ScmSetServiceGroup(lpService, NULL);
838
839 /* Release the SecurityDescriptor */
840 if (lpService->pSecurityDescriptor != NULL)
842
843 /* Remove the Service from the List */
845
846 DPRINT("Deleted Service %S\n", lpService->lpServiceName);
847
848 /* Delete the service record */
849 HeapFree(GetProcessHeap(), 0, lpService);
850
851 DPRINT("Done\n");
852}
853
854DWORD
856 PSERVICE lpService,
857 DWORD dwServiceState,
858 PSERVICE *lpServices,
860 LPDWORD lpServicesReturned);
861
863{
864 DWORD dwError;
866 DWORD dwServicesReturned = 0;
868
869 ASSERT(lpService->RefCount == 0);
870
871 /* Open the Services Reg key */
873 L"System\\CurrentControlSet\\Services",
874 0,
876 &hServicesKey);
877 if (dwError != ERROR_SUCCESS)
878 {
879 DPRINT1("Failed to open services key\n");
880 return dwError;
881 }
882
883 /* Call the function with NULL, just to get bytes we need */
885 lpService,
887 NULL,
889 &dwServicesReturned);
890
891 /* If pcbBytesNeeded returned a value then there are services running that are dependent on this service */
892 if (pcbBytesNeeded)
893 {
894 DPRINT1("Deletion failed due to running dependencies\n");
897 }
898
899 /* There are no references and no running dependencies,
900 it is now safe to delete the service */
901
902 /* Delete the Service Key */
903 dwError = ScmDeleteRegKey(hServicesKey, lpService->lpServiceName);
904
906
907 if (dwError != ERROR_SUCCESS)
908 {
909 DPRINT1("Failed to delete the Service Registry key\n");
910 return dwError;
911 }
912
913 /* Delete the Service */
914 ScmDeleteServiceRecord(lpService);
915
916 return ERROR_SUCCESS;
917}
918
919/*
920 * This function allows the caller to be sure that the service won't be freed unexpectedly.
921 * In order to be sure that lpService will be valid until the reference is added
922 * the caller needs to hold the database lock.
923 * A running service will keep a reference for the whole time it is not SERVICE_STOPPED.
924 * A service handle will also keep a reference to a service. Keeping a reference is
925 * really needed so that ScmControlService can be called without keeping the database locked.
926 * This means that eventually the correct order of operations to send a control message to
927 * a service looks like: lock, reference, unlock, send control, lock, dereference, unlock.
928 */
929DWORD
931{
932 return InterlockedIncrement(&lpService->RefCount);
933}
934
935/* This function must be called with the database lock held exclusively as
936 it can end up deleting the service */
937DWORD
939{
940 DWORD ref;
941
942 ASSERT(lpService->RefCount > 0);
943
944 ref = InterlockedDecrement(&lpService->RefCount);
945
946 if (ref == 0 && lpService->bDeleted &&
948 {
949 ScmDeleteService(lpService);
950 }
951 return ref;
952}
953
954static DWORD
956 HKEY hServiceKey)
957{
958 PSERVICE lpService = NULL;
960 LPWSTR lpGroup = NULL;
962 DWORD dwError;
963 DWORD dwServiceType;
964 DWORD dwStartType;
965 DWORD dwErrorControl;
966 DWORD dwTagId;
967
968 DPRINT("Service: '%S'\n", lpServiceName);
969 if (*lpServiceName == L'{')
970 return ERROR_SUCCESS;
971
972 dwSize = sizeof(DWORD);
973 dwError = RegQueryValueExW(hServiceKey,
974 L"Type",
975 NULL,
976 NULL,
977 (LPBYTE)&dwServiceType,
978 &dwSize);
979 if (dwError != ERROR_SUCCESS)
980 return ERROR_SUCCESS;
981
982 if (((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) &&
984 (dwServiceType != SERVICE_KERNEL_DRIVER) &&
985 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
986 return ERROR_SUCCESS;
987
988 DPRINT("Service type: %lx\n", dwServiceType);
989
990 dwSize = sizeof(DWORD);
991 dwError = RegQueryValueExW(hServiceKey,
992 L"Start",
993 NULL,
994 NULL,
995 (LPBYTE)&dwStartType,
996 &dwSize);
997 if (dwError != ERROR_SUCCESS)
998 return ERROR_SUCCESS;
999
1000 DPRINT("Start type: %lx\n", dwStartType);
1001
1002 dwSize = sizeof(DWORD);
1003 dwError = RegQueryValueExW(hServiceKey,
1004 L"ErrorControl",
1005 NULL,
1006 NULL,
1007 (LPBYTE)&dwErrorControl,
1008 &dwSize);
1009 if (dwError != ERROR_SUCCESS)
1010 return ERROR_SUCCESS;
1011
1012 DPRINT("Error control: %lx\n", dwErrorControl);
1013
1014 dwError = RegQueryValueExW(hServiceKey,
1015 L"Tag",
1016 NULL,
1017 NULL,
1018 (LPBYTE)&dwTagId,
1019 &dwSize);
1020 if (dwError != ERROR_SUCCESS)
1021 dwTagId = 0;
1022
1023 DPRINT("Tag: %lx\n", dwTagId);
1024
1025 dwError = ScmReadString(hServiceKey,
1026 L"Group",
1027 &lpGroup);
1028 if (dwError != ERROR_SUCCESS)
1029 lpGroup = NULL;
1030
1031 DPRINT("Group: %S\n", lpGroup);
1032
1033 dwError = ScmReadString(hServiceKey,
1034 L"DisplayName",
1035 &lpDisplayName);
1036 if (dwError != ERROR_SUCCESS)
1038
1039 DPRINT("Display name: %S\n", lpDisplayName);
1040
1041 dwError = ScmCreateNewServiceRecord(lpServiceName,
1042 &lpService,
1043 dwServiceType,
1044 dwStartType);
1045 if (dwError != ERROR_SUCCESS)
1046 goto done;
1047
1048 lpService->dwErrorControl = dwErrorControl;
1049 lpService->dwTag = dwTagId;
1050
1051 if (lpGroup != NULL)
1052 {
1053 dwError = ScmSetServiceGroup(lpService, lpGroup);
1054 if (dwError != ERROR_SUCCESS)
1055 goto done;
1056 }
1057
1058 if (lpDisplayName != NULL)
1059 {
1060 lpService->lpDisplayName = lpDisplayName;
1062 }
1063
1064 DPRINT("ServiceName: '%S'\n", lpService->lpServiceName);
1065 if (lpService->lpGroup != NULL)
1066 {
1067 DPRINT("Group: '%S'\n", lpService->lpGroup->lpGroupName);
1068 }
1069 DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
1070 lpService->dwStartType,
1071 lpService->Status.dwServiceType,
1072 lpService->dwTag,
1073 lpService->dwErrorControl);
1074
1075 if (ScmIsDeleteFlagSet(hServiceKey))
1076 lpService->bDeleted = TRUE;
1077 else
1078 ScmGenerateServiceTag(lpService);
1079
1080 if (lpService->Status.dwServiceType & SERVICE_WIN32)
1081 {
1082 dwError = ScmReadSecurityDescriptor(hServiceKey,
1083 &lpService->pSecurityDescriptor);
1084 if (dwError != ERROR_SUCCESS)
1085 goto done;
1086
1087 /* Assing the default security descriptor if the security descriptor cannot be read */
1088 if (lpService->pSecurityDescriptor == NULL)
1089 {
1090 DPRINT("No security descriptor found! Assign default security descriptor\n");
1091 dwError = ScmCreateDefaultServiceSD(&lpService->pSecurityDescriptor);
1092 if (dwError != ERROR_SUCCESS)
1093 goto done;
1094
1095 dwError = ScmWriteSecurityDescriptor(hServiceKey,
1096 lpService->pSecurityDescriptor);
1097 if (dwError != ERROR_SUCCESS)
1098 goto done;
1099 }
1100 }
1101
1102done:
1103 if (lpGroup != NULL)
1104 HeapFree(GetProcessHeap(), 0, lpGroup);
1105
1106 if (lpDisplayName != NULL)
1108
1109 if (lpService != NULL)
1110 {
1111 ASSERT(lpService->lpImage == NULL);
1112 }
1113
1114 return dwError;
1115}
1116
1117
1118VOID
1120{
1121 PLIST_ENTRY ServiceEntry;
1122 PSERVICE CurrentService;
1124 DWORD dwError;
1125
1126 ServiceEntry = ServiceListHead.Flink;
1127 while (ServiceEntry != &ServiceListHead)
1128 {
1129 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1130
1131 ServiceEntry = ServiceEntry->Flink;
1132
1133 if (CurrentService->bDeleted != FALSE)
1134 {
1136 L"System\\CurrentControlSet\\Services",
1137 0,
1138 DELETE,
1139 &hServicesKey);
1140 if (dwError == ERROR_SUCCESS)
1141 {
1142 dwError = ScmDeleteRegKey(hServicesKey, CurrentService->lpServiceName);
1144 if (dwError == ERROR_SUCCESS)
1145 {
1146 RemoveEntryList(&CurrentService->ServiceListEntry);
1147 HeapFree(GetProcessHeap(), 0, CurrentService);
1148 }
1149 }
1150
1151 if (dwError != ERROR_SUCCESS)
1152 DPRINT1("Delete service failed: %S\n", CurrentService->lpServiceName);
1153 }
1154 }
1155}
1156
1157
1158static
1159VOID
1161{
1162 HKEY hKey;
1163 DWORD dwKeySize;
1164 LONG lError;
1165
1167 L"SYSTEM\\CurrentControlSet\\Control\\Windows",
1168 0,
1169 KEY_READ,
1170 &hKey);
1171 if (lError == ERROR_SUCCESS)
1172 {
1173 dwKeySize = sizeof(NoInteractiveServices);
1174 lError = RegQueryValueExW(hKey,
1175 L"NoInteractiveServices",
1176 0,
1177 NULL,
1179 &dwKeySize);
1181 }
1182}
1183
1184
1185DWORD
1187{
1188 WCHAR szSubKey[MAX_PATH];
1190 HKEY hServiceKey;
1191 DWORD dwSubKey;
1192 DWORD dwSubKeyLength;
1193 FILETIME ftLastChanged;
1194 DWORD dwError;
1195
1196 DPRINT("ScmCreateServiceDatabase() called\n");
1197
1198 /* Retrieve the NoInteractiveServies value */
1200
1201 /* Create the service group list */
1202 dwError = ScmCreateGroupList();
1203 if (dwError != ERROR_SUCCESS)
1204 return dwError;
1205
1206 /* Initialize image and service lists */
1209
1210 /* Initialize the database lock */
1212
1214 L"System\\CurrentControlSet\\Services",
1215 0,
1216 KEY_READ,
1217 &hServicesKey);
1218 if (dwError != ERROR_SUCCESS)
1219 return dwError;
1220
1221 dwSubKey = 0;
1222 for (;;)
1223 {
1224 dwSubKeyLength = MAX_PATH;
1225 dwError = RegEnumKeyExW(hServicesKey,
1226 dwSubKey,
1227 szSubKey,
1228 &dwSubKeyLength,
1229 NULL,
1230 NULL,
1231 NULL,
1232 &ftLastChanged);
1233 if (dwError == ERROR_SUCCESS &&
1234 szSubKey[0] != L'{')
1235 {
1236 DPRINT("SubKeyName: '%S'\n", szSubKey);
1237
1238 dwError = RegOpenKeyExW(hServicesKey,
1239 szSubKey,
1240 0,
1241 KEY_READ,
1242 &hServiceKey);
1243 if (dwError == ERROR_SUCCESS)
1244 {
1245 dwError = CreateServiceListEntry(szSubKey,
1246 hServiceKey);
1247
1248 RegCloseKey(hServiceKey);
1249 }
1250 }
1251
1252 if (dwError != ERROR_SUCCESS)
1253 break;
1254
1255 dwSubKey++;
1256 }
1257
1259
1260 /* Wait for the LSA server */
1261 ScmWaitForLsa();
1262
1263 /* Delete services that are marked for delete */
1265
1266 DPRINT("ScmCreateServiceDatabase() done\n");
1267
1268 return ERROR_SUCCESS;
1269}
1270
1271
1272VOID
1274{
1275 DPRINT("ScmShutdownServiceDatabase() called\n");
1276
1279
1280 DPRINT("ScmShutdownServiceDatabase() done\n");
1281}
1282
1283
1284static NTSTATUS
1286{
1289 HANDLE DirHandle;
1294 ULONG Index;
1295
1296 DPRINT("ScmCheckDriver(%S) called\n", Service->lpServiceName);
1297
1298 if (Service->Status.dwServiceType == SERVICE_KERNEL_DRIVER)
1299 {
1300 RtlInitUnicodeString(&DirName, L"\\Driver");
1301 }
1302 else // if (Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER)
1303 {
1304 ASSERT(Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER);
1305 RtlInitUnicodeString(&DirName, L"\\FileSystem");
1306 }
1307
1309 &DirName,
1310 0,
1311 NULL,
1312 NULL);
1313
1314 Status = NtOpenDirectoryObject(&DirHandle,
1317 if (!NT_SUCCESS(Status))
1318 {
1319 return Status;
1320 }
1321
1323 2 * MAX_PATH * sizeof(WCHAR);
1324 DirInfo = HeapAlloc(GetProcessHeap(),
1326 BufferLength);
1327
1328 Index = 0;
1329 while (TRUE)
1330 {
1331 Status = NtQueryDirectoryObject(DirHandle,
1332 DirInfo,
1334 TRUE,
1335 FALSE,
1336 &Index,
1337 &DataLength);
1339 {
1340 /* FIXME: Add current service to 'failed service' list */
1341 DPRINT("Service '%S' failed\n", Service->lpServiceName);
1342 break;
1343 }
1344
1345 if (!NT_SUCCESS(Status))
1346 break;
1347
1348 DPRINT("Comparing: '%S' '%wZ'\n", Service->lpServiceName, &DirInfo->Name);
1349
1350 if (_wcsicmp(Service->lpServiceName, DirInfo->Name.Buffer) == 0)
1351 {
1352 DPRINT("Found: '%S' '%wZ'\n",
1353 Service->lpServiceName, &DirInfo->Name);
1354
1355 /* Mark service as 'running' */
1356 Service->Status.dwCurrentState = SERVICE_RUNNING;
1357 Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
1358 Service->Status.dwWin32ExitCode = ERROR_SUCCESS;
1359 Service->Status.dwServiceSpecificExitCode = 0;
1360 Service->Status.dwCheckPoint = 0;
1361 Service->Status.dwWaitHint = 0;
1362
1363 /* Mark the service group as 'running' */
1364 if (Service->lpGroup != NULL)
1365 {
1366 Service->lpGroup->ServicesRunning = TRUE;
1367 }
1368
1369 break;
1370 }
1371 }
1372
1374 0,
1375 DirInfo);
1376 NtClose(DirHandle);
1377
1378 return STATUS_SUCCESS;
1379}
1380
1381
1382VOID
1384{
1385 PLIST_ENTRY ServiceEntry;
1386 PSERVICE CurrentService;
1387
1388 DPRINT("ScmGetBootAndSystemDriverState() called\n");
1389
1390 ServiceEntry = ServiceListHead.Flink;
1391 while (ServiceEntry != &ServiceListHead)
1392 {
1393 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1394
1395 if (CurrentService->dwStartType == SERVICE_BOOT_START ||
1396 CurrentService->dwStartType == SERVICE_SYSTEM_START)
1397 {
1398 /* Check driver */
1399 DPRINT(" Checking service: %S\n", CurrentService->lpServiceName);
1400
1401 ScmCheckDriver(CurrentService);
1402 }
1403
1404 ServiceEntry = ServiceEntry->Flink;
1405 }
1406
1407 DPRINT("ScmGetBootAndSystemDriverState() done\n");
1408}
1409
1410
1411/*
1412 * ScmSendControlPacket must never be called with the database lock being held.
1413 * The service passed must always be referenced instead.
1414 */
1415DWORD
1417 _In_ HANDLE hControlPipe,
1418 _In_ PCWSTR pServiceName,
1419 _In_ DWORD dwControl,
1420 _In_ DWORD dwControlPacketSize,
1421 _In_ PVOID pControlPacket)
1422{
1423 DWORD dwError = ERROR_SUCCESS;
1424 BOOL bResult;
1425 SCM_REPLY_PACKET ReplyPacket;
1426 DWORD dwReadCount = 0;
1427 OVERLAPPED Overlapped = {0};
1428
1429 DPRINT("ScmSendControlPacket(%p, %lu, %p) called\n",
1430 hControlPipe, dwControlPacketSize, pControlPacket);
1431
1432 /* Acquire the service control critical section, to synchronize requests */
1434
1435 bResult = TransactNamedPipe(hControlPipe,
1436 pControlPacket,
1437 dwControlPacketSize,
1438 &ReplyPacket,
1439 sizeof(ReplyPacket),
1440 &dwReadCount,
1441 &Overlapped);
1442 if (!bResult)
1443 {
1444 /* Fail for any error other than pending IO */
1445 dwError = GetLastError();
1446 if (dwError != ERROR_IO_PENDING)
1447 {
1448 DPRINT1("TransactNamedPipe(%S, %d) failed (Error %lu)\n", pServiceName, dwControl, dwError);
1449 goto Done;
1450 }
1451
1452 DPRINT("TransactNamedPipe(%S, %d) returned ERROR_IO_PENDING\n", pServiceName, dwControl);
1453
1454 dwError = WaitForSingleObject(hControlPipe, PipeTimeout);
1455 DPRINT("WaitForSingleObject(%S, %d) returned %lu\n", pServiceName, dwControl, dwError);
1456
1457 if (dwError == WAIT_TIMEOUT)
1458 {
1459 DPRINT1("WaitForSingleObject(%S, %d) timed out\n", pServiceName, dwControl);
1460 bResult = CancelIo(hControlPipe);
1461 if (!bResult)
1462 DPRINT1("CancelIo(%S, %d) failed (Error %lu)\n", pServiceName, dwControl, GetLastError());
1463
1465 }
1466 else if (dwError == WAIT_OBJECT_0)
1467 {
1468 bResult = GetOverlappedResult(hControlPipe,
1469 &Overlapped,
1470 &dwReadCount,
1471 TRUE);
1472 if (!bResult)
1473 {
1474 dwError = GetLastError();
1475 DPRINT1("GetOverlappedResult(%S, %d) failed (Error %lu)\n", pServiceName, dwControl, dwError);
1476 }
1477 }
1478 }
1479
1480Done:
1481 /* Release the service control critical section */
1483
1484 if (dwReadCount == sizeof(ReplyPacket))
1485 dwError = ReplyPacket.dwError;
1486
1487 return dwError;
1488}
1489
1490
1491DWORD
1493 _In_ HANDLE hControlPipe,
1494 _In_ PCWSTR pServiceName,
1495 _In_ DWORD dwControl,
1497 _In_opt_ DWORD dwServiceTag,
1500{
1501 DWORD dwError = ERROR_SUCCESS;
1502 PSCM_CONTROL_PACKET ControlPacket;
1504 DWORD i;
1505 PWSTR Ptr;
1506
1507 DPRINT("ScmControlServiceEx(%S, %d) called\n", pServiceName, dwControl);
1508
1509 /* Calculate the total size of the control packet:
1510 * initial structure, the start command line, and the argument vector */
1512 PacketSize += (DWORD)((wcslen(pServiceName) + 1) * sizeof(WCHAR));
1513
1514 /*
1515 * Calculate the required packet size for the start argument vector 'argv',
1516 * composed of the pointer offsets list, followed by UNICODE strings.
1517 * The strings are stored successively after the offsets vector, with
1518 * the offsets being relative to the beginning of the vector, as in the
1519 * following layout (with N == argc):
1520 * [argOff(0)]...[argOff(N-1)][str(0)]...[str(N-1)] .
1521 */
1522 if (argc > 0 && argv != NULL)
1523 {
1525 PacketSize += (argc * sizeof(PWSTR));
1526
1527 DPRINT("Argc: %lu\n", argc);
1528 for (i = 0; i < argc; i++)
1529 {
1530 DPRINT("Argv[%lu]: %S\n", i, argv[i]);
1531 PacketSize += (DWORD)((wcslen(argv[i]) + 1) * sizeof(WCHAR));
1532 }
1533 }
1534
1535 /* Allocate the control packet */
1537 if (!ControlPacket)
1539
1540 ControlPacket->dwSize = PacketSize;
1541 ControlPacket->dwControl = dwControl;
1542 ControlPacket->hServiceStatus = hServiceStatus;
1543 ControlPacket->dwServiceTag = dwServiceTag;
1544
1545 /* Copy the start command line */
1546 ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
1547 Ptr = (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset);
1548 wcscpy(Ptr, pServiceName);
1549
1550 ControlPacket->dwArgumentsCount = 0;
1551 ControlPacket->dwArgumentsOffset = 0;
1552
1553 /* Copy the argument vector */
1554 if (argc > 0 && argv != NULL)
1555 {
1556 PWSTR *pOffPtr, pArgPtr;
1557
1558 Ptr += wcslen(pServiceName) + 1;
1559 pOffPtr = (PWSTR*)ALIGN_UP_POINTER(Ptr, PWSTR);
1560 pArgPtr = (PWSTR)((ULONG_PTR)pOffPtr + argc * sizeof(PWSTR));
1561
1562 ControlPacket->dwArgumentsCount = argc;
1563 ControlPacket->dwArgumentsOffset = (DWORD)((ULONG_PTR)pOffPtr - (ULONG_PTR)ControlPacket);
1564
1565 DPRINT("dwArgumentsCount: %lu\n", ControlPacket->dwArgumentsCount);
1566 DPRINT("dwArgumentsOffset: %lu\n", ControlPacket->dwArgumentsOffset);
1567
1568 for (i = 0; i < argc; i++)
1569 {
1570 wcscpy(pArgPtr, argv[i]);
1571 pOffPtr[i] = (PWSTR)((ULONG_PTR)pArgPtr - (ULONG_PTR)pOffPtr);
1572 DPRINT("offset[%lu]: %p\n", i, pOffPtr[i]);
1573 pArgPtr += wcslen(argv[i]) + 1;
1574 }
1575 }
1576
1577 dwError = ScmSendControlPacket(hControlPipe,
1578 pServiceName,
1579 dwControl,
1580 PacketSize,
1581 ControlPacket);
1582
1583 /* Free the control packet */
1584 HeapFree(GetProcessHeap(), 0, ControlPacket);
1585
1586 DPRINT("ScmControlServiceEx(%S, %d) done (Error %lu)\n", pServiceName, dwControl, dwError);
1587 return dwError;
1588}
1589
1590
1591DWORD
1593 _In_ HANDLE hControlPipe,
1594 _In_ PCWSTR pServiceName,
1595 _In_ DWORD dwControl,
1597{
1598 DWORD dwError = ERROR_SUCCESS;
1599 PSCM_CONTROL_PACKET ControlPacket;
1601 PWSTR Ptr;
1602
1603 DPRINT("ScmControlService(%S, %d) called\n", pServiceName, dwControl);
1604
1605 /* Calculate the total size of the control packet:
1606 * initial structure, the start command line, and the argument vector */
1608 PacketSize += (DWORD)((wcslen(pServiceName) + 1) * sizeof(WCHAR));
1609
1610 /* Allocate the control packet */
1612 if (!ControlPacket)
1614
1615 ControlPacket->dwSize = PacketSize;
1616 ControlPacket->dwControl = dwControl;
1617 ControlPacket->hServiceStatus = hServiceStatus;
1618
1619 /* Copy the service name */
1620 ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
1621 Ptr = (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset);
1622 wcscpy(Ptr, pServiceName);
1623
1624 /* Send the control packet */
1625 dwError = ScmSendControlPacket(hControlPipe,
1626 pServiceName,
1627 dwControl,
1628 PacketSize,
1629 ControlPacket);
1630
1631 /* Free the control packet */
1632 HeapFree(GetProcessHeap(), 0, ControlPacket);
1633
1634 DPRINT("ScmControlService(%S, %d) done (Error %lu)\n", pServiceName, dwControl, dwError);
1635 return dwError;
1636}
1637
1638
1639static DWORD
1641{
1642 DWORD dwRead = 0;
1643 DWORD dwProcessId = 0;
1644 DWORD dwError = ERROR_SUCCESS;
1645 BOOL bResult;
1646 OVERLAPPED Overlapped = {0};
1647#if 0
1648 LPCWSTR lpLogStrings[3];
1649 WCHAR szBuffer1[20];
1650 WCHAR szBuffer2[20];
1651#endif
1652
1653 DPRINT("ScmWaitForServiceConnect()\n");
1654
1655 bResult = ConnectNamedPipe(Service->lpImage->hControlPipe,
1656 &Overlapped);
1657 if (bResult == FALSE)
1658 {
1659 DPRINT("ConnectNamedPipe() returned FALSE\n");
1660
1661 dwError = GetLastError();
1662 if (dwError == ERROR_IO_PENDING)
1663 {
1664 DPRINT("dwError: ERROR_IO_PENDING\n");
1665
1666 dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
1667 PipeTimeout);
1668 DPRINT("WaitForSingleObject() returned %lu\n", dwError);
1669
1670 if (dwError == WAIT_TIMEOUT)
1671 {
1672 DPRINT("WaitForSingleObject() returned WAIT_TIMEOUT\n");
1673
1674 bResult = CancelIo(Service->lpImage->hControlPipe);
1675 if (bResult == FALSE)
1676 {
1677 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1678 }
1679
1680#if 0
1681 _ultow(PipeTimeout, szBuffer1, 10);
1682 lpLogStrings[0] = Service->lpDisplayName;
1683 lpLogStrings[1] = szBuffer1;
1684
1687 2,
1688 lpLogStrings);
1689#endif
1690 DPRINT1("Log EVENT_CONNECTION_TIMEOUT by %S\n", Service->lpDisplayName);
1691
1693 }
1694 else if (dwError == WAIT_OBJECT_0)
1695 {
1696 bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
1697 &Overlapped,
1698 &dwRead,
1699 TRUE);
1700 if (bResult == FALSE)
1701 {
1702 dwError = GetLastError();
1703 DPRINT1("GetOverlappedResult failed (Error %lu)\n", dwError);
1704
1705 return dwError;
1706 }
1707 }
1708 }
1709 else if (dwError != ERROR_PIPE_CONNECTED)
1710 {
1711 DPRINT1("ConnectNamedPipe failed (Error %lu)\n", dwError);
1712 return dwError;
1713 }
1714 }
1715
1716 DPRINT("Control pipe connected\n");
1717
1718 Overlapped.hEvent = NULL;
1719
1720 /* Read the process id from pipe */
1721 bResult = ReadFile(Service->lpImage->hControlPipe,
1722 (LPVOID)&dwProcessId,
1723 sizeof(DWORD),
1724 &dwRead,
1725 &Overlapped);
1726 if (bResult == FALSE)
1727 {
1728 DPRINT("ReadFile() returned FALSE\n");
1729
1730 dwError = GetLastError();
1731 if (dwError == ERROR_IO_PENDING)
1732 {
1733 DPRINT("dwError: ERROR_IO_PENDING\n");
1734
1735 dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
1736 PipeTimeout);
1737 if (dwError == WAIT_TIMEOUT)
1738 {
1739 DPRINT("WaitForSingleObject() returned WAIT_TIMEOUT\n");
1740
1741 bResult = CancelIo(Service->lpImage->hControlPipe);
1742 if (bResult == FALSE)
1743 {
1744 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1745 }
1746
1747#if 0
1748 _ultow(PipeTimeout, szBuffer1, 10);
1749 lpLogStrings[0] = szBuffer1;
1750
1753 1,
1754 lpLogStrings);
1755#endif
1756 DPRINT1("Log EVENT_READFILE_TIMEOUT by %S\n", Service->lpDisplayName);
1757
1759 }
1760 else if (dwError == WAIT_OBJECT_0)
1761 {
1762 DPRINT("WaitForSingleObject() returned WAIT_OBJECT_0\n");
1763
1764 DPRINT("Process Id: %lu\n", dwProcessId);
1765
1766 bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
1767 &Overlapped,
1768 &dwRead,
1769 TRUE);
1770 if (bResult == FALSE)
1771 {
1772 dwError = GetLastError();
1773 DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError);
1774
1775 return dwError;
1776 }
1777 }
1778 else
1779 {
1780 DPRINT1("WaitForSingleObject() returned %lu\n", dwError);
1781 }
1782 }
1783 else
1784 {
1785 DPRINT1("ReadFile() failed (Error %lu)\n", dwError);
1786 return dwError;
1787 }
1788 }
1789
1790 if ((ScmIsSecurityService(Service->lpImage) == FALSE)&&
1791 (dwProcessId != Service->lpImage->dwProcessId))
1792 {
1793#if 0
1794 _ultow(Service->lpImage->dwProcessId, szBuffer1, 10);
1795 _ultow(dwProcessId, szBuffer2, 10);
1796
1797 lpLogStrings[0] = Service->lpDisplayName;
1798 lpLogStrings[1] = szBuffer1;
1799 lpLogStrings[2] = szBuffer2;
1800
1803 3,
1804 lpLogStrings);
1805#endif
1806
1807 DPRINT1("Log EVENT_SERVICE_DIFFERENT_PID_CONNECTED by %S\n", Service->lpDisplayName);
1808 }
1809
1810 DPRINT("ScmWaitForServiceConnect() done\n");
1811
1812 return ERROR_SUCCESS;
1813}
1814
1815
1816static DWORD
1818 DWORD argc,
1819 const PCWSTR* argv)
1820{
1821 PROCESS_INFORMATION ProcessInformation;
1822 STARTUPINFOW StartupInfo;
1823 LPVOID lpEnvironment;
1824 BOOL Result;
1825 DWORD dwError = ERROR_SUCCESS;
1826
1827 DPRINT("ScmStartUserModeService(%p)\n", Service);
1828
1829 /* If the image is already running, just send a start command */
1830 if (Service->lpImage->dwImageRunCount > 1)
1831 goto Quit;
1832
1833 /* Otherwise start its process */
1834 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
1835 StartupInfo.cb = sizeof(StartupInfo);
1836 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
1837
1838 if (Service->lpImage->hToken)
1839 {
1840 /* User token: Run the service under the user account */
1841
1842 if (!CreateEnvironmentBlock(&lpEnvironment, Service->lpImage->hToken, FALSE))
1843 {
1844 /* We failed, run the service with the current environment */
1845 DPRINT1("CreateEnvironmentBlock() failed with error %d; service '%S' will run with current environment\n",
1846 GetLastError(), Service->lpServiceName);
1847 lpEnvironment = NULL;
1848 }
1849
1850 /* Impersonate the new user */
1851 Result = ImpersonateLoggedOnUser(Service->lpImage->hToken);
1852 if (Result)
1853 {
1854 /* Launch the process in the user's logon session */
1855 Result = CreateProcessAsUserW(Service->lpImage->hToken,
1856 NULL,
1857 Service->lpImage->pszImagePath,
1858 NULL,
1859 NULL,
1860 FALSE,
1862 lpEnvironment,
1863 NULL,
1864 &StartupInfo,
1865 &ProcessInformation);
1866 if (!Result)
1867 dwError = GetLastError();
1868
1869 /* Revert the impersonation */
1870 RevertToSelf();
1871 }
1872 else
1873 {
1874 dwError = GetLastError();
1875 DPRINT1("ImpersonateLoggedOnUser() failed with error %d\n", dwError);
1876 }
1877 }
1878 else
1879 {
1880 /* No user token: Run the service under the LocalSystem account */
1881
1882 if (!CreateEnvironmentBlock(&lpEnvironment, NULL, TRUE))
1883 {
1884 /* We failed, run the service with the current environment */
1885 DPRINT1("CreateEnvironmentBlock() failed with error %d; service '%S' will run with current environment\n",
1886 GetLastError(), Service->lpServiceName);
1887 lpEnvironment = NULL;
1888 }
1889
1890 /* Use the interactive desktop if the service is interactive */
1891 if ((NoInteractiveServices == 0) &&
1892 (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
1893 {
1894 StartupInfo.dwFlags |= STARTF_INHERITDESKTOP;
1895 StartupInfo.lpDesktop = L"WinSta0\\Default";
1896 }
1897
1898 if (!ScmIsSecurityService(Service->lpImage))
1899 {
1901 Service->lpImage->pszImagePath,
1902 NULL,
1903 NULL,
1904 FALSE,
1906 lpEnvironment,
1907 NULL,
1908 &StartupInfo,
1909 &ProcessInformation);
1910 if (!Result)
1911 dwError = GetLastError();
1912 }
1913 else
1914 {
1915 Result = TRUE;
1916 dwError = ERROR_SUCCESS;
1917 }
1918 }
1919
1920 if (lpEnvironment)
1921 DestroyEnvironmentBlock(lpEnvironment);
1922
1923 if (!Result)
1924 {
1925 DPRINT1("Starting '%S' failed with error %d\n",
1926 Service->lpServiceName, dwError);
1927 return dwError;
1928 }
1929
1930 DPRINT("Process Id: %lu Handle %p\n",
1931 ProcessInformation.dwProcessId,
1932 ProcessInformation.hProcess);
1933 DPRINT("Thread Id: %lu Handle %p\n",
1934 ProcessInformation.dwThreadId,
1935 ProcessInformation.hThread);
1936
1937 /* Get the process handle and ID */
1938 Service->lpImage->hProcess = ProcessInformation.hProcess;
1939 Service->lpImage->dwProcessId = ProcessInformation.dwProcessId;
1940
1941 /* Resume the main thread and close its handle */
1942 ResumeThread(ProcessInformation.hThread);
1943 CloseHandle(ProcessInformation.hThread);
1944
1945 /* Connect control pipe */
1947 if (dwError != ERROR_SUCCESS)
1948 {
1949 DPRINT1("Connecting control pipe failed! (Error %lu)\n", dwError);
1950 Service->lpImage->dwProcessId = 0;
1951 return dwError;
1952 }
1953
1954Quit:
1955 /* Send the start command and return */
1956 return ScmControlServiceEx(Service->lpImage->hControlPipe,
1957 Service->lpServiceName,
1958 (Service->Status.dwServiceType & SERVICE_WIN32_OWN_PROCESS)
1961 Service->dwServiceTag,
1962 argc, argv);
1963}
1964
1965
1966static DWORD
1968 DWORD argc,
1969 const PCWSTR* argv)
1970{
1971 PSERVICE_GROUP Group = Service->lpGroup;
1972 DWORD dwError = ERROR_SUCCESS;
1973 LPCWSTR lpLogStrings[2];
1974 WCHAR szLogBuffer[80];
1975
1976 DPRINT("ScmLoadService() called\n");
1977 DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName);
1978
1979 if (Service->Status.dwCurrentState != SERVICE_STOPPED)
1980 {
1981 DPRINT("Service %S is already running\n", Service->lpServiceName);
1983 }
1984
1985 DPRINT("Service->Type: %lu\n", Service->Status.dwServiceType);
1986
1987 if (Service->Status.dwServiceType & SERVICE_DRIVER)
1988 {
1989 /* Start the driver */
1990 dwError = ScmStartDriver(Service);
1991 }
1992 else // if (Service->Status.dwServiceType & (SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS))
1993 {
1994 /* Start user-mode service */
1996 if (dwError == ERROR_SUCCESS)
1997 {
1999 if (dwError == ERROR_SUCCESS)
2000 {
2001 Service->Status.dwCurrentState = SERVICE_START_PENDING;
2002 Service->Status.dwControlsAccepted = 0;
2004 }
2005 else
2006 {
2007 Service->lpImage->dwImageRunCount--;
2008 if (Service->lpImage->dwImageRunCount == 0)
2009 {
2011 Service->lpImage = NULL;
2012 }
2013 }
2014 }
2015 }
2016
2017 DPRINT("ScmLoadService() done (Error %lu)\n", dwError);
2018
2019 if (dwError == ERROR_SUCCESS)
2020 {
2021 if (Group != NULL)
2022 {
2023 Group->ServicesRunning = TRUE;
2024 }
2025
2026 /* Log a successful service start */
2028 lpLogStrings[0] = Service->lpDisplayName;
2029 lpLogStrings[1] = szLogBuffer;
2030
2033 2,
2034 lpLogStrings);
2035 }
2036 else
2037 {
2038 if (Service->dwErrorControl != SERVICE_ERROR_IGNORE)
2039 {
2040 /* Log a failed service start */
2041 StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer),
2042 L"%lu", dwError);
2043 lpLogStrings[0] = Service->lpServiceName;
2044 lpLogStrings[1] = szLogBuffer;
2047 2,
2048 lpLogStrings);
2049 }
2050
2051#if 0
2052 switch (Service->dwErrorControl)
2053 {
2055 if (IsLastKnownGood == FALSE)
2056 {
2057 /* FIXME: Boot last known good configuration */
2058 }
2059 break;
2060
2062 if (IsLastKnownGood == FALSE)
2063 {
2064 /* FIXME: Boot last known good configuration */
2065 }
2066 else
2067 {
2068 /* FIXME: BSOD! */
2069 }
2070 break;
2071 }
2072#endif
2073 }
2074
2075 return dwError;
2076}
2077
2078
2079DWORD
2081 DWORD argc,
2082 const PCWSTR* argv)
2083{
2084 DWORD dwError = ERROR_SUCCESS;
2086
2087 DPRINT("ScmStartService() called\n");
2088 DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName);
2089
2090 /* Acquire the service control critical section, to synchronize starts */
2092
2093 /*
2094 * Acquire the user service start lock while the service is starting, if
2095 * needed (i.e. if we are not starting it during the initialization phase).
2096 * If we don't success, bail out.
2097 */
2098 if (!ScmInitialize)
2099 {
2101 if (dwError != ERROR_SUCCESS)
2102 goto done;
2103 }
2104
2105 /* Really start the service */
2106 dwError = ScmLoadService(Service, argc, argv);
2107
2108 /* Release the service start lock, if needed, and the critical section */
2110
2111done:
2113
2114 DPRINT("ScmStartService() done (Error %lu)\n", dwError);
2115
2116 return dwError;
2117}
2118
2119
2120VOID
2122{
2123 DWORD dwError;
2124 PLIST_ENTRY GroupEntry;
2125 PLIST_ENTRY ServiceEntry;
2126 PSERVICE_GROUP CurrentGroup;
2127 PSERVICE CurrentService;
2128 WCHAR szSafeBootServicePath[MAX_PATH];
2129 DWORD SafeBootEnabled;
2130 HKEY hKey;
2131 DWORD dwKeySize;
2132 ULONG i;
2133
2134 /*
2135 * This function MUST be called ONLY at initialization time.
2136 * Therefore, no need to acquire the user service start lock.
2137 */
2139
2140 /* Retrieve the SafeBoot parameter */
2142 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option",
2143 0,
2144 KEY_READ,
2145 &hKey);
2146 if (dwError == ERROR_SUCCESS)
2147 {
2148 dwKeySize = sizeof(SafeBootEnabled);
2149 dwError = RegQueryValueExW(hKey,
2150 L"OptionValue",
2151 0,
2152 NULL,
2153 (LPBYTE)&SafeBootEnabled,
2154 &dwKeySize);
2156 }
2157
2158 /* Default to Normal boot if the value doesn't exist */
2159 if (dwError != ERROR_SUCCESS)
2160 SafeBootEnabled = 0;
2161
2162 /* Acquire the service control critical section, to synchronize starts */
2164
2165 /* Clear 'ServiceVisited' flag (or set if not to start in Safe Mode) */
2166 ServiceEntry = ServiceListHead.Flink;
2167 while (ServiceEntry != &ServiceListHead)
2168 {
2169 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2170
2171 /* Build the safe boot path */
2172 StringCchCopyW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2173 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot");
2174
2175 switch (SafeBootEnabled)
2176 {
2177 /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
2178 case 1:
2179 case 3:
2180 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2181 L"\\Minimal\\");
2182 break;
2183
2184 case 2:
2185 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2186 L"\\Network\\");
2187 break;
2188 }
2189
2190 if (SafeBootEnabled != 0)
2191 {
2192 /* If key does not exist then do not assume safe mode */
2194 szSafeBootServicePath,
2195 0,
2196 KEY_READ,
2197 &hKey);
2198 if (dwError == ERROR_SUCCESS)
2199 {
2201
2202 /* Finish Safe Boot path off */
2203 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2204 CurrentService->lpServiceName);
2205
2206 /* Check that the key is in the Safe Boot path */
2208 szSafeBootServicePath,
2209 0,
2210 KEY_READ,
2211 &hKey);
2212 if (dwError != ERROR_SUCCESS)
2213 {
2214 /* Mark service as visited so it is not auto-started */
2215 CurrentService->ServiceVisited = TRUE;
2216 }
2217 else
2218 {
2219 /* Must be auto-started in safe mode - mark as unvisited */
2221 CurrentService->ServiceVisited = FALSE;
2222 }
2223 }
2224 else
2225 {
2226 DPRINT1("WARNING: Could not open the associated Safe Boot key\n");
2227 CurrentService->ServiceVisited = FALSE;
2228 }
2229 }
2230
2231 ServiceEntry = ServiceEntry->Flink;
2232 }
2233
2234 /* Start all services which are members of an existing group */
2235 GroupEntry = GroupListHead.Flink;
2236 while (GroupEntry != &GroupListHead)
2237 {
2238 CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
2239
2240 DPRINT("Group '%S'\n", CurrentGroup->lpGroupName);
2241
2242 /* Start all services witch have a valid tag */
2243 for (i = 0; i < CurrentGroup->TagCount; i++)
2244 {
2245 ServiceEntry = ServiceListHead.Flink;
2246 while (ServiceEntry != &ServiceListHead)
2247 {
2248 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2249
2250 if ((CurrentService->lpGroup == CurrentGroup) &&
2251 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2252 (CurrentService->ServiceVisited == FALSE) &&
2253 (CurrentService->dwTag == CurrentGroup->TagArray[i]))
2254 {
2255 CurrentService->ServiceVisited = TRUE;
2256 ScmLoadService(CurrentService, 0, NULL);
2257 }
2258
2259 ServiceEntry = ServiceEntry->Flink;
2260 }
2261 }
2262
2263 /* Start all services which have an invalid tag or which do not have a tag */
2264 ServiceEntry = ServiceListHead.Flink;
2265 while (ServiceEntry != &ServiceListHead)
2266 {
2267 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2268
2269 if ((CurrentService->lpGroup == CurrentGroup) &&
2270 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2271 (CurrentService->ServiceVisited == FALSE))
2272 {
2273 CurrentService->ServiceVisited = TRUE;
2274 ScmLoadService(CurrentService, 0, NULL);
2275 }
2276
2277 ServiceEntry = ServiceEntry->Flink;
2278 }
2279
2280 GroupEntry = GroupEntry->Flink;
2281 }
2282
2283 /* Start all services which are members of any non-existing group */
2284 ServiceEntry = ServiceListHead.Flink;
2285 while (ServiceEntry != &ServiceListHead)
2286 {
2287 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2288
2289 if ((CurrentService->lpGroup != NULL) &&
2290 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2291 (CurrentService->ServiceVisited == FALSE))
2292 {
2293 CurrentService->ServiceVisited = TRUE;
2294 ScmLoadService(CurrentService, 0, NULL);
2295 }
2296
2297 ServiceEntry = ServiceEntry->Flink;
2298 }
2299
2300 /* Start all services which are not a member of any group */
2301 ServiceEntry = ServiceListHead.Flink;
2302 while (ServiceEntry != &ServiceListHead)
2303 {
2304 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2305
2306 if ((CurrentService->lpGroup == NULL) &&
2307 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2308 (CurrentService->ServiceVisited == FALSE))
2309 {
2310 CurrentService->ServiceVisited = TRUE;
2311 ScmLoadService(CurrentService, 0, NULL);
2312 }
2313
2314 ServiceEntry = ServiceEntry->Flink;
2315 }
2316
2317 /* Clear 'ServiceVisited' flag again */
2318 ServiceEntry = ServiceListHead.Flink;
2319 while (ServiceEntry != &ServiceListHead)
2320 {
2321 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2322 CurrentService->ServiceVisited = FALSE;
2323 ServiceEntry = ServiceEntry->Flink;
2324 }
2325
2326 /* Release the critical section */
2328}
2329
2330
2331VOID
2333{
2334 PLIST_ENTRY ServiceEntry;
2335 PSERVICE CurrentService;
2336
2337 DPRINT("ScmAutoShutdownServices() called\n");
2338
2339 /* Lock the service database exclusively */
2341
2342 ServiceEntry = ServiceListHead.Flink;
2343 while (ServiceEntry != &ServiceListHead)
2344 {
2345 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2346
2347 if ((CurrentService->Status.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN) &&
2348 (CurrentService->Status.dwCurrentState == SERVICE_RUNNING ||
2349 CurrentService->Status.dwCurrentState == SERVICE_START_PENDING))
2350 {
2351 /* Send the shutdown notification */
2352 DPRINT("Shutdown service: %S\n", CurrentService->lpServiceName);
2353 ScmControlService(CurrentService->lpImage->hControlPipe,
2354 CurrentService->lpServiceName,
2356 (SERVICE_STATUS_HANDLE)CurrentService);
2357 }
2358
2359 ServiceEntry = ServiceEntry->Flink;
2360 }
2361
2362 /* Unlock the service database */
2364
2365 DPRINT("ScmAutoShutdownServices() done\n");
2366}
2367
2368
2369BOOL
2371{
2373}
2374
2375
2376BOOL
2378{
2380}
2381
2382
2383VOID
2385{
2387}
2388
2389
2390VOID
2392{
2393 HKEY hKey;
2394 DWORD dwKeySize;
2395 DWORD dwError;
2396
2398
2400 L"SYSTEM\\CurrentControlSet\\Control",
2401 0,
2402 KEY_READ,
2403 &hKey);
2404 if (dwError == ERROR_SUCCESS)
2405 {
2406 dwKeySize = sizeof(PipeTimeout);
2408 L"ServicesPipeTimeout",
2409 0,
2410 NULL,
2412 &dwKeySize);
2414 }
2415}
2416
2417
2418VOID
2420{
2422}
2423
2424/* EOF */
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
static int argc
Definition: ServiceArgs.c:12
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
static HANDLE hServicesKey
Definition: devinst.c:21
DWORD ScmReadString(HKEY hServiceKey, LPCWSTR lpValueName, LPWSTR *lpValue)
Definition: config.c:270
BOOL ScmIsDeleteFlagSet(HKEY hServiceKey)
Definition: config.c:251
DWORD ScmWriteSecurityDescriptor(_In_ HKEY hServiceKey, _In_ PSECURITY_DESCRIPTOR pSecurityDescriptor)
Definition: config.c:530
DWORD ScmReadSecurityDescriptor(_In_ HKEY hServiceKey, _Out_ PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
Definition: config.c:566
DWORD ScmDeleteRegKey(_In_ HKEY hKey, _In_ PCWSTR pszSubKey)
Definition: config.c:646
static BOOL ScmEnableBackupRestorePrivileges(_In_ HANDLE hToken, _In_ BOOL bEnable)
Definition: database.c:311
DWORD ScmControlService(_In_ HANDLE hControlPipe, _In_ PCWSTR pServiceName, _In_ DWORD dwControl, _In_ SERVICE_STATUS_HANDLE hServiceStatus)
Definition: database.c:1592
DWORD ScmControlServiceEx(_In_ HANDLE hControlPipe, _In_ PCWSTR pServiceName, _In_ DWORD dwControl, _In_ SERVICE_STATUS_HANDLE hServiceStatus, _In_opt_ DWORD dwServiceTag, _In_opt_ DWORD argc, _In_reads_opt_(argc) const PCWSTR *argv)
Definition: database.c:1492
VOID ScmAutoStartServices(VOID)
Definition: database.c:2121
static PSERVICE_IMAGE ScmGetServiceImageByImagePath(LPWSTR lpImagePath)
Definition: database.c:152
static DWORD ScmStartUserModeService(PSERVICE Service, DWORD argc, const PCWSTR *argv)
Definition: database.c:1817
static DWORD CreateServiceListEntry(LPCWSTR lpServiceName, HKEY hServiceKey)
Definition: database.c:955
PSERVICE ScmGetServiceEntryByResumeCount(DWORD dwResumeCount)
Definition: database.c:714
VOID ScmRemoveServiceImage(PSERVICE_IMAGE pServiceImage)
Definition: database.c:621
VOID ScmUnlockDatabase(VOID)
Definition: database.c:2384
LIST_ENTRY ImageListHead
Definition: database.c:27
DWORD ScmGenerateServiceTag(PSERVICE lpServiceRecord)
Definition: database.c:743
static DWORD ResumeCount
Definition: database.c:31
static DWORD ScmLoadService(PSERVICE Service, DWORD argc, const PCWSTR *argv)
Definition: database.c:1967
static DWORD PipeTimeout
Definition: database.c:37
static NTSTATUS ScmCheckDriver(PSERVICE Service)
Definition: database.c:1285
static BOOL ScmIsSecurityService(_In_ PSERVICE_IMAGE pServiceImage)
Definition: database.c:44
DWORD ScmGetServiceNameFromTag(IN PTAG_INFO_NAME_FROM_TAG_IN_PARAMS InParams, OUT PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS *OutParams)
Definition: database.c:182
static BOOL ScmIsLocalSystemAccount(_In_ PCWSTR pszAccountName)
Definition: database.c:298
VOID ScmInitNamedPipeCriticalSection(VOID)
Definition: database.c:2391
DWORD ScmReferenceService(PSERVICE lpService)
Definition: database.c:930
static DWORD NoInteractiveServices
Definition: database.c:32
static DWORD ScmCreateOrReferenceServiceImage(PSERVICE pService)
Definition: database.c:457
DWORD ScmCreateServiceDatabase(VOID)
Definition: database.c:1186
DWORD ScmStartService(PSERVICE Service, DWORD argc, const PCWSTR *argv)
Definition: database.c:2080
static DWORD ScmLogonService(IN PSERVICE pService, IN PSERVICE_IMAGE pImage)
Definition: database.c:358
static RTL_RESOURCE DatabaseLock
Definition: database.c:30
VOID ScmDeleteServiceRecord(PSERVICE lpService)
Definition: database.c:815
VOID ScmAutoShutdownServices(VOID)
Definition: database.c:2332
BOOL ScmLockDatabaseExclusive(VOID)
Definition: database.c:2370
static BOOL ScmIsSameServiceAccount(_In_ PCWSTR pszAccountName1, _In_ PCWSTR pszAccountName2)
Definition: database.c:269
VOID ScmGetBootAndSystemDriverState(VOID)
Definition: database.c:1383
DWORD ScmSendControlPacket(_In_ HANDLE hControlPipe, _In_ PCWSTR pServiceName, _In_ DWORD dwControl, _In_ DWORD dwControlPacketSize, _In_ PVOID pControlPacket)
Definition: database.c:1416
DWORD ScmDereferenceService(PSERVICE lpService)
Definition: database.c:938
DWORD ScmCreateNewServiceRecord(LPCWSTR lpServiceName, PSERVICE *lpServiceRecord, DWORD dwServiceType, DWORD dwStartType)
Definition: database.c:766
PSERVICE ScmGetServiceEntryByName(LPCWSTR lpServiceName)
Definition: database.c:656
BOOL ScmLockDatabaseShared(VOID)
Definition: database.c:2377
LIST_ENTRY ServiceListHead
Definition: database.c:28
DWORD Int_EnumDependentServicesW(HKEY hServicesKey, PSERVICE lpService, DWORD dwServiceState, PSERVICE *lpServices, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned)
Definition: rpcserver.c:782
static DWORD ScmCreateNewControlPipe(_In_ PSERVICE_IMAGE pServiceImage, _In_ BOOL bSecurityServiceProcess)
Definition: database.c:52
static DWORD ScmWaitForServiceConnect(PSERVICE Service)
Definition: database.c:1640
static DWORD ServiceTag
Definition: database.c:33
VOID ScmDeleteNamedPipeCriticalSection(VOID)
Definition: database.c:2419
static VOID ScmGetNoInteractiveServicesValue(VOID)
Definition: database.c:1160
static CRITICAL_SECTION ControlServiceCriticalSection
Definition: database.c:36
VOID ScmDeleteMarkedServices(VOID)
Definition: database.c:1119
DWORD ScmDeleteService(PSERVICE lpService)
Definition: database.c:862
VOID ScmShutdownServiceDatabase(VOID)
Definition: database.c:1273
PSERVICE ScmGetServiceEntryByDisplayName(LPCWSTR lpDisplayName)
Definition: database.c:685
DWORD ScmStartDriver(PSERVICE pService)
Definition: driver.c:314
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_START
Definition: resource.h:3
PSECURITY_DESCRIPTOR pPipeSD
Definition: security.c:27
DWORD ScmCreateDefaultServiceSD(PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
Definition: security.c:320
VOID ScmWaitForLsa(VOID)
Definition: services.c:207
BOOL ScmInitialize
Definition: services.c:28
DWORD SetSecurityServicesEvent(VOID)
Definition: services.c:142
BOOL ScmLiveSetup
Definition: services.c:30
BOOL ScmSetupInProgress
Definition: services.c:31
VOID ScmLogEvent(DWORD dwEventId, WORD wType, WORD wStrings, LPCWSTR *lpStrings)
Definition: services.c:174
struct _SERVICE_IMAGE SERVICE_IMAGE
#define RegCloseKey(hKey)
Definition: registry.h:49
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:737
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
wcscat
wcscpy
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_IO_PENDING
Definition: dderror.h:15
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL WINAPI CancelIo(IN HANDLE hFile)
Definition: deviceio.c:290
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
BOOL WINAPI LogonUserW(_In_ LPWSTR lpszUsername, _In_opt_ LPWSTR lpszDomain, _In_opt_ LPWSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken)
Definition: logon.c:1137
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW(_In_opt_ HANDLE hToken, _In_opt_ LPCWSTR lpApplicationName, _Inout_opt_ LPWSTR lpCommandLine, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCWSTR lpCurrentDirectory, _In_ LPSTARTUPINFOW lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation)
Definition: logon.c:993
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
Definition: misc.c:152
BOOL WINAPI AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength)
Definition: security.c:374
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4598
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
BOOL WINAPI RevertToSelf(void)
Definition: security.c:855
INT WINAPI DECLSPEC_HOTPATCH LoadStringW(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen)
Definition: string.c:1220
BOOL WINAPI DestroyEnvironmentBlock(IN LPVOID lpEnvironment)
Definition: environment.c:725
BOOL WINAPI CreateEnvironmentBlock(OUT LPVOID *lpEnvironment, IN HANDLE hToken, IN BOOL bInherit)
Definition: environment.c:503
BOOL WINAPI LoadUserProfileW(_In_ HANDLE hToken, _Inout_ LPPROFILEINFOW lpProfileInfo)
Definition: profile.c:2005
BOOL WINAPI UnloadUserProfile(_In_ HANDLE hToken, _In_ HANDLE hProfile)
Definition: profile.c:2184
static const WCHAR Cleanup[]
Definition: register.c:80
#define ULONG_PTR
Definition: config.h:101
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
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
FxString * pString
FxAutoRegKey hKey
Status
Definition: gdiplustypes.h:25
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
LIST_ENTRY GroupListHead
Definition: groupdb.c:19
DWORD ScmCreateGroupList(VOID)
Definition: groupdb.c:235
DWORD ScmSetServiceGroup(PSERVICE lpService, LPCWSTR lpGroupName)
Definition: groupdb.c:61
_CRTIMP wchar_t *__cdecl _ultow(_In_ unsigned long _Value, _Pre_notnull_ _Post_z_ wchar_t *_Dest, _In_ int _Radix)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:221
void *__RPC_USER MIDL_user_allocate(SIZE_T size)
Definition: irotp.c:371
void __RPC_USER MIDL_user_free(void *p)
Definition: irotp.c:376
#define ASSERT(a)
Definition: mode.c:44
#define FILE_FLAG_OVERLAPPED
Definition: disk.h:46
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
#define SE_BACKUP_PRIVILEGE
Definition: security.c:671
#define SE_RESTORE_PRIVILEGE
Definition: security.c:672
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define argv
Definition: mplay32.c:18
struct _OBJECT_DIRECTORY_INFORMATION OBJECT_DIRECTORY_INFORMATION
NTSYSAPI BOOLEAN NTAPI RtlAcquireResourceShared(_In_ PRTL_RESOURCE Resource, _In_ BOOLEAN Wait)
_In_opt_ PSID Group
Definition: rtlfuncs.h:1670
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4203
NTSYSAPI VOID NTAPI RtlInitializeResource(_In_ PRTL_RESOURCE Resource)
NTSYSAPI BOOLEAN NTAPI RtlAcquireResourceExclusive(_In_ PRTL_RESOURCE Resource, _In_ BOOLEAN Wait)
NTSYSAPI VOID NTAPI RtlDeleteResource(_In_ PRTL_RESOURCE Resource)
NTSYSAPI VOID NTAPI RtlReleaseResource(_In_ PRTL_RESOURCE Resource)
#define EVENT_SERVICE_DIFFERENT_PID_CONNECTED
Definition: netevent.h:435
#define EVENT_CONNECTION_TIMEOUT
Definition: netevent.h:143
#define EVENT_SERVICE_CONTROL_SUCCESS
Definition: netevent.h:432
#define EVENT_SERVICE_START_FAILED
Definition: netevent.h:444
#define EVENT_READFILE_TIMEOUT
Definition: netevent.h:413
#define _In_reads_opt_(s)
Definition: no_sal2.h:222
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
BOOL WINAPI ConnectNamedPipe(IN HANDLE hNamedPipe, IN LPOVERLAPPED lpOverlapped)
Definition: npipe.c:701
BOOL WINAPI TransactNamedPipe(IN HANDLE hNamedPipe, IN LPVOID lpInBuffer, IN DWORD nInBufferSize, OUT LPVOID lpOutBuffer, IN DWORD nOutBufferSize, OUT LPDWORD lpBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: npipe.c:1315
HANDLE WINAPI CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:246
#define KEY_READ
Definition: nt_native.h:1023
#define DIRECTORY_QUERY
Definition: nt_native.h:1254
#define DIRECTORY_TRAVERSE
Definition: nt_native.h:1255
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define RTL_REGISTRY_SERVICES
Definition: nt_native.h:162
#define DELETE
Definition: nt_native.h:57
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define KEY_WRITE
Definition: nt_native.h:1031
#define DWORD
Definition: nt_native.h:44
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define UNICODE_NULL
@ Service
Definition: ntsecapi.h:292
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: obdir.c:393
NTSTATUS NTAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PVOID Buffer, IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
Definition: obdir.c:490
long LONG
Definition: pedump.c:60
static BOOL bSecurityServiceProcess
Definition: sctrl.c:63
#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)
_In_ UCHAR _In_ ULONG _Out_ PUCHAR _Outptr_result_bytebuffer_ OutBufferLength PVOID * OutBuffer
Definition: scsi.h:4071
struct _SCM_CONTROL_PACKET SCM_CONTROL_PACKET
#define SERVICE_CONTROL_START_OWN
Definition: services.h:20
#define SERVICE_CONTROL_START_SHARE
Definition: services.h:18
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LONG HighPart
DWORD LowPart
HANDLE hEvent
Definition: winbase.h:855
DWORD dwFlags
Definition: userenv.h:37
DWORD dwSize
Definition: userenv.h:36
HANDLE hProfile
Definition: userenv.h:43
LPWSTR lpUserName
Definition: userenv.h:38
DWORD dwServiceNameOffset
Definition: services.h:35
SERVICE_STATUS_HANDLE hServiceStatus
Definition: services.h:34
DWORD dwArgumentsOffset
Definition: services.h:36
DWORD dwArgumentsCount
Definition: services.h:32
LPVOID lpSecurityDescriptor
Definition: compat.h:193
PULONG TagArray
Definition: services.h:40
ULONG TagCount
Definition: services.h:39
LPWSTR lpGroupName
Definition: services.h:35
HANDLE hControlPipe
Definition: services.h:53
LPWSTR pszImagePath
Definition: services.h:49
LIST_ENTRY ImageListEntry
Definition: services.h:48
HANDLE hProfile
Definition: services.h:57
LPWSTR pszAccountName
Definition: services.h:50
HANDLE hToken
Definition: services.h:56
DWORD dwProcessId
Definition: services.h:55
DWORD dwImageRunCount
Definition: services.h:51
HANDLE hProcess
Definition: services.h:54
DWORD dwServiceType
Definition: winsvc.h:99
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwControlsAccepted
Definition: winsvc.h:101
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwCurrentState
Definition: winsvc.h:100
DWORD dwCheckPoint
Definition: winsvc.h:104
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
BOOL bDeleted
Definition: services.h:68
DWORD dwServiceTag
Definition: services.h:78
PSERVICE_GROUP lpGroup
Definition: services.h:66
PSECURITY_DESCRIPTOR pSecurityDescriptor
Definition: services.h:82
DWORD dwErrorControl
Definition: services.h:74
LPWSTR lpDisplayName
Definition: services.h:65
LIST_ENTRY ServiceListEntry
Definition: services.h:63
DWORD dwResumeCount
Definition: services.h:69
SERVICE_STATUS Status
Definition: services.h:72
BOOLEAN ServiceVisited
Definition: services.h:84
DWORD dwStartType
Definition: services.h:73
WCHAR szServiceName[1]
Definition: services.h:86
LONG RefCount
Definition: services.h:70
DWORD dwTag
Definition: services.h:75
PSERVICE_IMAGE lpImage
Definition: services.h:67
LPWSTR lpServiceName
Definition: services.h:64
LPWSTR lpDesktop
Definition: winbase.h:889
DWORD cb
Definition: winbase.h:887
DWORD dwFlags
Definition: winbase.h:898
$ULONG PrivilegeCount
Definition: setypes.h:1035
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]
Definition: setypes.h:1036
Definition: send.c:48
@ TagTypeService
Definition: svcctl.idl:304
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
uint16_t * PWSTR
Definition: typedefs.h:56
int32_t INT_PTR
Definition: typedefs.h:64
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t * LPDWORD
Definition: typedefs.h:59
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define ALIGN_UP(size, type)
Definition: umtypes.h:91
#define ALIGN_UP_POINTER(ptr, type)
Definition: umtypes.h:97
#define STARTF_INHERITDESKTOP
Definition: undocuser.h:166
#define PI_NOUI
Definition: userenv.h:8
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
SERVICE_STATUS_HANDLE hServiceStatus
Definition: main.c:10
#define ZeroMemory
Definition: winbase.h:1753
_In_ LPCSTR _Out_writes_to_opt_ cchDisplayName LPSTR lpDisplayName
Definition: winbase.h:2831
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define PIPE_ACCESS_DUPLEX
Definition: winbase.h:172
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define CREATE_UNICODE_ENVIRONMENT
Definition: winbase.h:196
#define GetModuleHandle
Definition: winbase.h:3868
#define PIPE_WAIT
Definition: winbase.h:179
#define CREATE_SUSPENDED
Definition: winbase.h:188
#define PIPE_READMODE_MESSAGE
Definition: winbase.h:178
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WAIT_OBJECT_0
Definition: winbase.h:439
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:176
#define DETACHED_PROCESS
Definition: winbase.h:189
#define LOGON32_LOGON_SERVICE
Definition: winbase.h:427
#define LOGON32_PROVIDER_DEFAULT
Definition: winbase.h:420
_In_ BOOL bEnable
Definition: winddi.h:3426
#define ERROR_SERVICE_LOGON_FAILED
Definition: winerror.h:620
#define ERROR_SERVICE_ALREADY_RUNNING
Definition: winerror.h:607
#define ERROR_SERVICE_NEVER_STARTED
Definition: winerror.h:628
#define ERROR_NOT_ALL_ASSIGNED
Definition: winerror.h:782
#define ERROR_RETRY
Definition: winerror.h:740
#define ERROR_DIFFERENT_SERVICE_ACCOUNT
Definition: winerror.h:630
#define ERROR_DEPENDENT_SERVICES_RUNNING
Definition: winerror.h:602
#define ERROR_SERVICE_DISABLED
Definition: winerror.h:609
#define ERROR_SERVICE_REQUEST_TIMEOUT
Definition: winerror.h:604
#define ERROR_INVALID_DATA
Definition: winerror.h:116
#define ERROR_PIPE_CONNECTED
Definition: winerror.h:352
#define EVENTLOG_ERROR_TYPE
Definition: winnt_old.h:2876
#define EVENTLOG_INFORMATION_TYPE
Definition: winnt_old.h:2878
#define EVENTLOG_WARNING_TYPE
Definition: winnt_old.h:2877
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
_In_ DWORD _In_ DWORD _Out_ LPDWORD pcbBytesNeeded
Definition: winsvc.h:425
#define SERVICE_ACTIVE
Definition: winsvc.h:50
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
_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
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64
#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
_In_ USHORT PacketSize
Definition: iofuncs.h:1058
struct _TOKEN_PRIVILEGES TOKEN_PRIVILEGES
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193