ReactOS 0.4.15-dev-7889-g76290a6
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)
 
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 ScmControlService (HANDLE hControlPipe, PWSTR pServiceName, SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwControl)
 
static DWORD ScmSendStartCommand (PSERVICE Service, DWORD argc, LPWSTR *argv)
 
static DWORD ScmWaitForServiceConnect (PSERVICE Service)
 
static DWORD ScmStartUserModeService (PSERVICE Service, DWORD argc, LPWSTR *argv)
 
static DWORD ScmLoadService (PSERVICE Service, DWORD argc, LPWSTR *argv)
 
DWORD ScmStartService (PSERVICE Service, DWORD argc, LPWSTR *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 857 of file database.c.

859{
860 PSERVICE lpService = NULL;
862 LPWSTR lpGroup = NULL;
864 DWORD dwError;
865 DWORD dwServiceType;
866 DWORD dwStartType;
867 DWORD dwErrorControl;
868 DWORD dwTagId;
869
870 DPRINT("Service: '%S'\n", lpServiceName);
871 if (*lpServiceName == L'{')
872 return ERROR_SUCCESS;
873
874 dwSize = sizeof(DWORD);
875 dwError = RegQueryValueExW(hServiceKey,
876 L"Type",
877 NULL,
878 NULL,
879 (LPBYTE)&dwServiceType,
880 &dwSize);
881 if (dwError != ERROR_SUCCESS)
882 return ERROR_SUCCESS;
883
884 if (((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) &&
886 (dwServiceType != SERVICE_KERNEL_DRIVER) &&
887 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
888 return ERROR_SUCCESS;
889
890 DPRINT("Service type: %lx\n", dwServiceType);
891
892 dwSize = sizeof(DWORD);
893 dwError = RegQueryValueExW(hServiceKey,
894 L"Start",
895 NULL,
896 NULL,
897 (LPBYTE)&dwStartType,
898 &dwSize);
899 if (dwError != ERROR_SUCCESS)
900 return ERROR_SUCCESS;
901
902 DPRINT("Start type: %lx\n", dwStartType);
903
904 dwSize = sizeof(DWORD);
905 dwError = RegQueryValueExW(hServiceKey,
906 L"ErrorControl",
907 NULL,
908 NULL,
909 (LPBYTE)&dwErrorControl,
910 &dwSize);
911 if (dwError != ERROR_SUCCESS)
912 return ERROR_SUCCESS;
913
914 DPRINT("Error control: %lx\n", dwErrorControl);
915
916 dwError = RegQueryValueExW(hServiceKey,
917 L"Tag",
918 NULL,
919 NULL,
920 (LPBYTE)&dwTagId,
921 &dwSize);
922 if (dwError != ERROR_SUCCESS)
923 dwTagId = 0;
924
925 DPRINT("Tag: %lx\n", dwTagId);
926
927 dwError = ScmReadString(hServiceKey,
928 L"Group",
929 &lpGroup);
930 if (dwError != ERROR_SUCCESS)
931 lpGroup = NULL;
932
933 DPRINT("Group: %S\n", lpGroup);
934
935 dwError = ScmReadString(hServiceKey,
936 L"DisplayName",
938 if (dwError != ERROR_SUCCESS)
940
941 DPRINT("Display name: %S\n", lpDisplayName);
942
943 dwError = ScmCreateNewServiceRecord(lpServiceName,
944 &lpService,
945 dwServiceType,
946 dwStartType);
947 if (dwError != ERROR_SUCCESS)
948 goto done;
949
950 lpService->dwErrorControl = dwErrorControl;
951 lpService->dwTag = dwTagId;
952
953 if (lpGroup != NULL)
954 {
955 dwError = ScmSetServiceGroup(lpService, lpGroup);
956 if (dwError != ERROR_SUCCESS)
957 goto done;
958 }
959
960 if (lpDisplayName != NULL)
961 {
962 lpService->lpDisplayName = lpDisplayName;
964 }
965
966 DPRINT("ServiceName: '%S'\n", lpService->lpServiceName);
967 if (lpService->lpGroup != NULL)
968 {
969 DPRINT("Group: '%S'\n", lpService->lpGroup->lpGroupName);
970 }
971 DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
972 lpService->dwStartType,
973 lpService->Status.dwServiceType,
974 lpService->dwTag,
975 lpService->dwErrorControl);
976
977 if (ScmIsDeleteFlagSet(hServiceKey))
978 lpService->bDeleted = TRUE;
979 else
980 ScmGenerateServiceTag(lpService);
981
982 if (lpService->Status.dwServiceType & SERVICE_WIN32)
983 {
984 dwError = ScmReadSecurityDescriptor(hServiceKey,
985 &lpService->pSecurityDescriptor);
986 if (dwError != ERROR_SUCCESS)
987 goto done;
988
989 /* Assing the default security descriptor if the security descriptor cannot be read */
990 if (lpService->pSecurityDescriptor == NULL)
991 {
992 DPRINT("No security descriptor found! Assign default security descriptor\n");
993 dwError = ScmCreateDefaultServiceSD(&lpService->pSecurityDescriptor);
994 if (dwError != ERROR_SUCCESS)
995 goto done;
996
997 dwError = ScmWriteSecurityDescriptor(hServiceKey,
998 lpService->pSecurityDescriptor);
999 if (dwError != ERROR_SUCCESS)
1000 goto done;
1001 }
1002 }
1003
1004done:
1005 if (lpGroup != NULL)
1006 HeapFree(GetProcessHeap(), 0, lpGroup);
1007
1008 if (lpDisplayName != NULL)
1010
1011 if (lpService != NULL)
1012 {
1013 ASSERT(lpService->lpImage == NULL);
1014 }
1015
1016 return dwError;
1017}
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:71
LPWSTR lpGroupName
Definition: services.h:33
DWORD dwServiceType
Definition: winsvc.h:99
BOOL bDeleted
Definition: services.h:66
PSERVICE_GROUP lpGroup
Definition: services.h:64
PSECURITY_DESCRIPTOR pSecurityDescriptor
Definition: services.h:80
DWORD dwErrorControl
Definition: services.h:72
LPWSTR lpDisplayName
Definition: services.h:63
SERVICE_STATUS Status
Definition: services.h:70
DWORD dwStartType
Definition: services.h:71
DWORD dwTag
Definition: services.h:73
PSERVICE_IMAGE lpImage
Definition: services.h:65
LPWSTR lpServiceName
Definition: services.h:62
unsigned char * LPBYTE
Definition: typedefs.h:53
_In_ LPCSTR _Out_writes_to_opt_ cchDisplayName LPSTR lpDisplayName
Definition: winbase.h:2790
#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().

◆ ScmAutoShutdownServices()

VOID ScmAutoShutdownServices ( VOID  )

Definition at line 2382 of file database.c.

2383{
2384 PLIST_ENTRY ServiceEntry;
2385 PSERVICE CurrentService;
2386
2387 DPRINT("ScmAutoShutdownServices() called\n");
2388
2389 /* Lock the service database exclusively */
2391
2392 ServiceEntry = ServiceListHead.Flink;
2393 while (ServiceEntry != &ServiceListHead)
2394 {
2395 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2396
2397 if ((CurrentService->Status.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN) &&
2398 (CurrentService->Status.dwCurrentState == SERVICE_RUNNING ||
2399 CurrentService->Status.dwCurrentState == SERVICE_START_PENDING))
2400 {
2401 /* Send the shutdown notification */
2402 DPRINT("Shutdown service: %S\n", CurrentService->lpServiceName);
2403 ScmControlService(CurrentService->lpImage->hControlPipe,
2404 CurrentService->lpServiceName,
2405 (SERVICE_STATUS_HANDLE)CurrentService,
2407 }
2408
2409 ServiceEntry = ServiceEntry->Flink;
2410 }
2411
2412 /* Unlock the service database */
2414
2415 DPRINT("ScmAutoShutdownServices() done\n");
2416}
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
VOID ScmUnlockDatabase(VOID)
Definition: database.c:2434
DWORD ScmControlService(HANDLE hControlPipe, PWSTR pServiceName, SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwControl)
Definition: database.c:1314
BOOL ScmLockDatabaseExclusive(VOID)
Definition: database.c:2420
LIST_ENTRY ServiceListHead
Definition: database.c:29
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
HANDLE hControlPipe
Definition: services.h:51
DWORD dwControlsAccepted
Definition: winsvc.h:101
DWORD dwCurrentState
Definition: winsvc.h:100
#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 2171 of file database.c.

2172{
2173 DWORD dwError;
2174 PLIST_ENTRY GroupEntry;
2175 PLIST_ENTRY ServiceEntry;
2176 PSERVICE_GROUP CurrentGroup;
2177 PSERVICE CurrentService;
2178 WCHAR szSafeBootServicePath[MAX_PATH];
2179 DWORD SafeBootEnabled;
2180 HKEY hKey;
2181 DWORD dwKeySize;
2182 ULONG i;
2183
2184 /*
2185 * This function MUST be called ONLY at initialization time.
2186 * Therefore, no need to acquire the user service start lock.
2187 */
2189
2190 /* Retrieve the SafeBoot parameter */
2192 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option",
2193 0,
2194 KEY_READ,
2195 &hKey);
2196 if (dwError == ERROR_SUCCESS)
2197 {
2198 dwKeySize = sizeof(SafeBootEnabled);
2199 dwError = RegQueryValueExW(hKey,
2200 L"OptionValue",
2201 0,
2202 NULL,
2203 (LPBYTE)&SafeBootEnabled,
2204 &dwKeySize);
2206 }
2207
2208 /* Default to Normal boot if the value doesn't exist */
2209 if (dwError != ERROR_SUCCESS)
2210 SafeBootEnabled = 0;
2211
2212 /* Acquire the service control critical section, to synchronize starts */
2214
2215 /* Clear 'ServiceVisited' flag (or set if not to start in Safe Mode) */
2216 ServiceEntry = ServiceListHead.Flink;
2217 while (ServiceEntry != &ServiceListHead)
2218 {
2219 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2220
2221 /* Build the safe boot path */
2222 StringCchCopyW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2223 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot");
2224
2225 switch (SafeBootEnabled)
2226 {
2227 /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
2228 case 1:
2229 case 3:
2230 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2231 L"\\Minimal\\");
2232 break;
2233
2234 case 2:
2235 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2236 L"\\Network\\");
2237 break;
2238 }
2239
2240 if (SafeBootEnabled != 0)
2241 {
2242 /* If key does not exist then do not assume safe mode */
2244 szSafeBootServicePath,
2245 0,
2246 KEY_READ,
2247 &hKey);
2248 if (dwError == ERROR_SUCCESS)
2249 {
2251
2252 /* Finish Safe Boot path off */
2253 StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
2254 CurrentService->lpServiceName);
2255
2256 /* Check that the key is in the Safe Boot path */
2258 szSafeBootServicePath,
2259 0,
2260 KEY_READ,
2261 &hKey);
2262 if (dwError != ERROR_SUCCESS)
2263 {
2264 /* Mark service as visited so it is not auto-started */
2265 CurrentService->ServiceVisited = TRUE;
2266 }
2267 else
2268 {
2269 /* Must be auto-started in safe mode - mark as unvisited */
2271 CurrentService->ServiceVisited = FALSE;
2272 }
2273 }
2274 else
2275 {
2276 DPRINT1("WARNING: Could not open the associated Safe Boot key\n");
2277 CurrentService->ServiceVisited = FALSE;
2278 }
2279 }
2280
2281 ServiceEntry = ServiceEntry->Flink;
2282 }
2283
2284 /* Start all services which are members of an existing group */
2285 GroupEntry = GroupListHead.Flink;
2286 while (GroupEntry != &GroupListHead)
2287 {
2288 CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
2289
2290 DPRINT("Group '%S'\n", CurrentGroup->lpGroupName);
2291
2292 /* Start all services witch have a valid tag */
2293 for (i = 0; i < CurrentGroup->TagCount; i++)
2294 {
2295 ServiceEntry = ServiceListHead.Flink;
2296 while (ServiceEntry != &ServiceListHead)
2297 {
2298 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2299
2300 if ((CurrentService->lpGroup == CurrentGroup) &&
2301 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2302 (CurrentService->ServiceVisited == FALSE) &&
2303 (CurrentService->dwTag == CurrentGroup->TagArray[i]))
2304 {
2305 CurrentService->ServiceVisited = TRUE;
2306 ScmLoadService(CurrentService, 0, NULL);
2307 }
2308
2309 ServiceEntry = ServiceEntry->Flink;
2310 }
2311 }
2312
2313 /* Start all services which have an invalid tag or which do not have a tag */
2314 ServiceEntry = ServiceListHead.Flink;
2315 while (ServiceEntry != &ServiceListHead)
2316 {
2317 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2318
2319 if ((CurrentService->lpGroup == CurrentGroup) &&
2320 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2321 (CurrentService->ServiceVisited == FALSE))
2322 {
2323 CurrentService->ServiceVisited = TRUE;
2324 ScmLoadService(CurrentService, 0, NULL);
2325 }
2326
2327 ServiceEntry = ServiceEntry->Flink;
2328 }
2329
2330 GroupEntry = GroupEntry->Flink;
2331 }
2332
2333 /* Start all services which are members of any non-existing group */
2334 ServiceEntry = ServiceListHead.Flink;
2335 while (ServiceEntry != &ServiceListHead)
2336 {
2337 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2338
2339 if ((CurrentService->lpGroup != NULL) &&
2340 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2341 (CurrentService->ServiceVisited == FALSE))
2342 {
2343 CurrentService->ServiceVisited = TRUE;
2344 ScmLoadService(CurrentService, 0, NULL);
2345 }
2346
2347 ServiceEntry = ServiceEntry->Flink;
2348 }
2349
2350 /* Start all services which are not a member of any group */
2351 ServiceEntry = ServiceListHead.Flink;
2352 while (ServiceEntry != &ServiceListHead)
2353 {
2354 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2355
2356 if ((CurrentService->lpGroup == NULL) &&
2357 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
2358 (CurrentService->ServiceVisited == FALSE))
2359 {
2360 CurrentService->ServiceVisited = TRUE;
2361 ScmLoadService(CurrentService, 0, NULL);
2362 }
2363
2364 ServiceEntry = ServiceEntry->Flink;
2365 }
2366
2367 /* Clear 'ServiceVisited' flag again */
2368 ServiceEntry = ServiceListHead.Flink;
2369 while (ServiceEntry != &ServiceListHead)
2370 {
2371 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
2372 CurrentService->ServiceVisited = FALSE;
2373 ServiceEntry = ServiceEntry->Flink;
2374 }
2375
2376 /* Release the critical section */
2378}
#define DPRINT1
Definition: precomp.h:8
static DWORD ScmLoadService(PSERVICE Service, DWORD argc, LPWSTR *argv)
Definition: database.c:2019
static CRITICAL_SECTION ControlServiceCriticalSection
Definition: database.c:37
BOOL ScmInitialize
Definition: services.c:28
#define RegCloseKey(hKey)
Definition: registry.h:49
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
#define MAX_PATH
Definition: compat.h:34
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
#define KEY_READ
Definition: nt_native.h:1023
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:38
ULONG TagCount
Definition: services.h:37
BOOLEAN ServiceVisited
Definition: services.h:82
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
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by wWinMain().

