Understanding Wine
DLL and Service Development in Wine
»Index
»Setup
»DLLs
»Services
»Windows
»svchost
»Links
»Notes
»Author
»Wine HQ

This tutorial combines the COM DLL tutorial and the COM service tutorial to run a DLL as a service with the help of svchost.exe. The svchost.exe program acts as the service process for the DLL and associates the DLL with the service control manager (SCM). All of this requires support from the registry.

This tutorial explores in detail the svchost.exe program and demonstrates how to create DLLs wrapped in svchost.exe.

Source code for this tutorial is available from the tutorial's introduction.

Warning
Work in Progress

This section of the tutorial is still a work in progress and potentially rougher than other parts of the tutorial. As always, feel free to email roy at cs.ucla.edu with comments, bugs, or corrections. (Nov. 2007)

Synopsis

  • The svchost.exe Program

  • Registry Entries Used by svchost.exe

  • Wrapping a DLL with svchost.exe

  • Building and Testing a DLL Wrapped with svchost.exe

The svchost Program

Windows uses svchost.exe to execute DLLs as services. A single instance of svchost.exe can group together a collection of process. This is said to provide, "better control and easier debugging". Since little documentation is publicly available, the version of svchost.exe presented in this tutorial is a best guess implementation.

The basic operation of svchost.exe is to:

  • Look up in the registry the service group specified on the command line using the -k option.

  • Populate a service table with entries specifying the service name and the entry point into the DLL.

  • Use StartServiceCtrlDispatcher to start the services in the service table.

These last two steps are nearly identical to those used general COM servers. The important distinction is that svchost.exe must load a DLL (specified in the registry) and find the address of the function acting as the entry point into the DLL.

A simple version of svchost.exe is available in $WINEPATH/programs/svchost/svchost.c with a corresponding Makefile.in in $WINEPATH/programs/svchost/Makefile.in.

Note
Key Points
  • This is a best guess implementation of svchost.exe and may not properly handle all svchost.exe wrapped services.

  • Please email me if you find a service that fails to properly start using this version of svchost.exe. If possible include the name of the service and the service's registry entry (described below).

  • And yes, the new Makafile.in must be added the build system for use in Wine.

Registry Entries Used by svchost

A number of registry entries are used to support svchost.exe. Tracing the execution of a client using a svchost.exe demonstrates the role of each key. Assume that a user runs the count_proxy_test.exe.so program developed in the last tutorial and is using the svchost.exe wrapped DLL developed in this tutorial to provide the count service.

Server Side

  • Service control manager sees a request for an instance of the Count class and looks for the class ID corresponding to the Count IID handling these requests to find the AppID for the class:

[Software\\Classes\\CLSID\\{55E9B534-76AA-11DC-8B8E-F6CC56D89593}] 1194559933
"AppID"="{72f5782a-867e-11dc-8314-0800200c9a66}"
  • The LocalService value is found under the AppID key specifying that the application is run as the count_svchost local service:

[Software\\Classes\\AppID\\{72f5782a-867e-11dc-8314-0800200c9a66}] 1194640587
"LocalService"="count_svchost"

[Software\\Classes\\AppID\\count_svchost] 1194559933
"AppID"="{72f5782a-867e-11dc-8314-0800200c9a66}"
  • The ImagePath of the count_svchost service is examined to find the actual executable to run to start the server. In this example the value is specified as svchost.exe -k count_svchost to note that the svchost.exe executable should start the count_svchost service group. The .so extension seen below is a relic of Wine and would not be seen in the corresponding Windows registry entry:

[System\\CurrentControlSet\\Services\\count_svchost] 1194560007
"Description"="Simple Counter"
"DispalyName"="Count Svchost"
"ErrorControl"=dword:00000001
"ImagePath"=str(2):"Z:\\data\\wine-git\\programs\\svchost\\svchost.exe.so -k count_svchost"
"ObjectName"="LocalSystem"
"Start"=dword:00000003
"Type"=dword:00000110
  • The svchost.exe executable is started and it looks up the services to be started for the count_svchost service group:

[Software\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost] 1194559933
.
.
"count_svchost"=str(7):"count_svchost\0"
.
.
  • The Parameters key of each service specified in the service group is examined to find the DLL to be started for that service. Optionally, the Parameters key can specify the name of a function to be called by svchost.exe to start the DLL as a service. This function defaults to ServiceMain:

