Function Discovery Provider Sample Readme

Contents

Purpose. 1

Prerequisites. 1

Components. 2

Building the sample. 3

To build the sample using the command prompt. 3

To build the sample using Visual Studio 2008 (preferred method). 3

Installing the sample. 4

To install the sample. 4

Running the sample. 4

To grant permission to the Local Service account. 4

Troubleshooting. 5

Limitations. 5

Notes for provider writers. 5

Activation contexts. 5

Security considerations. 6

Preservation of Add / Remove notification order. 6

Steps for writing a provider. 6

 

Purpose

This sample demonstrates how to write a fully functional PnP-X Function Discovery provider.

Prerequisites

You can build the sample on Windows XP, Vista or 7. You must have the Windows Vista SDK installed on the build machine. Before building the sample, you must integrate the SDK with Visual Studio.  To integrate the Windows SDK with Visual Studio 2008, click Start, click All Programs, click Microsoft Windows SDK v7.0, click Visual Studio Registration, and then click Integrate Windows SDK Configuration Tool. For more information about installing and integrating the SDK, see the SDK Release Notes.

You must run the sample on Windows Vista or Windows 7.          

Components

The sample consists of 3 components:  FDProviderHostSample.exe, FDProviderSample.dll, and FDProviderSampleDevice.exe.  FDProviderSample implements a COM class that implements the IFunctionDiscoveryProvider interface.  This is the heart of the sample and where most of the implementation work is focused.  FDProviderHostSample.exe implements an EXE host for the provider; this allows the provider to be hosted out of proc, which is a requirement for PnP-X providers.  FDProviderSampleDevice.exe implements a simple soft device that is enumerated by the sample provider.

The sample directory layout is shown below with brief descriptions of the files.

FDProviderHostSample                                 Implementation of FDProviderHostSample.exe.

FDProviderHostSample.cpp                    All the code for the EXE host.

FDProviderHostSample.rc                        Version resource.

FDProviderHostSample.vcproj               Visual Studio Project file.

resource.h                                                      Header for the resources.

stdafx.cpp                                                       Precompiled header cpp.

stdafx.h                                                           Precompiled header.

FDProviderSample                                          Implementation for FDProvider.dll

ClientNotificationWork.cpp                     Implementation for TClientNotificationWork.  This class represents queued notifications that must be sent to the provider client.

ClientNotificationWork.h                          Definition for TClientNotificationWork.

ComServer.cpp                                             Implementation of the ClassFactory and DLL host support functions for the Provider COM class.

ComServer.def                                             DLL Export definitions for FDProviderSample.dll

ComServer.h                                                 Definitions for DLL host support functions.

DiscoveryProtocol.cpp                               Implementation of the simple enumeration network protocol used by the sample.

DiscoveryProtocol.h                                   Public interface for the implementation.

FDProvider.cpp                                             Implementation of the Function Discovery provider (TFunctionDiscoveryProvider).

FDProvider.h                                                 Definition of TFunctionDiscoveryProvider

FDProviderSample.rc                                 Version resource.

FDProviderSample.vcproj                        Visual Studio Project file.

FunctionInstanceInfo.cpp                        Implementation of TFunctionInstanceInfo.  This class acts as a container for the data that will ultimately become the function instance.

FunctionInstanceInfo.h                             Declaration for TFunctionInstanceInfo.

LinkedList.h                                                    A circular double linked list implementation.

Locks.h                                                             A simple class wrapper for SRWLOCK.

resource.h                                                      Version resource.

stdafx.cpp                                                       Precompiled header cpp.

stdafx.h                                                           Precompiled header.

ThreadPool.h                                                 Implementation for TThreadPool<>, a utility class that present Windows ThreadPool as a singleton, allowing for easy sharing of a thread pool across objects.

FDProviderSampleDevice                             Implementation of FDProviderSampleDevice.exe

FDProviderSampleDevice.cpp                Implementation of the soft device.

FDProviderSampleDevice.rc                    Version resource.

FDProviderSampleDevice.vcproj           Visual Studio project.

stdafx.cpp                                                       Precompiled header cpp.

stdafx.h                                                           Precompiled header.

Inc                                                                          Shared header files.

IEXEHostControl.h                                       Definition of IEXEHostControl, a private interface used to communicate between the EXEHost and the hosted providers.

Messages.h                                                    Definitions of the messages for the network protocol.

FunctionDiscoveryProvider.sln                  Visual Studio solution.

Install.bat                                                            Batch file to configure the firewall and import the registry keys.

Install.reg                                                            Registry file describing the registry modifications required for registering the COM objects and PnP-X provider.

Readme.htm                                                     This file.

Building the sample

Before building the sample, you should copy the sample files to a working folder not under the Program Files directory.

To build the sample using the command prompt

1.       Click Start, click All Programs, click Microsoft Windows SDK, and then click CMD Shell.

2.       Navigate to the FunctionDiscoveryProvider directory.

3.       Type msbuild FunctionDiscoveryProvider.sln

To build the sample using Visual Studio 2008 (preferred method)

1.       Open Windows Explorer.

2.       Navigate to the FunctionDiscoveryProvider directory.

3.       Double-click FunctionDiscoveryProvider.sln to open the file in Visual Studio.

4.       On the Build menu, click Build Solution. By Default, this will build 32 bit checked (Debug) binaries.  By using the Configuration Manager in Visual Studio, you can change to building free (Release) and x64 binaries, or you can also use the Batch Build tool.  Please note that the binaries must match the host they will be running on, 32 bit Windows will use the 32 bit binaries, and x64 Windows will use the 64 bit binaries. 

