ReactOS 0.4.16-dev-258-g81860b4
database.c File Reference
#include "services.h"
#include <userenv.h>
#include <strsafe.h>
#include <reactos/undocuser.h>
#include <debug.h>
Include dependency graph for database.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static BOOL ScmIsSecurityService (_In_ PSERVICE_IMAGE pServiceImage)
 
static DWORD ScmCreateNewControlPipe (_In_ PSERVICE_IMAGE pServiceImage, _In_ BOOL bSecurityServiceProcess)
 
static PSERVICE_IMAGE ScmGetServiceImageByImagePath (LPWSTR lpImagePath)
 
DWORD ScmGetServiceNameFromTag (IN PTAG_INFO_NAME_FROM_TAG_IN_PARAMS InParams, OUT PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS *OutParams)
 
static BOOL ScmIsSameServiceAccount (_In_ PCWSTR pszAccountName1, _In_ PCWSTR pszAccountName2)
 
static BOOL ScmIsLocalSystemAccount (_In_ PCWSTR pszAccountName)
 
static BOOL ScmEnableBackupRestorePrivileges (_In_ HANDLE hToken, _In_ BOOL bEnable)
 
static DWORD ScmLogonService (IN PSERVICE pService, IN PSERVICE_IMAGE pImage)
 
static DWORD ScmCreateOrReferenceServiceImage (PSERVICE pService)
 
VOID ScmRemoveServiceImage (PSERVICE_IMAGE pServiceImage)
 
PSERVICE ScmGetServiceEntryByName (LPCWSTR lpServiceName)
 
PSERVICE ScmGetServiceEntryByDisplayName (LPCWSTR lpDisplayName)
 
PSERVICE ScmGetServiceEntryByResumeCount (DWORD dwResumeCount)
 
DWORD ScmGenerateServiceTag (PSERVICE lpServiceRecord)
 
DWORD ScmCreateNewServiceRecord (LPCWSTR lpServiceName, PSERVICE *lpServiceRecord, DWORD dwServiceType, DWORD dwStartType)
 
VOID ScmDeleteServiceRecord (PSERVICE lpService)
 
DWORD Int_EnumDependentServicesW (HKEY hServicesKey, PSERVICE lpService, DWORD dwServiceState, PSERVICE *lpServices, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned)
 
DWORD ScmDeleteService (PSERVICE lpService)
 
DWORD ScmReferenceService (PSERVICE lpService)
 
DWORD ScmDereferenceService (PSERVICE lpService)
 
static DWORD CreateServiceListEntry (LPCWSTR lpServiceName, HKEY hServiceKey)
 
VOID ScmDeleteMarkedServices (VOID)
 
static VOID ScmGetNoInteractiveServicesValue (VOID)
 
DWORD ScmCreateServiceDatabase (VOID)
 
VOID ScmShutdownServiceDatabase (VOID)
 
static NTSTATUS ScmCheckDriver (PSERVICE Service)
 
VOID ScmGetBootAndSystemDriverState (VOID)
 
DWORD ScmControlServiceEx (_In_ HANDLE hControlPipe, _In_ PCWSTR pServiceName, _In_ DWORD dwControl, _In_ SERVICE_STATUS_HANDLE hServiceStatus, _In_opt_ DWORD dwServiceTag, _In_opt_ DWORD argc, _In_reads_opt_(argc) const PCWSTR *argv)
 
DWORD ScmControlService (_In_ HANDLE hControlPipe, _In_ PCWSTR pServiceName, _In_ DWORD dwControl, _In_ SERVICE_STATUS_HANDLE hServiceStatus)
 
static DWORD ScmWaitForServiceConnect (PSERVICE Service)
 
static DWORD ScmStartUserModeService (PSERVICE Service, DWORD argc, const PCWSTR *argv)
 
static DWORD ScmLoadService (PSERVICE Service, DWORD argc, const PCWSTR *argv)
 
DWORD ScmStartService (PSERVICE Service, DWORD argc, const PCWSTR *argv)
 
VOID ScmAutoStartServices (VOID)
 
VOID ScmAutoShutdownServices (VOID)
 
BOOL ScmLockDatabaseExclusive (VOID)
 
BOOL ScmLockDatabaseShared (VOID)
 
VOID ScmUnlockDatabase (VOID)
 
VOID ScmInitNamedPipeCriticalSection (VOID)
 
VOID ScmDeleteNamedPipeCriticalSection (VOID)
 

Variables

LIST_ENTRY ImageListHead
 
LIST_ENTRY ServiceListHead
 
static RTL_RESOURCE DatabaseLock
 
static DWORD ResumeCount = 1
 
static DWORD NoInteractiveServices = 0
 
static DWORD ServiceTag = 0
 
static CRITICAL_SECTION ControlServiceCriticalSection
 
static DWORD PipeTimeout = 30000
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 22 of file database.c.

Function Documentation

◆ CreateServiceListEntry()

static DWORD CreateServiceListEntry ( LPCWSTR  lpServiceName,
HKEY  hServiceKey 
)
static

Definition at line 956 of file database.c.

