ReactOS  0.4.12-dev-102-g4b7f1e0
svchost.c File Reference
#include "svchost.h"
#include <objidl.h>
Include dependency graph for svchost.c:

Go to the source code of this file.

Functions

__callback LONG WINAPI SvchostUnhandledExceptionFilter (_In_ struct _EXCEPTION_POINTERS *ExceptionInfo)
 
VOID WINAPI DummySvchostCtrlHandler (_In_ DWORD dwControl)
 
PSVCHOST_OPTIONS WINAPI BuildCommandOptions (_In_ LPWSTR pszCmdLine)
 
DWORD WINAPI ReadPerInstanceRegistryParameters (_In_ HKEY hKey, _In_ PSVCHOST_OPTIONS pOptions)
 
VOID WINAPI BuildServiceArray (_In_ PSVCHOST_OPTIONS lpOptions)
 
BOOL WINAPI FDebugBreakForService (_In_ LPCWSTR ServiceName)
 
DWORD WINAPI OpenServiceParametersKey (_In_ LPCWSTR lpSubKey, _Out_ PHKEY phKey)
 
VOID WINAPI UnloadServiceDll (_In_ PSVCHOST_SERVICE pService)
 
VOID WINAPI SvchostStopCallback (_In_ PVOID Context, _In_ BOOLEAN TimerOrWaitFired)
 
DWORD WINAPI SvcRegisterStopCallback (_In_ PHANDLE phNewWaitObject, _In_ LPCWSTR ServiceName, _In_ HANDLE hObject, _In_ PSVCHOST_STOP_CALLBACK pfnStopCallback, _In_ PVOID pContext, _In_ ULONG dwFlags)
 
VOID WINAPI AbortSvchostService (_In_ LPCWSTR lpServiceName, _In_ DWORD dwExitCode)
 
PVOID WINAPI GetServiceDllFunction (_In_ PSVCHOST_DLL pDll, _In_ LPCSTR lpProcName, _Out_ PDWORD lpdwError)
 
PSVCHOST_DLL WINAPI FindDll (_In_ LPCWSTR pszManifestPath, _In_ LPCWSTR pszDllPath, _In_ PSVCHOST_SERVICE pService)
 
PSVCHOST_DLL WINAPI AddDll (_In_ LPCWSTR pszManifestPath, _In_ LPCWSTR pszDllPath, _In_ PSVCHOST_SERVICE pService, _Out_ PDWORD lpdwError)
 
VOID WINAPI GetServiceMainFunctions (_In_ PSVCHOST_SERVICE pService, _Out_ PVOID *pServiceMain, _Out_ PVOID *pPushServiceGlobals, _Out_ PDWORD lpdwError)
 
VOID WINAPI ServiceStarter (_In_ DWORD dwNumServicesArgs, _In_ LPWSTR *lpServiceArgVectors)
 
SERVICE_TABLE_ENTRYW *WINAPI BuildServiceTable (VOID)
 
BOOLEAN WINAPI CallPerInstanceInitFunctions (_In_ PSVCHOST_OPTIONS pOptions)
 
VOID __cdecl wmainCRTStartup (VOID)
 

Variables

LIST_ENTRY DllList
 
CRITICAL_SECTION ListLock
 
DWORD ServiceCount
 
LPCWSTR ServiceNames
 
PSVCHOST_SERVICE ServiceArray
 

Function Documentation

◆ AbortSvchostService()

VOID WINAPI AbortSvchostService ( _In_ LPCWSTR  lpServiceName,
_In_ DWORD  dwExitCode 
)

Definition at line 618 of file svchost.c.

Referenced by ServiceStarter().

622 {
623  SERVICE_STATUS_HANDLE scHandle;
625 
626  /* Make us stopped and accept only query commands */
627  ServiceStatus.dwCheckPoint = 0;
628  ServiceStatus.dwWaitHint = 0;
629  ServiceStatus.dwServiceSpecificExitCode = 0;
630  ServiceStatus.dwCurrentState = SERVICE_STOPPED;
632  ServiceStatus.dwServiceType = SERVICE_WIN32;
633  ServiceStatus.dwWin32ExitCode = dwExitCode;
634 
635  /* Register a handler that will do nothing while we are being stopped */
636  scHandle = RegisterServiceCtrlHandlerW(lpServiceName,
638  if (scHandle)
639  {
640  /* Stop us */
641  if (!SetServiceStatus(scHandle, &ServiceStatus))
642  {
643  /* Tell the debugger if this didn't work */
644  DBG_ERR("AbortSvchostService: SetServiceStatus error %ld\n",
645  GetLastError());
646  }
647  }
648  else
649  {
650  /* Tell the debugger if we couldn't register the handler */
651  DBG_ERR("AbortSvchostService: RegisterServiceCtrlHandler failed %d\n",
652  GetLastError());
653  }
654 }
VOID WINAPI DummySvchostCtrlHandler(_In_ DWORD dwControl)
Definition: svchost.c:38
DWORD dwCurrentState
Definition: winsvc.h:100
#define DBG_ERR(fmt,...)
Definition: svchost.h:35
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc)
Definition: sctrl.c:703
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:957
DWORD dwCheckPoint
Definition: winsvc.h:104
#define SERVICE_STOPPED
Definition: winsvc.h:21
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwServiceType
Definition: winsvc.h:99
DWORD dwControlsAccepted
Definition: winsvc.h:101
#define SERVICE_WIN32
Definition: cmtypes.h:962
SERVICE_STATUS ServiceStatus
Definition: dhcpcsvc.c:18
#define SERVICE_QUERY_CONFIG
Definition: winsvc.h:53

◆ AddDll()

PSVCHOST_DLL WINAPI AddDll ( _In_ LPCWSTR  pszManifestPath,
_In_ LPCWSTR  pszDllPath,
_In_ PSVCHOST_SERVICE  pService,
_Out_ PDWORD  lpdwError 
)

Definition at line 760 of file svchost.c.

Referenced by GetServiceMainFunctions().

766 {
767  PSVCHOST_DLL pDll;
768  ULONG nDllPathLength, nManifestPathLength;
769  ASSERT(pszDllPath);
770  ASSERT(*pszDllPath);
771 
772  /* Compute the length of the two paths */
773  nDllPathLength = lstrlenW(pszDllPath);
774  nManifestPathLength = lstrlenW(pszManifestPath);
775 
776  /* Allocate the DLL entry for this service */
777  pDll = MemAlloc(HEAP_ZERO_MEMORY,
778  sizeof(*pDll) +
779  (nDllPathLength + nManifestPathLength) * sizeof(WCHAR) +
780  2 * sizeof(UNICODE_NULL));
781  if (pDll == NULL)
782  {
783  /* Bail out with failure */
784  *lpdwError = ERROR_NOT_ENOUGH_MEMORY;
785  return pDll;
786  }
787 
788  /* Put the DLL path right after the DLL entry */
789  pDll->pszDllPath = (LPCWSTR)(pDll + 1);
790 
791  /* Put the manifest path right past the DLL path (note the pointer math) */
792  pDll->pszManifestPath = pDll->pszDllPath + nDllPathLength + 1;
793 
794  /* Now copy both paths */
795  CopyMemory((PVOID)pDll->pszDllPath,
796  pszDllPath,
797  sizeof(WCHAR) * nDllPathLength);
799  pszManifestPath,
800  sizeof(WCHAR) * nManifestPathLength);
801 
802  /* Now set the service, and make sure both paths are NULL-terminated */
803  pDll->pService = pService;
804  ASSERT(pDll->hActCtx == NULL);
805  ASSERT(pDll->pszDllPath[nDllPathLength] == UNICODE_NULL);
806  ASSERT(pDll->pszManifestPath[nManifestPathLength] == UNICODE_NULL);
807 
808  /* Finally, add the entry to the DLL database, while holding the lock */
810  InsertTailList(&DllList, &pDll->DllList);
812 
813  /* And return it */
814  return pDll;
815 }
__wchar_t WCHAR
Definition: xmlstorage.h:180
PVOID MemAlloc(IN DWORD dwFlags, IN DWORD dwBytes)
Definition: utils.c:33
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
HANDLE hActCtx
Definition: svchost.h:140
LIST_ENTRY DllList
Definition: svchost.c:17
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define InsertTailList(ListHead, Entry)
#define lstrlenW
Definition: compat.h:407
#define UNICODE_NULL
LIST_ENTRY DllList
Definition: svchost.h:136
CRITICAL_SECTION ListLock
Definition: svchost.c:18
smooth NULL
Definition: ftsmooth.c:416
struct _SVCHOST_SERVICE * pService
Definition: svchost.h:141
#define CopyMemory
Definition: winbase.h:1633
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LPCWSTR pszManifestPath
Definition: svchost.h:139
LPCWSTR pszDllPath
Definition: svchost.h:138
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
unsigned int ULONG
Definition: retypes.h:1
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define LPCWSTR
Definition: msvc.h:45

