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

Using COM to Develop UMDF Drivers : Using UMDF COM Objects

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
4/29/2013 4:06:20 PM

A process that uses a COM object is known as a COM client. Both UMDF drivers and the UMDF run-time function as COM clients. UMDF drivers interact with UMDF run time by using UMDF-provided COM objects. For example, the UMDF device object represents the device, and drivers can use the object for tasks such as setting or retrieving the device’s Plug and Play state.

The UMDF run time interacts with drivers through the drive-provided COM-based callback objects. For example, a driver can create one or more queue callback objects to handle I/O requests. The UMDF run time uses those objects to pass request to the driver.

After you get a pointer to an interface, you can call the interface methods by using the same syntax that is used for a pointer to a C++ method. For example, if pWdfRequest is a pointer to an IWDFloRequest interface, the following code is an example of how to invoke the interface’s Send method:

HRESULT hr;

hr = pWdfRequest- >Send( m_pIUsbTargetDevice,

                          WDR_REQUEST_SEND_OPTION_SYNCHRONOUS,

                             0);

The method’s return value is an HRESULT, a typical return type for COM methods. HRESULT is similar to the NTSTATUS type that Kernel Mode Drivers use as a return value and is used in much the same way. It is important not to think of HRESULT as error values. Methods sometimes have multiple return values for success as well as for failure. You can determine the result of calling a method by comparing the returned HRESULT to the list of possible values in the reference documentation. However, be aware that these lists are not always complete. Use the error-checking macros that are discussed shortly to ensure that you do not miss a possible return value.

You can also test an HRESULT for simple success or failure. COM provides two macros for that purpose that work much like the NT_SUCCESS macro. For an HRESULT return value of hr:

  • FAILED(hr) returns TRUE for failure and FALSE for success.

  • SUCCEEDED(hr) returns FALSE for failure and TRUE for success.

Although NTSTATUS and HRESULT are similar, they are not interchangeable. Occasionally, information in the form of an NTSTATUS value must be returned as an HRESULT. In that case, you can use the HRESULT_FROM_NT macro to convert the NTSTATUS into an equivalent HRESULT. Do not use this macro for an NTSTATUS value of STATUS_SUCCESS. In that case, return the S_OK HRESULT value.

1. Obtaining an Interface on a UMDF Object

You can obtain an interface on a UMDF object in one of three ways:

  • The UMDF run time passes an interface pointer in to one of the driver’s callback methods.

  • The driver creates a new WDF object by calling a UMDF object creation method.

  • The driver calls IUnknown::QueryInterface to request a new interface from an existing WDF object.

You can also receive an Interface through a Driver Method. The first case is the simplest. For example, when the UMDF run time calls a driver’s IDriverEntry::OnDeviceAdd method, it passes a pointer to the device object’s IWDFDriver interface.

The following example shows this activity:

HRESULT CMyDriver::OnDeviceAdd(
            __in IWDFDriver *FxWdfDriver,
            __in IWDFDeviceInitialize *FxDeviceInit
            )
{
   // Install the driver in the device stack
}

You can then use FxWdfDriver to access the methods on the driver object’s IWDFDriver interface. Do not release FxWdfDriver when you are finished with it. The caller ensures that the object remains valid during the scope of the method call.

Another way to create a WDF object is by calling the appropriate UMDF object creation method. For example, to create a request object, call the UMDF device object’s IWDFDevice::CreateRequest method. If you look at the UMDF reference in the Windows Driver Kit (WDK), you will find syntax like that for IWDFDevice::CreateRequest:

HRESULT CreateRequest(
           IN IUnknown*  pCallbackInterface,
           IN IWdfObject*  pParentObject,
           OUT IWDFIoRequest**  ppRequest
           );

ppRequest is an OUT parameter that provides an address at which the CreateRequest method can store a pointer to the newly created request object’s IWDFObject interface. The following procedure and sample show how to handle such parameters, by using a call to CreateRequest by the UMDF’s fx2_driver sample as an example.

We would declare a variable, pWdfRequest, to hold a pointer to IWDFloRequest.

Then we would pass a reference to pWdfRequest to CreateRequest as follows:

IWDFIoRequest *pWdfRequest = NULL;
...
hr = m_FxDevice- >CreateRequest ( NULL, NULL, &pWdfRequest);

