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