◆ BuildCommandOptions()

PSVCHOST_OPTIONS WINAPI BuildCommandOptions ( _In_ LPWSTR  pszCmdLine)

Definition at line 48 of file svchost.c.

Referenced by wmainCRTStartup().

51 {
52  ULONG cbCmdLine;
53  PSVCHOST_OPTIONS pOptions;
54  LPWSTR pch, pGroupNameStart, lpServiceGroup;
55  LPWSTR *pGroupName = NULL;
56 
57  /* Nothing to do without a command-line */
58  if (pszCmdLine == NULL) return ERROR_SUCCESS;
59 
60  /* Get the length if the command line*/
61  cbCmdLine = sizeof(WCHAR) * lstrlenW(pszCmdLine) + sizeof(UNICODE_NULL);
62 
63  /* Allocate a buffer for the parsed options */
64  pOptions = MemAlloc(HEAP_ZERO_MEMORY, cbCmdLine + sizeof(*pOptions));
65  if (pOptions == NULL) return ERROR_SUCCESS;
66 
67  /* Copy the buffer into the parsed options block */
68  pOptions->CmdLineBuffer = (PWCHAR)(pOptions + 1);
69  memcpy(pOptions->CmdLineBuffer, pszCmdLine, cbCmdLine);
70 
71  /* Set the command-line as being inside the block itself */
72  pch = pOptions->CmdLineBuffer;
73  ASSERT(pch);
74  pOptions->CmdLine = pch;
75 
76  /* Now scan it */
77  while (*pch != UNICODE_NULL)
78  {
79  /* And look for the first space or TAB */
80  if ((*pch == ' ') || (*pch == '\t'))
81  {
82  /* Terminate the command-line there */
83  *pch++ = UNICODE_NULL;
84  break;
85  }
86 
87  /* Keep searching */
88  pch++;
89  }
90 
91  /* Lowercase the entire command line, but not the options */
92  SvchostCharLowerW(pOptions->CmdLine);
93 
94  /* Loop over the command-line */
95  while (*pch != UNICODE_NULL)
96  {
97  /* Do an inner loop within it */
98  while (*pch != UNICODE_NULL)
99  {
100  /* And keep going until we find a space or TAB */
101  if ((*pch != ' ') && (*pch != '\t')) break;
102  pch++;
103  }
104 
105  /* Did we reach the end? If so, bail out */
106  if (*pch == UNICODE_NULL) break;
107 
108  /* We found the space -- is it followed by a dash or slash? */
109  if ((*pch == '-' || *pch == '/') && (*(pch + 1) != UNICODE_NULL))
110  {
111  /* Yep, and there's at least one character. Is it k or K? */
112  pch++;
113  if (*pch == 'k' || *pch == 'K')
114  {
115  /* Yep, we have a proper command line with a group! */
116  pOptions->HasServiceGroup = TRUE;
117  pGroupName = &pOptions->ServiceGroupName;
118  }
119 
120  /* Keep going -- the name follows between spaces or quotes */
121  pch++;
122  }
123  else
124  {
125  /* Nope, so this might be the group being entered */
126  pGroupNameStart = pch;
127 
128  /* Check if there's a quote */
129  if ((*pch == '"') && (*(pch + 1) != UNICODE_NULL))
130  {
131  /* There is, keep going until the quote is over with */
132  pGroupNameStart = ++pch;
133  while (*pch) if (*pch++ == '"') break;
134  }
135  else
136  {
137  /* No quote, so keep going until the next space or TAB */
138  while ((*pch) && ((*pch != ' ') && (*pch != '\t'))) pch++;
139  }
140 
141  /* Now we have a space or quote delimited name, terminate it */
142  if (*pch) *pch++ = UNICODE_NULL;
143 
144  /* Ok, so we have a string -- was it preceded by a -K or /K? */
145  if (pGroupName)
146  {
147  /* Yes it was, remember this, and don't overwrite it later */
148  *pGroupName = pGroupNameStart;
149  pGroupName = NULL;
150  }
151  }
152  }
153 
154  /* Print out the service group for the debugger, and the command line */
155  DBG_TRACE("Command line : %ws\n", pszCmdLine);
156  lpServiceGroup = (pOptions->HasServiceGroup) ?
157  pOptions->ServiceGroupName : L"No";
158  DBG_TRACE("Service Group : %ws\n", lpServiceGroup);
159 
160  /* Was a group specified? */
161  if (pOptions->HasServiceGroup == FALSE)
162  {
163  /* This isn't valid. Print out help on the debugger and fail */
164  DBG_TRACE("Generic Service Host\n\n"
165  "%ws [-k <key>] | [-r] | <service>\n\n"
166  " -k <key> Host all services whose ImagePath matches\n"
167  " %ws -k <key>.\n\n",
168  lpServiceGroup);
169  MemFree(pOptions);
170  pOptions = NULL;
171  }
172 
173  /* Return the allocated option block, if valid*/
174  return pOptions;
175 }
#define TRUE
Definition: types.h:120
BOOL MemFree(IN PVOID lpMem)
Definition: utils.c:26
#define ERROR_SUCCESS
Definition: deptool.c:10
PVOID MemAlloc(IN DWORD dwFlags, IN DWORD dwBytes)
Definition: utils.c:33
uint16_t * PWCHAR
Definition: typedefs.h:54
#define WCHAR
Definition: msvc.h:43
#define lstrlenW
Definition: compat.h:407
#define UNICODE_NULL
PWCHAR CmdLineBuffer
Definition: svchost.h:119
smooth NULL
Definition: ftsmooth.c:416
PWCHAR CmdLine
Definition: svchost.h:120
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define DBG_TRACE(fmt,...)
Definition: svchost.h:36
static const WCHAR L[]
Definition: oid.c:1087
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
VOID WINAPI SvchostCharLowerW(_In_ LPCWSTR lpSrcStr)
Definition: globals.c:162
LPWSTR ServiceGroupName
Definition: svchost.h:122
unsigned int ULONG
Definition: retypes.h:1
WCHAR * pch
Definition: msvc.h:81
WCHAR * LPWSTR
Definition: xmlstorage.h:184
BOOL HasServiceGroup
Definition: svchost.h:121

◆ BuildServiceArray()

VOID WINAPI BuildServiceArray ( _In_ PSVCHOST_OPTIONS  lpOptions)

Definition at line 276 of file svchost.c.

Referenced by wmainCRTStartup().

279 {
280  DWORD dwError;
281  PSVCHOST_SERVICE pService;
282  LPCWSTR pszServiceName;
283  HKEY hKey;
284 
285  /* Open the service host key */
287  L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Svchost",
288  0,
289  KEY_READ,
290  &hKey);
291  if (dwError != ERROR_SUCCESS) return;
292 
293  /* Read all the parameters for this service group */
294  dwError = ReadPerInstanceRegistryParameters(hKey, lpOptions);
295  RegCloseKey(hKey);
296  if (dwError != ERROR_SUCCESS) return;
297 
298  /* Acquire the database lock while we create the service group */
300 
301  /* Loop the array of services for this group */
302  pszServiceName = ServiceNames;
303  while (*pszServiceName != UNICODE_NULL)
304  {
305  /* For each one, increment the amount of services we'llhost */
306  ServiceCount++;
307  pszServiceName += lstrlenW(pszServiceName) + 1;
308  }
309 
310  /* We should host at least one... */
312 
313  /* Now allocate an array to hold all their pointers */
314  ServiceArray = MemAlloc(HEAP_ZERO_MEMORY, sizeof(*pService) * ServiceCount);
315  if (ServiceArray)
316  {
317  /* Start at the beginning of the array */
318  pService = ServiceArray;
319 
320  /* Loop through all the services */
321  pszServiceName = ServiceNames;
322  while (*pszServiceName != UNICODE_NULL)
323  {
324  /* Save the service's name and move to the next entry */
325  pService++->pszServiceName = pszServiceName;
326  pszServiceName += lstrlenW(pszServiceName) + 1;
327  }
328 
329  /* We should have gotten the same count as earlier! */
330  ASSERT(pService == ServiceArray + ServiceCount);
331  }
332 
333  /* We're done, drop the lock */
335 }
#define ERROR_SUCCESS
Definition: deptool.c:10
#define KEY_READ
Definition: nt_native.h:1023
PVOID MemAlloc(IN DWORD dwFlags, IN DWORD dwBytes)
Definition: utils.c:33
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
LPCWSTR pszServiceName
Definition: svchost.h:149
#define lstrlenW
Definition: compat.h:407
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
#define UNICODE_NULL
CRITICAL_SECTION ListLock
Definition: svchost.c:18
DWORD ServiceCount
Definition: svchost.c:19
unsigned long DWORD
Definition: ntddk_ex.h:95
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LPCWSTR ServiceNames
Definition: svchost.c:20
static const WCHAR L[]
Definition: oid.c:1087
PSVCHOST_SERVICE ServiceArray
Definition: svchost.c:21
DWORD WINAPI ReadPerInstanceRegistryParameters(_In_ HKEY hKey, _In_ PSVCHOST_OPTIONS pOptions)
Definition: svchost.c:179
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12

