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

Plug and Play and Power Management : WMI Request Handler, Synchronization Issues, Security

- Windows 10 Product Activation Keys Free 2019
- How to active Windows 8 without product key
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
6/14/2013 5:18:59 PM

1. WMI Request Handler

WMI provides a way for drivers to export information to other components. Drivers typically use WMI to enable the following:

  • User mode applications to query and set device-related information, such as time-out values.

  • An administrator with the necessary privileges to control a device by running an application on a remote system.

A driver that supports WMI registers as a provider of information and registers one or more instances of that information. Each WMI provider is associated with a particular Globally Unique Identifier (GUID). Another component can register with the same GUID to consume the data from the instances. User mode components request WMI instance data by calling COM functions, which the system translates into IRP_MJ_SYSTEM_CONTROL requests and sends to the target providers.

KMDF supports WMI requests through its WMI request handler, which provides the following features for drivers:

  • A default WMI implementation. Drivers that do not provide WMI data are not required to register as WMI providers; KMDF handles all IRP_MJ_SYSTEM_CONTROL requests.

  • Callbacks on individual instances, rather than just at the device object level, so that different instances can behave differently.

  • Validation of buffer sizes to ensure that buffers that are used in WMI queries meet the size requirements of the associated provider and instance.

The default WMI implementation includes support for the check boxes on the Power Management tab of Device Manager. These check boxes enable a user to control whether the device can wake the system and whether the system can power down the device when it is idle. WDM drivers must include code to support the WMI controls that map to these check boxes, but KMDF drivers do not require such code. If the driver enables this feature in its power policy options, KMDF handles these requests automatically.

The driver enables buffer size validation when it configures a WMI provider object (WDFWMIPROVIDER). In the WDF_WMI_PROVIDER_CONFIG structure, the driver can specify the minimum size of the buffer that is required for the provider’s EvtWmiInstanceQueryInstance and EvtWmiInstanceSetInstance callbacks. If the driver specifies such a value, KMDF validates the buffer size when the IRP_MJ_SYSTEM_CONTROL request arrives and calls the callbacks only if the supplied buffer is large enough. If the driver does not configure a buffer size—because the instance size is either dynamic or is not available when the provider is created—the driver should specify zero for this field and the callbacks themselves should validate the buffer size.

When KMDF receives an IRP_MJ_SYSTEM_CONTROL request that is targeted at a KMDF driver, it proceeds as follows:

  • If the driver has registered as a WMI provider and registered one or more instances, the WMI handler invokes the callbacks for those instances as appropriate.

  • If the driver has not registered any WMI instances, the WMI handler responds to the request by providing the requested data (if it can), passing the request to the next lower driver, or failing the request.

Like all KMDF objects, WMI instance objects (WDFWMIINSTANCE) have a context area. A driver can use the context area of a WDFWMIINSTANCE object as a source of read-only data, thus enabling easy data collection with minimal effort. A driver can delete WDFWMIINSTANCE objects any time after their creation.

WMI callbacks are not synchronized with the Plug and Play and power management state of the device. Therefore, when WMI events occur, KMDF calls a driver’s WMI callbacks even if the device is not in the working state.

2. Synchronization Issues

Because Windows is a pre-emptive, multitasking operating system, multiple threads can try to access shared data structures or resources concurrently and multiple driver routines can run concurrently. To ensure data integrity, all drivers must synchronize access to shared data structures. Correctly implementing such synchronization can be difficult in WDM drivers.

For KMDF drivers, ensuring proper synchronization requires attention to several areas:

  • The number of concurrently active requests that are dispatched from a particular queue.

  • The number of concurrently active callbacks for a particular object.

  • The driver utility functions that access object-specific data.

  • The IRQL at which an object’s callbacks run.

The dispatch method for an I/O queue controls the number of requests from the queue that can be concurrently active in the driver. Limiting concurrent requests does not, however, resolve all potential synchronization issues. Concurrently active callbacks on the same object might require access to shared object-specific data, such as the information that is stored in the object context area. Similarly, driver utility functions might share object-specific data with callbacks. Furthermore, a driver must be aware of the IRQL at which its callbacks can be invoked. At DISPATCH_LEVEL and above, drivers must not access pageable data and thread pre-emption does not occur.

KMDF simplifies synchronization for driver by providing automatic synchronization of many callbacks. Calls to most PDO, FDO, Plug and Play, and power event callback functions are synchronized so that only one such callback function is invoked at a time for each device. These callback functions are called at IRQL PASSIVE_LEVEL. Note, however, that calls to the EvtDeviceSurpriseRemoval, EvtDeviceQueryRemove, and EvtDeviceQueryStop callbacks are not synchronized with the other callbacks and so occur while the device is changing power state or is not in the working state.