958{
959 PSERVICE lpService = NULL;
961 LPWSTR lpGroup = NULL;
963 DWORD dwError;
964 DWORD dwServiceType;
965 DWORD dwStartType;
966 DWORD dwErrorControl;
967 DWORD dwTagId;
968
969 DPRINT("Service: '%S'\n", lpServiceName);
970 if (*lpServiceName == L'{')
971 return ERROR_SUCCESS;
972
973 dwSize = sizeof(DWORD);
974 dwError = RegQueryValueExW(hServiceKey,
975 L"Type",
976 NULL,
977 NULL,
978 (LPBYTE)&dwServiceType,
979 &dwSize);
980 if (dwError != ERROR_SUCCESS)
981 return ERROR_SUCCESS;
982
983 if (((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) &&
985 (dwServiceType != SERVICE_KERNEL_DRIVER) &&
986 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
987 return ERROR_SUCCESS;
988
989 DPRINT("Service type: %lx\n", dwServiceType);
990
991 dwSize = sizeof(DWORD);
992 dwError = RegQueryValueExW(hServiceKey,
993 L"Start",
994 NULL,
995 NULL,
996 (LPBYTE)&dwStartType,
997 &dwSize);
998 if (dwError != ERROR_SUCCESS)
999 return ERROR_SUCCESS;
1000
1001 DPRINT("Start type: %lx\n", dwStartType);
1002
1003 dwSize = sizeof(DWORD);
1004 dwError = RegQueryValueExW(hServiceKey,
1005 L"ErrorControl",
1006 NULL,
1007 NULL,
1008 (LPBYTE)&dwErrorControl,
1009 &dwSize);
1010 if (dwError != ERROR_SUCCESS)
1011 return ERROR_SUCCESS;
1012
1013 DPRINT("Error control: %lx\n", dwErrorControl);
1014
1015 dwError = RegQueryValueExW(hServiceKey,
1016 L"Tag",
1017 NULL,
1018 NULL,
1019 (LPBYTE)&dwTagId,
1020 &dwSize);
1021 if (dwError != ERROR_SUCCESS)
1022 dwTagId = 0;
1023
1024 DPRINT("Tag: %lx\n", dwTagId);
1025
1026 dwError = ScmReadString(hServiceKey,
1027 L"Group",
1028 &lpGroup);
1029 if (dwError != ERROR_SUCCESS)
1030 lpGroup = NULL;
1031
1032 DPRINT("Group: %S\n", lpGroup);
1033
1034 dwError = ScmReadString(hServiceKey,
1035 L"DisplayName",
1036 &lpDisplayName);
1037 if (dwError != ERROR_SUCCESS)
1039
1040 DPRINT("Display name: %S\n", lpDisplayName);
1041
1042 dwError = ScmCreateNewServiceRecord(lpServiceName,
1043 &lpService,
1044 dwServiceType,
1045 dwStartType);
1046 if (dwError != ERROR_SUCCESS)
1047 goto done;
1048
1049 lpService->dwErrorControl = dwErrorControl;
1050 lpService->dwTag = dwTagId;
1051
1052 if (lpGroup != NULL)
1053 {
1054 dwError = ScmSetServiceGroup(lpService, lpGroup);
1055 if (dwError != ERROR_SUCCESS)
1056 goto done;
1057 }
1058
1059 if (lpDisplayName != NULL)
1060 {
1061 lpService->lpDisplayName = lpDisplayName;
1063 }
1064
1065 DPRINT("ServiceName: '%S'\n", lpService->lpServiceName);
1066 if (lpService->lpGroup != NULL)
1067 {
1068 DPRINT("Group: '%S'\n", lpService->lpGroup->lpGroupName);
1069 }
1070 DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
1071 lpService->dwStartType,
1072 lpService->Status.dwServiceType,
1073 lpService->dwTag,
1074 lpService->dwErrorControl);
1075
1076 if (ScmIsDeleteFlagSet(hServiceKey))
1077 lpService->bDeleted = TRUE;
1078 else
1079 ScmGenerateServiceTag(lpService);
1080
1081 if (lpService->Status.dwServiceType & SERVICE_WIN32)
1082 {
1083 dwError = ScmReadSecurityDescriptor(hServiceKey,
1084 &lpService->pSecurityDescriptor);
1085 if (dwError != ERROR_SUCCESS)
1086 goto done;
1087
1088 /* Assing the default security descriptor if the security descriptor cannot be read */
1089 if (lpService->pSecurityDescriptor == NULL)
1090 {
1091 DPRINT("No security descriptor found! Assign default security descriptor\n");
1092 dwError = ScmCreateDefaultServiceSD(&lpService->pSecurityDescriptor);
1093 if (dwError != ERROR_SUCCESS)
1094 goto done;
1095
1096 dwError = ScmWriteSecurityDescriptor(hServiceKey,
1097 lpService->pSecurityDescriptor);
1098 if (dwError != ERROR_SUCCESS)
1099 goto done;
1100 }
1101 }
1102
1103done:
1104 if (lpGroup != NULL)
1105 HeapFree(GetProcessHeap(), 0, lpGroup);
1106
1107 if (lpDisplayName != NULL)
1109
1110 if (lpService != NULL)
1111 {
1112 ASSERT(lpService->lpImage == NULL);
1113 }
1114
1115 return dwError;
1116}
DWORD ScmReadString(HKEY hServiceKey, LPCWSTR lpValueName, LPWSTR *lpValue)
Definition: config.c:270
BOOL ScmIsDeleteFlagSet(HKEY hServiceKey)
Definition: config.c:251
DWORD ScmWriteSecurityDescriptor(_In_ HKEY hServiceKey, _In_ PSECURITY_DESCRIPTOR pSecurityDescriptor)
Definition: config.c:530
DWORD ScmReadSecurityDescriptor(_In_ HKEY hServiceKey, _Out_ PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
Definition: config.c:566
DWORD ScmGenerateServiceTag(PSERVICE lpServiceRecord)
Definition: database.c:744
DWORD ScmCreateNewServiceRecord(LPCWSTR lpServiceName, PSERVICE *lpServiceRecord, DWORD dwServiceType, DWORD dwStartType)
Definition: database.c:767
DWORD ScmCreateDefaultServiceSD(PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
Definition: security.c:320
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define GetProcessHeap()
Definition: compat.h:736
#define HeapFree(x, y, z)
Definition: compat.h:735
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD ScmSetServiceGroup(PSERVICE lpService, LPCWSTR lpGroupName)
Definition: groupdb.c:61
#define ASSERT(a)
Definition: mode.c:44
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define DWORD
Definition: nt_native.h:44
#define L(x)
Definition: ntvdm.h:50
#define DPRINT
Definition: sndvol32.h:73
LPWSTR lpGroupName
Definition: services.h:35
DWORD dwServiceType
Definition: winsvc.h:99
BOOL bDeleted
Definition: services.h:68
PSERVICE_GROUP lpGroup
Definition: services.h:66
PSECURITY_DESCRIPTOR pSecurityDescriptor
Definition: services.h:82
DWORD dwErrorControl
Definition: services.h:74
LPWSTR lpDisplayName
Definition: services.h:65
SERVICE_STATUS Status
Definition: services.h:72
DWORD dwStartType
Definition: services.h:73
DWORD dwTag
Definition: services.h:75
PSERVICE_IMAGE lpImage
Definition: services.h:67
LPWSTR lpServiceName
Definition: services.h:64
unsigned char * LPBYTE
Definition: typedefs.h:53
_In_ LPCSTR _Out_writes_to_opt_ cchDisplayName LPSTR lpDisplayName
Definition: winbase.h:2815
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:953
#define SERVICE_WIN32_SHARE_PROCESS
Definition: cmtypes.h:963
#define SERVICE_INTERACTIVE_PROCESS
Definition: cmtypes.h:967
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:962
#define SERVICE_FILE_SYSTEM_DRIVER
Definition: cmtypes.h:954
#define SERVICE_WIN32
Definition: cmtypes.h:964
WCHAR * LPWSTR
Definition: xmlstorage.h:184

Referenced by ScmCreateServiceDatabase().

◆ Int_EnumDependentServicesW()

DWORD Int_EnumDependentServicesW ( HKEY  hServicesKey,
PSERVICE  lpService,
DWORD  dwServiceState,
PSERVICE lpServices,
LPDWORD  pcbBytesNeeded,
LPDWORD  lpServicesReturned 
)

Definition at line 782 of file rpcserver.c.

788{
789 DWORD dwError = ERROR_SUCCESS;
790 WCHAR szNameBuf[MAX_PATH];
791 WCHAR szValueBuf[MAX_PATH];
792 WCHAR *lpszNameBuf = szNameBuf;
793 WCHAR *lpszValueBuf = szValueBuf;
795 DWORD dwNumSubKeys;
796 DWORD dwIteration;
797 PSERVICE lpCurrentService;
798 HKEY hServiceEnumKey;
799 DWORD dwCurrentServiceState = SERVICE_ACTIVE;
800 DWORD dwDependServiceStrPtr = 0;
801 DWORD dwRequiredSize = 0;
802
803 /* Get the number of service keys */
805 NULL,
806 NULL,
807 NULL,
808 &dwNumSubKeys,
809 NULL,
810 NULL,
811 NULL,
812 NULL,
813 NULL,
814 NULL,
815 NULL);
816 if (dwError != ERROR_SUCCESS)
817 {
818 DPRINT("ERROR! Unable to get number of services keys\n");
819 return dwError;
820 }
821
822 /* Iterate the service keys to see if another service depends on the this service */
823 for (dwIteration = 0; dwIteration < dwNumSubKeys; dwIteration++)
824 {
826 dwError = RegEnumKeyExW(hServicesKey,
827 dwIteration,
828 lpszNameBuf,
829 &dwSize,
830 NULL,
831 NULL,
832 NULL,
833 NULL);
834 if (dwError != ERROR_SUCCESS)
835 return dwError;
836
837 /* Open the Service key */
838 dwError = RegOpenKeyExW(hServicesKey,
839 lpszNameBuf,
840 0,
841 KEY_READ,
842 &hServiceEnumKey);
843 if (dwError != ERROR_SUCCESS)
844 return dwError;
845
846 dwSize = MAX_PATH * sizeof(WCHAR);
847
848 /* Check for the DependOnService Value */
849 dwError = RegQueryValueExW(hServiceEnumKey,
850 L"DependOnService",
851 NULL,
852 NULL,
853 (LPBYTE)lpszValueBuf,
854 &dwSize);
855
856 /* FIXME: Handle load order. */
857
858 /* If the service found has a DependOnService value */
859 if (dwError == ERROR_SUCCESS)
860 {
861 dwDependServiceStrPtr = 0;
862
863 /* Can be more than one Dependencies in the DependOnService string */
864 while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0)
865 {
866 if (_wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0)
867 {
868 /* Get the current enumed service pointer */
869 lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf);
870
871 /* Check for valid Service */
872 if (!lpCurrentService)
873 {
874 /* This should never happen! */
875 DPRINT("This should not happen at this point, report to Developer\n");
876 return ERROR_NOT_FOUND;
877 }
878
879 /* Determine state the service is in */
880 if (lpCurrentService->Status.dwCurrentState == SERVICE_STOPPED)
881 dwCurrentServiceState = SERVICE_INACTIVE;
882
883 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
884 if ((dwCurrentServiceState == dwServiceState) ||
885 (dwServiceState == SERVICE_STATE_ALL))
886 {
887 /* Calculate the required size */
888 dwRequiredSize += sizeof(SERVICE_STATUS);
889 dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR));
890 dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
891
892 /* Add the size for service name and display name pointers */
893 dwRequiredSize += (2 * sizeof(PVOID));
894
895 /* increase the BytesNeeded size */
896 *pcbBytesNeeded = *pcbBytesNeeded + dwRequiredSize;
897
898 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
899 comes first */
900
901 /* Recursive call to check for its dependencies */
903 lpCurrentService,
904 dwServiceState,
905 lpServices,
907 lpServicesReturned);
908
909 /* If the lpServices is valid set the service pointer */
910 if (lpServices)
911 lpServices[*lpServicesReturned] = lpCurrentService;
912
913 *lpServicesReturned = *lpServicesReturned + 1;
914 }
915 }
916
917 dwDependServiceStrPtr += (DWORD)(wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1);
918 }
919 }
920 else if (*pcbBytesNeeded)
921 {
922 dwError = ERROR_SUCCESS;
923 }
924
925 RegCloseKey(hServiceEnumKey);
926 }
927
928 return dwError;
929}
static HANDLE hServicesKey
Definition: devinst.c:21
PSERVICE ScmGetServiceEntryByName(LPCWSTR lpServiceName)
Definition: database.c:657
DWORD Int_EnumDependentServicesW(HKEY hServicesKey, PSERVICE lpService, DWORD dwServiceState, PSERVICE *lpServices, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned)
Definition: rpcserver.c:782
#define RegCloseKey(hKey)
Definition: registry.h:49
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3662
#define MAX_PATH
Definition: compat.h:34
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define KEY_READ
Definition: nt_native.h:1023
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
DWORD dwCurrentState
Definition: winsvc.h:100
void * PVOID
Definition: typedefs.h:50
#define ERROR_NOT_FOUND
Definition: winerror.h:690
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_STATE_ALL
Definition: winsvc.h:52
_In_ DWORD _In_ DWORD _Out_ LPDWORD pcbBytesNeeded
Definition: winsvc.h:425
#define SERVICE_ACTIVE
Definition: winsvc.h:50
struct _SERVICE_STATUS SERVICE_STATUS
#define SERVICE_INACTIVE
Definition: winsvc.h:51
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by Int_EnumDependentServicesW(), RControlService(), REnumDependentServicesA(), REnumDependentServicesW(), and ScmDeleteService().

◆ ScmAutoShutdownServices()

VOID ScmAutoShutdownServices ( VOID  )

Definition at line 2276 of file database.c.

2277{
2278 PLIST_ENTRY ServiceEntry;
2279 PSERVICE CurrentService;
2280
2281 DPRINT("ScmAutoShutdownServices() called\n");
2282
2283 /* Lock the service database exclusively */
2285
2286 ServiceEntry = ServiceListHead.Flink;
2287 while (ServiceEntry != &ServiceListHead)
2288 {
2289 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2290
2291 if ((CurrentService->Status.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN) &&
2292 (CurrentService->Status.dwCurrentState == SERVICE_RUNNING ||
2293 CurrentService->Status.dwCurrentState == SERVICE_START_PENDING))
2294 {
2295 /* Send the shutdown notification */
2296 DPRINT("Shutdown service: %S\n", CurrentService->lpServiceName);
2297 ScmControlService(CurrentService->lpImage->hControlPipe,
2298 CurrentService->lpServiceName,
2300 (SERVICE_STATUS_HANDLE)CurrentService);
2301 }
2302
2303 ServiceEntry = ServiceEntry->Flink;
2304 }
2305
2306 /* Unlock the service database */
2308
2309 DPRINT("ScmAutoShutdownServices() done\n");
2310}
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
DWORD ScmControlService(_In_ HANDLE hControlPipe, _In_ PCWSTR pServiceName, _In_ DWORD dwControl, _In_ SERVICE_STATUS_HANDLE hServiceStatus)
Definition: database.c:1569
VOID ScmUnlockDatabase(VOID)
Definition: database.c:2328
BOOL ScmLockDatabaseExclusive(VOID)
Definition: database.c:2314
LIST_ENTRY ServiceListHead
Definition: database.c:29
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
HANDLE hControlPipe
Definition: services.h:53
DWORD dwControlsAccepted
Definition: winsvc.h:101
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30

Referenced by ShutdownHandlerRoutine().

◆ ScmAutoStartServices()

VOID ScmAutoStartServices ( VOID  )

Definition at line 2065 of file database.c.