◆ BuildServiceTable()

SERVICE_TABLE_ENTRYW* WINAPI BuildServiceTable ( VOID  )

Definition at line 1166 of file svchost.c.

Referenced by wmainCRTStartup().

1169 {
1170  SERVICE_TABLE_ENTRYW *pServiceTable;
1171  ULONG i;
1172 
1173  /* Acquire the database lock while we go over the services */
1175 
1176  /* Allocate space for a NULL entry at the end as well, Windows needs this */
1177  pServiceTable = MemAlloc(HEAP_ZERO_MEMORY,
1178  (ServiceCount + 1) * sizeof(*pServiceTable));
1179  if (pServiceTable)
1180  {
1181  /* Go over all our registered services */
1182  for (i = 0; i < ServiceCount; i++)
1183  {
1184  /* And set their parameters in the service table */
1185  pServiceTable[i].lpServiceName = (LPWSTR)ServiceArray[i].pszServiceName;
1186  pServiceTable[i].lpServiceProc = ServiceStarter;
1187  DBG_TRACE("Added service table entry for %ws\n",
1188  pServiceTable[i].lpServiceName);
1189  }
1190  }
1191 
1192  /* All done, can release the lock now */
1194  return pServiceTable;
1195 }
LPSERVICE_MAIN_FUNCTIONW lpServiceProc
Definition: winsvc.h:184
PVOID MemAlloc(IN DWORD dwFlags, IN DWORD dwBytes)
Definition: utils.c:33
LPWSTR lpServiceName
Definition: winsvc.h:183
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
GLenum GLclampf GLint i
Definition: glfuncs.h:14
VOID WINAPI ServiceStarter(_In_ DWORD dwNumServicesArgs, _In_ LPWSTR *lpServiceArgVectors)
Definition: svchost.c:1050
CRITICAL_SECTION ListLock
Definition: svchost.c:18
DWORD ServiceCount
Definition: svchost.c:19
#define DBG_TRACE(fmt,...)
Definition: svchost.h:36
PSVCHOST_SERVICE ServiceArray
Definition: svchost.c:21
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
unsigned int ULONG
Definition: retypes.h:1
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
WCHAR * LPWSTR
Definition: xmlstorage.h:184

◆ CallPerInstanceInitFunctions()

BOOLEAN WINAPI CallPerInstanceInitFunctions ( _In_ PSVCHOST_OPTIONS  pOptions)

Definition at line 1199 of file svchost.c.

Referenced by wmainCRTStartup().

1202 {
1203  PIMAGE_NT_HEADERS pNtHeaders;
1204  BOOLEAN bResult;
1205 
1206  /* Is COM required for this host? */
1207  if (pOptions->CoInitializeSecurityParam != 0)
1208  {
1209  /* Yes, initialize COM security and parameters */
1210  bResult = InitializeSecurity(pOptions->CoInitializeSecurityParam,
1211  pOptions->AuthenticationLevel,
1212  pOptions->ImpersonationLevel,
1213  pOptions->AuthenticationCapabilities);
1214  if (bResult == FALSE) return FALSE;
1215  }
1216 
1217  /* Do we have a custom RPC stack size? */
1218  if (pOptions->DefaultRpcStackSize != 0)
1219  {
1220  /* Yes, go set it */
1221  RpcMgmtSetServerStackSize(pOptions->DefaultRpcStackSize << 10);
1222  }
1223  else
1224  {
1225  /* Nope, get the NT headers from the image */
1226  pNtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
1227  if (pNtHeaders)
1228  {
1229  /* And just use whatever the default thread stack is */
1231  }
1232  }
1233 
1234  /* Is this host holding critical services? */
1235  if (pOptions->SystemCritical != FALSE)
1236  {
1237  /* Mark the process as critical if so */
1239  }
1240 
1241  /* All done */
1242  return TRUE;
1243 }
#define TRUE
Definition: types.h:120
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
RPC_STATUS WINAPI RpcMgmtSetServerStackSize(ULONG ThreadStackSize)
Definition: rpc_server.c:1737
BOOL WINAPI InitializeSecurity(_In_ DWORD dwParam, _In_ DWORD dwAuthnLevel, _In_ DWORD dwImpLevel, _In_ DWORD dwCapabilities)
Definition: security.cxx:161
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define NtCurrentPeb()
Definition: FLS.c:19
#define RtlImageNtHeader
Definition: compat.h:457
NTSYSAPI NTSTATUS __cdecl RtlSetProcessIsCritical(_In_ BOOLEAN NewValue, _Out_opt_ PBOOLEAN OldValue, _In_ BOOLEAN NeedBreaks)

◆ DummySvchostCtrlHandler()

VOID WINAPI DummySvchostCtrlHandler ( _In_ DWORD  dwControl)

Definition at line 38 of file svchost.c.

Referenced by AbortSvchostService().

41 {
42  /* This is just a stub while we abort loading */
43  return;
44 }

◆ FDebugBreakForService()

BOOL WINAPI FDebugBreakForService ( _In_ LPCWSTR  ServiceName)

Definition at line 339 of file svchost.c.

Referenced by ServiceStarter().

342 {
343  DWORD Data;
344  BOOL DebugBreakOn = FALSE;
345  HKEY hKey, hSubKey;
346 
347  /* Open the key for Svchost itself */
349  L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Svchost",
350  0,
351  KEY_READ,
352  &hKey) == ERROR_SUCCESS)
353  {
354  /* That worked, now open the key for this service, if it exists */
355  if (RegOpenKeyExW(hKey, ServiceName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
356  {
357  /* It does -- is there a DebugBreak value set? */
358  if (RegQueryDword(hSubKey, L"DebugBreak", &Data) == ERROR_SUCCESS)
359  {
360  /* There is! Check if it's 0 or 1 */
361  DebugBreakOn = Data != 0;
362  }
363 
364  /* Done, close the service key */
365  RegCloseKey(hSubKey);
366  }
367 
368  /* Done, close the svchost key */
369  RegCloseKey(hKey);
370  }
371 
372  /* Return if the value was set or not */
373  return DebugBreakOn;
374 }
#define ERROR_SUCCESS
Definition: deptool.c:10
#define KEY_READ
Definition: nt_native.h:1023
DWORD WINAPI RegQueryDword(_In_ HKEY hKey, _In_ LPCWSTR pszValueName, _Out_ PDWORD pdwValue)
Definition: registry.c:78
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
unsigned int BOOL
Definition: ntddk_ex.h:94
LPTSTR ServiceName
Definition: ServiceMain.c:15
unsigned long DWORD
Definition: ntddk_ex.h:95
static const WCHAR L[]
Definition: oid.c:1087
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12

◆ FindDll()

PSVCHOST_DLL WINAPI FindDll ( _In_ LPCWSTR  pszManifestPath,
_In_ LPCWSTR  pszDllPath,
_In_ PSVCHOST_SERVICE  pService 
)

Definition at line 721 of file svchost.c.

Referenced by GetServiceMainFunctions().

726 {
727  PSVCHOST_DLL pDll, pFoundDll = NULL;
728  PLIST_ENTRY pNextEntry;
729  ASSERT(pszDllPath);
730 
731  /* Lock the DLL database */
733 
734  /* Scan through the database */
735  pNextEntry = DllList.Flink;
736  while (pNextEntry != &DllList)
737  {
738  /* Search for an existing DLL with the same parameters */
739  pDll = CONTAINING_RECORD(pNextEntry, SVCHOST_DLL, DllList);
740  if ((lstrcmpW(pDll->pszDllPath, pszDllPath) == 0) &&
741  (lstrcmpW(pDll->pszManifestPath, pszManifestPath) == 0) &&
742  (lstrcmpW(pDll->pService->pszServiceName, pService->pszServiceName) == 0))
743  {
744  /* Found it! */
745  pFoundDll = pDll;
746  break;
747  }
748 
749  /* Keep searching */
750  pNextEntry = pNextEntry->Flink;
751  }
752 
753  /* All done, release the lock and return what we found, if anything */
755  return pFoundDll;
756 }
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
LIST_ENTRY DllList
Definition: svchost.c:17
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
CRITICAL_SECTION ListLock
Definition: svchost.c:18
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _SVCHOST_SERVICE * pService
Definition: svchost.h:141
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LPCWSTR pszManifestPath
Definition: svchost.h:139
Definition: typedefs.h:117
LPCWSTR pszDllPath
Definition: svchost.h:138
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)