[System\\CurrentControlSet\\Services\\count_svchost\\Parameters] 1194560007
"ServiceDll"=str(2):"Z:\\data\\wine-git\\dlls\\count_svchost\\count_svchost.dll"
  • The services associated with the service group can then be started by and associated with the SCM by scvhost.exe.

Client Side

  • Client program queries the registry for the provider of the ICount interface and finds that it should use the count_proxy.dll for communication to the provider of the class:

[Software\\Classes\\CLSID\\{3ee455d8-76aa-11dc-86b3-c4cc56d89593}\\InProcServer32] 1194560563
@="c:\\windows\\system32\\count_proxy.dll"
"ThreadingModel"="Both"
Note
Key Points
  • The proxy specific registry entry is added to the registry using regsvr32 to register the proxy with the system.

  • The other registry entries are probably provided using regsvr32 to register the DLL acting as a service.

Wrapping a DLL with svchost

Creating a DLL to run via svchost.exe simply involves combining a DLL with a service. The DLL should use the structure common to all DLLs as described in the COM DLL tutorial. In addition to the basic DLL functionality, the DLL must expose a ServiceMain function with all the characteristics of service main seen in the COM service tutorial.

Since we have these pieces from the last two tutorials, constructing the count service as a DLL wrapped with svchost.exe is easy. For the count_svchost DLL I copied the files used by the count and DLL and count_service.c from the service with updates to:

  • The MODULE field of the Makefile.in to specify a new module name.

  • The IMPORTLIB field of Makefile.in whose field must correspond to the name of the created DLL.

  • Added the C file implementing ServiceMain (in this case count_service.c) to the C_SRCS in Makefile.in.

  • Add #include "winsvc.h" to count_private.h.

  • Changed count_service_nameW to be "count_svchost" in count_service.c.

  • Removed unused variables and functions from count_service.c that had been associated with wmain.

  • Add the entry @ stdcall ServiceMain(long ptr) to count_svchost.spec (renamed version of count.spec) to expose ServiceMain.

  • Changed calls to WINE_TRACE and WINE_ERR (located in count_service.c) to TRACE and ERR.

  • Updated the WINE_DEFAULT_DEBUG_CHANNEL of all C files.

Source code with these changes is located in the $WINEPATH/dlls/count_svchost directory of the tutorial code.

Building and Testing a DLL Wrapped with svchost

Be sure that the the Makefile.in for count_svchost, count_proxy, the count proxy test, and svchost have been added to Wine`s build system. Then build and test the project:

Warning
Work in Progress

The current version of count_svchost.dll does not have all of the required regestration functionality. The registry should contain the following entries to execute this example program:

[Software\\Classes\\AppID\\count_svchost] 1194559933
"AppID"="{72f5782a-867e-11dc-8314-0800200c9a66}"

[Software\\Classes\\AppID\\{72f5782a-867e-11dc-8314-0800200c9a66}] 1194640587
"LocalService"="count_svchost"

[Software\\Classes\\CLSID\\{55E9B534-76AA-11DC-8B8E-F6CC56D89593}] 1194559933
"AppID"="{72f5782a-867e-11dc-8314-0800200c9a66}"

[Software\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost] 1194559933
"count_svchost"=str(7):"count_svchost\0"

[System\\CurrentControlSet\\Services\\count_svchost] 1194560007
"Description"="Simple Counter"
"DispalyName"="Count Svchost"
"ErrorControl"=dword:00000001
"ImagePath"=str(2):"Z:\\data\\wine-git\\programs\\svchost\\svchost.exe.so -k
count_svchost"
"ObjectName"="LocalSystem"
"Start"=dword:00000003
"Type"=dword:00000110

[System\\CurrentControlSet\\Services\\count_svchost\\Parameters] 1194560007
"ServiceDll"=str(2):"Z:\\data\\wine-git\\dlls\\count_svchost\\count_svchost.dll"

I this functionality will soon be included in the code distributed with this tutorial. (Nov. 2007)

cd $WINEPATH
make -C dlls/count_svchost
make -C dlls/count_proxy
make -C dlls/count_proxy_tests
make -C programs/svchost
$WINEPATH/programs/regsvr32/regsvr32 count_svchost
$WINEPATH/programs/regsvr32/regsvr32 count_proxy
$WINEPATH/programs/regsvr32/regsvr32 ole32
$WINEPATH/wine dlls/count_proxy/tests/count_proxy_test.exe.so