2066{
2067 DWORD dwError;
2068 PLIST_ENTRY GroupEntry;
2069 PLIST_ENTRY ServiceEntry;
2070 PSERVICE_GROUP CurrentGroup;
2071 PSERVICE CurrentService;
2072 WCHAR szSafeBootServicePath[MAX_PATH];
2073 DWORD SafeBootEnabled;
2074 HKEY hKey;
2075 DWORD dwKeySize;
2076 ULONG i;
2077
2078 /*
2079 * This function MUST be called ONLY at initialization time.
2080 * Therefore, no need to acquire the user service start lock.
2081 */
2083
2084 /* Retrieve the SafeBoot parameter */
2086 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option",
2087 0,
2088 KEY_READ,
2089 &hKey);
2090 if (dwError == ERROR_SUCCESS)
2091 {
2092 dwKeySize = sizeof(SafeBootEnabled);
2093 dwError = RegQueryValueExW(hKey,
2094 L"OptionValue",
2095 0,
2096 NULL,
2097 (LPBYTE)&SafeBootEnabled,
2098 &dwKeySize);
2100 }
2101
2102 /* Default to Normal boot if the value doesn't exist */
2103 if (dwError != ERROR_SUCCESS)
2104 SafeBootEnabled = 0;
2105
2106 /* Acquire the service control critical section, to synchronize starts */
2108
2109 /* Clear 'ServiceVisited' flag (or set if not to start in Safe Mode) */
2110 ServiceEntry = ServiceListHead.Flink;
2111 while (ServiceEntry != &ServiceListHead)
2112 {
2113 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2114
2115 /* Build the safe boot path */
2116 StringCchCopyW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2117 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot");
2118
2119 switch (SafeBootEnabled)
2120 {
2121 /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
2122 case 1:
2123 case 3:
2124 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2125 L"\\Minimal\\");
2126 break;
2127
2128 case 2:
2129 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2130 L"\\Network\\");
2131 break;
2132 }
2133
2134 if (SafeBootEnabled != 0)
2135 {
2136 /* If key does not exist then do not assume safe mode */
2138 szSafeBootServicePath,
2139 0,
2140 KEY_READ,
2141 &hKey);
2142 if (dwError == ERROR_SUCCESS)
2143 {
2145
2146 /* Finish Safe Boot path off */
2147 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2148 CurrentService->lpServiceName);
2149
2150 /* Check that the key is in the Safe Boot path */
2152 szSafeBootServicePath,
2153 0,
2154 KEY_READ,
2155 &hKey);
2156 if (dwError != ERROR_SUCCESS)
2157 {
2158 /* Mark service as visited so it is not auto-started */
2159 CurrentService->ServiceVisited = TRUE;
2160 }
2161 else
2162 {
2163 /* Must be auto-started in safe mode - mark as unvisited */
2165 CurrentService->ServiceVisited = FALSE;
2166 }
2167 }
2168 else
2169 {
2170 DPRINT1("WARNING: Could not open the associated Safe Boot key\n");
2171 CurrentService->ServiceVisited = FALSE;
2172 }
2173 }
2174
2175 ServiceEntry = ServiceEntry->Flink;
2176 }
2177
2178 /* Start all services which are members of an existing group */
2179 GroupEntry = GroupListHead.Flink;
2180 while (GroupEntry != &GroupListHead)
2181 {
2182 CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
2183
2184 DPRINT("Group '%S'\n", CurrentGroup->lpGroupName);
2185
2186 /* Start all services witch have a valid tag */
2187 for (i = 0; i < CurrentGroup->TagCount; i++)
2188 {
2189 ServiceEntry = ServiceListHead.Flink;
2190 while (ServiceEntry != &ServiceListHead)
2191 {
2192 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2193
2194 if ((CurrentService->lpGroup == CurrentGroup) &&
2195 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2196 (CurrentService->ServiceVisited == FALSE) &&
2197 (CurrentService->dwTag == CurrentGroup->TagArray[i]))
2198 {
2199 CurrentService->ServiceVisited = TRUE;
2200 ScmLoadService(CurrentService, 0, NULL);
2201 }
2202
2203 ServiceEntry = ServiceEntry->Flink;
2204 }
2205 }
2206
2207 /* Start all services which have an invalid tag or which do not have a tag */
2208 ServiceEntry = ServiceListHead.Flink;
2209 while (ServiceEntry != &ServiceListHead)
2210 {
2211 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2212
2213 if ((CurrentService->lpGroup == CurrentGroup) &&
2214 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2215 (CurrentService->ServiceVisited == FALSE))
2216 {
2217 CurrentService->ServiceVisited = TRUE;
2218 ScmLoadService(CurrentService, 0, NULL);
2219 }
2220
2221 ServiceEntry = ServiceEntry->Flink;
2222 }
2223
2224 GroupEntry = GroupEntry->Flink;
2225 }
2226
2227 /* Start all services which are members of any non-existing group */
2228 ServiceEntry = ServiceListHead.Flink;
2229 while (ServiceEntry != &ServiceListHead)
2230 {
2231 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2232
2233 if ((CurrentService->lpGroup != NULL) &&
2234 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2235 (CurrentService->ServiceVisited == FALSE))
2236 {
2237 CurrentService->ServiceVisited = TRUE;
2238 ScmLoadService(CurrentService, 0, NULL);
2239 }
2240
2241 ServiceEntry = ServiceEntry->Flink;
2242 }
2243
2244 /* Start all services which are not a member of any group */
2245 ServiceEntry = ServiceListHead.Flink;
2246 while (ServiceEntry != &ServiceListHead)
2247 {
2248 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2249
2250 if ((CurrentService->lpGroup == NULL) &&
2251 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2252 (CurrentService->ServiceVisited == FALSE))
2253 {
2254 CurrentService->ServiceVisited = TRUE;
2255 ScmLoadService(CurrentService, 0, NULL);
2256 }
2257
2258 ServiceEntry = ServiceEntry->Flink;
2259 }
2260
2261 /* Clear 'ServiceVisited' flag again */
2262 ServiceEntry = ServiceListHead.Flink;
2263 while (ServiceEntry != &ServiceListHead)
2264 {
2265 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2266 CurrentService->ServiceVisited = FALSE;
2267 ServiceEntry = ServiceEntry->Flink;
2268 }
2269
2270 /* Release the critical section */
2272}
#define DPRINT1
Definition: precomp.h:8
static DWORD ScmLoadService(PSERVICE Service, DWORD argc, const PCWSTR *argv)
Definition: database.c:1911
static CRITICAL_SECTION ControlServiceCriticalSection
Definition: database.c:37
BOOL ScmInitialize
Definition: services.c:28
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
FxAutoRegKey hKey
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LIST_ENTRY GroupListHead
Definition: groupdb.c:19
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
PULONG TagArray
Definition: services.h:40
ULONG TagCount
Definition: services.h:39
BOOLEAN ServiceVisited
Definition: services.h:84
uint32_t ULONG
Definition: typedefs.h:59
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define SERVICE_AUTO_START
Definition: cmtypes.h:977

Referenced by wWinMain().

◆ ScmCheckDriver()

static NTSTATUS ScmCheckDriver ( PSERVICE  Service)
static

Definition at line 1286 of file database.c.

1287{
1290 HANDLE DirHandle;
1295 ULONG Index;
1296
1297 DPRINT("ScmCheckDriver(%S) called\n", Service->lpServiceName);
1298
1299 if (Service->Status.dwServiceType == SERVICE_KERNEL_DRIVER)
1300 {
1301 RtlInitUnicodeString(&DirName, L"\\Driver");
1302 }
1303 else // if (Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER)
1304 {
1305 ASSERT(Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER);
1306 RtlInitUnicodeString(&DirName, L"\\FileSystem");
1307 }
1308
1310 &DirName,
1311 0,
1312 NULL,
1313 NULL);
1314
1315 Status = NtOpenDirectoryObject(&DirHandle,
1318 if (!NT_SUCCESS(Status))
1319 {
1320 return Status;
1321 }
1322
1324 2 * MAX_PATH * sizeof(WCHAR);
1325 DirInfo = HeapAlloc(GetProcessHeap(),
1327 BufferLength);
1328
1329 Index = 0;
1330 while (TRUE)
1331 {
1332 Status = NtQueryDirectoryObject(DirHandle,
1333 DirInfo,
1335 TRUE,
1336 FALSE,
1337 &Index,
1338 &DataLength);
1340 {
1341 /* FIXME: Add current service to 'failed service' list */
1342 DPRINT("Service '%S' failed\n", Service->lpServiceName);
1343 break;
1344 }
1345
1346 if (!NT_SUCCESS(Status))
1347 break;
1348
1349 DPRINT("Comparing: '%S' '%wZ'\n", Service->lpServiceName, &DirInfo->Name);
1350
1351 if (_wcsicmp(Service->lpServiceName, DirInfo->Name.Buffer) == 0)
1352 {
1353 DPRINT("Found: '%S' '%wZ'\n",
1354 Service->lpServiceName, &DirInfo->Name);
1355
1356 /* Mark service as 'running' */
1357 Service->Status.dwCurrentState = SERVICE_RUNNING;
1358 Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
1359 Service->Status.dwWin32ExitCode = ERROR_SUCCESS;
1360 Service->Status.dwServiceSpecificExitCode = 0;
1361 Service->Status.dwCheckPoint = 0;
1362 Service->Status.dwWaitHint = 0;
1363
1364 /* Mark the service group as 'running' */
1365 if (Service->lpGroup != NULL)
1366 {
1367 Service->lpGroup->ServicesRunning = TRUE;
1368 }
1369
1370 break;
1371 }
1372 }
1373
1375 0,
1376 DirInfo);
1377 NtClose(DirHandle);
1378
1379 return STATUS_SUCCESS;
1380}
LONG NTSTATUS
Definition: precomp.h:26
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:737
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define HeapAlloc
Definition: compat.h:733
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
Status
Definition: gdiplustypes.h:25
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
struct _OBJECT_DIRECTORY_INFORMATION OBJECT_DIRECTORY_INFORMATION
#define DIRECTORY_QUERY
Definition: nt_native.h:1254
#define DIRECTORY_TRAVERSE
Definition: nt_native.h:1255
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
@ Service
Definition: ntsecapi.h:292
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: obdir.c:393
NTSTATUS NTAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PVOID Buffer, IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
Definition: obdir.c:490
#define STATUS_SUCCESS
Definition: shellext.h:65
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28

Referenced by ScmGetBootAndSystemDriverState().

◆ ScmControlService()