◆ ScmCheckDriver()

static NTSTATUS ScmCheckDriver ( PSERVICE  Service)
static

Definition at line 1187 of file database.c.

1188{
1191 HANDLE DirHandle;
1196 ULONG Index;
1197
1198 DPRINT("ScmCheckDriver(%S) called\n", Service->lpServiceName);
1199
1200 if (Service->Status.dwServiceType == SERVICE_KERNEL_DRIVER)
1201 {
1202 RtlInitUnicodeString(&DirName, L"\\Driver");
1203 }
1204 else // if (Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER)
1205 {
1206 ASSERT(Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER);
1207 RtlInitUnicodeString(&DirName, L"\\FileSystem");
1208 }
1209
1211 &DirName,
1212 0,
1213 NULL,
1214 NULL);
1215
1216 Status = NtOpenDirectoryObject(&DirHandle,
1219 if (!NT_SUCCESS(Status))
1220 {
1221 return Status;
1222 }
1223
1225 2 * MAX_PATH * sizeof(WCHAR);
1226 DirInfo = HeapAlloc(GetProcessHeap(),
1228 BufferLength);
1229
1230 Index = 0;
1231 while (TRUE)
1232 {
1233 Status = NtQueryDirectoryObject(DirHandle,
1234 DirInfo,
1236 TRUE,
1237 FALSE,
1238 &Index,
1239 &DataLength);
1241 {
1242 /* FIXME: Add current service to 'failed service' list */
1243 DPRINT("Service '%S' failed\n", Service->lpServiceName);
1244 break;
1245 }
1246
1247 if (!NT_SUCCESS(Status))
1248 break;
1249
1250 DPRINT("Comparing: '%S' '%wZ'\n", Service->lpServiceName, &DirInfo->Name);
1251
1252 if (_wcsicmp(Service->lpServiceName, DirInfo->Name.Buffer) == 0)
1253 {
1254 DPRINT("Found: '%S' '%wZ'\n",
1255 Service->lpServiceName, &DirInfo->Name);
1256
1257 /* Mark service as 'running' */
1258 Service->Status.dwCurrentState = SERVICE_RUNNING;
1259 Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
1260 Service->Status.dwWin32ExitCode = ERROR_SUCCESS;
1261 Service->Status.dwServiceSpecificExitCode = 0;
1262 Service->Status.dwCheckPoint = 0;
1263 Service->Status.dwWaitHint = 0;
1264
1265 /* Mark the service group as 'running' */
1266 if (Service->lpGroup != NULL)
1267 {
1268 Service->lpGroup->ServicesRunning = TRUE;
1269 }
1270
1271 break;
1272 }
1273 }
1274
1276 0,
1277 DirInfo);
1278 NtClose(DirHandle);
1279
1280 return STATUS_SUCCESS;
1281}
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:32
#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
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#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 ( HANDLE  hControlPipe,
PWSTR  pServiceName,
SERVICE_STATUS_HANDLE  hServiceStatus,
DWORD  dwControl 
)