For other types of callbacks—primarily I/O related callbacks—the driver can specify the synchronization scope (degree of concurrency) and the maximum execution level (IRQL).

KMDF provides the following configurable synchronization features:

  • Synchronization scope

  • Execution level

  • Locks

Although implementing synchronization is much less complicated in KMDF drivers than in WDM drivers, you should nevertheless be familiar with the basics of Windows IRQL, synchronization, and locking.

2.1. Synchronization Scope

KMDF provides configurable concurrency control, called synchronization scope, for the callbacks of several types of objects. An object’s synchronization scope determines whether KMDF invokes certain event callbacks on the object concurrently.

KMDF define the following synchronization scopes:

  • Device scope means that KMDF does not call certain I/O event callbacks concurrently for an individual device object or any file objects or queues that are children of the device object. Specifically, device scope applies to the following event callbacks: EvtDeviceFileCreate, EvtFileCleanup, EvtFileClose, EvtIoDefault, EvtIoRead, EvtIoWrite, EvtIoDeviceControl, EvtIoInternalDeviceControl, EvtIoStop, EvtIoResume, EvtIoQueueState, EvtIoCanceledOnQueue, and EvtRequestCancel.

    However, callbacks for different device objects that were created by the same driver object can be called concurrently. Internally, KMDF creates a synchronization lock for each device object. To implement device synchronization scope, KMDF acquires this lock before invoking any of the device callbacks.

  • Queue scope means that KMDF does not call certain I/O callbacks concurrently on a per-queue basis. If a Kernel Mode Driver specifies queue scope for a device object, some callbacks for the device object and its queues can run concurrently. However, the following callbacks for an individual queue object are not called concurrently: EvtIoDefault, EvtIoRead, EvtIoWrite, EvtIoDeviceControl, EvtIoInternalDeviceControl, EvtIoStop, EvtIoResume, EvtIoQueueState, EvtIoCanceledOnQueue, and EvtRequestCancel. If the driver specifies queue scope, KMDF creates a synchronization lock for each queue object and acquires this lock before invoking any of the listed callbacks.

  • No scope means that KMDF does not acquire any locks and can call any event callback concurrently with any other event callback. The driver must create and acquire all its own locks. By default, KMDF uses no scope. A driver must “opt in” to synchronization for its objects by setting device scope explicitly.

Each KMDF object inherits its scope from its parent object (WdfSynchronizationScopeInheritFromParent). The parent of each WDFDEVICE object is the WDFDRIVER object, and the default value of the synchronization scope for the WDFDRIVER object is WdfSynchronizationScopeNone. Thus, a driver must explicitly set the synchronization scope on its objects to use frameworks synchronization.

A driver can change the scope by setting a value in the WDR_OBJECT_ATTRIBUTES structure when it creates the object. Because scope is inherited, a driver can easily set synchronization for most of its objects by setting the scope for the device object, which is the parent to most KMDF objects. 

For example, to set the concurrency for its I/O callback functions, a driver sets the SynchronizationScope in the WDF_OBJECT_ATTRIBUTES for the device object that is the parent to the I/O queues. If the driver sets device scope (WdfSynchronizationScopeDevice), KMDF calls only one I/O callback function at a time across all the queues. To use queue scope, the driver sets WdfSynchronizationScopeQueue for the device object and WdfSynchronizationScopeInheritFromParent for the queue object. Queue scope means that only one of the listed callback functions can be active for the queue at any time. A driver cannot set concurrency separately for each queue. Restricting the concurrency of I/O callbacks can help to manage access to shared data in the WDFQUEUE context memory.

By default, a file object inherits its scope from its parent device object. Attempting to set queue scope for a file object causes an error. Therefore, drivers that set queue scope for a device object must manually set the synchronization scope for any file objects that are its children. The best practice for file objects is to use no scope and to acquire locks in the event callback functions when they are required to synchronize access.

If a driver sets device scope for a file object, it must also set the passive execution level for the object, as described in the upcoming section “Execution Level.” The reason is that the framework uses spin locks (which raise IRQL to DISPATCH_LEVEL) to synchronize access to objects with device scope. However, the EvtDeviceFileCreate, EvtFileClose, and EvtFileCleanup callbacks run in the caller’s thread context and use pageable data, so they must be called at PASSIVE_LEVEL. At PASSIVE_LEVEL, the framework uses a FAST_MUTEX instead of a spin lock for synchronization.

Interrupt objects are the children of device objects. KMDF acquires the interrupt object’s spin lock at device interrupt request level (DIRQL) to synchronize calls to the EvtInterruptEnable, EvtInterruptDisable, and EvtInterruptlsr callbacks. A driver can also ensure that calls to its interrupt object’s EvtInterruptDpc callback are serialized with other callbacks on the parent device object.