DWORD ScmControlService ( _In_ HANDLE  hControlPipe,
_In_ PCWSTR  pServiceName,
_In_ DWORD  dwControl,
_In_ SERVICE_STATUS_HANDLE  hServiceStatus 
)

Definition at line 1569 of file database.c.

1574{
1575 return ScmControlServiceEx(hControlPipe,
1576 pServiceName,
1577 dwControl,
1579 0, 0, NULL);
1580}
DWORD ScmControlServiceEx(_In_ HANDLE hControlPipe, _In_ PCWSTR pServiceName, _In_ DWORD dwControl, _In_ SERVICE_STATUS_HANDLE hServiceStatus, _In_opt_ DWORD dwServiceTag, _In_opt_ DWORD argc, _In_reads_opt_(argc) const PCWSTR *argv)
Definition: database.c:1417
SERVICE_STATUS_HANDLE hServiceStatus
Definition: main.c:10

Referenced by RControlService(), ScmAutoShutdownServices(), and ScmStopThread().

◆ ScmControlServiceEx()

DWORD ScmControlServiceEx ( _In_ HANDLE  hControlPipe,
_In_ PCWSTR  pServiceName,
_In_ DWORD  dwControl,
_In_ SERVICE_STATUS_HANDLE  hServiceStatus,
_In_opt_ DWORD  dwServiceTag,
_In_opt_ DWORD  argc,
_In_reads_opt_(argc) const PCWSTR argv 
)

Definition at line 1417 of file database.c.

1425{
1426 DWORD dwError = ERROR_SUCCESS;
1427 BOOL bResult;
1428 PSCM_CONTROL_PACKET ControlPacket;
1429 SCM_REPLY_PACKET ReplyPacket;
1431 DWORD i;
1432 PWSTR Ptr;
1433 DWORD dwReadCount = 0;
1434 OVERLAPPED Overlapped = {0};
1435
1436 DPRINT("ScmControlService(%S, %d) called\n", pServiceName, dwControl);
1437
1438 /* Calculate the total size of the control packet:
1439 * initial structure, the start command line, and the argument vector */
1441 PacketSize += (DWORD)((wcslen(pServiceName) + 1) * sizeof(WCHAR));
1442
1443 /*
1444 * Calculate the required packet size for the start argument vector 'argv',
1445 * composed of the pointer offsets list, followed by UNICODE strings.
1446 * The strings are stored successively after the offsets vector, with
1447 * the offsets being relative to the beginning of the vector, as in the
1448 * following layout (with N == argc):
1449 * [argOff(0)]...[argOff(N-1)][str(0)]...[str(N-1)] .
1450 */
1451 if (argc > 0 && argv != NULL)
1452 {
1454 PacketSize += (argc * sizeof(PWSTR));
1455
1456 DPRINT("Argc: %lu\n", argc);
1457 for (i = 0; i < argc; i++)
1458 {
1459 DPRINT("Argv[%lu]: %S\n", i, argv[i]);
1460 PacketSize += (DWORD)((wcslen(argv[i]) + 1) * sizeof(WCHAR));
1461 }
1462 }
1463
1464 /* Allocate the control packet */
1466 if (!ControlPacket)
1468
1469 ControlPacket->dwSize = PacketSize;
1470 ControlPacket->dwControl = dwControl;
1471 ControlPacket->hServiceStatus = hServiceStatus;
1472 ControlPacket->dwServiceTag = dwServiceTag;
1473
1474 /* Copy the start command line */
1475 ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
1476 Ptr = (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset);
1477 wcscpy(Ptr, pServiceName);
1478
1479 ControlPacket->dwArgumentsCount = 0;
1480 ControlPacket->dwArgumentsOffset = 0;
1481
1482 /* Copy the argument vector */
1483 if (argc > 0 && argv != NULL)
1484 {
1485 PWSTR *pOffPtr, pArgPtr;
1486
1487 Ptr += wcslen(pServiceName) + 1;
1488 pOffPtr = (PWSTR*)ALIGN_UP_POINTER(Ptr, PWSTR);
1489 pArgPtr = (PWSTR)((ULONG_PTR)pOffPtr + argc * sizeof(PWSTR));
1490
1491 ControlPacket->dwArgumentsCount = argc;
1492 ControlPacket->dwArgumentsOffset = (DWORD)((ULONG_PTR)pOffPtr - (ULONG_PTR)ControlPacket);
1493
1494 DPRINT("dwArgumentsCount: %lu\n", ControlPacket->dwArgumentsCount);
1495 DPRINT("dwArgumentsOffset: %lu\n", ControlPacket->dwArgumentsOffset);
1496
1497 for (i = 0; i < argc; i++)
1498 {
1499 wcscpy(pArgPtr, argv[i]);
1500 pOffPtr[i] = (PWSTR)((ULONG_PTR)pArgPtr - (ULONG_PTR)pOffPtr);
1501 DPRINT("offset[%lu]: %p\n", i, pOffPtr[i]);
1502 pArgPtr += wcslen(argv[i]) + 1;
1503 }
1504 }
1505
1506 /* Acquire the service control critical section, to synchronize requests */
1508
1509 bResult = TransactNamedPipe(hControlPipe,
1510 ControlPacket,
1511 PacketSize,
1512 &ReplyPacket,
1513 sizeof(ReplyPacket),
1514 &dwReadCount,
1515 &Overlapped);
1516 if (!bResult)
1517 {
1518 /* Fail for any error other than pending IO */
1519 dwError = GetLastError();
1520 if (dwError != ERROR_IO_PENDING)
1521 {
1522 DPRINT1("TransactNamedPipe(%S, %d) failed (Error %lu)\n", pServiceName, dwControl, dwError);
1523 goto Done;
1524 }
1525
1526 DPRINT("TransactNamedPipe(%S, %d) returned ERROR_IO_PENDING\n", pServiceName, dwControl);
1527
1528 dwError = WaitForSingleObject(hControlPipe, PipeTimeout);
1529 DPRINT("WaitForSingleObject(%S, %d) returned %lu\n", pServiceName, dwControl, dwError);
1530
1531 if (dwError == WAIT_TIMEOUT)
1532 {
1533 DPRINT1("WaitForSingleObject(%S, %d) timed out\n", pServiceName, dwControl);
1534 bResult = CancelIo(hControlPipe);
1535 if (!bResult)
1536 DPRINT1("CancelIo(%S, %d) failed (Error %lu)\n", pServiceName, dwControl, GetLastError());
1537
1539 }
1540 else if (dwError == WAIT_OBJECT_0)
1541 {
1542 bResult = GetOverlappedResult(hControlPipe,
1543 &Overlapped,
1544 &dwReadCount,
1545 TRUE);
1546 if (!bResult)
1547 {
1548 dwError = GetLastError();
1549 DPRINT1("GetOverlappedResult(%S, %d) failed (Error %lu)\n", pServiceName, dwControl, dwError);
1550 }
1551 }
1552 }
1553
1554Done:
1555 /* Release the service control critical section */
1557
1558 /* Free the control packet */
1559 HeapFree(GetProcessHeap(), 0, ControlPacket);
1560
1561 if (dwReadCount == sizeof(ReplyPacket))
1562 dwError = ReplyPacket.dwError;
1563
1564 DPRINT("ScmControlService(%S, %d) done (Error %lu)\n", pServiceName, dwControl, dwError);
1565 return dwError;
1566}
static int argc
Definition: ServiceArgs.c:12
static DWORD PipeTimeout
Definition: database.c:38
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_IO_PENDING
Definition: dderror.h:15
BOOL WINAPI CancelIo(IN HANDLE hFile)
Definition: deviceio.c:290
#define ULONG_PTR
Definition: config.h:101
unsigned int BOOL
Definition: ntddk_ex.h:94
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:221
#define argv
Definition: mplay32.c:18
BOOL WINAPI TransactNamedPipe(IN HANDLE hNamedPipe, IN LPVOID lpInBuffer, IN DWORD nInBufferSize, OUT LPVOID lpOutBuffer, IN DWORD nOutBufferSize, OUT LPDWORD lpBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: npipe.c:1315
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
struct _SCM_CONTROL_PACKET SCM_CONTROL_PACKET
DWORD dwServiceNameOffset
Definition: services.h:35
SERVICE_STATUS_HANDLE hServiceStatus
Definition: services.h:34
DWORD dwArgumentsOffset
Definition: services.h:36
DWORD dwArgumentsCount
Definition: services.h:32
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define ALIGN_UP(size, type)
Definition: umtypes.h:91
#define ALIGN_UP_POINTER(ptr, type)
Definition: umtypes.h:97
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_OBJECT_0
Definition: winbase.h:432
#define ERROR_SERVICE_REQUEST_TIMEOUT
Definition: winerror.h:604
_In_ USHORT PacketSize
Definition: iofuncs.h:1058

Referenced by ScmControlService(), and ScmStartUserModeService().

◆ ScmCreateNewControlPipe()

static DWORD ScmCreateNewControlPipe ( _In_ PSERVICE_IMAGE  pServiceImage,
_In_ BOOL  bSecurityServiceProcess 
)
static

Definition at line 53 of file database.c.

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,
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}
PSECURITY_DESCRIPTOR pPipeSD
Definition: security.c:27
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FILE_FLAG_OVERLAPPED
Definition: disk.h:46
HANDLE WINAPI CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:246
#define KEY_WRITE
Definition: nt_native.h:1031
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
static BOOL bSecurityServiceProcess
Definition: sctrl.c:63
#define REG_DWORD
Definition: sdbapi.c:596
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
LPVOID lpSecurityDescriptor
Definition: compat.h:193
#define PIPE_ACCESS_DUPLEX
Definition: winbase.h:165
#define PIPE_WAIT
Definition: winbase.h:172
#define PIPE_READMODE_MESSAGE
Definition: winbase.h:171
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:169
unsigned char BYTE
Definition: xxhash.c:193

Referenced by ScmCreateOrReferenceServiceImage().

◆ ScmCreateNewServiceRecord()

DWORD ScmCreateNewServiceRecord ( LPCWSTR  lpServiceName,
PSERVICE lpServiceRecord,
DWORD  dwServiceType,
DWORD  dwStartType 
)

Definition at line 767 of file database.c.

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}
static DWORD ResumeCount
Definition: database.c:32
#define InsertTailList(ListHead, Entry)
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwCheckPoint
Definition: winsvc.h:104
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
LIST_ENTRY ServiceListEntry
Definition: services.h:63
DWORD dwResumeCount
Definition: services.h:69
WCHAR szServiceName[1]
Definition: services.h:86
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define ERROR_SERVICE_NEVER_STARTED
Definition: winerror.h:628
#define ERROR_SERVICE_DISABLED
Definition: winerror.h:609
#define SERVICE_DISABLED
Definition: cmtypes.h:979
#define SERVICE_DRIVER
Definition: cmtypes.h:958