◆ GetServiceDllFunction()

PVOID WINAPI GetServiceDllFunction ( _In_ PSVCHOST_DLL  pDll,
_In_ LPCSTR  lpProcName,
_Out_ PDWORD  lpdwError 
)

Definition at line 658 of file svchost.c.

Referenced by GetServiceMainFunctions().

663 {
665  PVOID lpAddress = NULL;
666  ULONG_PTR ulCookie = 0;
667 
668  /* Activate the context */
669  if (ActivateActCtx(pDll->hActCtx, &ulCookie) == FALSE)
670  {
671  /* We couldn't, bail out */
672  if (lpdwError) *lpdwError = GetLastError();
673  DBG_ERR("ActivateActCtx for %ws failed. Error %d.\n",
674  pDll->pszDllPath,
675  GetLastError());
676  return lpAddress;
677  }
678 
679  /* Check if we already have a loaded module for this service */
680  hModule = pDll->hModule;
681  if (!hModule)
682  {
683  /* We don't -- load it */
684  hModule = LoadLibraryExW(pDll->pszDllPath,
685  NULL,
687  if (!hModule)
688  {
689  /* We failed to load it, bail out */
690  if (lpdwError) *lpdwError = GetLastError();
691  DBG_ERR("LoadLibrary (%ws) failed. Error %d.\n",
692  pDll->pszDllPath,
693  GetLastError());
694  DeactivateActCtx(0, ulCookie);
695  return lpAddress;
696  }
697 
698  /* Loaded! */
699  pDll->hModule = hModule;
700  }
701 
702  /* Next, get the address being looked up*/
703  lpAddress = GetProcAddress(hModule, lpProcName);
704  if (!lpAddress && lpdwError)
705  {
706  /* We couldn't find it, write the error code and a debug statement */
707  *lpdwError = GetLastError();
708  DBG_ERR("GetProcAddress (%s) failed on DLL %ws. Error %d.\n",
709  lpProcName,
710  pDll->pszDllPath,
711  GetLastError());
712  }
713 
714  /* All done, get rid of the activation context */
715  DeactivateActCtx(0, ulCookie);
716  return lpAddress;
717 }
BOOL WINAPI ActivateActCtx(IN HANDLE hActCtx, OUT PULONG_PTR ulCookie)
Definition: actctx.c:237
#define DBG_ERR(fmt,...)
Definition: svchost.h:35
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:286
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define LOAD_WITH_ALTERED_SEARCH_PATH
Definition: winbase.h:339
uint32_t ULONG_PTR
Definition: typedefs.h:63
BOOL WINAPI DeactivateActCtx(IN DWORD dwFlags, IN ULONG_PTR ulCookie)
Definition: actctx.c:268
smooth NULL
Definition: ftsmooth.c:416
#define GetProcAddress(x, y)
Definition: compat.h:410
HMODULE hModule
Definition: animate.c:44

◆ GetServiceMainFunctions()

VOID WINAPI GetServiceMainFunctions ( _In_ PSVCHOST_SERVICE  pService,
_Out_ PVOID pServiceMain,
_Out_ PVOID pPushServiceGlobals,
_Out_ PDWORD  lpdwError 
)

Definition at line 819 of file svchost.c.

Referenced by ServiceStarter().

825 {
826  DWORD dwError, cbDllLength, cbData, dwType;
827  PSVCHOST_DLL pDll;
828  ACTCTXW actCtx;
829  LPCWSTR pszDllPath;
830  HKEY hKey;
831  HANDLE hActCtx;
832  LPWSTR lpData;
833  WCHAR szDllBuffer[MAX_PATH + 2], szManifestBuffer[MAX_PATH + 2];
834 
835  /* Initialize the activation context we might need later */
836  RtlZeroMemory(&actCtx, sizeof(actCtx));
837  actCtx.cbSize = sizeof(actCtx);
838 
839  /* We clean these up in our failure path so initialize them to NULL here */
840  hActCtx = NULL;
841  hKey = NULL;
842  lpData = NULL;
843  *lpdwError = ERROR_SUCCESS;
844 
845  /* Null terminate the string buffers */
846  szDllBuffer[0] = UNICODE_NULL;
847  szManifestBuffer[0] = UNICODE_NULL;
848 
849  /* Do we already have a DLL ready to go for this service? */
850  pDll = pService->pDll;
851  if (pDll != NULL) goto HaveDll;
852 
853  /* Nope, we're starting from scratch. Open a handle to parameters key */
854  dwError = OpenServiceParametersKey(pService->pszServiceName, &hKey);
855  if (dwError)
856  {
857  *lpdwError = dwError;
858  ASSERT(*lpdwError != NO_ERROR);
859  goto Quickie;
860  }
861 
862  /* Allocate enough space to hold a unicode path (NULL-terminated) */
863  cbData = MAX_PATH * sizeof(WCHAR) + sizeof(UNICODE_NULL);
864  lpData = MemAlloc(0, cbData);
865  if (lpData == NULL)
866  {
867  /* No memory, bail out */
868  *lpdwError = ERROR_NOT_ENOUGH_MEMORY;
869  goto Quickie;
870  }
871 
872  /* Query the DLL path */
873  lpData[0] = UNICODE_NULL;
874  dwError = RegQueryValueExW(hKey,
875  L"ServiceDll",
876  0,
877  &dwType,
878  (LPBYTE)lpData,
879  &cbData);
880  if (dwError != ERROR_SUCCESS)
881  {
882  *lpdwError = dwError;
883  DBG_ERR("RegQueryValueEx for the ServiceDll parameter of the %ws "
884  "service returned %u\n",
885  pService->pszServiceName,
886  dwError);
887  goto Quickie;
888  }
889 
890  /* Is the registry data valid and present? */
891  if ((dwType != REG_EXPAND_SZ) || (lpData[0] == UNICODE_NULL))
892  {
893  /* Nope, bail out */
894  *lpdwError = ERROR_FILE_NOT_FOUND;
895  DBG_ERR("The ServiceDll parameter for the %ws service is not of type "
896  "REG_EXPAND_SZ\n",
897  pService->pszServiceName);
898  goto Quickie;
899  }
900 
901  /* Convert the expandable path into an absolute path */
902  ExpandEnvironmentStringsW(lpData, szDllBuffer, MAX_PATH);
903  SvchostCharLowerW(szDllBuffer);
904 
905  /* Check if the service has a manifest file associated with it */
906  cbData = MAX_PATH * sizeof(WCHAR) + sizeof(UNICODE_NULL);
907  dwError = RegQueryValueExW(hKey,
908  L"ServiceManifest",
909  NULL,
910  &dwType,
911  (LPBYTE)lpData,
912  &cbData);
913  if (dwError != ERROR_SUCCESS)
914  {
915  /* Did we fail because one wasn't set? */
916  if ((dwError != ERROR_PATH_NOT_FOUND) &&
917  (dwError != ERROR_FILE_NOT_FOUND))
918  {
919  /* We failed for some other reason, bail out */
920  *lpdwError = dwError;
921  DBG_ERR("RegQueryValueEx for the ServiceManifest parameter of the "
922  "%ws service returned %u\n",
923  pService->pszServiceName,
924  dwError);
925  goto Quickie;
926  }
927 
928  /* We have no manifest, make sure the buffer is empty */
929  szManifestBuffer[0] = UNICODE_NULL;
930 
931  /* We're done with this buffer */
932  MemFree(lpData);
933  lpData = NULL;
934 
935  /* Use the whole DLL path, since we don't have a manifest */
936  pszDllPath = szDllBuffer;
937  }
938  else
939  {
940  /* Do we have invalid registry data? */
941  if ((dwType != REG_EXPAND_SZ) || (*lpData == UNICODE_NULL))
942  {
943  /* Yes, pretend there's no manifest and bail out */
944  *lpdwError = ERROR_FILE_NOT_FOUND;
945  DBG_ERR("The ServiceManifest parameter for the %ws service is not "
946  "of type REG_EXPAND_SZ\n",
947  pService->pszServiceName);
948  goto Quickie;
949  }
950 
951  /* Expand the string into our stack buffer */
952  ExpandEnvironmentStringsW(lpData, szManifestBuffer, MAX_PATH);
953 
954  /* We no longer need the heap buffer*/
955  MemFree(lpData);
956  lpData = NULL;
957 
958  /* Lowercase the manifest path */
959  SvchostCharLowerW(szManifestBuffer);
960 
961  /* Now loop over the DLL path */
962  cbDllLength = lstrlenW(szDllBuffer);
963  while (cbDllLength)
964  {
965  /* From the end, until we find the first path separator */
966  if (szDllBuffer[cbDllLength] == '\\' || szDllBuffer[cbDllLength] == '/')
967  {
968  /* Use just a short name (cut out the rest of the path) */
969  pszDllPath = &szDllBuffer[cbDllLength + 1];
970  break;
971  }
972 
973  /* Try the next character */
974  cbDllLength--;
975  }
976  }
977 
978  /* See if we already have a matching DLL and manifest for this service */
979  pDll = FindDll(szManifestBuffer, pszDllPath, pService);
980  if (pDll == NULL)
981  {
982  /* We don't have it yet -- does this DLL have a manifest? */
983  if (szManifestBuffer[0] != UNICODE_NULL)
984  {
985  /* Create an activation context for it */
986  actCtx.lpSource = szManifestBuffer;
987  hActCtx = CreateActCtxW(&actCtx);
988  if (hActCtx == INVALID_HANDLE_VALUE)
989  {
990  /* We've failed to create one, bail out */
991  *lpdwError = GetLastError();
992  DBG_ERR("CreateActCtxW(%ws) for the %ws service returned %u\n",
993  szManifestBuffer,
994  pService->pszServiceName,
995  *lpdwError);
996  goto Quickie;
997  }
998  }
999 
1000  /* Add this new DLL into the database */
1001  pDll = AddDll(szManifestBuffer, pszDllPath, pService, lpdwError);
1002  if (pDll)
1003  {
1004  /* Save the activation context and zero it so we don't release later */
1005  pDll->hActCtx = hActCtx;
1006  hActCtx = NULL;
1007  }
1008  }
1009 
1010  /* We either found, added, or failed to add, the DLL for this service */
1011  ASSERT(!pService->pDll);
1012  pService->pDll = pDll;
1013 
1014  /* In all cases, we will query the ServiceMain function, however*/
1015  RegQueryStringA(hKey,
1016  L"ServiceMain",
1017  REG_SZ,
1018  &pService->pszServiceMain);
1019 
1020  /* And now we'll check if we were able to create it earlier (or find it) */
1021  if (!pService->pDll)
1022  {
1023  /* We were not, so there's no point in going on */
1024  ASSERT(*lpdwError != NO_ERROR);
1025  goto Quickie;
1026  }
1027 
1028  /* We do have a valid DLL, so now get the service main routine out of it */
1029 HaveDll:
1030  *pServiceMain = GetServiceDllFunction(pDll,
1031  pService->pszServiceMain ?
1032  pService->pszServiceMain :
1033  "ServiceMain",
1034  lpdwError);
1035 
1036  /* And now get the globals routine out of it (this one is optional) */
1037  *pPushServiceGlobals = GetServiceDllFunction(pDll,
1038  "SvchostPushServiceGlobals",
1039  NULL);
1040 
1041 Quickie:
1042  /* We're done, cleanup any resources we left behind */
1043  if (hKey != NULL) RegCloseKey(hKey);
1044  if (lpData != NULL) MemFree(lpData);
1045  if ((hActCtx) && (hActCtx != INVALID_HANDLE_VALUE)) ReleaseActCtx(hActCtx);
1046 }
BOOL MemFree(IN PVOID lpMem)
Definition: utils.c:26
#define ERROR_SUCCESS
Definition: deptool.c:10
PSVCHOST_DLL WINAPI AddDll(_In_ LPCWSTR pszManifestPath, _In_ LPCWSTR pszDllPath, _In_ PSVCHOST_SERVICE pService, _Out_ PDWORD lpdwError)
Definition: svchost.c:760
#define DBG_ERR(fmt,...)
Definition: svchost.h:35
PVOID WINAPI GetServiceDllFunction(_In_ PSVCHOST_DLL pDll, _In_ LPCSTR lpProcName, _Out_ PDWORD lpdwError)
Definition: svchost.c:658
__wchar_t WCHAR
Definition: xmlstorage.h:180
PVOID MemAlloc(IN DWORD dwFlags, IN DWORD dwBytes)
Definition: utils.c:33
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
HANDLE hActCtx
Definition: svchost.h:140
PSVCHOST_DLL WINAPI FindDll(_In_ LPCWSTR pszManifestPath, _In_ LPCWSTR pszDllPath, _In_ PSVCHOST_SERVICE pService)
Definition: svchost.c:721
DWORD WINAPI RegQueryStringA(_In_ HKEY hKey, _In_ LPCWSTR pszValueName, _In_ DWORD dwExpectedType, _Out_ LPCSTR *ppszData)
Definition: registry.c:128
#define WCHAR
Definition: msvc.h:43
#define NO_ERROR
Definition: dderror.h:5
#define lstrlenW
Definition: compat.h:407
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
#define UNICODE_NULL
smooth NULL
Definition: ftsmooth.c:416
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4134
VOID WINAPI ReleaseActCtx(IN HANDLE hActCtx)
Definition: actctx.c:208
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR L[]
Definition: oid.c:1087
DWORD WINAPI OpenServiceParametersKey(_In_ LPCWSTR lpSubKey, _Out_ PHKEY phKey)
Definition: svchost.c:378
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
VOID WINAPI SvchostCharLowerW(_In_ LPCWSTR lpSrcStr)
Definition: globals.c:162
HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx)
Definition: actctx.c:104
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define REG_SZ
Definition: layer.c:22