Definition at line 1314 of file database.c.

1318{
1319 PSCM_CONTROL_PACKET ControlPacket;
1320 SCM_REPLY_PACKET ReplyPacket;
1321
1322 DWORD dwWriteCount = 0;
1323 DWORD dwReadCount = 0;
1325 PWSTR Ptr;
1326 DWORD dwError = ERROR_SUCCESS;
1327 BOOL bResult;
1328 OVERLAPPED Overlapped = {0};
1329
1330 DPRINT("ScmControlService() called\n");
1331
1332 /* Acquire the service control critical section, to synchronize requests */
1334
1335 /* Calculate the total length of the start command line */
1337 PacketSize += (DWORD)((wcslen(pServiceName) + 1) * sizeof(WCHAR));
1338
1339 ControlPacket = HeapAlloc(GetProcessHeap(),
1341 PacketSize);
1342 if (ControlPacket == NULL)
1343 {
1346 }
1347
1348 ControlPacket->dwSize = PacketSize;
1349 ControlPacket->dwControl = dwControl;
1350 ControlPacket->hServiceStatus = hServiceStatus;
1351
1352 ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
1353
1354 Ptr = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
1355 wcscpy(Ptr, pServiceName);
1356
1357 ControlPacket->dwArgumentsCount = 0;
1358 ControlPacket->dwArgumentsOffset = 0;
1359
1360 bResult = WriteFile(hControlPipe,
1361 ControlPacket,
1362 PacketSize,
1363 &dwWriteCount,
1364 &Overlapped);
1365 if (bResult == FALSE)
1366 {
1367 DPRINT("WriteFile() returned FALSE\n");
1368
1369 dwError = GetLastError();
1370 if (dwError == ERROR_IO_PENDING)
1371 {
1372 DPRINT("dwError: ERROR_IO_PENDING\n");
1373
1374 dwError = WaitForSingleObject(hControlPipe,
1375 PipeTimeout);
1376 DPRINT("WaitForSingleObject() returned %lu\n", dwError);
1377
1378 if (dwError == WAIT_TIMEOUT)
1379 {
1380 bResult = CancelIo(hControlPipe);
1381 if (bResult == FALSE)
1382 {
1383 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1384 }
1385
1387 goto Done;
1388 }
1389 else if (dwError == WAIT_OBJECT_0)
1390 {
1391 bResult = GetOverlappedResult(hControlPipe,
1392 &Overlapped,
1393 &dwWriteCount,
1394 TRUE);
1395 if (bResult == FALSE)
1396 {
1397 dwError = GetLastError();
1398 DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError);
1399
1400 goto Done;
1401 }
1402 }
1403 }
1404 else
1405 {
1406 DPRINT1("WriteFile() failed (Error %lu)\n", dwError);
1407 goto Done;
1408 }
1409 }
1410
1411 /* Read the reply */
1412 Overlapped.hEvent = (HANDLE) NULL;
1413
1414 bResult = ReadFile(hControlPipe,
1415 &ReplyPacket,
1416 sizeof(SCM_REPLY_PACKET),
1417 &dwReadCount,
1418 &Overlapped);
1419 if (bResult == FALSE)
1420 {
1421 DPRINT("ReadFile() returned FALSE\n");
1422
1423 dwError = GetLastError();
1424 if (dwError == ERROR_IO_PENDING)
1425 {
1426 DPRINT("dwError: ERROR_IO_PENDING\n");
1427
1428 dwError = WaitForSingleObject(hControlPipe,
1429 PipeTimeout);
1430 DPRINT("WaitForSingleObject() returned %lu\n", dwError);
1431
1432 if (dwError == WAIT_TIMEOUT)
1433 {
1434 bResult = CancelIo(hControlPipe);
1435 if (bResult == FALSE)
1436 {
1437 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1438 }
1439
1441 goto Done;
1442 }
1443 else if (dwError == WAIT_OBJECT_0)
1444 {
1445 bResult = GetOverlappedResult(hControlPipe,
1446 &Overlapped,
1447 &dwReadCount,
1448 TRUE);
1449 if (bResult == FALSE)
1450 {
1451 dwError = GetLastError();
1452 DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError);
1453
1454 goto Done;
1455 }
1456 }
1457 }
1458 else
1459 {
1460 DPRINT1("ReadFile() failed (Error %lu)\n", dwError);
1461 goto Done;
1462 }
1463 }
1464
1465Done:
1466 /* Release the control packet */
1468 0,
1469 ControlPacket);
1470
1471 if (dwReadCount == sizeof(SCM_REPLY_PACKET))
1472 {
1473 dwError = ReplyPacket.dwError;
1474 }
1475
1477
1478 DPRINT("ScmControlService() done\n");
1479
1480 return dwError;
1481}
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 ReadFile(a, b, c, d, e)
Definition: compat.h:742
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
unsigned int BOOL
Definition: ntddk_ex.h:94
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:221
BYTE * PBYTE
Definition: pedump.c:66
_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
HANDLE hEvent
Definition: winbase.h:820
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
PVOID HANDLE
Definition: typedefs.h:73
SERVICE_STATUS_HANDLE hServiceStatus
Definition: main.c:10
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define ERROR_SERVICE_REQUEST_TIMEOUT
Definition: winerror.h:604
_In_ USHORT PacketSize
Definition: iofuncs.h:1058

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