Referenced by CreateServiceListEntry(), and RCreateServiceW().

◆ ScmCreateOrReferenceServiceImage()

static DWORD ScmCreateOrReferenceServiceImage ( PSERVICE  pService)
static

Definition at line 458 of file database.c.

459{
461 UNICODE_STRING ImagePath;
463 PSERVICE_IMAGE pServiceImage = NULL;
465 DWORD dwError = ERROR_SUCCESS;
466 DWORD dwRecordSize;
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,
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
611done:
613 RtlFreeUnicodeString(&ImagePath);
614
615 DPRINT("ScmCreateOrReferenceServiceImage() done (Error: %lu)\n", dwError);
616
617 return dwError;
618}
static BOOL ScmEnableBackupRestorePrivileges(_In_ HANDLE hToken, _In_ BOOL bEnable)
Definition: database.c:312
static PSERVICE_IMAGE ScmGetServiceImageByImagePath(LPWSTR lpImagePath)
Definition: database.c:153
LIST_ENTRY ImageListHead
Definition: database.c:28
static BOOL ScmIsSecurityService(_In_ PSERVICE_IMAGE pServiceImage)
Definition: database.c:45
static DWORD ScmLogonService(IN PSERVICE pService, IN PSERVICE_IMAGE pImage)
Definition: database.c:359
static BOOL ScmIsSameServiceAccount(_In_ PCWSTR pszAccountName1, _In_ PCWSTR pszAccountName2)
Definition: database.c:270
static DWORD ScmCreateNewControlPipe(_In_ PSERVICE_IMAGE pServiceImage, _In_ BOOL bSecurityServiceProcess)
Definition: database.c:53
DWORD SetSecurityServicesEvent(VOID)
Definition: services.c:142
struct _SERVICE_IMAGE SERVICE_IMAGE
#define CloseHandle
Definition: compat.h:739
BOOL WINAPI UnloadUserProfile(_In_ HANDLE hToken, _In_ HANDLE hProfile)
Definition: profile.c:2184
FxString * pString
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4220
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define RTL_REGISTRY_SERVICES
Definition: nt_native.h:162
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
LPWSTR pszImagePath
Definition: services.h:49
LIST_ENTRY ImageListEntry
Definition: services.h:48
HANDLE hProfile
Definition: services.h:57
LPWSTR pszAccountName
Definition: services.h:50
HANDLE hToken
Definition: services.h:56
DWORD dwImageRunCount
Definition: services.h:51
HANDLE hProcess
Definition: services.h:54
int32_t INT_PTR
Definition: typedefs.h:64
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ERROR_DIFFERENT_SERVICE_ACCOUNT
Definition: winerror.h:630
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64

Referenced by ScmLoadService().

◆ ScmCreateServiceDatabase()

DWORD ScmCreateServiceDatabase ( VOID  )

Definition at line 1187 of file database.c.

1188{
1189 WCHAR szSubKey[MAX_PATH];
1191 HKEY hServiceKey;
1192 DWORD dwSubKey;
1193 DWORD dwSubKeyLength;
1194 FILETIME ftLastChanged;
1195 DWORD dwError;
1196
1197 DPRINT("ScmCreateServiceDatabase() called\n");
1198
1199 /* Retrieve the NoInteractiveServies value */
1201
1202 /* Create the service group list */
1203 dwError = ScmCreateGroupList();
1204 if (dwError != ERROR_SUCCESS)
1205 return dwError;
1206
1207 /* Initialize image and service lists */
1210
1211 /* Initialize the database lock */
1213
1215 L"System\\CurrentControlSet\\Services",
1216 0,
1217 KEY_READ,
1218 &hServicesKey);
1219 if (dwError != ERROR_SUCCESS)
1220 return dwError;
1221
1222 dwSubKey = 0;
1223 for (;;)
1224 {
1225 dwSubKeyLength = MAX_PATH;
1226 dwError = RegEnumKeyExW(hServicesKey,
1227 dwSubKey,
1228 szSubKey,
1229 &dwSubKeyLength,
1230 NULL,
1231 NULL,
1232 NULL,
1233 &ftLastChanged);
1234 if (dwError == ERROR_SUCCESS &&
1235 szSubKey[0] != L'{')
1236 {
1237 DPRINT("SubKeyName: '%S'\n", szSubKey);
1238
1239 dwError = RegOpenKeyExW(hServicesKey,
1240 szSubKey,
1241 0,
1242 KEY_READ,
1243 &hServiceKey);
1244 if (dwError == ERROR_SUCCESS)
1245 {
1246 dwError = CreateServiceListEntry(szSubKey,
1247 hServiceKey);
1248
1249 RegCloseKey(hServiceKey);
1250 }
1251 }
1252
1253 if (dwError != ERROR_SUCCESS)
1254 break;
1255
1256 dwSubKey++;
1257 }
1258
1260
1261 /* Wait for the LSA server */
1262 ScmWaitForLsa();
1263
1264 /* Delete services that are marked for delete */
1266
1267 DPRINT("ScmCreateServiceDatabase() done\n");
1268
1269 return ERROR_SUCCESS;
1270}
static DWORD CreateServiceListEntry(LPCWSTR lpServiceName, HKEY hServiceKey)
Definition: database.c:956
static RTL_RESOURCE DatabaseLock
Definition: database.c:31
static VOID ScmGetNoInteractiveServicesValue(VOID)
Definition: database.c:1161
VOID ScmDeleteMarkedServices(VOID)
Definition: database.c:1120
VOID ScmWaitForLsa(VOID)
Definition: services.c:207
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
DWORD ScmCreateGroupList(VOID)
Definition: groupdb.c:235
NTSYSAPI VOID NTAPI RtlInitializeResource(_In_ PRTL_RESOURCE Resource)

Referenced by wWinMain().

◆ ScmDeleteMarkedServices()

VOID ScmDeleteMarkedServices ( VOID  )

Definition at line 1120 of file database.c.

1121{
1122 PLIST_ENTRY ServiceEntry;
1123 PSERVICE CurrentService;
1125 DWORD dwError;
1126
1127 ServiceEntry = ServiceListHead.Flink;
1128 while (ServiceEntry != &ServiceListHead)
1129 {
1130 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1131
1132 ServiceEntry = ServiceEntry->Flink;
1133
1134 if (CurrentService->bDeleted != FALSE)
1135 {
1137 L"System\\CurrentControlSet\\Services",
1138 0,
1139 DELETE,
1140 &hServicesKey);
1141 if (dwError == ERROR_SUCCESS)
1142 {
1143 dwError = ScmDeleteRegKey(hServicesKey, CurrentService->lpServiceName);
1145 if (dwError == ERROR_SUCCESS)
1146 {
1147 RemoveEntryList(&CurrentService->ServiceListEntry);
1148 HeapFree(GetProcessHeap(), 0, CurrentService);
1149 }
1150 }
1151
1152 if (dwError != ERROR_SUCCESS)
1153 DPRINT1("Delete service failed: %S\n", CurrentService->lpServiceName);
1154 }
1155 }
1156}
DWORD ScmDeleteRegKey(_In_ HKEY hKey, _In_ PCWSTR pszSubKey)
Definition: config.c:646
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define DELETE
Definition: nt_native.h:57

Referenced by ScmCreateServiceDatabase(), and ScmShutdownServiceDatabase().

◆ ScmDeleteNamedPipeCriticalSection()

VOID ScmDeleteNamedPipeCriticalSection ( VOID  )

Definition at line 2363 of file database.c.

2364{
2366}
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)

Referenced by wWinMain().

◆ ScmDeleteService()

DWORD ScmDeleteService ( PSERVICE  lpService)

Definition at line 863 of file database.c.

864{
865 DWORD dwError;
867 DWORD dwServicesReturned = 0;
869
870 ASSERT(lpService->RefCount == 0);
871
872 /* Open the Services Reg key */
874 L"System\\CurrentControlSet\\Services",
875 0,
877 &hServicesKey);
878 if (dwError != ERROR_SUCCESS)
879 {
880 DPRINT1("Failed to open services key\n");
881 return dwError;
882 }
883
884 /* Call the function with NULL, just to get bytes we need */
886 lpService,
888 NULL,
890 &dwServicesReturned);
891
892 /* If pcbBytesNeeded returned a value then there are services running that are dependent on this service */
893 if (pcbBytesNeeded)
894 {
895 DPRINT1("Deletion failed due to running dependencies\n");
898 }
899
900 /* There are no references and no running dependencies,
901 it is now safe to delete the service */
902
903 /* Delete the Service Key */
904 dwError = ScmDeleteRegKey(hServicesKey, lpService->lpServiceName);
905
907
908 if (dwError != ERROR_SUCCESS)
909 {
910 DPRINT1("Failed to delete the Service Registry key\n");
911 return dwError;
912 }
913
914 /* Delete the Service */
915 ScmDeleteServiceRecord(lpService);
916
917 return ERROR_SUCCESS;
918}
VOID ScmDeleteServiceRecord(PSERVICE lpService)
Definition: database.c:816
DWORD Int_EnumDependentServicesW(HKEY hServicesKey, PSERVICE lpService, DWORD dwServiceState, PSERVICE *lpServices, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned)
Definition: rpcserver.c:782
#define KEY_SET_VALUE
Definition: nt_native.h:1017
LONG RefCount
Definition: services.h:70
#define ERROR_DEPENDENT_SERVICES_RUNNING
Definition: winerror.h:602

Referenced by ScmDereferenceService().

◆ ScmDeleteServiceRecord()

VOID ScmDeleteServiceRecord ( PSERVICE  lpService)

Definition at line 816 of file database.c.

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)
843
844 /* Remove the Service from the List */
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}
VOID ScmRemoveServiceImage(PSERVICE_IMAGE pServiceImage)
Definition: database.c:622

Referenced by ScmDeleteService().

◆ ScmDereferenceService()

DWORD ScmDereferenceService ( PSERVICE  lpService)

Definition at line 939 of file database.c.