◆ OpenServiceParametersKey()

DWORD WINAPI OpenServiceParametersKey ( _In_ LPCWSTR  lpSubKey,
_Out_ PHKEY  phKey 
)

Definition at line 378 of file svchost.c.

Referenced by GetServiceMainFunctions(), and UnloadServiceDll().

382 {
383  DWORD dwError;
384  HKEY hSubKey = NULL, hKey = NULL;
385  ASSERT(phKey);
386 
387  /* Open the services key */
389  L"System\\CurrentControlSet\\Services",
390  0,
391  KEY_READ,
392  &hKey);
393  if (dwError == ERROR_SUCCESS)
394  {
395  /* Now open the service specific key, returning its handle */
396  dwError = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ, &hSubKey);
397  if (dwError == ERROR_SUCCESS)
398  {
399  /* And if that worked, return a handle to the parameters key */
400  dwError = RegOpenKeyExW(hSubKey,
401  L"Parameters",
402  0,
403  KEY_READ,
404  phKey);
405  }
406  }
407 
408  /* Clean up any leftovers*/
409  if (hKey != NULL) RegCloseKey(hKey);
410  if (hSubKey != NULL) RegCloseKey(hSubKey);
411  return dwError;
412 }
#define ERROR_SUCCESS
Definition: deptool.c:10
#define KEY_READ
Definition: nt_native.h:1023
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
smooth NULL
Definition: ftsmooth.c:416
unsigned long DWORD
Definition: ntddk_ex.h:95
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR L[]
Definition: oid.c:1087
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12

◆ ReadPerInstanceRegistryParameters()

DWORD WINAPI ReadPerInstanceRegistryParameters ( _In_ HKEY  hKey,
_In_ PSVCHOST_OPTIONS  pOptions 
)

Definition at line 179 of file svchost.c.

Referenced by BuildServiceArray().

