Geoff Chappell, Software Analyst
Before a SVCHOST instance receives any requests to start a service, before any service DLLs are loaded, SVCHOST works through various initialisations such as each service might have wanted for itself and would have needed to code for itself (or reproduce, e.g., from libraries) were the service implemented as its own service program. These initialisations are non-trivial, such that writers of service DLLs ought be aware of what has already been set up for them (or could be):
Note that the RPC Run-Time (RPCRT4.DLL) is loaded into every SVCHOST instance, whether or not any service DLLs in that instance ever make any Remote Procedure Calls. By contrast, the COM Run-Time (OLE32.DLL) is not loaded unless initialisation of COM security is configured.
For COM initialisation, if enabled by a registry setting described below, SVCHOST does the following:
Version 6.00 allows that all these except for calling CoInitializeEx can be deferred until a request is received to start any of a specified set of services (which are presumably the ones that actually will be COM servers).
SVCHOST initialises COM for the multi-threaded concurrency model, with DDE disabled. The call to CoInitializeSecurity is configurable for the authentication and impersonation levels (version 5.1 and higher) and the authentication capabilities. For access control, early versions provide a NULL DACL, thus allowing all access. Starting with the version 5.1 from Windows XP SP2, SVCHOST provides just the one DACL, for Authenticated Users to have COM execution rights.
Early versions set the owner and primary group from the thread token else the process token. Version 6.00 uses only the process token. When security is initialised during process initialisation, as it must be for the earlier versions, then SVCHOST has only its initial thread, which is not impersonating. So, is the earlier coding without practical consequence?
Given that COM initialisation is enabled, it is treated as critical in version 5.2 and higher. If any of the steps listed above fail during process initialisation, then SVCHOST terminates. The exit code 1 distinguishes this case. Earlier versions ignore the failure and may let their services start, but with security left to the COM Run-Time defaults.
If some of the steps are deferred, as supported in version 6.00, their failure is critical only to the service that they are performed for. Though the service DLL will be loaded already, it does not get called to start the service. Moroever, so that the service never can start, SVCHOST registers a dummy control handler and puts the service into the stopped state. This case is distinguished by ERROR_FUNCTION_FAILED for the Win32 exit code in the service’s status. A failure for one service does not prevent the initialisation from being attempted again for another service.
A few points of this process-wide initialisation are separately configurable for each SVCHOST instance. The name of the service group that runs in the instance, as from a -k group switch on SVCHOST’s command line, becomes a subkey in which to find this instance’s settings.
None of these settings are formally documented. It may be, of course, that they are left undocumented because none would be useful even to advanced users or system administrators. On the other hand, see that one of the settings had a change of default and that this was not just for a new version but also for a Service Pack. It would be surprising if there was not someone somewhere to benefit from specifying this setting, either so that an old version gets the tighter security that is the new (and presumably more appropriate) default or so that a new version keeps old behaviour.
Key | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Svchost\group |
Value | DefaultRpcStackSize |
Type | REG_DWORD |
Default | 0 |
Availability | version 5.1 and higher |
The DefaultRpcStackSize setting tells the RPC Run Time what size of stack to set for each thread it creates. The unit of measurement is KB.
Without this setting, or if the setting is zero, SVCHOST specifies whatever size is given (in bytes) by the SizeOfStackCommit field in the header of SVCHOST’s executable image. This is 16KB in all the SVCHOST versions that support the setting.
Key | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Svchost\group |
Value | SystemCritical |
Type | REG_DWORD |
Default | 0 |
Availability | version 5.2 and higher |
If SystemCritical is non-zero, then the SVCHOST instance asks to be treated as a critical process if the “Enable system critical breaks” feature is enabled. What this means is that termination should break to a kernel debugger or stop the system. Without a kernel debugger, the bug check code is CRITICAL_PROCESS_DIED (0xEF) or CRITICAL_OBJECT_TERMINATION (0xF4), depending on whether the termination is orderly or unexpected. For more of what to expect, see RtlSetProcessIsCritical.
Termination during process initialisation is not affected by this setting, since such exits are taken before SVCHOST gets as far as asking to be a critical process.
Key | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Svchost\group |
Value | CoInitializeSecurityParam |
Type | REG_DWORD |
Default | 0 |
COM initialisation is enabled if CoInitializeSecurityParam is non-zero. Let it be stressed: none of the remaining settings for COM security are meaningful unless CoInitializeSecurityParam is non-zero.
For initialising COM security, SVCHOST takes the authentication level, impersonation level and authentication capabilities from the registry, as shown below. Beware that SVCHOST accepts whatever it finds for these settings. Invalid data may cause CoInitializeSecurity to fail, with the version-dependent consequences noted above.
Key | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Svchost\group |
Value | AuthenticationLevel |
Type | REG_DWORD |
Default | 4 (RPC_C_AUTHN_LEVEL_PKT) |
Availability | version 5.1 and higher |
Version 5.0, which does not support AuthenticationLevel in the registry, acts as if set to 4.
Key | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Svchost\group |
Value | ImpersonationLevel |
Type | REG_DWORD |
Default | 2 (RPC_C_IMP_LEVEL_IDENTIFY) in version 5.1
from Windows XP SP2, and higher; 3 (RPC_C_IMP_LEVEL_IMPERSONATE) in earlier versions |
Availability | version 5.1 and higher |
Version 5.0, which does not support ImpersonationLevel in the registry, acts as if set to 3.
Key | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Svchost\group |
Value | AuthenticationCapabilities |
Type | REG_DWORD |
Default | 0x3000 (EOAC_DISABLE_AAA and EOAC_NO_CUSTOM_MARSHAL) |
Special caution applies to the AuthenticationCapabilities setting with respect to the note above about the data being accepted as is. Do not set either the 0x04 (EOAC_ACCESS_CONTROL) or 0x08 (EOAC_APPID) bit, else behaviour is undefined. The reason is that when SVCHOST calls CoInitializeSecurity, it specifies the COM access permissions by passing a security descriptor. This style of call requires that both the 0x04 and 0x08 bits be clear in whatever is passed as the authentication capabilities, but SVCHOST simply passes the authentication capabilities that it reads from this registry setting.
Key | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Svchost\group |
Value | CoInitializeSecurityAppID |
Type | REG_SZ |
Availability | version 5.2 from Windows Server 2003 SP2, and higher |
The CoInitializeSecurityAppID setting specifies a GUID from which COM Security is to obtain an AppID key. Note that this registry setting is ignored unless the service group contains only one service.
Key | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Svchost\group |
Value | DeferredCoInitializeSecurityServices |
Type | REG_MULTI_SZ |
Availability | version 6.0 and higher |
The DeferredCoInitializeSecurityServices setting specifies which services in the group are subject to deferred initialisation of COM security.