940{
941 DWORD ref;
942
943 ASSERT(lpService->RefCount > 0);
944
945 ref = InterlockedDecrement(&lpService->RefCount);
946
947 if (ref == 0 && lpService->bDeleted &&
949 {
950 ScmDeleteService(lpService);
951 }
952 return ref;
953}
#define InterlockedDecrement
Definition: armddk.h:52
DWORD ScmDeleteService(PSERVICE lpService)
Definition: database.c:863
Definition: send.c:48

Referenced by RCloseServiceHandle(), RSetServiceStatus(), and ScmStopThread().

◆ ScmEnableBackupRestorePrivileges()

static BOOL ScmEnableBackupRestorePrivileges ( _In_ HANDLE  hToken,
_In_ BOOL  bEnable 
)
static

Definition at line 312 of file database.c.

315{
316 PTOKEN_PRIVILEGES pTokenPrivileges = NULL;
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 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 }
344 {
345 DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
346 bRet = FALSE;
347 }
348
349done:
350 if (pTokenPrivileges != NULL)
351 HeapFree(GetProcessHeap(), 0, pTokenPrivileges);
352
353 return bRet;
354}
BOOL WINAPI AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength)
Definition: security.c:374
#define SE_BACKUP_PRIVILEGE
Definition: security.c:671
#define SE_RESTORE_PRIVILEGE
Definition: security.c:672
LONG HighPart
DWORD LowPart
$ULONG PrivilegeCount
Definition: setypes.h:1023
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]
Definition: setypes.h:1024
_In_ BOOL bEnable
Definition: winddi.h:3426
#define ERROR_NOT_ALL_ASSIGNED
Definition: winerror.h:782
struct _TOKEN_PRIVILEGES TOKEN_PRIVILEGES
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63

Referenced by ScmCreateOrReferenceServiceImage(), ScmLogonService(), and ScmRemoveServiceImage().

◆ ScmGenerateServiceTag()

DWORD ScmGenerateServiceTag ( PSERVICE  lpServiceRecord)

Definition at line 744 of file database.c.

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->dwServiceTag = ServiceTag;
761
762 return ERROR_SUCCESS;
763}
static DWORD ServiceTag
Definition: database.c:34
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
DWORD dwServiceTag
Definition: services.h:78
#define ERROR_INVALID_DATA
Definition: winerror.h:116

Referenced by CreateServiceListEntry(), and RCreateServiceW().

◆ ScmGetBootAndSystemDriverState()

VOID ScmGetBootAndSystemDriverState ( VOID  )

Definition at line 1384 of file database.c.

1385{
1386 PLIST_ENTRY ServiceEntry;
1387 PSERVICE CurrentService;
1388
1389 DPRINT("ScmGetBootAndSystemDriverState() called\n");
1390
1391 ServiceEntry = ServiceListHead.Flink;
1392 while (ServiceEntry != &ServiceListHead)
1393 {
1394 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1395
1396 if (CurrentService->dwStartType == SERVICE_BOOT_START ||
1397 CurrentService->dwStartType == SERVICE_SYSTEM_START)
1398 {
1399 /* Check driver */
1400 DPRINT(" Checking service: %S\n", CurrentService->lpServiceName);
1401
1402 ScmCheckDriver(CurrentService);
1403 }
1404
1405 ServiceEntry = ServiceEntry->Flink;
1406 }
1407
1408 DPRINT("ScmGetBootAndSystemDriverState() done\n");
1409}
static NTSTATUS ScmCheckDriver(PSERVICE Service)
Definition: database.c:1286
#define SERVICE_BOOT_START
Definition: cmtypes.h:975
#define SERVICE_SYSTEM_START
Definition: cmtypes.h:976

Referenced by wWinMain().

◆ ScmGetNoInteractiveServicesValue()

static VOID ScmGetNoInteractiveServicesValue ( VOID  )
static

Definition at line 1161 of file database.c.

1162{
1163 HKEY hKey;
1164 DWORD dwKeySize;
1165 LONG lError;
1166
1168 L"SYSTEM\\CurrentControlSet\\Control\\Windows",
1169 0,
1170 KEY_READ,
1171 &hKey);
1172 if (lError == ERROR_SUCCESS)
1173 {
1174 dwKeySize = sizeof(NoInteractiveServices);
1175 lError = RegQueryValueExW(hKey,
1176 L"NoInteractiveServices",
1177 0,
1178 NULL,
1180 &dwKeySize);
1182 }
1183}
static DWORD NoInteractiveServices
Definition: database.c:33
long LONG
Definition: pedump.c:60

Referenced by ScmCreateServiceDatabase().

◆ ScmGetServiceEntryByDisplayName()

PSERVICE ScmGetServiceEntryByDisplayName ( LPCWSTR  lpDisplayName)

Definition at line 686 of file database.c.

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}

Referenced by RCreateServiceW(), RGetServiceKeyNameA(), and RGetServiceKeyNameW().

◆ ScmGetServiceEntryByName()

PSERVICE ScmGetServiceEntryByName ( LPCWSTR  lpServiceName)

Definition at line 657 of file database.c.

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}

Referenced by Int_EnumDependentServicesW(), RCreateServiceW(), RGetServiceDisplayNameA(), RGetServiceDisplayNameW(), RI_ScValidatePnPService(), and ROpenServiceW().

◆ ScmGetServiceEntryByResumeCount()

PSERVICE ScmGetServiceEntryByResumeCount ( DWORD  dwResumeCount)

Definition at line 715 of file database.c.

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}

Referenced by REnumServiceGroupW(), and REnumServicesStatusExW().

◆ ScmGetServiceImageByImagePath()

static PSERVICE_IMAGE ScmGetServiceImageByImagePath ( LPWSTR  lpImagePath)
static

Definition at line 153 of file database.c.

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}

Referenced by ScmCreateOrReferenceServiceImage().

◆ ScmGetServiceNameFromTag()

DWORD ScmGetServiceNameFromTag ( IN PTAG_INFO_NAME_FROM_TAG_IN_PARAMS  InParams,
OUT PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS OutParams 
)

Definition at line 183 of file database.c.

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->dwServiceTag == 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
249Cleanup:
250
251 /* Unlock database */
253
254 /* If failure, free allocated memory */
255 if (dwError != ERROR_SUCCESS)
256 {
257 if (OutBuffer != NULL)
258 {
260 }
261 }
262
263 /* Return error/success */
264 return dwError;
265}
static const WCHAR Cleanup[]
Definition: register.c:80
void *__RPC_USER MIDL_user_allocate(SIZE_T size)
Definition: irotp.c:371
void __RPC_USER MIDL_user_free(void *p)
Definition: irotp.c:376
#define UNICODE_NULL
_In_ UCHAR _In_ ULONG _Out_ PUCHAR _Outptr_result_bytebuffer_ OutBufferLength PVOID * OutBuffer
Definition: scsi.h:4071
DWORD dwProcessId
Definition: services.h:55
@ TagTypeService
Definition: svcctl.idl:304
#define ERROR_RETRY
Definition: winerror.h:740

Referenced by RI_ScQueryServiceTagInfo().

◆ ScmInitNamedPipeCriticalSection()

VOID ScmInitNamedPipeCriticalSection ( VOID  )

Definition at line 2335 of file database.c.

2336{
2337 HKEY hKey;
2338 DWORD dwKeySize;
2339 DWORD dwError;
2340
2342
2344 L"SYSTEM\\CurrentControlSet\\Control",
2345 0,
2346 KEY_READ,
2347 &hKey);
2348 if (dwError == ERROR_SUCCESS)
2349 {
2350 dwKeySize = sizeof(PipeTimeout);
2352 L"ServicesPipeTimeout",
2353 0,
2354 NULL,
2356 &dwKeySize);
2358 }
2359}
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751

Referenced by wWinMain().

◆ ScmIsLocalSystemAccount()

static BOOL ScmIsLocalSystemAccount ( _In_ PCWSTR  pszAccountName)
static

Definition at line 299 of file database.c.

301{
302 if (pszAccountName == NULL ||
303 _wcsicmp(pszAccountName, L"LocalSystem") == 0)
304 return TRUE;
305
306 return FALSE;
307}

Referenced by ScmLogonService().

◆ ScmIsSameServiceAccount()

static BOOL ScmIsSameServiceAccount ( _In_ PCWSTR  pszAccountName1,
_In_ PCWSTR  pszAccountName2 
)
static

Definition at line 270 of file database.c.

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}

Referenced by ScmCreateOrReferenceServiceImage().

◆ ScmIsSecurityService()

static BOOL ScmIsSecurityService ( _In_ PSERVICE_IMAGE  pServiceImage)
static

Definition at line 45 of file database.c.

47{
48 return (wcsstr(pServiceImage->pszImagePath, L"\\system32\\lsass.exe") != NULL);
49}
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)

Referenced by ScmCreateOrReferenceServiceImage(), ScmStartUserModeService(), and ScmWaitForServiceConnect().

◆ ScmLoadService()

static DWORD ScmLoadService ( PSERVICE  Service,
DWORD  argc,
const PCWSTR argv 
)
static

Definition at line 1911 of file database.c.