183 {
184  DWORD dwError, dwData;
185  HKEY hSubKey;
186 
187  /* We should have a name for this service group... */
188  ASSERT(pOptions->ServiceGroupName);
189 
190  /* Query the group to see what services are part of it */
191  dwError = RegQueryString(hKey,
192  pOptions->ServiceGroupName,
193  REG_MULTI_SZ,
194  (PBYTE*)&ServiceNames);
195  if ((dwError == ERROR_SUCCESS) &&
196  ((ServiceNames == NULL) || (*ServiceNames == UNICODE_NULL)))
197  {
198  /* If the key exists but there's no data, fail */
199  return ERROR_INVALID_DATA;
200  }
201 
202  /* Open the key for this group */
203  if (RegOpenKeyExW(hKey,
204  pOptions->ServiceGroupName,
205  0,
206  KEY_READ,
207  &hSubKey) != ERROR_SUCCESS)
208  {
209  /* If we couldn't, bail out */
210  return dwError;
211  }
212 
213  /* Check if we should initialize COM */
214  if (RegQueryDword(hSubKey,
215  L"CoInitializeSecurityParam",
216  &dwData) == ERROR_SUCCESS)
217  {
218  /* Yes, remember the parameter to be sent when we do so */
219  pOptions->CoInitializeSecurityParam = dwData;
220  }
221 
222  /* Also, if COM is requested, we must read a bunch more data... */
223  if (pOptions->CoInitializeSecurityParam)
224  {
225  /* First, read the authentication level, use a default if none is set */
226  if (RegQueryDword(hSubKey, L"AuthenticationLevel", &dwData))
227  {
228  pOptions->AuthenticationLevel = RPC_C_AUTHN_LEVEL_PKT;
229  }
230  else
231  {
232  pOptions->AuthenticationLevel = dwData;
233  }
234 
235  /* Do the same for the impersonation level */
236  if (RegQueryDword(hSubKey, L"ImpersonationLevel", &dwData))
237  {
238  pOptions->ImpersonationLevel = RPC_C_IMP_LEVEL_IDENTIFY;
239  }
240  else
241  {
242  pOptions->ImpersonationLevel = dwData;
243  }
244 
245  /* Do the same for the authentication capabilities */
246  if (RegQueryDword(hSubKey, L"AuthenticationCapabilities", &dwData))
247  {
248  pOptions->AuthenticationCapabilities = EOAC_NO_CUSTOM_MARSHAL |
249  EOAC_DISABLE_AAA;
250  }
251  else
252  {
253  pOptions->AuthenticationCapabilities = dwData;
254  }
255  }
256 
257  /* Check if we need a specific RPC stack size, if not, we'll set it later */
258  if (!RegQueryDword(hSubKey, L"DefaultRpcStackSize", &dwData))
259  {
260  pOptions->DefaultRpcStackSize = dwData;
261  }
262 
263  /* Finally, check if the services should be marked critical later on */
264  if (!RegQueryDword(hSubKey, L"SystemCritical", &dwData))
265  {
266  pOptions->SystemCritical = dwData;
267  }
268 
269  /* All done reading the settings */
270  RegCloseKey(hSubKey);
271  return dwError;
272 }
#define ERROR_SUCCESS
Definition: deptool.c:10
#define KEY_READ
Definition: nt_native.h:1023
DWORD WINAPI RegQueryDword(_In_ HKEY hKey, _In_ LPCWSTR pszValueName, _Out_ PDWORD pdwValue)
Definition: registry.c:78
static HANDLE ULONG_PTR dwData
Definition: file.c:35
#define RPC_C_IMP_LEVEL_IDENTIFY
Definition: rpcdce.h:175
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
#define UNICODE_NULL
#define REG_MULTI_SZ
Definition: nt_native.h:1501
smooth NULL
Definition: ftsmooth.c:416
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD WINAPI RegQueryString(_In_ HKEY hKey, _In_ LPCWSTR pszValueName, _In_ DWORD dwExpectedType, _Out_ PBYTE *ppbData)
Definition: registry.c:107
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LPCWSTR ServiceNames
Definition: svchost.c:20
static const WCHAR L[]
Definition: oid.c:1087
#define ERROR_INVALID_DATA
Definition: winerror.h:116
#define RPC_C_AUTHN_LEVEL_PKT
Definition: rpcdce.h:149
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
BYTE * PBYTE
Definition: pedump.c:66

◆ ServiceStarter()

VOID WINAPI ServiceStarter ( _In_ DWORD  dwNumServicesArgs,
_In_ LPWSTR lpServiceArgVectors 
)

Definition at line 1050 of file svchost.c.

Referenced by BuildServiceTable().

1054 {
1055  DWORD i, dwError = ERROR_FILE_NOT_FOUND;
1056  PSVCHOST_SERVICE ServiceEntry;
1057  LPCWSTR lpServiceName;
1059  PSVCHOST_INIT_GLOBALS ServiceInitGlobals = NULL;
1060 
1061  /* Hold the lock while we start a service */
1063 
1064  /* Get this service's name, and loop the database */
1065  lpServiceName = *lpServiceArgVectors;
1066  for (i = 0; i < ServiceCount; i++)
1067  {
1068  /* Try to find a match by name */
1069  if (!lstrcmpiW(lpServiceName, ServiceArray[i].pszServiceName)) break;
1070  }
1071 
1072  /* Check if we didn't find it */
1073  if (i == ServiceCount)
1074  {
1075  /* This looks like a bogus attempt, bail out */
1077  return;
1078  }
1079 
1080  /* We have it */
1081  ServiceEntry = &ServiceArray[i];
1082 
1083  /* Should we breakpoint before loading this service? */
1084  if (FDebugBreakForService(lpServiceName) != FALSE)
1085  {
1086  /* Yep -- do it */
1087  DBG_TRACE("Attaching debugger before getting ServiceMain for %ws...\n",
1088  lpServiceName);
1089  DebugBreak();
1090  }
1091 
1092  /* Get the callbacks for this service */
1094  (PVOID*)&ServiceMain,
1095  (PVOID*)&ServiceInitGlobals,
1096  &dwError);
1097 
1098  /* If this service is valid and needs globals, but we don't have them... */
1099  if ((ServiceMain != NULL) &&
1100  (ServiceInitGlobals != NULL) &&
1102  {
1103  /* Go and build them for the first time! */
1105  }
1106 
1107  /* We call a service if it has a main, or if wants globals and we have them */
1108  if (((ServiceInitGlobals != NULL) && (g_pSvchostSharedGlobals != NULL)) ||
1109  ((ServiceMain != NULL) && (ServiceInitGlobals == NULL)))
1110  {
1111  /* Therefore, make sure it won't be unloaded as we drop the lock */
1112  ServiceEntry->cServiceActiveThreadCount++;
1113  }
1114 
1115  /* Drop the lock while we call into the service DLL */
1117 
1118  /* First: does this service want globals? */
1119  if (ServiceInitGlobals != NULL)
1120  {
1121  /* Do we have any to give? */
1123  {
1124  /* Yes, push them to the service */
1125  ServiceInitGlobals(g_pSvchostSharedGlobals);
1126 
1127  /* Does the service NOT have an entrypoint? */
1128  if (ServiceMain == NULL)
1129  {
1130  /* We're going to abort loading, it serves no use */
1131  if (lpServiceName != NULL)
1132  {
1133  AbortSvchostService(lpServiceName, dwError);
1134  }
1135 
1136  /* And drop a reference count since it's not active anymore */
1137  UnloadServiceDll(ServiceEntry);
1138  }
1139  }
1140  else if (lpServiceName != NULL)
1141  {
1142  /* We have no globals to give, so don't even bother calling it */
1143  AbortSvchostService(lpServiceName, dwError);
1144  }
1145  }
1146 
1147  /* Next up, does it have an entrypoint? */
1148  if (ServiceMain != NULL)
1149  {
1150  /* It does, so call it */
1151  DBG_TRACE("Calling ServiceMain for %ws...\n", lpServiceName);
1152  ServiceMain(dwNumServicesArgs, lpServiceArgVectors);
1153 
1154  /* We're out of the service now, so we can drop a reference */
1155  UnloadServiceDll(ServiceEntry);
1156  }
1157  else if (lpServiceName != NULL)
1158  {
1159  /* It has no entrypoint, so abort its launch */
1160  AbortSvchostService(lpServiceName, dwError);
1161  }
1162 }
LONG cServiceActiveThreadCount
Definition: svchost.h:151
PSVCHOST_GLOBALS g_pSvchostSharedGlobals
Definition: globals.c:50
void(WINAPI * LPSERVICE_MAIN_FUNCTIONW)(DWORD, LPWSTR *)
Definition: winsvc.h:177
VOID WINAPI UnloadServiceDll(_In_ PSVCHOST_SERVICE pService)
Definition: svchost.c:416
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
GLenum GLclampf GLint i
Definition: glfuncs.h:14
void WINAPI DebugBreak(void)
CRITICAL_SECTION ListLock
Definition: svchost.c:18
smooth NULL
Definition: ftsmooth.c:416
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
DWORD ServiceCount
Definition: svchost.c:19
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID WINAPI SvchostBuildSharedGlobals(VOID)
Definition: globals.c:89
#define DBG_TRACE(fmt,...)
Definition: svchost.h:36
VOID CALLBACK ServiceMain(DWORD argc, LPWSTR argv)
Definition: main.c:79
BOOL WINAPI FDebugBreakForService(_In_ LPCWSTR ServiceName)
Definition: svchost.c:339
VOID WINAPI AbortSvchostService(_In_ LPCWSTR lpServiceName, _In_ DWORD dwExitCode)
Definition: svchost.c:618
PSVCHOST_SERVICE ServiceArray
Definition: svchost.c:21
VOID WINAPI GetServiceMainFunctions(_In_ PSVCHOST_SERVICE pService, _Out_ PVOID *pServiceMain, _Out_ PVOID *pPushServiceGlobals, _Out_ PDWORD lpdwError)
Definition: svchost.c:819
VOID(WINAPI * PSVCHOST_INIT_GLOBALS)(_In_ PSVCHOST_GLOBALS Globals)
Definition: svchost.h:85
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)