Deferred Procedure Call (DPC), timer, and work item objects can be children of device objects or of queue objects. To simplify a driver’s implementation of callbacks for DPCs, timers, and work items, KMDF enables the driver to synchronize their callbacks with those of either the associated queue object or the device object (which might be the parent or the grandparent of the DPC, timer, or work item).

A driver sets callback synchronization on interrupt, DPC, timer, and work item objects by setting AutomaticSerialization in the object’s configuration structure during object creation.

2.2. Execution Level

KMDF drivers can specify the maximum IRQL at which the callbacks for driver, device, file, and general objects are invoked. Like synchronization scope, execution level is an attribute that the driver can configure when it creates the object. KMDF supports the following execution levels:

  • Default execution level indicates that the driver has placed no particular constraints on the IRQL at which the callbacks for the object can be invoked. For most objects, this is the default.

  • Passive execution level (WdfExecutionLevelPassive) means that all event callbacks for the object occur at PASSIVE_LEVEL. If necessary, KMDF invokes the callback from a system worker thread. Drivers can set this level only for device and file object. Typically, a driver should set passive execution level only if the callbacks access pageable code or data or call other functions that must be called at PASSIVE_LEVEL.

    Callbacks for events on file objects (WDFFILEOBJECT type) are always called at PASSIVE_LEVEL because these functions must be able to access pageable code and data.

  • Dispatch execution level (WdfExecutionLevelDispatch) means that KMDF can invoke the callbacks from any IRQL up to and including DISPATCH_LEVEL. This setting does not force all callbacks to occur at DISPATCH_LEVEL. However, if a callback requires synchronization, KMDF uses a spin lock, which raises IRQL to DISPATCH_LEVEL. Drivers can set dispatch execution level but nevertheless ensure that some tasks are performed at PASSIVE_LEVEL by using work items (WDFWORKITEM objects). Work item callbacks are always invoked at PASSIVE_LEVEL in the context of a system thread.

By default, an object inherits its execution level from its parent object. The default execution level for the WDFDRIVER object is WdfExecutionLevelDispatch.

2.3. Locks

In addition to internal synchronization, synchronization scope, and execution level, KMDF provides the following additional ways for a driver to synchronize operations:

  • Acquire the lock that is associated with a device or queue object.

  • Create and use additional, KMDF-defined, driver-created lock objects.

Driver code that runs outside an event callback sometimes must synchronize with code that runs inside an event callback. To accomplish this synchronization, KMDF provides methods (WdfObjectAcquireLock and WdfObjectReleaseLock) through which the driver can acquire and release the internal framework lock that is associated with a particular device or queue object.

Given the handle to a device or queue object, WdfObjectAcquireLock acquires the lock that protects that object. After acquiring the lock, the driver can safely access the object context data or properties and can perform other actions that affect the object. If the driver has set WdfExecutionLevelPassive for the object (or if the object has inherited this value from its parent), KMDF uses a PASSIVE_LEVEL synchronization primitive (a fast mutex) for the lock. If the object does not have this constraint, use of the lock raises IRQL to DISPATCH_LEVEL and, while the driver holds the lock, it must not touch pageable code or data or call functions that must run at PASSIVE_LEVEL.

KMDF also defines two types of lock objects:

  • Wait locks (WDFWAITLOCK) synchronize access from code that runs at IRQL PASSIVE_LEVEL or APC_LEVEL. Such locks prevent thread suspension. Internally, KMDF implements wait locks by using kernel dispatcher events, so each wait lock is associated with an optional time-out value (as are the kernel dispatcher events). If the time-out value is zero, the driver can acquire the lock at DISPATCH_LEVEL.

  • Spin locks (WDFSPINLOCK) synchronize access from code that runs at any IRQL up to DISPATCH_LEVEL. Because code that holds a spin lock runs at DISPATCH_LEVEL, it cannot take a page fault and therefore must not access any pageable data. The WDFSPINLOCK object keeps track of its acquisition history and ensures that deadlocks cannot occur. Internally, KMDF uses the system’s spin lock mechanisms to implement spin lock objects.

As with all other KMDF objects, each instance of a lock object can have its own context area that holds lock-specific information.

Drivers that do not use the built-in frameworks locking (synchronization scope, execution level, and AutomaticSerialization) can implement their own locking schemes by using KMDF wait locks and spin locks. Drivers that use frameworks locking can use KMDF wait locks and spin locks to synchronize access to data that is not associated with a particular device or queue object. In general, drivers can rely on frameworks locking while communicating with their own hardware and calling within their own code. Drivers that communicate with other drivers generally must implement their own locking schemes.

2.4. Interaction of Synchronization Mechanisms