◆ 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:164
#define PIPE_WAIT
Definition: winbase.h:171
#define PIPE_READMODE_MESSAGE
Definition: winbase.h:170
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:168
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:61
DWORD dwResumeCount
Definition: services.h:67
WCHAR szServiceName[1]
Definition: services.h:84
#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_STOPPED
Definition: winsvc.h:21
#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:4208
#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:47
LIST_ENTRY ImageListEntry
Definition: services.h:46
HANDLE hProfile
Definition: services.h:55
LPWSTR pszAccountName
Definition: services.h:48
HANDLE hToken
Definition: services.h:54
DWORD dwImageRunCount
Definition: services.h:49
HANDLE hProcess
Definition: services.h:52
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 1088 of file database.c.

1089{
1090 WCHAR szSubKey[MAX_PATH];
1092 HKEY hServiceKey;
1093 DWORD dwSubKey;
1094 DWORD dwSubKeyLength;
1095 FILETIME ftLastChanged;
1096 DWORD dwError;
1097
1098 DPRINT("ScmCreateServiceDatabase() called\n");
1099
1100 /* Retrieve the NoInteractiveServies value */
1102
1103 /* Create the service group list */
1104 dwError = ScmCreateGroupList();
1105 if (dwError != ERROR_SUCCESS)
1106 return dwError;
1107
1108 /* Initialize image and service lists */
1111
1112 /* Initialize the database lock */
1114
1116 L"System\\CurrentControlSet\\Services",
1117 0,
1118 KEY_READ,
1119 &hServicesKey);
1120 if (dwError != ERROR_SUCCESS)
1121 return dwError;
1122
1123 dwSubKey = 0;
1124 for (;;)
1125 {
1126 dwSubKeyLength = MAX_PATH;
1127 dwError = RegEnumKeyExW(hServicesKey,
1128 dwSubKey,
1129 szSubKey,
1130 &dwSubKeyLength,
1131 NULL,
1132 NULL,
1133 NULL,
1134 &ftLastChanged);
1135 if (dwError == ERROR_SUCCESS &&
1136 szSubKey[0] != L'{')
1137 {
1138 DPRINT("SubKeyName: '%S'\n", szSubKey);
1139
1140 dwError = RegOpenKeyExW(hServicesKey,
1141 szSubKey,
1142 0,
1143 KEY_READ,
1144 &hServiceKey);
1145 if (dwError == ERROR_SUCCESS)
1146 {
1147 dwError = CreateServiceListEntry(szSubKey,
1148 hServiceKey);
1149
1150 RegCloseKey(hServiceKey);
1151 }
1152 }
1153
1154 if (dwError != ERROR_SUCCESS)
1155 break;
1156
1157 dwSubKey++;
1158 }
1159
1161
1162 /* Wait for the LSA server */
1163 ScmWaitForLsa();
1164
1165 /* Delete services that are marked for delete */
1167
1168 DPRINT("ScmCreateServiceDatabase() done\n");
1169
1170 return ERROR_SUCCESS;
1171}
static HANDLE hServicesKey
Definition: devinst.c:21
static DWORD CreateServiceListEntry(LPCWSTR lpServiceName, HKEY hServiceKey)
Definition: database.c:857
static RTL_RESOURCE DatabaseLock
Definition: database.c:31
static VOID ScmGetNoInteractiveServicesValue(VOID)
Definition: database.c:1062
VOID ScmDeleteMarkedServices(VOID)
Definition: database.c:1021
VOID ScmWaitForLsa(VOID)
Definition: services.c:207
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
#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 1021 of file database.c.