◆ SvchostStopCallback()

VOID WINAPI SvchostStopCallback ( _In_ PVOID  Context,
_In_ BOOLEAN  TimerOrWaitFired 
)

Definition at line 483 of file svchost.c.

Referenced by SvcRegisterStopCallback().

487 {
488  PSVCHOST_CALLBACK_CONTEXT pSvcsStopCbContext = Context;
489  PSVCHOST_STOP_CALLBACK pfnStopCallback;
490 
491  /* Hold the lock while we grab the callback */
493 
494  /* Grab the callback, then clear it */
495  ASSERT(pSvcsStopCbContext->pService != NULL);
496  pfnStopCallback = pSvcsStopCbContext->pService->pfnStopCallback;
497  ASSERT(pfnStopCallback != NULL);
498  pSvcsStopCbContext->pService->pfnStopCallback = NULL;
499 
500  /* Now release the lock, making sure the above was atomic */
502 
503  /* Now make the callout */
504  DBG_TRACE("Call stop callback for service %ws, active threads %d\n",
505  pSvcsStopCbContext->pService->pszServiceName,
506  pSvcsStopCbContext->pService->cServiceActiveThreadCount);
507  pfnStopCallback(pSvcsStopCbContext->pContext, TimerOrWaitFired);
508 
509  /* Decrement the active threads -- maybe the DLL can unload now */
510  UnloadServiceDll(pSvcsStopCbContext->pService);
511 
512  /* We no longer need the context */
513  MemFree(pSvcsStopCbContext);
514 }
LONG cServiceActiveThreadCount
Definition: svchost.h:151
BOOL MemFree(IN PVOID lpMem)
Definition: utils.c:26
VOID WINAPI UnloadServiceDll(_In_ PSVCHOST_SERVICE pService)
Definition: svchost.c:416
PSVCHOST_SERVICE pService
Definition: svchost.h:162
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
PSVCHOST_STOP_CALLBACK pfnStopCallback
Definition: svchost.h:153
LPCWSTR pszServiceName
Definition: svchost.h:149
CRITICAL_SECTION ListLock
Definition: svchost.c:18
smooth NULL
Definition: ftsmooth.c:416
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define DBG_TRACE(fmt,...)
Definition: svchost.h:36
struct tagContext Context
Definition: acpixf.h:1027
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
VOID(CALLBACK * PSVCHOST_STOP_CALLBACK)(_In_ PVOID lpParameter, _In_ BOOLEAN TimerOrWaitFired)
Definition: svchost.h:43

◆ SvchostUnhandledExceptionFilter()

__callback LONG WINAPI SvchostUnhandledExceptionFilter ( _In_ struct _EXCEPTION_POINTERS ExceptionInfo)

Definition at line 28 of file svchost.c.

Referenced by wmainCRTStartup().

31 {
32  /* Call the default OS handler */
33  return RtlUnhandledExceptionFilter(ExceptionInfo);
34 }
LONG NTAPI RtlUnhandledExceptionFilter(IN struct _EXCEPTION_POINTERS *ExceptionInfo)
Definition: exception.c:306

◆ SvcRegisterStopCallback()

DWORD WINAPI SvcRegisterStopCallback ( _In_ PHANDLE  phNewWaitObject,
_In_ LPCWSTR  ServiceName,
_In_ HANDLE  hObject,
_In_ PSVCHOST_STOP_CALLBACK  pfnStopCallback,
_In_ PVOID  pContext,
_In_ ULONG  dwFlags 
)

Definition at line 518 of file svchost.c.

Referenced by SvchostBuildSharedGlobals().

526 {
527  ULONG i;
528  PSVCHOST_CALLBACK_CONTEXT pSvcsStopCbContext = NULL;
529  PSVCHOST_SERVICE pService = NULL;
530  DWORD dwError = ERROR_SUCCESS;
531 
532  /* All parameters must be present */
533  if ((phNewWaitObject == NULL) ||
534  (ServiceName == NULL) ||
535  (hObject == NULL) ||
536  (pfnStopCallback == NULL))
537  {
538  /* Fail otherwise */
540  }
541 
542  /* Don't allow new DLLs while we send notifications */
544 
545  /* Scan all registered services */
546  for (i = 0; i < ServiceCount; i++)
547  {
548  /* Search for the service entry matching this service name */
549  if (lstrcmpiW(ServiceName, ServiceArray[i].pszServiceName) == 0)
550  {
551  /* Found it */
552  pService = &ServiceArray[i];
553  break;
554  }
555  }
556 
557  /* Do we have a service? Does it already have a callback? */
558  if ((pService == NULL) || (pService->pfnStopCallback != NULL))
559  {
560  /* Affirmative, nothing for us to do */
561  dwError = ERROR_INVALID_DATA;
562  DBG_ERR("Service %ws missing or already registered for callback, "
563  "status %d\n",
564  ServiceName,
565  dwError);
566  goto Quickie;
567  }
568 
569  /* Allocate our internal context */
570  pSvcsStopCbContext = MemAlloc(HEAP_ZERO_MEMORY, sizeof(*pSvcsStopCbContext));
571  if (pSvcsStopCbContext == NULL)
572  {
573  /* We failed, bail out */
574  dwError = ERROR_NOT_ENOUGH_MEMORY;
575  DBG_ERR("MemAlloc for context block for service %ws failed, status "
576  "%d\n",
577  ServiceName,
578  dwError);
579  goto Quickie;
580  }
581 
582  /* Setup the context and register for the wait */
583  pSvcsStopCbContext->pContext = pContext;
584  pSvcsStopCbContext->pService = pService;
585  if (RegisterWaitForSingleObject(phNewWaitObject,
586  hObject,
588  pSvcsStopCbContext,
589  INFINITE,
590  dwFlags))
591  {
592  /* We now have an active thread associated with this wait */
593  pService->cServiceActiveThreadCount++;
594  pService->pfnStopCallback = pfnStopCallback;
595  DBG_TRACE("Registered stop callback for service %ws, active threads %d\n",
596  ServiceName,
597  pService->cServiceActiveThreadCount);
598  }
599  else
600  {
601  /* Registration failed, bail out */
602  dwError = GetLastError();
603  DBG_ERR("Registration for stop callback for service %ws failed, "
604  "status %d\n",
605  ServiceName,
606  dwError);
607  }
608 
609 Quickie:
610  /* Drop the lock, and free the context if we failed */
612  if (dwError != ERROR_SUCCESS) MemFree(pSvcsStopCbContext);
613  return dwError;
614 }
LONG cServiceActiveThreadCount
Definition: svchost.h:151
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
BOOL MemFree(IN PVOID lpMem)
Definition: utils.c:26
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DBG_ERR(fmt,...)
Definition: svchost.h:35
PVOID MemAlloc(IN DWORD dwFlags, IN DWORD dwBytes)
Definition: utils.c:33
PSVCHOST_SERVICE pService
Definition: svchost.h:162
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
PSVCHOST_STOP_CALLBACK pfnStopCallback
Definition: svchost.h:153
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
GLenum GLclampf GLint i
Definition: glfuncs.h:14
CRITICAL_SECTION ListLock
Definition: svchost.c:18
smooth NULL
Definition: ftsmooth.c:416
DWORD ServiceCount
Definition: svchost.c:19
LPTSTR ServiceName
Definition: ServiceMain.c:15
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID WINAPI SvchostStopCallback(_In_ PVOID Context, _In_ BOOLEAN TimerOrWaitFired)
Definition: svchost.c:483
#define DBG_TRACE(fmt,...)
Definition: svchost.h:36
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
PSVCHOST_SERVICE ServiceArray
Definition: svchost.c:21
#define ERROR_INVALID_DATA
Definition: winerror.h:116
BOOL WINAPI RegisterWaitForSingleObject(OUT PHANDLE phNewWaitObject, IN HANDLE hObject, IN WAITORTIMERCALLBACK Callback, IN PVOID Context, IN ULONG dwMilliseconds, IN ULONG dwFlags)
Definition: synch.c:796
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
unsigned int ULONG
Definition: retypes.h:1
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define INFINITE
Definition: serial.h:102

