Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
programming4us
Windows 7

Programming Drivers for the User Mode Driver Framework : Functions for COM Support

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
4/12/2013 3:42:35 PM

The source file Comsup.cpp supplies code that is required to support COM. It implements methods for the IUnknown and IClassFactory interfaces. This section briefly describes what these methods do, but does not show any of the sample code. You can simply copy the Comsup.cpp and Comsup.h files for use in your own drivers, typically without any changes.

1. IUnknown Methods

CUnknown is the base class from which all other classes derive, and it supports the IUnknown interface. Every UMDF driver must implement this class with a constructor method and the IUnknown interface, which includes the AddRef, QueryInterface, QueryIUnknown, and Release methods. Table 1 summarizes the IUnknown methods.

Table 1. IUnknown Method Names
Method NameDescription
CUnknownConstructor, which initializes the reference count for this instance of the CUnknown class to 1.
QueryInterfaceReturns a pointer to the IUnknown interface for the object.
QueryIUnknownPublic helper method that casts a CUnknown pointer to an IUnknown pointer.
AddRefIncrements the reference count for the object.
ReleaseDecrements the object’s reference count and deletes the object if the reference count reaches zero.

2. IClassFactory Interface

The CClassFactory class object implements the IClassFactory interface. The framework invokes methods in this interface to create an instance of the driver callback class. The driver callback class instance is the only callback object that the framework creates; the driver itself creates all other callback objects in response to calls from the framework. Table 2 summarizes the methods in this interface.

Table 2. IClassFactory Methods
MethodDescription
QueryInterfaceReturns a pointer to the requested interface.
QueryIClassFactoryPublic helper method that casts a CClassFactory pointer to an IClassFactory pointer; essentially similar to the IQueryIUnknown method in the IUnknown interface.
CreateInstanceCreates an instance of the driver callback class and returns a pointer to a requested interface for that class.
LockServerMaintains a lock count that indicates whether the driver DLL should remain in memory.

3. Driver CallBack Object

When UMDF gets a pointer to the IClassFactory interface, it calls the CreateInstance method in that interface to create an instance of an object. That method, in turn, calls the CMyDriver::CreateInstance method, which creates and initializes the driver callback object. In general, any CreateInstance method is a factory method that creates an object.

CMyDriver::CreateInstance is defined in the source file Driver.cpp and is straightforward, as the following shows:

HRESULT
CMyDriver::CreateInstance(
   __out PCMyDriver *Driver
)
/*++

   Routine Description:

This static method is invoked to create and initialize a new
instance of the driver class. The caller should arrange for
the object to be released when it is no longer in use.

   Arguments:

      Driver - a location to store a referenced pointer to
      the new instance

   Return Value:

      S_OK if successful, or error otherwise

--*/
{
PCMyDriver driver;
HRESULT hr;

//
// Allocate the callback object
//
driver = new CMyDriver();

if (NULL == driver)
{
return E_OUTOFMEMORY;
   }

   //
   // Initialize the callback object
   //
   hr = driver->Initialize();
if (SUCCEEDED (hr))
{
       //
       // Store a pointer to the new, initialized object in
       // the output parameter.
       //
       *Driver = driver;
   }
   else
   {

       //
       // Release the reference on the driver object so that
       // it will delete itself
       //
       driver->Release();
}
return hr;
}

					  

This method allocates and creates an instance of the driver callback object, and then calls the initialize method to initialize the object. The Skeleton driver object requires no initialization, so the Initialize method is a stub (and so is not shown here). CreateInstance returns a pointer to the new driver callback object and releases its reference on this object before returning.

Every UMDF driver must implement the IDriverEntry interface on the driver callback object. This interface supports methods to initialize the driver, perform tasks when one of the driver’s devices is added to the system, and prepare the driver for unloading, just before DllMain.DetachProcess is called. The driver.cpp file contains code that implements IDriverEntry.

IDriverEntry defines three methods: OnDeviceAdd, OnInitialize, and OnDeInitialize. In the Skeleton driver, the OnInitialize and OnDeInitialize methods are stubs.

When one of the driver’s devices is added, UMDF calls the OnDevice method, passing as parameters pointers to the IWdfDriver and IWdfDeviceInitialize interfaces, which the framework implements. The Skeleton driver does not support physical hardware, so its OnDeviceAdd method is minimal:

HRESULT
CMyDriver::OnDeviceAdd{
   __in IWDFDriver *FxWdDriver,
   __in IWDFDeviceInitialize *FxDeviceInit
}
/*++
   Routine Description:

The FX invokes this method to install our driver on a device
stack. This method creates a device callback object, then
calls the Fx to create an Fx device object and associate the
new callback object with it.

   Arguments:

   FxWdfDriver - the Fx driver object.
   FxDeviceInit - the initialization information for the
   device.

   Return Value:
   Status
--*/
{
   HRESULT hr;

   PCMyDevice device = NULL;

   //
   // TODO: Here is where to do any per device initialization
   // (reading settings from the registry, for example) that is
   // required before you create the device callback object.
   // You can leave initialization of the device callback
   // object itself to the device event handler.
   //


//
// Create a new instance of our device callback object
//

hr = CMyDevice::CreateInstance(FxWdfDriver, FxDeviceInit,
   &device);

   //
   // TODO: Change any per device settings that the object
   // exposes before you call Configure to complete its
   // initialization.
   //
   //
   // If that succeeded then call the device's construct
   // method. The construct method can create queues or
   // other structures that are required for the device object.

   if (S_OK == hr)
   {
       hr = device->Configure();
   }

   //
   // Release the reference on the device callback object
   // now that it's associated with an fx device object.
   //

   if (NULL != device)
{
       device->Release();
   }

   return hr;
}

					  

The Skeleton driver’s OnDeviceAdd method calls the CreateInstance method on the CMyDevice class to instantiate the device callback object. It passes the pointers to the IWdfDeviceInitialize and IWdfDriver interfaces so that CreateInstance can use these UMDF defined interfaces to create and initialize the device object.

By convention, a CreateInstance method in the sample represents a factory for building objects of a particular type.

4. Device CallBack Object

The device callback object represents the device in the driver. The driver creates an instance of this object when its IDriverEntry::OnDeviceAdd method is called. The driver implements the CreateInstance, Initialize, Configure, and QueryInterface methods for the device callback object.

The code for the device callback object for the Skeleton driver is in the Device.cpp. This module includes the header files Internal.h, which contains driver-specific internal definitions, and Device.tmh, which defines tracing information for Event Tracing for Windows (ETW).

4.1. CreateInstance Method

A driver’s IDriverEntry::OnDeviceAdd method calls IDeviceObject::CreateInstance to create an instance of the device callback object. This method simply allocates and initializes an instance of the device callback object as follows:

HRESULT
CMyDevice::CreateInstance(
   __in IWDFDriver *FxDriver,
   __in IWDFDeviceInitialize *FxDeviceInit,
   __out PCMyDevice *Device
   )
/*++

   Routine Description:

   This method creates and initializes an instance of the
   skeleton Driver's device callback object.

   Arguments:

   FxDeviceInit - the settings for the device.
   Device - a location to store the referenced pointed to the
            device object.
   Return Value:

   Status
--*/
{
   PCMyDevice device;
   HRESULT hr;

   //
   // Allocate a new instance of the device class.
   //

   device = new CMyDevice();

   if (NULL == device)
  {
      Return E_OUTOFMEMORY;
   }
   //
   // Initialize the instance.
   //

   hr = device->Initialize(FxDriver, FxDeviceInit);

   if (S_OK == hr)
   {
      *Device = device;
   }
   else
   {
      device->Release();
   }

   return hr;
}

					  

When UMDF calls the OnDeviceAdd method, it passes a pointer to the IWdfDriver interface and a pointer to the IWdfDeviceInitialize interface. These interfaces provide methods through which the driver can initialize per-device-object settings and create a device callback object. OnDeviceAdd passes these pointers to CreateInstance, which in turn passes them as parameters to the Initialize method to initialize the instance.

4.2. Initialize Method

The Initialize method of the device callback object does exactly what its name implies: It initializes the callback object. It also calls the framework to create the framework’s device object.

The initialize method receives a handle to the framework’s IWdfDeviceInitialize interface and stores it in FxDeviceInit. It uses this handle to call methods on that interface to initialize certain device characteristics that must be set before the framework’s device object is created. Such characteristics include the synchronization (locking) model and the Plug and Play features. They also indicate whether the driver is a filter driver, whether the driver controls device power policy, and whether the framework should forward or fail certain request types. The driver must set these values before creating the framework’s device object because they determine which callbacks the framework initializes for the device object. The following code shows how to set the needed values:

HRESULT
CMyDevice::Initialize(
__in IWDFDriver      *FxDriver,
__in IWDFDeviceInitialize   *FxDeviceInit
)
/*++

   Routine Description:

   This method initializes the device callback object and
   creates the partner device object.

   The method should perform any device specific configuration
   that:
Could fail (these can't be done in the constructor)
must be done before the partner object is created-or-
can be done after the partner object is created and
isn't influenced, by any device level parameters that the
parent (the driver in this case) might set.

   Arguments:

   FxDeviceInit - the settings for this device.

   Return Value:

   status.

--*/
{
   IWDFDevice   *fxDevice;
   HRESULT      hr;

   //
   // Configure things like the locking model before we
   // create our partner device.
   //

   //
   // TODO: Set her locking mode. The skeleton uses device level
   //             locking, but you can choose "none" as well.
   //

   FxDeviceInit->SetLockingConstraint (WdfDeviceLevel);

   //
   // TODO: If you're writing a filter driver indicate that
   // here.
   //
   // FxDeviceInit->SetFilter();
   //

   //
   // TODO: Any per-device initialization which must be done
   //               before creating the partner object.
   //
   //
   // Create a new FX device object and assign the new
   // callback object to handle any device level events that
   // occur.
   //

   //
   // QueryIUnknown references the IUnknown interface that it
   // returns (which is the same as referencing the device). We
   // pass that to CreateDevice, which takes its own reference
   // if everything works.
   //

   {
       IUnknown *unknown = this->QueryIUnknown();

       hr = FxDriver->CreateDevice(FxDeviceInit, unknown,
             &fxDevice);

       unknown->Release();
   }

   //
   // If that succeeded, then set our FxDevice member variable.
   //

   if (S_OK == hr)
   {
       m_FxDevice = fxDevice;
       //
       // Drop the reference we got from CreateDevice. Since
       // this object is partnered with the framework object
       // they have the same lifespan. There is no need for an
       // additional reference.
       //
   }

   return hr;
}

					  

The Initialize method first sets the locking model for the driver by calling the SetLockingConstraint method of the IWdfDeviceInitialize interface. The locking model determines whether the framework calls the driver’s callback methods concurrently on a per-device-object level or not at all. The Skeleton driver sets WdfDeviceLevel, which means that the framework synchronizes calls to methods at the device object level or lower. Therefore, the driver does not require code to synchronize access to shared data in such methods.

Device-level locking applies to methods on the IWdfIoQueue interface, the IFileCallbackCleanup interface, and the IFileCallbackClose interface. The IWdfIoQueue interface is implemented by the I/O queue object, and the IFileCallbackCleanup and IFileCallbackClose interfaces are implemented by the device object.

The Skeleton does not support physical hardware, so it does not set any Plug and Play characteristics. If it supported an actual Plug and Play device, it might also have to specify whether the device is ejectable, lockable, and other similar settings.

After the driver has set the device characteristics, it can call UMDF to create the framework’s device object. The IWdfDriver::CreateDevice method takes a pointer to the IWdfDeviceInitialize interface that was passed to the driver, a pointer to the driver’s device callback object, and a location in which to return the handle to the created framework device object. To get a pointer to the device callback object, the driver calls QueryIUnknown on the current interface. It then passes this pointer when it calls CreateDevice. Calling QueryIUnknown adds a reference on the IUnknown interface it returns—in this case, the driver’s callback object interface. After the CreateDevice method returns, the driver releases this reference.

If UMDF successfully creates the framework device object, the driver initializes the variable m_FxDevice to hold the pointer to the returned interface. It then calls the Release method to release the reference that the CreateDevice method added on the returned interface. The m_FxDevice interface has the same lifetime as the framework’s IWdfDevice interface, so this reference is not required to ensure that the interface persists for the driver.

4.3. Configure Method

The Configure method handles tasks that are related to configuration after the framework and device callback objects have been created. The Skeleton driver’s OnDeviceAdd callback invokes the Configure method after CreateInstance has successfully returned.

In the Skeleton driver, Configure is a stub. In a driver that handles I/O requests, this method would create and configure I/O queues and queue callback objects.

4.4. QueryInterface Method

The QueryInterface method returns a pointer to any of the device callback object’s interfaces. It takes the interfaceId as an input parameter and returns a pointer to the interface.

The Skeleton driver does not implement any of the event callback interfaces for the device object because it does not support actual hardware. Therefore, it simply returns the pointer to the IUnknown interface of the base class CUnknown, as follows:

return CUnknown::QueryInterface(InterfaceId, object);

In a driver that supports actual hardware, this method should validate the input interfaceId and return a pointer to the requested interface.

Other -----------------
- Customizing Windows 7 : Customize the Taskbar
- Microsoft Excel 2010 : Using Formulas - Troubleshooting Formulas
- Microsoft Excel 2010 : Using Formulas - Table References in Formulas, Using Array Formulas
- Microsoft Word 2010 : Creating Desktop Publishing Documents - Adding a Watermark
- Microsoft Word 2010 : Creating Desktop Publishing Documents - Adding Desktop Publishing Effects
- Customizing Windows 7 : Customize the Start Menu
- Customizing Windows 7 : Change the Windows 7 Color Scheme
- Customizing Windows 7 : Set the Screen Saver
- Customizing Windows 7 : Set Up a Desktop Slide Show
- Customizing Windows 7 : Change the Desktop Background
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server