1022{
1023 PLIST_ENTRY ServiceEntry;
1024 PSERVICE CurrentService;
1026 DWORD dwError;
1027
1028 ServiceEntry = ServiceListHead.Flink;
1029 while (ServiceEntry != &ServiceListHead)
1030 {
1031 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1032
1033 ServiceEntry = ServiceEntry->Flink;
1034
1035 if (CurrentService->bDeleted != FALSE)
1036 {
1038 L"System\\CurrentControlSet\\Services",
1039 0,
1040 DELETE,
1041 &hServicesKey);
1042 if (dwError == ERROR_SUCCESS)
1043 {
1044 dwError = ScmDeleteRegKey(hServicesKey, CurrentService->lpServiceName);
1046 if (dwError == ERROR_SUCCESS)
1047 {
1048 RemoveEntryList(&CurrentService->ServiceListEntry);
1049 HeapFree(GetProcessHeap(), 0, CurrentService);
1050 }
1051 }
1052
1053 if (dwError != ERROR_SUCCESS)
1054 DPRINT1("Delete service failed: %S\n", CurrentService->lpServiceName);
1055 }
1056 }
1057}
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 2469 of file database.c.

2470{
2472}
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)

Referenced by wWinMain().

◆ 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 RCloseServiceHandle().

◆ 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:76
#define ERROR_INVALID_DATA
Definition: winerror.h:116

Referenced by CreateServiceListEntry(), and RCreateServiceW().

◆ ScmGetBootAndSystemDriverState()

VOID ScmGetBootAndSystemDriverState ( VOID  )

Definition at line 1285 of file database.c.

1286{
1287 PLIST_ENTRY ServiceEntry;
1288 PSERVICE CurrentService;
1289
1290 DPRINT("ScmGetBootAndSystemDriverState() called\n");
1291
1292 ServiceEntry = ServiceListHead.Flink;
1293 while (ServiceEntry != &ServiceListHead)
1294 {
1295 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1296
1297 if (CurrentService->dwStartType == SERVICE_BOOT_START ||
1298 CurrentService->dwStartType == SERVICE_SYSTEM_START)
1299 {
1300 /* Check driver */
1301 DPRINT(" Checking service: %S\n", CurrentService->lpServiceName);
1302
1303 ScmCheckDriver(CurrentService);
1304 }
1305
1306 ServiceEntry = ServiceEntry->Flink;
1307 }
1308
1309 DPRINT("ScmGetBootAndSystemDriverState() done\n");
1310}
static NTSTATUS ScmCheckDriver(PSERVICE Service)
Definition: database.c:1187
#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 1062 of file database.c.

1063{
1064 HKEY hKey;
1065 DWORD dwKeySize;
1066 LONG lError;
1067
1069 L"SYSTEM\\CurrentControlSet\\Control\\Windows",
1070 0,
1071 KEY_READ,
1072 &hKey);
1073 if (lError == ERROR_SUCCESS)
1074 {
1075 dwKeySize = sizeof(NoInteractiveServices);
1076 lError = RegQueryValueExW(hKey,
1077 L"NoInteractiveServices",
1078 0,
1079 NULL,
1081 &dwKeySize);
1083 }
1084}
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:53
@ TagTypeService
Definition: svcctl.idl:304
#define ERROR_RETRY
Definition: winerror.h:740

Referenced by RI_ScQueryServiceTagInfo().

◆ ScmInitNamedPipeCriticalSection()

VOID ScmInitNamedPipeCriticalSection ( VOID  )

Definition at line 2441 of file database.c.

2442{
2443 HKEY hKey;
2444 DWORD dwKeySize;
2445 DWORD dwError;
2446
2448
2450 L"SYSTEM\\CurrentControlSet\\Control",
2451 0,
2452 KEY_READ,
2453 &hKey);
2454 if (dwError == ERROR_SUCCESS)
2455 {
2456 dwKeySize = sizeof(PipeTimeout);
2458 L"ServicesPipeTimeout",
2459 0,
2460 NULL,
2462 &dwKeySize);
2464 }
2465}
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,
LPWSTR argv 
)
static

Definition at line 2019 of file database.c.

2022{
2023 PSERVICE_GROUP Group = Service->lpGroup;
2024 DWORD dwError = ERROR_SUCCESS;
2025 LPCWSTR lpLogStrings[2];
2026 WCHAR szLogBuffer[80];
2027
2028 DPRINT("ScmLoadService() called\n");
2029 DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName);
2030
2031 if (Service->Status.dwCurrentState != SERVICE_STOPPED)
2032 {
2033 DPRINT("Service %S is already running\n", Service->lpServiceName);
2035 }
2036
2037 DPRINT("Service->Type: %lu\n", Service->Status.dwServiceType);
2038
2039 if (Service->Status.dwServiceType & SERVICE_DRIVER)
2040 {
2041 /* Start the driver */
2042 dwError = ScmStartDriver(Service);
2043 }
2044 else // if (Service->Status.dwServiceType & (SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS))
2045 {
2046 /* Start user-mode service */
2048 if (dwError == ERROR_SUCCESS)
2049 {
2051 if (dwError == ERROR_SUCCESS)
2052 {
2053 Service->Status.dwCurrentState = SERVICE_START_PENDING;
2054 Service->Status.dwControlsAccepted = 0;
2055 }
2056 else
2057 {
2058 Service->lpImage->dwImageRunCount--;
2059 if (Service->lpImage->dwImageRunCount == 0)
2060 {
2062 Service->lpImage = NULL;
2063 }
2064 }
2065 }
2066 }
2067
2068 DPRINT("ScmLoadService() done (Error %lu)\n", dwError);
2069
2070 if (dwError == ERROR_SUCCESS)
2071 {
2072 if (Group != NULL)
2073 {
2074 Group->ServicesRunning = TRUE;
2075 }
2076
2077 /* Log a successful service start */
2079 lpLogStrings[0] = Service->lpDisplayName;
2080 lpLogStrings[1] = szLogBuffer;
2081
2084 2,
2085 lpLogStrings);
2086 }
2087 else
2088 {
2089 if (Service->dwErrorControl != SERVICE_ERROR_IGNORE)
2090 {
2091 /* Log a failed service start */
2092 StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer),
2093 L"%lu", dwError);
2094 lpLogStrings[0] = Service->lpServiceName;
2095 lpLogStrings[1] = szLogBuffer;
2098 2,
2099 lpLogStrings);
2100 }
2101
2102#if 0
2103 switch (Service->dwErrorControl)
2104 {
2106 if (IsLastKnownGood == FALSE)
2107 {
2108 /* FIXME: Boot last known good configuration */
2109 }
2110 break;
2111
2113 if (IsLastKnownGood == FALSE)
2114 {
2115 /* FIXME: Boot last known good configuration */
2116 }
2117 else
2118 {
2119 /* FIXME: BSOD! */
2120 }
2121 break;
2122 }
2123#endif
2124 }
2125
2126 return dwError;
2127}
static int argc
Definition: ServiceArgs.c:12
static DWORD ScmCreateOrReferenceServiceImage(PSERVICE pService)
Definition: database.c:458
static DWORD ScmStartUserModeService(PSERVICE Service, DWORD argc, LPWSTR *argv)
Definition: database.c:1873
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
#define argv
Definition: mplay32.c:18
_In_opt_ PSID Group
Definition: rtlfuncs.h:1646
#define EVENT_SERVICE_CONTROL_SUCCESS
Definition: netevent.h:432
#define EVENT_SERVICE_START_FAILED
Definition: netevent.h:444
#define GetModuleHandle
Definition: winbase.h:3827
#define ERROR_SERVICE_ALREADY_RUNNING
Definition: winerror.h:607
#define EVENTLOG_ERROR_TYPE
Definition: winnt_old.h:2834
#define EVENTLOG_INFORMATION_TYPE
Definition: winnt_old.h:2836
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:1712
#define LOGON32_LOGON_SERVICE
Definition: winbase.h:394
#define LOGON32_PROVIDER_DEFAULT
Definition: winbase.h:387
#define ERROR_SERVICE_LOGON_FAILED
Definition: winerror.h:620