1914{
1915 PSERVICE_GROUP Group = Service->lpGroup;
1916 DWORD dwError = ERROR_SUCCESS;
1917 LPCWSTR lpLogStrings[2];
1918 WCHAR szLogBuffer[80];
1919
1920 DPRINT("ScmLoadService() called\n");
1921 DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName);
1922
1923 if (Service->Status.dwCurrentState != SERVICE_STOPPED)
1924 {
1925 DPRINT("Service %S is already running\n", Service->lpServiceName);
1927 }
1928
1929 DPRINT("Service->Type: %lu\n", Service->Status.dwServiceType);
1930
1931 if (Service->Status.dwServiceType & SERVICE_DRIVER)
1932 {
1933 /* Start the driver */
1934 dwError = ScmStartDriver(Service);
1935 }
1936 else // if (Service->Status.dwServiceType & (SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS))
1937 {
1938 /* Start user-mode service */
1940 if (dwError == ERROR_SUCCESS)
1941 {
1943 if (dwError == ERROR_SUCCESS)
1944 {
1945 Service->Status.dwCurrentState = SERVICE_START_PENDING;
1946 Service->Status.dwControlsAccepted = 0;
1948 }
1949 else
1950 {
1951 Service->lpImage->dwImageRunCount--;
1952 if (Service->lpImage->dwImageRunCount == 0)
1953 {
1955 Service->lpImage = NULL;
1956 }
1957 }
1958 }
1959 }
1960
1961 DPRINT("ScmLoadService() done (Error %lu)\n", dwError);
1962
1963 if (dwError == ERROR_SUCCESS)
1964 {
1965 if (Group != NULL)
1966 {
1967 Group->ServicesRunning = TRUE;
1968 }
1969
1970 /* Log a successful service start */
1972 lpLogStrings[0] = Service->lpDisplayName;
1973 lpLogStrings[1] = szLogBuffer;
1974
1977 2,
1978 lpLogStrings);
1979 }
1980 else
1981 {
1982 if (Service->dwErrorControl != SERVICE_ERROR_IGNORE)
1983 {
1984 /* Log a failed service start */
1985 StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer),
1986 L"%lu", dwError);
1987 lpLogStrings[0] = Service->lpServiceName;
1988 lpLogStrings[1] = szLogBuffer;
1991 2,
1992 lpLogStrings);
1993 }
1994
1995#if 0
1996 switch (Service->dwErrorControl)
1997 {
1999 if (IsLastKnownGood == FALSE)
2000 {
2001 /* FIXME: Boot last known good configuration */
2002 }
2003 break;
2004
2006 if (IsLastKnownGood == FALSE)
2007 {
2008 /* FIXME: Boot last known good configuration */
2009 }
2010 else
2011 {
2012 /* FIXME: BSOD! */
2013 }
2014 break;
2015 }
2016#endif
2017 }
2018
2019 return dwError;
2020}
static DWORD ScmStartUserModeService(PSERVICE Service, DWORD argc, const PCWSTR *argv)
Definition: database.c:1761
DWORD ScmReferenceService(PSERVICE lpService)
Definition: database.c:931
static DWORD ScmCreateOrReferenceServiceImage(PSERVICE pService)
Definition: database.c:458
DWORD ScmStartDriver(PSERVICE pService)
Definition: driver.c:314
#define IDS_SERVICE_START
Definition: resource.h:3
VOID ScmLogEvent(DWORD dwEventId, WORD wType, WORD wStrings, LPCWSTR *lpStrings)
Definition: services.c:174
_In_opt_ PSID Group
Definition: rtlfuncs.h:1658
#define EVENT_SERVICE_CONTROL_SUCCESS
Definition: netevent.h:432
#define EVENT_SERVICE_START_FAILED
Definition: netevent.h:444
#define GetModuleHandle
Definition: winbase.h:3852
#define ERROR_SERVICE_ALREADY_RUNNING
Definition: winerror.h:607
#define EVENTLOG_ERROR_TYPE
Definition: winnt_old.h:2863
#define EVENTLOG_INFORMATION_TYPE
Definition: winnt_old.h:2865
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define SERVICE_ERROR_SEVERE
Definition: cmtypes.h:983
#define SERVICE_ERROR_CRITICAL
Definition: cmtypes.h:984
#define SERVICE_ERROR_IGNORE
Definition: cmtypes.h:981
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185

Referenced by ScmAutoStartServices(), and ScmStartService().

◆ ScmLockDatabaseExclusive()

◆ ScmLockDatabaseShared()

◆ ScmLogonService()

static DWORD ScmLogonService ( IN PSERVICE  pService,
IN PSERVICE_IMAGE  pImage 
)
static

Definition at line 359 of file database.c.

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) || ScmLiveSetup || ScmSetupInProgress)
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 */
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();
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
446done:
447 if (pszPassword != NULL)
448 HeapFree(GetProcessHeap(), 0, pszPassword);
449
450 if (ptr != NULL)
451 *ptr = L'\\';
452
453 return dwError;
454}
static BOOL ScmIsLocalSystemAccount(_In_ PCWSTR pszAccountName)
Definition: database.c:299
BOOL ScmLiveSetup
Definition: services.c:30
BOOL ScmSetupInProgress
Definition: services.c:31
BOOL WINAPI LogonUserW(_In_ LPWSTR lpszUsername, _In_opt_ LPWSTR lpszDomain, _In_opt_ LPWSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken)
Definition: logon.c:1137
#define wcschr
Definition: compat.h:17
BOOL WINAPI LoadUserProfileW(_In_ HANDLE hToken, _Inout_ LPPROFILEINFOW lpProfileInfo)
Definition: profile.c:2005
static PVOID ptr
Definition: dispmode.c:27
_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 dwFlags
Definition: userenv.h:37
DWORD dwSize
Definition: userenv.h:36
HANDLE hProfile
Definition: userenv.h:43
LPWSTR lpUserName
Definition: userenv.h:38
#define PI_NOUI
Definition: userenv.h:8
#define ZeroMemory
Definition: winbase.h:1737
#define LOGON32_LOGON_SERVICE
Definition: winbase.h:420
#define LOGON32_PROVIDER_DEFAULT
Definition: winbase.h:413
#define ERROR_SERVICE_LOGON_FAILED
Definition: winerror.h:620

Referenced by ScmCreateOrReferenceServiceImage().

◆ ScmReferenceService()

DWORD ScmReferenceService ( PSERVICE  lpService)

Definition at line 931 of file database.c.

932{
933 return InterlockedIncrement(&lpService->RefCount);
934}
#define InterlockedIncrement
Definition: armddk.h:53

Referenced by RCreateServiceW(), ROpenServiceW(), RSetServiceStatus(), and ScmLoadService().

◆ ScmRemoveServiceImage()

VOID ScmRemoveServiceImage ( PSERVICE_IMAGE  pServiceImage)

Definition at line 622 of file database.c.

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}

Referenced by ScmDeleteServiceRecord(), ScmLoadService(), and ScmStopThread().

◆ ScmShutdownServiceDatabase()

VOID ScmShutdownServiceDatabase ( VOID  )

Definition at line 1274 of file database.c.

1275{
1276 DPRINT("ScmShutdownServiceDatabase() called\n");
1277
1280
1281 DPRINT("ScmShutdownServiceDatabase() done\n");
1282}
NTSYSAPI VOID NTAPI RtlDeleteResource(_In_ PRTL_RESOURCE Resource)

Referenced by ShutdownHandlerRoutine().

◆ ScmStartService()

DWORD ScmStartService ( PSERVICE  Service,
DWORD  argc,
const PCWSTR argv 
)

Definition at line 2024 of file database.c.

2027{
2028 DWORD dwError = ERROR_SUCCESS;
2030
2031 DPRINT("ScmStartService() called\n");
2032 DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName);
2033
2034 /* Acquire the service control critical section, to synchronize starts */
2036
2037 /*
2038 * Acquire the user service start lock while the service is starting, if
2039 * needed (i.e. if we are not starting it during the initialization phase).
2040 * If we don't success, bail out.
2041 */
2042 if (!ScmInitialize)
2043 {
2045 if (dwError != ERROR_SUCCESS)
2046 goto done;
2047 }
2048
2049 /* Really start the service */
2050 dwError = ScmLoadService(Service, argc, argv);
2051
2052 /* Release the service start lock, if needed, and the critical section */
2054
2055done:
2057
2058 DPRINT("ScmStartService() done (Error %lu)\n", dwError);
2059
2060 return dwError;
2061}
DWORD ScmAcquireServiceStartLock(IN BOOL IsServiceController, OUT LPSC_RPC_LOCK lpLock)
Definition: lock.c:31
DWORD ScmReleaseServiceStartLock(IN OUT LPSC_RPC_LOCK lpLock)
Definition: lock.c:82
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127

Referenced by RStartServiceA(), and RStartServiceW().

◆ ScmStartUserModeService()

static DWORD ScmStartUserModeService ( PSERVICE  Service,
DWORD  argc,
const PCWSTR argv 
)
static

Definition at line 1761 of file database.c.