When CreateRequest returns, pWdfRequest holds a pointer to an IWDFIoRequest interface. When the caller has finished with pWdfRequest, it should release the interface pointer by calling IUnknown::Release.

Another approach is to call QueryInterface to request a new interface. Objects can expose more than one interface. Sometimes, you have a pointer to one interface and need a pointer to another interface on the same object. In that case, call IUnknown::QueryInterface to request the desired pointer. Pass QueryInterface the IID of the desired interface and the address of the interface pointer, and QueryInterface returns the requested pointer. When the caller is finished with the interface pointer, the caller should release it. The following is an example:

VOID CMyDevice::StartTarget ( IWDFIoTarget * pTarget)
{
   IWDFIoTargetStateManagement * pStateMgmt = NULL;
   HRESULT hrQI  =
           pTarget->QueryInterface(IID_PPV_ARGS(&pStateMgmt));
   ...
}

This example requests an IWDFIoTargetStateManagement interface pointer from the UMDF’s I/O target object. It uses the IID_PPV_ARGS macro—declared in objbase.h—which takes an interface pointer and produces the correct arguments for QueryInterface.

QueryInterface belongs to the IUnknown interface. However, as shown earlier, there is no need to have an explicit pointer to an object’s IUnknown interface to call QueryInterface. All interfaces inherit from IUnknown, so you can use any interface to call QueryInterface.

2. Reference Counting

Unlike C++ objects, a client does not directly manage the lifetime of a COM object. Instead, a COM object maintains a reference count on itself. When a client creates a new object with an object-creation method, the object has a reference count of 1. Each time the client requests an additional interface on the object, the object increments the reference count. When a client is finished with an interface, it releases the interface pointer, which decrements the reference count. When all the interface pointers on the object have been released, the reference count is zero and the object destroys itself.

You must be extremely careful about handling reference counts when you use or implement COM objects. Although clients do not explicitly destroy COM objects, there is no garbage collection to take care of the problem automatically as there is with managed code. A common mistake is to fail to release an interface. In that case, the reference count never goes to zero and the object remains in memory indefinitely. Conversely, releasing the interface pointer too many times causes the object to be destroyed prematurely, which can cause a crash. Failure to correctly manage reference counts is a common cause of memory leaks in COM-based applications, along with a variety of other problems. Even worse, bugs that are caused by mismanaged reference counts can be very difficult to locate.

The following are some basic rules for reference counting:

  • Release any interface pointer that is passed to you as an OUT parameter when you are finished with it by calling IUnknown::Release. Do not release pointers that are passed as IN parameters. A common practice to ensure that all interface pointers are properly released is to initialize all pointers to NULL. Then set them to NULL again when they are released. That convention allows you to test all the interface pointers in your cleanup code; any non-NULL pointers are still valid and should be released.

  • The reference count is usually incremented for you. The main exception is when you make a copy of an interface pointer. In that case, call IUnknown::AddRef to explicitly increment the object’s reference count. You must then release the pointer when you are finished.

  • When you discover that the driver has reference counting problems, do not attempt to fix them by simply adding calls to AddRef or Release. Make sure that the driver is acquiring and releasing references according to the rules. Otherwise, you may find, for example, that the Release calls that you added to solve a memory leak occasionally deletes the object prematurely and instead causes a crash.

As with QueryInterface, you do not need a pointer to the object’s IUnknown interface to call AddRef or Release. You can call these methods from any of the object’s interfaces.

Other -----------------
- Using COM to Develop UMDF Drivers : Getting Started - COM Fundamentals, HRESULT
- Repairing and Removing Programs : Removing Programs, Returning to a Previous Version, Turning Windows Features On and Off
- Repairing and Removing Programs : Changing and Repairing Programs
- Windows 7 Mobility Features : Power Management (part 2) - Power Options Control Panel
- Windows 7 Mobility Features : Power Management (part 1) - Battery Meter, Power Plans
- Windows 7 Mobility Features : Working with the Windows 7 User Interface
- Microsoft Access 2010 : Viewing the Design of a Report
- Microsoft Access 2010 : The AutoReport Feature and the Report Wizard
- Microsoft PowerPoint 2010 : Finalizing Your Slide Show - Setting Up a Slide Show
- Microsoft PowerPoint 2010 : Finalizing Your Slide Show - Reviewing Your Presentation
 
 
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