Referenced by ScmCreateOrReferenceServiceImage().

◆ 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 RSetServiceStatus(), ScmDeleteServiceRecord(), and ScmLoadService().

◆ ScmSendStartCommand()

static DWORD ScmSendStartCommand ( PSERVICE  Service,
DWORD  argc,
LPWSTR argv 
)
static

Definition at line 1485 of file database.c.

1488{
1489 DWORD dwError = ERROR_SUCCESS;
1490 PSCM_CONTROL_PACKET ControlPacket;
1491 SCM_REPLY_PACKET ReplyPacket;
1493 DWORD i;
1494 PWSTR Ptr;
1495 PWSTR *pOffPtr;
1496 PWSTR pArgPtr;
1497 BOOL bResult;
1498 DWORD dwWriteCount = 0;
1499 DWORD dwReadCount = 0;
1500 OVERLAPPED Overlapped = {0};
1501
1502 DPRINT("ScmSendStartCommand() called\n");
1503
1504 /* Calculate the total length of the start command line */
1506 PacketSize += (DWORD)((wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR));
1507
1508 /*
1509 * Calculate the required packet size for the start argument vector 'argv',
1510 * composed of the list of pointer offsets, followed by UNICODE strings.
1511 * The strings are stored continuously after the vector of offsets, with
1512 * the offsets being relative to the beginning of the vector, as in the
1513 * following layout (with N == argc):
1514 * [argOff(0)]...[argOff(N-1)][str(0)]...[str(N-1)] .
1515 */
1516 if (argc > 0 && argv != NULL)
1517 {
1519 PacketSize += (argc * sizeof(PWSTR));
1520
1521 DPRINT("Argc: %lu\n", argc);
1522 for (i = 0; i < argc; i++)
1523 {
1524 DPRINT("Argv[%lu]: %S\n", i, argv[i]);
1525 PacketSize += (DWORD)((wcslen(argv[i]) + 1) * sizeof(WCHAR));
1526 }
1527 }
1528
1529 /* Allocate a control packet */
1531 if (ControlPacket == NULL)
1533
1534 ControlPacket->dwSize = PacketSize;
1535 ControlPacket->dwControl = (Service->Status.dwServiceType & SERVICE_WIN32_OWN_PROCESS)
1539 ControlPacket->dwServiceTag = Service->dwServiceTag;
1540
1541 /* Copy the start command line */
1542 ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
1543 Ptr = (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset);
1544 wcscpy(Ptr, Service->lpServiceName);
1545
1546 ControlPacket->dwArgumentsCount = 0;
1547 ControlPacket->dwArgumentsOffset = 0;
1548
1549 /* Copy the argument vector */
1550 if (argc > 0 && argv != NULL)
1551 {
1552 Ptr += wcslen(Service->lpServiceName) + 1;
1553 pOffPtr = (PWSTR*)ALIGN_UP_POINTER(Ptr, PWSTR);
1554 pArgPtr = (PWSTR)((ULONG_PTR)pOffPtr + argc * sizeof(PWSTR));
1555
1556 ControlPacket->dwArgumentsCount = argc;
1557 ControlPacket->dwArgumentsOffset = (DWORD)((ULONG_PTR)pOffPtr - (ULONG_PTR)ControlPacket);
1558
1559 DPRINT("dwArgumentsCount: %lu\n", ControlPacket->dwArgumentsCount);
1560 DPRINT("dwArgumentsOffset: %lu\n", ControlPacket->dwArgumentsOffset);
1561
1562 for (i = 0; i < argc; i++)
1563 {
1564 wcscpy(pArgPtr, argv[i]);
1565 pOffPtr[i] = (PWSTR)((ULONG_PTR)pArgPtr - (ULONG_PTR)pOffPtr);
1566 DPRINT("offset[%lu]: %p\n", i, pOffPtr[i]);
1567 pArgPtr += wcslen(argv[i]) + 1;
1568 }
1569 }
1570
1571 bResult = WriteFile(Service->lpImage->hControlPipe,
1572 ControlPacket,
1573 PacketSize,
1574 &dwWriteCount,
1575 &Overlapped);
1576 if (bResult == FALSE)
1577 {
1578 DPRINT("WriteFile() returned FALSE\n");
1579
1580 dwError = GetLastError();
1581 if (dwError == ERROR_IO_PENDING)
1582 {
1583 DPRINT("dwError: ERROR_IO_PENDING\n");
1584
1585 dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
1586 PipeTimeout);
1587 DPRINT("WaitForSingleObject() returned %lu\n", dwError);
1588
1589 if (dwError == WAIT_TIMEOUT)
1590 {
1591 bResult = CancelIo(Service->lpImage->hControlPipe);
1592 if (bResult == FALSE)
1593 {
1594 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1595 }
1596
1598 goto Done;
1599 }
1600 else if (dwError == WAIT_OBJECT_0)
1601 {
1602 bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
1603 &Overlapped,
1604 &dwWriteCount,
1605 TRUE);
1606 if (bResult == FALSE)
1607 {
1608 dwError = GetLastError();
1609 DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError);
1610
1611 goto Done;
1612 }
1613 }
1614 }
1615 else
1616 {
1617 DPRINT1("WriteFile() failed (Error %lu)\n", dwError);
1618 goto Done;
1619 }
1620 }
1621
1622 /* Read the reply */
1623 Overlapped.hEvent = (HANDLE) NULL;
1624
1625 bResult = ReadFile(Service->lpImage->hControlPipe,
1626 &ReplyPacket,
1627 sizeof(SCM_REPLY_PACKET),
1628 &dwReadCount,
1629 &Overlapped);
1630 if (bResult == FALSE)
1631 {
1632 DPRINT("ReadFile() returned FALSE\n");
1633
1634 dwError = GetLastError();
1635 if (dwError == ERROR_IO_PENDING)
1636 {
1637 DPRINT("dwError: ERROR_IO_PENDING\n");
1638
1639 dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
1640 PipeTimeout);
1641 DPRINT("WaitForSingleObject() returned %lu\n", dwError);
1642
1643 if (dwError == WAIT_TIMEOUT)
1644 {
1645 bResult = CancelIo(Service->lpImage->hControlPipe);
1646 if (bResult == FALSE)
1647 {
1648 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1649 }
1650
1652 goto Done;
1653 }
1654 else if (dwError == WAIT_OBJECT_0)
1655 {
1656 bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
1657 &Overlapped,
1658 &dwReadCount,
1659 TRUE);
1660 if (bResult == FALSE)
1661 {
1662 dwError = GetLastError();
1663 DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError);
1664
1665 goto Done;
1666 }
1667 }
1668 }
1669 else
1670 {
1671 DPRINT1("ReadFile() failed (Error %lu)\n", dwError);
1672 goto Done;
1673 }
1674 }
1675
1676Done:
1677 /* Release the control packet */
1679 0,
1680 ControlPacket);
1681
1682 if (dwReadCount == sizeof(SCM_REPLY_PACKET))
1683 {
1684 dwError = ReplyPacket.dwError;
1685 }
1686
1687 DPRINT("ScmSendStartCommand() done\n");
1688
1689 return dwError;
1690}
#define ULONG_PTR
Definition: config.h:101
#define SERVICE_CONTROL_START_OWN
Definition: services.h:20
#define SERVICE_CONTROL_START_SHARE
Definition: services.h:18
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

