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