1764{
1765 PROCESS_INFORMATION ProcessInformation;
1766 STARTUPINFOW StartupInfo;
1767 LPVOID lpEnvironment;
1768 BOOL Result;
1769 DWORD dwError = ERROR_SUCCESS;
1770
1771 DPRINT("ScmStartUserModeService(%p)\n", Service);
1772
1773 /* If the image is already running, just send a start command */
1774 if (Service->lpImage->dwImageRunCount > 1)
1775 goto Quit;
1776
1777 /* Otherwise start its process */
1778 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
1779 StartupInfo.cb = sizeof(StartupInfo);
1780 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
1781
1782 if (Service->lpImage->hToken)
1783 {
1784 /* User token: Run the service under the user account */
1785
1786 if (!CreateEnvironmentBlock(&lpEnvironment, Service->lpImage->hToken, FALSE))
1787 {
1788 /* We failed, run the service with the current environment */
1789 DPRINT1("CreateEnvironmentBlock() failed with error %d; service '%S' will run with current environment\n",
1790 GetLastError(), Service->lpServiceName);
1791 lpEnvironment = NULL;
1792 }
1793
1794 /* Impersonate the new user */
1795 Result = ImpersonateLoggedOnUser(Service->lpImage->hToken);
1796 if (Result)
1797 {
1798 /* Launch the process in the user's logon session */
1799 Result = CreateProcessAsUserW(Service->lpImage->hToken,
1800 NULL,
1801 Service->lpImage->pszImagePath,
1802 NULL,
1803 NULL,
1804 FALSE,
1806 lpEnvironment,
1807 NULL,
1808 &StartupInfo,
1809 &ProcessInformation);
1810 if (!Result)
1811 dwError = GetLastError();
1812
1813 /* Revert the impersonation */
1814 RevertToSelf();
1815 }
1816 else
1817 {
1818 dwError = GetLastError();
1819 DPRINT1("ImpersonateLoggedOnUser() failed with error %d\n", dwError);
1820 }
1821 }
1822 else
1823 {
1824 /* No user token: Run the service under the LocalSystem account */
1825
1826 if (!CreateEnvironmentBlock(&lpEnvironment, NULL, TRUE))
1827 {
1828 /* We failed, run the service with the current environment */
1829 DPRINT1("CreateEnvironmentBlock() failed with error %d; service '%S' will run with current environment\n",
1830 GetLastError(), Service->lpServiceName);
1831 lpEnvironment = NULL;
1832 }
1833
1834 /* Use the interactive desktop if the service is interactive */
1835 if ((NoInteractiveServices == 0) &&
1836 (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
1837 {
1838 StartupInfo.dwFlags |= STARTF_INHERITDESKTOP;
1839 StartupInfo.lpDesktop = L"WinSta0\\Default";
1840 }
1841
1842 if (!ScmIsSecurityService(Service->lpImage))
1843 {
1845 Service->lpImage->pszImagePath,
1846 NULL,
1847 NULL,
1848 FALSE,
1850 lpEnvironment,
1851 NULL,
1852 &StartupInfo,
1853 &ProcessInformation);
1854 if (!Result)
1855 dwError = GetLastError();
1856 }
1857 else
1858 {
1859 Result = TRUE;
1860 dwError = ERROR_SUCCESS;
1861 }
1862 }
1863
1864 if (lpEnvironment)
1865 DestroyEnvironmentBlock(lpEnvironment);
1866
1867 if (!Result)
1868 {
1869 DPRINT1("Starting '%S' failed with error %d\n",
1870 Service->lpServiceName, dwError);
1871 return dwError;
1872 }
1873
1874 DPRINT("Process Id: %lu Handle %p\n",
1875 ProcessInformation.dwProcessId,
1876 ProcessInformation.hProcess);
1877 DPRINT("Thread Id: %lu Handle %p\n",
1878 ProcessInformation.dwThreadId,
1879 ProcessInformation.hThread);
1880
1881 /* Get the process handle and ID */
1882 Service->lpImage->hProcess = ProcessInformation.hProcess;
1883 Service->lpImage->dwProcessId = ProcessInformation.dwProcessId;
1884
1885 /* Resume the main thread and close its handle */
1886 ResumeThread(ProcessInformation.hThread);
1887 CloseHandle(ProcessInformation.hThread);
1888
1889 /* Connect control pipe */
1891 if (dwError != ERROR_SUCCESS)
1892 {
1893 DPRINT1("Connecting control pipe failed! (Error %lu)\n", dwError);
1894 Service->lpImage->dwProcessId = 0;
1895 return dwError;
1896 }
1897
1898Quit:
1899 /* Send the start command and return */
1900 return ScmControlServiceEx(Service->lpImage->hControlPipe,
1901 Service->lpServiceName,
1902 (Service->Status.dwServiceType & SERVICE_WIN32_OWN_PROCESS)
1905 Service->dwServiceTag,
1906 argc, argv);
1907}
static DWORD ScmWaitForServiceConnect(PSERVICE Service)
Definition: database.c:1584
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW(_In_opt_ HANDLE hToken, _In_opt_ LPCWSTR lpApplicationName, _Inout_opt_ LPWSTR lpCommandLine, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCWSTR lpCurrentDirectory, _In_ LPSTARTUPINFOW lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation)
Definition: logon.c:993
BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
Definition: misc.c:152
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4598
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
BOOL WINAPI DestroyEnvironmentBlock(IN LPVOID lpEnvironment)
Definition: environment.c:725
BOOL WINAPI CreateEnvironmentBlock(OUT LPVOID *lpEnvironment, IN HANDLE hToken, IN BOOL bInherit)
Definition: environment.c:503
#define SERVICE_CONTROL_START_OWN
Definition: services.h:20
#define SERVICE_CONTROL_START_SHARE
Definition: services.h:18
LPWSTR lpDesktop
Definition: winbase.h:879
DWORD cb
Definition: winbase.h:877
DWORD dwFlags
Definition: winbase.h:888
#define STARTF_INHERITDESKTOP
Definition: undocuser.h:164
#define CREATE_UNICODE_ENVIRONMENT
Definition: winbase.h:189
#define CREATE_SUSPENDED
Definition: winbase.h:181
#define DETACHED_PROCESS
Definition: winbase.h:182
BOOL WINAPI RevertToSelf(void)
Definition: security.c:1608
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409

Referenced by ScmLoadService().

◆ ScmUnlockDatabase()

◆ ScmWaitForServiceConnect()

static DWORD ScmWaitForServiceConnect ( PSERVICE  Service)
static

Definition at line 1584 of file database.c.

1585{
1586 DWORD dwRead = 0;
1587 DWORD dwProcessId = 0;
1588 DWORD dwError = ERROR_SUCCESS;
1589 BOOL bResult;
1590 OVERLAPPED Overlapped = {0};
1591#if 0
1592 LPCWSTR lpLogStrings[3];
1593 WCHAR szBuffer1[20];
1594 WCHAR szBuffer2[20];
1595#endif
1596
1597 DPRINT("ScmWaitForServiceConnect()\n");
1598
1599 bResult = ConnectNamedPipe(Service->lpImage->hControlPipe,
1600 &Overlapped);
1601 if (bResult == FALSE)
1602 {
1603 DPRINT("ConnectNamedPipe() returned FALSE\n");
1604
1605 dwError = GetLastError();
1606 if (dwError == ERROR_IO_PENDING)
1607 {
1608 DPRINT("dwError: ERROR_IO_PENDING\n");
1609
1610 dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
1611 PipeTimeout);
1612 DPRINT("WaitForSingleObject() returned %lu\n", dwError);
1613
1614 if (dwError == WAIT_TIMEOUT)
1615 {
1616 DPRINT("WaitForSingleObject() returned WAIT_TIMEOUT\n");
1617
1618 bResult = CancelIo(Service->lpImage->hControlPipe);
1619 if (bResult == FALSE)
1620 {
1621 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1622 }
1623
1624#if 0
1625 _ultow(PipeTimeout, szBuffer1, 10);
1626 lpLogStrings[0] = Service->lpDisplayName;
1627 lpLogStrings[1] = szBuffer1;
1628
1631 2,
1632 lpLogStrings);
1633#endif
1634 DPRINT1("Log EVENT_CONNECTION_TIMEOUT by %S\n", Service->lpDisplayName);
1635
1637 }
1638 else if (dwError == WAIT_OBJECT_0)
1639 {
1640 bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
1641 &Overlapped,
1642 &dwRead,
1643 TRUE);
1644 if (bResult == FALSE)
1645 {
1646 dwError = GetLastError();
1647 DPRINT1("GetOverlappedResult failed (Error %lu)\n", dwError);
1648
1649 return dwError;
1650 }
1651 }
1652 }
1653 else if (dwError != ERROR_PIPE_CONNECTED)
1654 {
1655 DPRINT1("ConnectNamedPipe failed (Error %lu)\n", dwError);
1656 return dwError;
1657 }
1658 }
1659
1660 DPRINT("Control pipe connected\n");
1661
1662 Overlapped.hEvent = NULL;
1663
1664 /* Read the process id from pipe */
1665 bResult = ReadFile(Service->lpImage->hControlPipe,
1666 (LPVOID)&dwProcessId,
1667 sizeof(DWORD),
1668 &dwRead,
1669 &Overlapped);
1670 if (bResult == FALSE)
1671 {
1672 DPRINT("ReadFile() returned FALSE\n");
1673
1674 dwError = GetLastError();
1675 if (dwError == ERROR_IO_PENDING)
1676 {
1677 DPRINT("dwError: ERROR_IO_PENDING\n");
1678
1679 dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
1680 PipeTimeout);
1681 if (dwError == WAIT_TIMEOUT)
1682 {
1683 DPRINT("WaitForSingleObject() returned WAIT_TIMEOUT\n");
1684
1685 bResult = CancelIo(Service->lpImage->hControlPipe);
1686 if (bResult == FALSE)
1687 {
1688 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1689 }
1690
1691#if 0
1692 _ultow(PipeTimeout, szBuffer1, 10);
1693 lpLogStrings[0] = szBuffer1;
1694
1697 1,
1698 lpLogStrings);
1699#endif
1700 DPRINT1("Log EVENT_READFILE_TIMEOUT by %S\n", Service->lpDisplayName);
1701
1703 }
1704 else if (dwError == WAIT_OBJECT_0)
1705 {
1706 DPRINT("WaitForSingleObject() returned WAIT_OBJECT_0\n");
1707
1708 DPRINT("Process Id: %lu\n", dwProcessId);
1709
1710 bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
1711 &Overlapped,
1712 &dwRead,
1713 TRUE);
1714 if (bResult == FALSE)
1715 {
1716 dwError = GetLastError();
1717 DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError);
1718
1719 return dwError;
1720 }
1721 }
1722 else
1723 {
1724 DPRINT1("WaitForSingleObject() returned %lu\n", dwError);
1725 }
1726 }
1727 else
1728 {
1729 DPRINT1("ReadFile() failed (Error %lu)\n", dwError);
1730 return dwError;
1731 }
1732 }
1733
1734 if ((ScmIsSecurityService(Service->lpImage) == FALSE)&&
1735 (dwProcessId != Service->lpImage->dwProcessId))
1736 {
1737#if 0
1738 _ultow(Service->lpImage->dwProcessId, szBuffer1, 10);
1739 _ultow(dwProcessId, szBuffer2, 10);
1740
1741 lpLogStrings[0] = Service->lpDisplayName;
1742 lpLogStrings[1] = szBuffer1;
1743 lpLogStrings[2] = szBuffer2;
1744
1747 3,
1748 lpLogStrings);
1749#endif
1750
1751 DPRINT1("Log EVENT_SERVICE_DIFFERENT_PID_CONNECTED by %S\n", Service->lpDisplayName);
1752 }
1753
1754 DPRINT("ScmWaitForServiceConnect() done\n");
1755
1756 return ERROR_SUCCESS;
1757}
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
_CRTIMP wchar_t *__cdecl _ultow(_In_ unsigned long _Value, _Pre_notnull_ _Post_z_ wchar_t *_Dest, _In_ int _Radix)
#define EVENT_SERVICE_DIFFERENT_PID_CONNECTED
Definition: netevent.h:435
#define EVENT_CONNECTION_TIMEOUT
Definition: netevent.h:143
#define EVENT_READFILE_TIMEOUT
Definition: netevent.h:413
BOOL WINAPI ConnectNamedPipe(IN HANDLE hNamedPipe, IN LPOVERLAPPED lpOverlapped)
Definition: npipe.c:701
HANDLE hEvent
Definition: winbase.h:845
#define ERROR_PIPE_CONNECTED
Definition: winerror.h:352
#define EVENTLOG_WARNING_TYPE
Definition: winnt_old.h:2864

Referenced by ScmStartUserModeService().

Variable Documentation

◆ ControlServiceCriticalSection

◆ DatabaseLock

◆ ImageListHead

◆ NoInteractiveServices

DWORD NoInteractiveServices = 0
static

Definition at line 33 of file database.c.

Referenced by ScmGetNoInteractiveServicesValue(), and ScmStartUserModeService().

◆ PipeTimeout

DWORD PipeTimeout = 30000
static

◆ ResumeCount

DWORD ResumeCount = 1
static

Definition at line 32 of file database.c.

Referenced by CreateProcessInternalW(), and ScmCreateNewServiceRecord().

◆ ServiceListHead

◆ ServiceTag

DWORD ServiceTag = 0
static

Definition at line 34 of file database.c.

Referenced by GetOwnerModuleFromTagEntry(), ScmGenerateServiceTag(), and service_main().