Referenced by ScmStartUserModeService().

◆ ScmShutdownServiceDatabase()

VOID ScmShutdownServiceDatabase ( VOID  )

Definition at line 1175 of file database.c.

1176{
1177 DPRINT("ScmShutdownServiceDatabase() called\n");
1178
1181
1182 DPRINT("ScmShutdownServiceDatabase() done\n");
1183}
NTSYSAPI VOID NTAPI RtlDeleteResource(_In_ PRTL_RESOURCE Resource)

Referenced by ShutdownHandlerRoutine().

◆ ScmStartService()

DWORD ScmStartService ( PSERVICE  Service,
DWORD  argc,
LPWSTR argv 
)

Definition at line 2131 of file database.c.

2134{
2135 DWORD dwError = ERROR_SUCCESS;
2137
2138 DPRINT("ScmStartService() called\n");
2139 DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName);
2140
2141 /* Acquire the service control critical section, to synchronize starts */
2143
2144 /*
2145 * Acquire the user service start lock while the service is starting, if
2146 * needed (i.e. if we are not starting it during the initialization phase).
2147 * If we don't success, bail out.
2148 */
2149 if (!ScmInitialize)
2150 {
2152 if (dwError != ERROR_SUCCESS) goto done;
2153 }
2154
2155 /* Really start the service */
2156 dwError = ScmLoadService(Service, argc, argv);
2157
2158 /* Release the service start lock, if needed, and the critical section */
2160
2161done:
2163
2164 DPRINT("ScmStartService() done (Error %lu)\n", dwError);
2165
2166 return dwError;
2167}
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,
LPWSTR argv 
)
static

Definition at line 1873 of file database.c.