Synchronization scope and execution level interact because of the way in which KMDF implements synchronization. By default, KMDF uses spin locks, which raise IRQL to DISPATCH_LEVEL, to synchronize callbacks. Therefore, if the driver specifies device or queue synchronization scope, its device and queue callbacks must be able to run at DISPATCH_LEVEL.

If the driver sets the WdfExecutionLevelPassive constraint for a parent device or queue object, KMDF uses a fast mutex instead of a spin lock. In this case, however, KMDF cannot automatically synchronize callbacks for timer and DPC child objects (including the DPC object that is associated with the interrupt object) because DPC and timer callbacks, by definition, always run at DISPATCH_LEVEL. Trying to create any of these objects with AutomaticSerialization fails if the WdfExecutionLevelPassive constraint is set for the parent object.

Instead, the driver can synchronize the event callbacks for these objects by using a WDFSPINLOCK object. The driver acquires and releases the lock manually by the KMDF locking methods WdfSpinLockAcquire and WdfSpinLockRelease.

Alternatively, the driver can perform whatever processing is required within the DPC or timer callback and then queue a work item that is synchronized with the callbacks at PASSIVE_LEVEL to perform further detailed processing.

3. Security

KMDF is designed to enhance the creation of secure driver by providing:

  • Safe defaults

  • Parameter validation

  • Counted Unicode strings

  • Safe device naming techniques

3.1. Safe Defaults

Unless the driver specifies otherwise, KMDF provides access control lists (ACLs) that require Administrator privileges for access to any exposed driver constructs, such as names, device IDs, WMI management interfaces, and so forth. In addition, KMDF automatically handles I/O requests for which a driver has not registered by completing them with STATUS_INVALID_DEVICE_REQUEST.

3.2. Parameter Validation

One of the most common driver security problems involves improper handling of buffers in IOCTL requests, particularly requests that specify neither buffered nor direct I/O (METHOD_NEITHER). By default, KMDF does not grant drivers direct access to user mode buffer pointers, which is inherently unsafe. Instead, it provides methods for accessing the user mode buffer pointer that require probing and locking, and it provides methods to probe and lock the buffer for reading and writing.

All KMDF DDIs that require a buffer take a length parameter that specifies a required minimum buffer size. I/O buffers use the WDFMEMORY object, which provides data access methods that automatically validate length and determine whether the buffer permissions allow write access to the underlying memory.

3.3. Counted UNICODE Strings

To help prevent string handling errors, KMDF DDIs use only counted PUNICCODE_STRING values. To aid drivers in using and formatting UNICODE_STRING values, the safe string routines in ntstrsafe.h have been updated to take PUNICODE_STRING parameters.

3.4. Safe Device Naming Techniques

KMDF device objects do not have fixed names. KMDF sets FILE_AUTOGENERATED_DEVICE_NAME in the device’s characteristics for PDOs, according to the WDM requirements.

KMDF also supports the creation and registration of device interfaces on all Plug and Play devices and manages device interfaces for its drivers. Whenever possible, you should use device interfaces instead of the older fixed name/symbolic link techniques.

However, if legacy applications require that a device has a name, KMDF enables you to name a device and to specify its security description definition language (SDDL). The SDDL controls which users can open the device.

By convention, a fixed device name is associated with a fixed symbolic link name (such as \DosDevices\MyDeviceName). KMDF supports the creation and management of a symbolic link and automatically deletes the link when the device is destroyed. KMDF also enables the creation of a symbolic link name for an unnamed Plug and Play device.

Other -----------------
- Plug and Play and Power Management : Device Enumeration and Startup (part 2) - Device Power-Down and Removal
- Plug and Play and Power Management : Device Enumeration and Startup (part 1)
- Evaluating Applications for Windows 7 Compatibility : Deploying XP Mode
- Configuring Startup and Troubleshooting Startup Issues : The Process of Troubleshooting Startup (part 3) - Troubleshooting Startup Problems After Logon
- Configuring Startup and Troubleshooting Startup Issues : The Process of Troubleshooting Startup (part 2) - Startup Troubleshooting After the Starting Windows Logo Appears
- Configuring Startup and Troubleshooting Startup Issues : The Process of Troubleshooting Startup (part 1) - Startup Troubleshooting Before the Starting Windows Logo Appears
- Configuring Startup and Troubleshooting Startup Issues : Important Startup Files, How to Configure Startup Settings
- Managing Windows 7 : Managing Navigational and Editing Flicks
- Managing Windows 7 : Configuring a Pen or Touch Computer, Managing Pen Settings
- Configuring Startup and Troubleshooting Startup Issues : Understanding the Startup Process
 
 
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
Popular tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 windows Phone 7 windows Phone 8
programming4us programming4us
Celebrity Style, Fashion Trends, Beauty and Makeup Tips.
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server