For more information about building samples, see the SDK Release Notes.

Installing the sample

To install the sample

1.       Build the sample using one of the methods described above.

2.       Open Install.reg (located in the FunctionDiscoveryProvider directory).

3.       Edit the path to FDProviderSample.dll to match the path to the file on your computer.

4.       Edit the path to FDProviderHostSample.exe to match the path to the file on your computer.

5.       Save and close Install.reg.

6.       Open Install.bat (located in the FunctionDiscoveryProvider directory).

7.       Edit the path to FDProviderHostSample.exe to match the path to the file on your computer.

8.       Save and close Install.bat.

9.       Run Install.bat. This batch file creates the required registry entries and configures the firewall to allow network communication.

Running the sample

Before you can run the sample, you must install the sample using the instructions given above.   You must also ensure that the Local Service account has permission to execute files in the folder in which the sample DLL files were built.

To grant permission to the Local Service account

1.       Start Windows Explorer.

2.       Browse to the folder in which the sample DLLs were built.

3.       Right-click the folder, click Properties, and then click the Security tab.

4.       Click Edit.

5.       Click Add.

6.       Type “LOCAL SERVICE” into the text box, and then click Check Names.

7.       Click OK to close the next three dialog boxes.

To run the sample, start FDProviderSampleDevice.exe on one or more machines. To view usage instructions at the command prompt, type FDProviderSampleDevice.exe /?

The command line parameters for FDProviderSampleDevice.exe control the properties of the devices. You must specify a DeviceID, a HardwareID, a device category, and a friendly name for the device. These properties are used by PnP and by the Network Explorer.  For example, specifying a device category of “Printers” will display the device as a printer in the Network Explorer.  Also, the specified HardwareID will be used to match a driver during installation.

Once some sample soft devices are running, the Network Explorer will enumerate the devices, display properties for devices, and install devices.

Troubleshooting


There could be many causes if your sample devices do not show up in the Network Explorer.  First check to see if you host process (FDProviderHostSample.exe) is running while you are in the network folder.  You can check this by opening Task Manager and clicking “Show processes from all users.”  If it is not running, normally this means that your registrations or file permissions are not correct.  Carefully recheck the steps on installing and granting permissions; chances are you might have missed something there.  Another possibility is that you might be trying to run the wrong binary.  Make sure you use the “Win32” binaries for 32 bit Windows, and “x64” binaries for x64 Windows.  One final suggestion is to check your firewall settings for the host processes and sample devices.

Limitations

The sample implements a very simple network protocol and the implementation specifically does not address multi-homed machines or network connectivity changes.  When running the sample on a multi-homed machine, you should disable one of the interfaces to ensure that the multicast traffic uses the right interface.

Notes for provider writers

Activation contexts

Function Discovery providers must be free threaded.

By default, the PnP-X subsystem activates providers using the CLSCTX_LOCAL_SERVER activation context; however, some clients may activate the provider using the CLSCTX_INPROC_SERVER activation context.  Therefore, providers must support activation in both contexts.  To accomplish this, the sample implements the provider as a DLL to support in-proc activation and a host process running as an EXE that that loads the DLL to support out-of-proc activation.  An EXE host is used in the sample because it is simpler and consumes fewer resources than a Windows service.  The sample host process will automatically be started by COM when a client activates a provider and will exit once all clients have disconnected.

If you are writing a provider that must maintain state even when no clients are connected to the provider, then you should use a Windows service to host the provider.

Security considerations

PnP-X Function Discovery providers typically communicate on the network, often using multicast.  For this reason, providers are attack vectors which, if exploited, can result in remote compromise of the system.  To mitigate security risks and as a defense-in-depth strategy, providers should run with the least privilege required.  The sample provider host runs as the LocalService account. It is recommended that all provider hosts run as LocalService.

Because providers do not run as the same user account as the client process, they need to cache the caller’s impersonation token and use it to call CoSetSecurityBlanket on client interfaces.  There are two points to note about this:

·         The provider must call CoSetSecurityBlanket, even if it will not use the interface passed to it.  Failure to do so will result in the interface not being released until COM rundown occurs.

·         Because the provider caches the impersonation token as well as some interfaces on which CoSetSecurityBlanket has been called using the token, the provider host must register for logoff notifications and free the cached token and interfaces for all providers that were in use by the client for which a logoff have been received.  A logon session is only completely ended when all tokens for the session have been closed, so failure to close the cached token and interfaces effectively prevents the session from ending until COM rundown occurs.

The sample provider correctly deals with both points.

Preservation of Add / Remove notification order

Network enumeration protocols generally have a mechanism to order events on the network and detect and discard older information.  Function Discovery providers must take care that OnUpdate events are communicated to the client in the same order that events occurred on the network.

To accomplish this, the sample provider keeps a per-provider queue of notification data and will only deliver one notification to a client at a time.  All the queues are serviced by a thread pool, so multiple clients may concurrently receive notifications.  This is an efficient and scalable approach.

Steps for writing a provider

The Function Discovery provider sample was developed with the goal of serving as the foundation for implementing providers.  It is structured in a way that makes it easy to replace the sample network protocol with a real protocol but preserve the bulk of the code.

To this end, the entire network protocol implementation is contained in DiscoveryProtocol.cpp.  TFunctionInstanceInfo is a class that encapsulates all the work of representing the data that represents a device on the network and turns that information into a function instance.  The bulk of the work in creating a new provider should be focused on the protocol implementation and in modifying TFunctionInstanceInfo.

Places that require attention during implementation are marked with TODO comments.