1876{
1877 PROCESS_INFORMATION ProcessInformation;
1878 STARTUPINFOW StartupInfo;
1879 LPVOID lpEnvironment;
1880 BOOL Result;
1881 DWORD dwError = ERROR_SUCCESS;
1882
1883 DPRINT("ScmStartUserModeService(%p)\n", Service);
1884
1885 /* If the image is already running ... */
1886 if (Service->lpImage->dwImageRunCount > 1)
1887 {
1888 /* ... just send a start command */
1890 }
1891
1892 /* Otherwise start its process */
1893 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
1894 StartupInfo.cb = sizeof(StartupInfo);
1895 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
1896
1897 if (Service->lpImage->hToken)
1898 {
1899 /* User token: Run the service under the user account */
1900
1901 if (!CreateEnvironmentBlock(&lpEnvironment, Service->lpImage->hToken, FALSE))
1902 {
1903 /* We failed, run the service with the current environment */
1904 DPRINT1("CreateEnvironmentBlock() failed with error %d; service '%S' will run with current environment\n",
1905 GetLastError(), Service->lpServiceName);
1906 lpEnvironment = NULL;
1907 }
1908
1909 /* Impersonate the new user */
1910 Result = ImpersonateLoggedOnUser(Service->lpImage->hToken);
1911 if (Result)
1912 {
1913 /* Launch the process in the user's logon session */
1914 Result = CreateProcessAsUserW(Service->lpImage->hToken,
1915 NULL,
1916 Service->lpImage->pszImagePath,
1917 NULL,
1918 NULL,
1919 FALSE,
1921 lpEnvironment,
1922 NULL,
1923 &StartupInfo,
1924 &ProcessInformation);
1925 if (!Result)
1926 dwError = GetLastError();
1927
1928 /* Revert the impersonation */
1929 RevertToSelf();
1930 }
1931 else
1932 {
1933 dwError = GetLastError();
1934 DPRINT1("ImpersonateLoggedOnUser() failed with error %d\n", dwError);
1935 }
1936 }
1937 else
1938 {
1939 /* No user token: Run the service under the LocalSystem account */
1940
1941 if (!CreateEnvironmentBlock(&lpEnvironment, NULL, TRUE))
1942 {
1943 /* We failed, run the service with the current environment */
1944 DPRINT1("CreateEnvironmentBlock() failed with error %d; service '%S' will run with current environment\n",
1945 GetLastError(), Service->lpServiceName);
1946 lpEnvironment = NULL;
1947 }
1948
1949 /* Use the interactive desktop if the service is interactive */
1950 if ((NoInteractiveServices == 0) &&
1951 (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
1952 {
1953 StartupInfo.dwFlags |= STARTF_INHERITDESKTOP;
1954 StartupInfo.lpDesktop = L"WinSta0\\Default";
1955 }
1956
1957 if (!ScmIsSecurityService(Service->lpImage))
1958 {
1960 Service->lpImage->pszImagePath,
1961 NULL,
1962 NULL,
1963 FALSE,
1965 lpEnvironment,
1966 NULL,
1967 &StartupInfo,
1968 &ProcessInformation);
1969 if (!Result)
1970 dwError = GetLastError();
1971 }
1972 else
1973 {
1974 Result = TRUE;
1975 dwError = ERROR_SUCCESS;
1976 }
1977 }
1978
1979 if (lpEnvironment)
1980 DestroyEnvironmentBlock(lpEnvironment);
1981
1982 if (!Result)
1983 {
1984 DPRINT1("Starting '%S' failed with error %d\n",
1985 Service->lpServiceName, dwError);
1986 return dwError;
1987 }
1988
1989 DPRINT("Process Id: %lu Handle %p\n",
1990 ProcessInformation.dwProcessId,
1991 ProcessInformation.hProcess);
1992 DPRINT("Thread Id: %lu Handle %p\n",
1993 ProcessInformation.dwThreadId,
1994 ProcessInformation.hThread);
1995
1996 /* Get the process handle and ID */
1997 Service->lpImage->hProcess = ProcessInformation.hProcess;
1998 Service->lpImage->dwProcessId = ProcessInformation.dwProcessId;
1999
2000 /* Resume the main thread and close its handle */
2001 ResumeThread(ProcessInformation.hThread);
2002 CloseHandle(ProcessInformation.hThread);
2003
2004 /* Connect control pipe */
2006 if (dwError != ERROR_SUCCESS)
2007 {
2008 DPRINT1("Connecting control pipe failed! (Error %lu)\n", dwError);
2009 Service->lpImage->dwProcessId = 0;
2010 return dwError;
2011 }
2012
2013 /* Send the start command */
2015}
static DWORD ScmSendStartCommand(PSERVICE Service, DWORD argc, LPWSTR *argv)
Definition: database.c:1485
static DWORD ScmWaitForServiceConnect(PSERVICE Service)
Definition: database.c:1694
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:4592
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
LPWSTR lpDesktop
Definition: winbase.h:854
DWORD cb
Definition: winbase.h:852
DWORD dwFlags
Definition: winbase.h:863
#define STARTF_INHERITDESKTOP
Definition: undocuser.h:164
#define CREATE_UNICODE_ENVIRONMENT
Definition: winbase.h:186
#define CREATE_SUSPENDED
Definition: winbase.h:178
#define DETACHED_PROCESS
Definition: winbase.h:179
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 1694 of file database.c.

1695{
1696 DWORD dwRead = 0;
1697 DWORD dwProcessId = 0;
1698 DWORD dwError = ERROR_SUCCESS;
1699 BOOL bResult;
1700 OVERLAPPED Overlapped = {0};
1701#if 0
1702 LPCWSTR lpLogStrings[3];
1703 WCHAR szBuffer1[20];
1704 WCHAR szBuffer2[20];
1705#endif
1706
1707 DPRINT("ScmWaitForServiceConnect()\n");
1708
1709 Overlapped.hEvent = (HANDLE)NULL;
1710
1711 bResult = ConnectNamedPipe(Service->lpImage->hControlPipe,
1712 &Overlapped);
1713 if (bResult == FALSE)
1714 {
1715 DPRINT("ConnectNamedPipe() returned FALSE\n");
1716
1717 dwError = GetLastError();
1718 if (dwError == ERROR_IO_PENDING)
1719 {
1720 DPRINT("dwError: ERROR_IO_PENDING\n");
1721
1722 dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
1723 PipeTimeout);
1724 DPRINT("WaitForSingleObject() returned %lu\n", dwError);
1725
1726 if (dwError == WAIT_TIMEOUT)
1727 {
1728 DPRINT("WaitForSingleObject() returned WAIT_TIMEOUT\n");
1729
1730 bResult = CancelIo(Service->lpImage->hControlPipe);
1731 if (bResult == FALSE)
1732 {
1733 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1734 }
1735
1736#if 0
1737 _ultow(PipeTimeout, szBuffer1, 10);
1738 lpLogStrings[0] = Service->lpDisplayName;
1739 lpLogStrings[1] = szBuffer1;
1740
1743 2,
1744 lpLogStrings);
1745#endif
1746 DPRINT1("Log EVENT_CONNECTION_TIMEOUT by %S\n", Service->lpDisplayName);
1747
1749 }
1750 else if (dwError == WAIT_OBJECT_0)
1751 {
1752 bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
1753 &Overlapped,
1754 &dwRead,
1755 TRUE);
1756 if (bResult == FALSE)
1757 {
1758 dwError = GetLastError();
1759 DPRINT1("GetOverlappedResult failed (Error %lu)\n", dwError);
1760
1761 return dwError;
1762 }
1763 }
1764 }
1765 else if (dwError != ERROR_PIPE_CONNECTED)
1766 {
1767 DPRINT1("ConnectNamedPipe failed (Error %lu)\n", dwError);
1768 return dwError;
1769 }
1770 }
1771
1772 DPRINT("Control pipe connected\n");
1773
1774 Overlapped.hEvent = (HANDLE) NULL;
1775
1776 /* Read the process id from pipe */
1777 bResult = ReadFile(Service->lpImage->hControlPipe,
1778 (LPVOID)&dwProcessId,
1779 sizeof(DWORD),
1780 &dwRead,
1781 &Overlapped);
1782 if (bResult == FALSE)
1783 {
1784 DPRINT("ReadFile() returned FALSE\n");
1785
1786 dwError = GetLastError();
1787 if (dwError == ERROR_IO_PENDING)
1788 {
1789 DPRINT("dwError: ERROR_IO_PENDING\n");
1790
1791 dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
1792 PipeTimeout);
1793 if (dwError == WAIT_TIMEOUT)
1794 {
1795 DPRINT("WaitForSingleObject() returned WAIT_TIMEOUT\n");
1796
1797 bResult = CancelIo(Service->lpImage->hControlPipe);
1798 if (bResult == FALSE)
1799 {
1800 DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
1801 }
1802
1803#if 0
1804 _ultow(PipeTimeout, szBuffer1, 10);
1805 lpLogStrings[0] = szBuffer1;
1806
1809 1,
1810 lpLogStrings);
1811#endif
1812 DPRINT1("Log EVENT_READFILE_TIMEOUT by %S\n", Service->lpDisplayName);
1813
1815 }
1816 else if (dwError == WAIT_OBJECT_0)
1817 {
1818 DPRINT("WaitForSingleObject() returned WAIT_OBJECT_0\n");
1819
1820 DPRINT("Process Id: %lu\n", dwProcessId);
1821
1822 bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
1823 &Overlapped,
1824 &dwRead,
1825 TRUE);
1826 if (bResult == FALSE)
1827 {
1828 dwError = GetLastError();
1829 DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError);
1830
1831 return dwError;
1832 }
1833 }
1834 else
1835 {
1836 DPRINT1("WaitForSingleObject() returned %lu\n", dwError);
1837 }
1838 }
1839 else
1840 {
1841 DPRINT1("ReadFile() failed (Error %lu)\n", dwError);
1842 return dwError;
1843 }
1844 }
1845
1846 if ((ScmIsSecurityService(Service->lpImage) == FALSE)&&
1847 (dwProcessId != Service->lpImage->dwProcessId))
1848 {
1849#if 0
1850 _ultow(Service->lpImage->dwProcessId, szBuffer1, 10);
1851 _ultow(dwProcessId, szBuffer2, 10);
1852
1853 lpLogStrings[0] = Service->lpDisplayName;
1854 lpLogStrings[1] = szBuffer1;
1855 lpLogStrings[2] = szBuffer2;
1856
1859 3,
1860 lpLogStrings);
1861#endif
1862
1863 DPRINT1("Log EVENT_SERVICE_DIFFERENT_PID_CONNECTED by %S\n", Service->lpDisplayName);
1864 }
1865
1866 DPRINT("ScmWaitForServiceConnect() done\n");
1867
1868 return ERROR_SUCCESS;
1869}
_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
#define ERROR_PIPE_CONNECTED
Definition: winerror.h:352
#define EVENTLOG_WARNING_TYPE
Definition: winnt_old.h:2835

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

◆ 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().