◆ UnloadServiceDll()

VOID WINAPI UnloadServiceDll ( _In_ PSVCHOST_SERVICE  pService)

Definition at line 416 of file svchost.c.

Referenced by ServiceStarter(), and SvchostStopCallback().

419 {
420  DWORD cbData;
421  DWORD Data;
422  DWORD dwType;
423  HKEY hKey = NULL;
424 
425  cbData = 4;
426  Data = 0;
427 
428  /* Grab the lock while we touch the thread count and potentially unload */
430 
431  /* There is one less active callout into the DLL, it may be unloadabl now */
432  ASSERT(pService->cServiceActiveThreadCount > 0);
433  pService->cServiceActiveThreadCount--;
434 
435  /* Try to open the service registry key */
436  if (OpenServiceParametersKey(pService->pszServiceName, &hKey) == ERROR_SUCCESS)
437  {
438  /* It worked -- check if we should unload the service when stopped */
439  if (RegQueryValueExW(hKey,
440  L"ServiceDllUnloadOnStop",
441  0,
442  &dwType,
443  (LPBYTE)&Data,
444  &cbData) == ERROR_SUCCESS)
445  {
446  /* Make sure the data is correctly formatted */
447  if ((dwType == REG_DWORD) && (Data == 1))
448  {
449  /* Does the service still have active threads? */
450  if (pService->cServiceActiveThreadCount != 0)
451  {
452  /* Yep, so we can't kill it just yet */
453  DBG_TRACE("Skip Unload dll %ws for service %ws, "
454  "active threads %d\n",
455  pService->pDll->pszDllPath,
456  pService->pszServiceName,
457  pService->cServiceActiveThreadCount);
458  }
459  else
460  {
461  /* Nope, we're good to go */
462  DBG_TRACE("Unload dll %ws for service %ws\n",
463  pService->pDll->pszDllPath,
464  pService->pszServiceName);
465 
466  /* Free the library and clear the module handle */
467  FreeLibrary(pService->pDll->hModule);
468  pService->pDll->hModule = NULL;
469  }
470  }
471  }
472  }
473 
474  /* Drop the lock, unload is complete */
476 
477  /* Close the parameters key if we had it */
478  if (hKey) RegCloseKey(hKey);
479 }
#define ERROR_SUCCESS
Definition: deptool.c:10
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
CRITICAL_SECTION ListLock
Definition: svchost.c:18
smooth NULL
Definition: ftsmooth.c:416
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
#define FreeLibrary(x)
Definition: compat.h:405
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4134
unsigned long DWORD
Definition: ntddk_ex.h:95
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define DBG_TRACE(fmt,...)
Definition: svchost.h:36
static const WCHAR L[]
Definition: oid.c:1087
DWORD WINAPI OpenServiceParametersKey(_In_ LPCWSTR lpSubKey, _Out_ PHKEY phKey)
Definition: svchost.c:378
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define REG_DWORD
Definition: sdbapi.c:539

◆ wmainCRTStartup()

VOID __cdecl wmainCRTStartup ( VOID  )

Definition at line 1247 of file svchost.c.

1250 {
1251  PSVCHOST_OPTIONS lpOptions;
1252  SERVICE_TABLE_ENTRYW *pServiceTable;
1253  LPWSTR pszCmdLine;
1254 
1255  /* Set a generic SEH filter and hard fail all critical errors */
1258 
1259  /* Initialize the heap allocator */
1261 
1262  /* Initialize the DLL database and lock */
1265 
1266  /* Get the command-line and parse it to get the service group */
1267  pszCmdLine = GetCommandLineW();
1268  lpOptions = BuildCommandOptions(pszCmdLine);
1269  if (lpOptions == NULL)
1270  {
1271  /* Without a valid command-line, there's nothing for us to do */
1272  DBG_TRACE("Calling ExitProcess for %ws\n", pszCmdLine);
1273  ExitProcess(0);
1274  }
1275 
1276  /* Now use the service group information to lookup all the services */
1277  BuildServiceArray(lpOptions);
1278 
1279  /* Convert the list of services in this group to the SCM format */
1280  pServiceTable = BuildServiceTable();
1281  if (pServiceTable == NULL)
1282  {
1283  /* This is critical, bail out without it */
1284  MemFree(lpOptions);
1285  return;
1286  }
1287 
1288  /* Initialize COM and RPC as needed for this service group */
1289  if (CallPerInstanceInitFunctions(lpOptions) == FALSE)
1290  {
1291  /* Exit with a special code indicating COM/RPC setup has failed */
1292  DBG_ERR("%s", "CallPerInstanceInitFunctions failed -- exiting!\n");
1293  ExitProcess(1);
1294  }
1295 
1296  /* We're ready to go -- free the options buffer */
1297  MemFree(lpOptions);
1298 
1299  /* And call into ADVAPI32 to get our services going */
1300  StartServiceCtrlDispatcherW(pServiceTable);
1301 }
UINT WINAPI SetErrorMode(IN UINT uMode)
Definition: except.c:753
BOOL MemFree(IN PVOID lpMem)
Definition: utils.c:26
BOOLEAN WINAPI CallPerInstanceInitFunctions(_In_ PSVCHOST_OPTIONS pOptions)
Definition: svchost.c:1199
#define SEM_FAILCRITICALERRORS
Definition: rtltypes.h:69
#define DBG_ERR(fmt,...)
Definition: svchost.h:35
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1517
LIST_ENTRY DllList
Definition: svchost.c:17
BOOL WINAPI StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
Definition: sctrl.c:1094
VOID WINAPI MemInit(_In_ HANDLE Heap)
Definition: globals.c:58
__callback LONG WINAPI SvchostUnhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS *ExceptionInfo)
Definition: svchost.c:28
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
Definition: except.c:792
LPWSTR WINAPI GetCommandLineW(VOID)
Definition: proc.c:2043
CRITICAL_SECTION ListLock
Definition: svchost.c:18
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
smooth NULL
Definition: ftsmooth.c:416
VOID WINAPI BuildServiceArray(_In_ PSVCHOST_OPTIONS lpOptions)
Definition: svchost.c:276
SERVICE_TABLE_ENTRYW *WINAPI BuildServiceTable(VOID)
Definition: svchost.c:1166
#define GetProcessHeap()
Definition: compat.h:395
#define DBG_TRACE(fmt,...)
Definition: svchost.h:36
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
WCHAR * LPWSTR
Definition: xmlstorage.h:184
PSVCHOST_OPTIONS WINAPI BuildCommandOptions(_In_ LPWSTR pszCmdLine)
Definition: svchost.c:48

Variable Documentation

◆ DllList

LIST_ENTRY DllList

Definition at line 17 of file svchost.c.

◆ ListLock

CRITICAL_SECTION ListLock

Definition at line 18 of file svchost.c.

◆ ServiceArray

PSVCHOST_SERVICE ServiceArray

Definition at line 21 of file svchost.c.

Referenced by BuildServiceArray().

◆ ServiceCount

DWORD ServiceCount

◆ ServiceNames

LPCWSTR ServiceNames

Definition at line 20 of file svchost.c.

Referenced by BuildServiceArray(), and ReadPerInstanceRegistryParameters().