haihongyuan.com
海量文库 文档专家
全站搜索:
您现在的位置:首页 > 幼儿教育 > 育儿理论经验育儿理论经验

育儿宝典:[3]七到八个月宝宝菜肉粥制作

发布时间:2014-02-22 19:32:22  

育儿知识 http://www.pangbaba.cc

How to Develop a UMDF Driver Part 1

Outline
Architectural Goals Architectural Description
Core components
Driver Manager, Reflector, Host Process, and Drivers

Driver startup and teardown I/O flow Layered drivers

Driver Programming Model
WDF object model COM-lite UMDF DDIs

Goals
An understanding of UMDF infrastructure An understanding of the UMDF DDIs and how they are structured

Architectural Goals
Stability
Driver failures should NOT bring down the system

Build on Windows NT I/O model
Applications are transparent to driver runtime environment – User or Kernel mode Asynchronous, layered drivers, and packet based Integrate into PnP for device installs, driver load/unload

Security
Driver failures should NOT compromise the system Driver runs in “LocalService” account

Shared model between KMDF and UMDF
Shared model != same DDIs or data structures

Architectural Block Diagram
Host Process Application(s) Driver Manager UM Driver Host Process UM Driver
WinSock

User Kernel

Reflector Windows Kernel (I/O Mgr, PnP)
Provided by:
Microsoft
ISV IHV

Reflector

Kernel Driver (e.g., WinUSB) Kernel Driver 2

Device Stack

Device Stack

UMDF Components
Driver manager
Global, system-wide Windows Service Responsible for host process lifetime Responds to messages from reflector Always running Started during installation of the first UMDF device
Driver Manager Host Process
UM Driver

Reflector

UMDF Components
Reflector
Nucleus of UMDF Installed with each device stack Proxy for UM device stack in kernel Forwards I/O, Power, and PnP messages from kernel to host process Ties the UM device stack to KM side Ensures “good behavior” of UM drivers Proper responses to messages Timely completion of critical system messages Tracks all outstanding kernel resources
Driver Manager Reflector

Host Process
UM Driver

UMDF Components : Host Process
Child process of the UM Driver Manager Unit of isolation for the device stack
Driver crash will not affect other device stacks

Container for Framework and UM driver(s) Runtime environment for framework and driver
I/O dispatching, driver loading, driver layering, thread pool Handles messages from reflector and driver manager

Driver Manager

Runtime

Framework

DDI

UM Driver

Reflector

Host Process - Framework
Implements all of the WDF model
Queues, Request, I/O target, etc

Implements default behavior
Reduces vendor written code

Exposes DDI Implemented as DLL

Runtime

Framework

DDI

UM Driver

IPC : Message Passing
Requirements
Packet-based and asynchronous Cancelable Fail-safe Efficient data transfer Secure

Several potential solution
Pending I/O, synchronous message passing

Windows codenamed “Longhorn” solution: ALPC
Standard Windows OS Component

Processing Messages
KM drivers handle I/O in caller?s thread
Obviously not a option for UMDF

Host has a thread pool processing messages
Dedicated thread for “critical” operations
To ensure I/O doesn?t block th

em e.g., PnP/PM, Cancellation, Cleanup, and Close

Shared threads for non-critical operations like I/O
Pool could grow or shrink as load changes
Fixed at 2 threads for Beta 1

For long operations the driver should consider using work-items

Driver Loading
5 Host Runtime

Driver Manager

3

6

Framework

UM Driver

2
Windows Kernel (I/O Mgr, PnP)

4

IPC Channel
Reflector

1
Add Device

Kernel Driver

Provided by:
Microsoft

IHV

Driver Loading (Layered UM Drivers)
7 Driver Manager Host Runtime 8 Framework 5 6 Framework UM Driver UM Filter Driver

3

2
Windows Kernel (I/O Mgr, PnP)

4

IPC Channel
Reflector

1
Add Device

Kernel Driver

Provided by:
Microsoft

IHV

Driver Loading (Host Process)

Add Device

Add Device Driver creates WDF Device Framework Driver creates WDF Queue Driver creates WDF Queue UM Driver

Host Runtime

Add Device

Provided by:
Microsoft

IHV

I/O Data Flow
Application UM I/O Mgr 4 7 Host Process Framework 5 UM Filter Driver

6
9 Framework 10

1

Device Stack

8
11 3 IPC Message

Win32 I/O API

UM Driver

12

Windows Kernel
IRP Provided by:
Microsoft ISV IHV

2

“Up” Device Object

“Down” Device Object Reflector

Kernel driver

I/O in Host Process
Run-time
Host File Object

Invoke driver callback passing in I/O request UM Irp

UM IRP
Device Stack

Framework

Driver can return without completing i/o (asynch)

UM Driver

Driver eventually completes i/o.

IPC Message Host File Object returned as context to the reflector. Provided by:
Microsoft ISV IHV

Device Removal and Cleanup
Run-time
Device Remove

Framework

UM Driver

Message path similar to “add device” path
Driver gets several PnP notifications for remove

UM driver may unload when remove finishes Host process may exit when all drivers are unloaded
Host lifetime controlled by the driver manager

When Driver or Application Crashes
When the UM driver crashes:
Reflector gets notification from OS Reflector tracks outstanding I/O in the host.
Completed with STATUS_DRIVER_PROCESS_TERMINATED Win32 apps will see ERROR_DRIVER_PROCESS_TERMINATED

The kernel drivers for the device stack are unloaded Device is disabled (yellow bang in device manager)

When the application crashes:
Reflectors gets IRP_MJ_CLEANUP Sent to host on the “cancel” IPC channel Host/UM driver complete pending I/O requests

Timeout Policy
UMDF enforces timeouts on “critical” operations
Operations that run under system wide locks Operations that affect user experience

If operations do not complete on time
Host is forcibly terminated and error report is generated

Critical operations include
PnP and PM operations
These run under a system-wide PnP lock Blocks other PnP operations

I/O Cancellation
Long term operations must be cancelable Adversely affects user experience (application hangs)

In WinHEC release, time out = 1 minute
Will adjust based on feedback & failure report data for RTM

Impersonation
Driver runs in LocalService security context Drivers can impersonate the client

process
Only for I/O requests Not for PnP or other system messages
typedef enum _SECURITY_IMPERSONATION_LEVEL { SecurityAnonymous, SecurityIdentification, SecurityImpersonation, SecurityDelegation } SECURITY_IMPERSONATION_LEVEL;

Using Impersonation
Application controls the allowed level
Specified in QOS settings in CreateFile API See dwFlagsAndAttributes parameter in MSDN

INF sets the driver?s maximum desired level
Stored in registry during device installation Set this as low as possible for your driver Reduces chance of “elevation of privilege” attack

Driver requests impersonation for given request
Specifies desired level and a callback Isolate impersonated code
Do minimal work to reduce the attack surface

UMDF Verifier
Built-in verification
Checks for problems in framework code Checks for problems in device driver code Always enabled & always fatal
Unless you have a debugger attached

DDI misusage result in verifier failure
Passing incorrect parameters, including NULL, in DDI Incorrect DDI call sequence More aggressive checks planned for Beta 2

Verifier failure causes a UMDF “Bugcheck”
Generates Memory Dump Generates Error Report Sends Error Report to Microsoft (opt-in)

UMDF Verifier Failures
Driver failures will “Bugcheck” the host
Bugcheck is NOT the “Blue Screen of Death”
We will pick a less scary name in Beta 2

Bugcheck will:
Save memory dump to log file directory
%windir%\System32\LogFiles\WUDF\xxx.dmp

Create an error report to report to Microsoft (opt-in) Break into debugger if present
Prints out error message Developer can continue…but that may lead to another crash

Terminate the host process and disable the device

UMDF Error Reporting
Current driver failure reports are hard to analyze
Too much information in the running kernel Not enough fits into a minidump

User-Mode Drivers reports can be better
Compartmentalized – less information to collect Specialized – not mixed with irrelevant state Better collection – we?re not limited by crash dump

UMDF reports problems through Windows Error Reporting (WER)
UMDF queues reports for later approval and upload
WER provides for a global “opt-in” to upload quicker

No modal crash dialogs
Bubble on the task bar indicating an incident has occurred

Please upload error reports for Beta 1
Even if you think it?s your driver We need data to refine what we?re collecting

Types of Error Reports
UMDF will report the following problems :
UM Driver Verifier failure Unhandled Exception in host process Unexpected Host Termination Failure or Timeout of “Critical” Operation

Error Report may contain:
Memory dump of the host process Copy of UMDF?s internal trace log Configuration information about the device
Device name, manufacturer, drivers installed Driver binary versions

Internal analysis of the problem
Address of the last driver to framework call (or vice versa) Problem code, exception info, etc...

Report contents depend on the problem detected

Devi

ce Driver Interfaces (DDI) and Programming Patterns

Framework Object Model
Framework objects have a hierarchical relationship WDF Driver is the root object Child lifetime scoped by parent
WDF Driver

WDF Device
WDF Queue WDF Queue

Every WDF object is defined by
Methods: actions on objects Properties: are object attributes Events: notifications from Framework objects to the driver

Key Framework Objects
Object
Driver Device I/O Request I/O Queue File I/O Target

Description
Supports one or more devices One per driver per host process Tracks PnP/PM state changes and notifies driver Represents application?s I/O request Controls I/O request flow into driver Provides per-handle context for driver Represents next lower device in stack Encapsulates driver to driver communication

Parent-Child Object Hierarchy
Applies to lifetime management
Lifetime of child is scoped within that of the parent Child is cleaned up when the parent goes away
Driver Device I/O Queue File I/O Request I/O Target

Framework Object Model
Framework
WDF Driver MyDriver WDF Device MyRead Queue MyDevice

Driver

WDF Queue

WDF Queue

MyWrite Queue

WDF Objects
Provided by:
Microsoft

Driver implemented Callback Objects

IHV

Framework Object Model
Framework
WDF Driver WDF Device WDF Queue WDF Queue MyWrite Queue1

Driver 1
MyDriver1

MyDevice1
MyRead Queue1

WDF Driver WDF Device WDF Queue WDF Queue

MyDevice2

MyDriver2

Device Stack

MyRead Queue2

MyWrite Queue2

Driver 2

Each driver in the stack has its own set of framework objects

DDI Design
Common object model with KMDF
Driver writers familiar with KMDF can quickly come up to speed with UMDF

Interface based programming model
UM developers are familiar with C++ and OOP Interfaces allow logical grouping of functions making it easy to navigate through the DDI Facilitates opt-in programming Built-in extensibility C++ is the supported language in the first version

Uses a small subset of COM (COM-Lite)
COM complexity is in COM RTL features
Threading Model, Automation, etc...

UMDF doesn?t depend on COM RTL

DDI : COM Interfaces
Problems solved by Interfaces
Allows us to evolve the DDI without changing exported functions
Older drivers do not need to be rebuilt

No C++ name mangling No C++ fragile base class problem

COM facilitates this
Well understood Existing tools like ATL We don?t want to invent another model

C++ facilitates this
Interfaces are just abstract base classes
With only pure virtual functions

Compiler implements interface as function pointer table
(V-Table)

All You Need to Know about COM …
COM interfaces, by convention, start with “I”
e.g., IUnknown

All COM interfaces are derived from IUknown
QueryInterface, AddRef, Release

Lifetime management of COM objects
AddRef: takes a reference on Framework object
WDF object model simplifies ref-counting

Release: drops ref-count on Framework object
Driver should release interfaces retrieved from Fx when done

Query Interface (QI): allows discovery

of “interfaces” supported by the driver

Device Driver Interfaces (DDI)
UMDF DDI is in wudfddi.idl
interface IWDFObject : IUnknown { HRESULT DeleteWdfObject(); ... VOID AcquireLock(); VOID ReleaseLock(); };

Simplified C++ equivalent generated by MIDL
struct IWDFObject : public IUnknown { virtual HRESULT DeleteWdfObject() = 0; ... virtual VOID AcquireLock() = 0; virtual VOID ReleaseLock() = 0; };

IWDFObject is base interface for all WDF objects

Device Driver Interfaces (DDI)
DDIs are grouped into 2 types of interfaces
Functionality exported by Framework
By convention these begin with IWDF E.g., IWDFDriver, IWDFDevice, IWDFIoQueue

Callbacks exported by Driver
These are of the form I<WdfObject><Function>
e.g., IQueueCallbackRead, IRequestCallbackCancel

Methods on callback interfaces begin with “On” interface IQueueCallbackRead : IUnknown { void OnRead ( IWDFIoQueue* pWdfQueue, IWDFIoRequest* pWdfRequest, SIZE_T NumOfBytesToRead ); };

Device Driver Interfaces (DDI) KMDF and UMDF DDI are similar
Tuned to language and runtime environment

KMDF
NTSTATUS WdfDeviceConfigureRequestDispatching( WDFDEVICE Device, WDFQUEUE Queue, WDF_REQUEST_TYPE RequestType, BOOLEAN Forward );

UMDF
HRESULT IWDFDevice::ConfigureRequestDispatching( IWDFIoQueue * pQueue, WDF_REQUEST_TYPE RequestType, BOOL Forward );

Device parameter is implicit in C++

Driver Entry
IDriverEntry is the top driver-exported interface
interface IDriverEntry::IUnknown { HRESULT OnInitialize( IWDFDriver* pWdfDriver ); HRESULT OnDeviceAdd( IWDFDriver* pWdfDriver, IWDFDeviceInitialize* pWdfDeviceInit ); VOID OnDeinitialize(); };

OnInitialize and OnDeinitialize
Do driver-wide initialization and cleanup

OnDeviceAdd
Invoked once for each new device detected by Windows

Callback Objects Callback objects = Callbacks + Context Example: Creating Device Object
HRESULT CMyDriver::OnDeviceAdd( IWDFDriver* pDriver, IWDFDeviceInitialize* pDeviceInit ) { IUnknown *pDeviceCallback = NULL; ... // Create callback object hr = CMyDevice::CreateInstance( &pDeviceCallback, 1 pDeviceInit, completionPort ); ... // Create WDF Device hr = pDriver->CreateDevice( pDeviceInit, pDeviceCallback, 2 &pIWDFDevice ); ... }

Callback Objects (con’t)
class CMyDevice : public IDevicePnpHardware { private: HANDLE WINUSB_INTERFACE HANDLE UCHAR ULONG ... public: virtual HRESULT stdcall // Callback interface exposed to // framework.

m_CompletionPort; m_UsbHandle; m_BulkOutPipe; m_BulkOutMaxPacket;

Context

OnPrepareHardware( IWDFDevice* pDevice ); STDMETHOD( OnReleaseHardware )( IWDFDevice *pDevice ); // Factory method static HRESULT CreateInstance( IUnknown *pUnknown, IWDFDeviceInitialize *pDeviceInit, HANDLE CompletionPort ); ...

Callback

};

Callback Objects (con’t)
static HRESULT CreateInstance( IUnknown **ppUnknown, IWDFDeviceInitialize *pDeviceInit, HANDLE CompletionPort ) { ... // Allocate our callback context 1 CMyDevice *pMyDevice = new CMyDevice(); ... // Get our callback interface 2 hr = pMyDevice-

>QueryInterface( __uuidof(IUnknown), (void **) ppUnknown ); ... return hr; }

Callback Objects (con’t)
1
WDF Driver
IWDFDriver::CreateDevice( … ) 3
OnDeviceAdd IDriverEntry

Callback Object

2
MyDevice

WDF Device

IUnknown

5

4
QueryInterface for ? IDevicePnP ? IDevicePnPHardware ---IDevicePnpHardware

Framework

Driver

Provided by:
Microsoft

IHV

Summary
Discussed driver loading/unloading, I/O data flow
Driver installation and setup are same as WDM drivers Keep in the mind the “timeout” polices in reflector Built-in verifier checks Error reporting via WER

Discussed driver programming model
KMDF and UMDF share same model UMDF DDI is based on C++ and COM-lite Callback objects = Context + Callbacks

How to Develop a UMDF Driver Part 2

Outline
Goals Getting Started
Writing your Driver Installing your Driver Debugging the Driver

Plug and Play / Power Management
Design goals Design overview Device Driver Interface (DDI) PnP/PM driver callback example

Goals
How to start writing and debugging a UMDF driver How to interact with UMDF?s Plug And Play and Power Management support The basics of creating and configuring a device driver

Writing Your Driver

What is a User-Mode Driver?
User-Mode (UM) Drivers are DLLs
Provide driver?s “callback object” classes Use COM programming pattern, not runtime
At least, not very much of the runtime

Expose standard COM entry points
DllGetClassObject, DllRegisterServer, DllUnregisterServer

Can write UM Drivers in C or C++
Implementing COM objects is easier in C++ Can use ATL with C++ for additional COM support

WDF Supplement CD contains several examples
This talk references the “Skeleton” driver

UMDF Driver DLL Exports
DllMain
Called when DLL loads (and unloads) Construct global objects, initialize tracing

Dll[Un]RegisterServer
Called by CoInstaller during device installation Skeleton sample uses ATL
Rather than write another implementation

DllGetClassObject
Called on device arrival by COM to get “class factory”

DllCanUnloadNow
Just return S_FALSE

Common Driver Classes
COM objects must implement IUnknown
Independently, or with help from CUnknown base class

UMDF driver implements these classes
CClassFactory
Instantiates your driver event handler

CMyDriver
Your Driver-Callback Class Must implement IDriverEntry Paired with an IWDFDriver object

CMyDevice
Your Device-Callback Class May implement IDevicePnpHardware and/or IDevicePnp Paired with an IWDFDevice object

UMDF Skeleton Driver
Example code based on UMDF Skeleton sample
Code in slides should not be used as-is

UMDF Skeleton does just enough to get loaded
Boilerplate code found in all UM Drivers Minimal callback objects for driver and device

Description of files
ComSup.h & ComSup.cpp
COM Support code – provides classes for IUnknown & IClassFactory

DllSup.h & DllSup.cpp
DLL Support code – provides implementation of required exports Depends on COM support code

Driver.h & Driver.cpp
Driver-Callback Class

Devic

e.h & Device.cpp
Device-Callback Class

“TODO” comments mark where to add your driver code
COM and DLL support files require no changes The driver and device files you?ll need to modify for your driver

Example: CMyDriver Definition (Driver.h)
class CMyDriver: public CUnknown, public IDriverEntry { IDriverEntry *QueryIDriverEntry(); HRESULT Initialize(); public: static HRESULT CreateInstance( PCMyDriver *Driver ); HRESULT OnInitialize( IWDFDriver *FxDriver ){ return S_OK; } HRESULT OnDeviceAdd(IWDFDriver *FxDriver, IWDFDeviceInitialize *FxDeviceInit);

HRESULT OnDeinitialize( IWDFDriver *FxDriver ) { return S_OK; } ... // IUnknown methods, etc... };

Example: CMyDriver Implementation (Driver.cpp)
HRESULT CMyDriver::CreateInstance( CMyDriver **Driver ) { CMyDriver *driver = new CMyDriver(); if (driver == NULL) { return E_OUTOFMEMORY; } HRESULT hr = driver->Initialize(); if (S_OK == hr) { *Driver = driver; } else { driver->Release(); } return hr;

} HRESULT CMyDriver::Initialize() { HRESULT hr = S_OK; ... // Do any initialization that could fail here return hr; }

Example: CMyDriver Implementation (con’t)
HRESULT CMyDriver::OnDeviceAdd(...) { CMyDevice *deviceCallback; IWDFDevice *fxDevice; HRESULT hr = CMyDevice::CreateInstance( FxDeviceInit, &device ); if (S_OK == hr) { ... // Call SetLockingModel(), SetFilter(), etc... hr = FxWdfDevice->CreateDevice( FxDeviceInit, deviceCallback->QueryIUnknown(), &fxDevice ); // Release Reference from QueryIUnknown() deviceCallback->Release(); } if (S_OK == hr) {fxDevice->Release();} if (NULL != deviceCallback) {deviceCallback->Release();} return hr; }

Example: CMyDevice Definition (Device.h)
class CMyDevice : public CUnknown { HRESULT Initialize( IWDFDeviceInitialize *DeviceInit ) { return S_OK; } static HRESULT CreateInstance( IWdfDeviceInitialize *FxDeviceInit, CMyDevice **Device ); // Add IUnknown methods here

}

Writing Your Driver (Summary)
Create the common code
Required DLL Exports COM support classes Copy from skeleton, use existing ones (ATL), or write your own

Implement CMyDriver class
Including the OnDeviceAdd() method
Allocate and initialize a CMyDevice object Create IWDFDevice object & connect to CMyDevice callbacks

Implement CMyDevice class
Add Device-Callback interfaces later

Your driver should now load
But can?t talk to your device or do I/O Next two talks will address that

Installing Your Driver
INF Based Installation
Just like WDM and kernel-mode WDF drivers Device Matching, Driver Signing, etc... work normally

User-Mode Driver?s INF does extra work
Use UMDF CoInstaller Register Driver DLLs Configure the Driver List Setup UM Driver Key Add the Reflector driver

We plan to simplify the installation for Beta 2
Still INF based, but more support from CoInstaller

Registry Locations
UMDF keeps information in several registry keys
We?ll refer to them using these names as we go Defined in the [Strings] section of the Skeleton INF Key Name
%UMDF_Software%

Location
HKLM \ S

oftware \ Microsoft \ Windows NT \ CurrentVersion \ WUDF %UMDF_Software% \ Services %UMDF_Services% \ {193a1820-d9ac-4997-8c55-be817523f6aa}

%UMDF_Services% %UMDF_Host%

Use UMDF CoInstaller
System provided CoInstaller
Sets Driver Manager to start automatically

WUDFCoInstaller.dll is already installed
No need to copy the file

Driver?s INF must reference this CoInstaller
[Skeleton.CoInstallers] AddReg = Skeleton.CoInstallers_AddReg [Skeleton.CoInstallers_AddReg] HKR,,CoInstallers32,0x00010000,“WUDFCoInstaller.dll”

Without the CoInstaller your driver may not start
Driver can?t start if the Driver Manager isn?t running Problem code 37 in device manager

Register Driver DLLs
UMDF uses CoCreateInstance to load drivers
This requires the driver to be “registered”

INF must register any user-mode drivers it copies
Do this in the [DDInstall] section
[Skeleton] CopyFiles=DriverCopy RegisterDlls=Skeleton.RegisterDlls [Skeleton.RegisterDlls] 11,,WUDFSkeleton.dll,1

Unregistered drivers will not load
Problem code 43 in the device manager

Configure the Driver List
UMDF loads drivers by “Driver Name”
We recommend the binary name (without extension)

UMDF Maintains its own driver list
Lists drivers in order of attachment to the stack
Drivers are listed by “Driver Name”

User-Mode drivers load above kernel-mode drivers

MultiString stored under the device node?s key
[Skeleton_AddReg] HKR, “WUDF”, “DriverList”, 0x00010000, “WUDFSkeleton”

If this is missing
Problem 43 in device manager

Setup UM Driver Key
Create an entry under UMDF Services Key
One for each driver installed Key name is the Device Name

Contains UMDF-Specific Driver Information:
The Driver?s CLSID Configure this in the INF Replace CLSID with your driver?s class ID.
[Skeleton_AddReg] HKLM, %WUDF_Services%\WUDFSkeleton, “ComCLSID”, 0, “{CLSID}”

Without this:
Problem 43 in device manager

Adding the Reflector Driver
Reflector driver is WUDFRd.sys
Already installed on the system Your INF must make this the top-most kernel driver

If you?re writing a UM function driver
Assign reflector as service with AddService directive You?ll need a service install section too

If you?re writing a UM Upper-Level filter driver
Assign reflector as top-most Upper Device Filter

Without this UMDF is never loaded
Device may start, but no host process

Installing Your Driver (Summary)
Use the UMDF CoInstaller Register your Driver DLLs with COM Configure the Driver List Setup UM Driver Key
Record your driver?s CLSID

Add Reflector driver to the kernel drivers If it doesn?t work:
Is Driver Manager started? Does device manager show a problem code? Is WUDFHost.exe (host process) running ?

Debugging Your Driver

Debugging Overview
Similar to service debugging
UM Drivers cannot be started by the debugger No Just-In-Time debugging

Host process starts when device is installed
Plug & Replug the device to restart
Or disable & re-enable in device manager

Each

device stack runs in host process
WUDFHost.exe Child of Driver Manager service One stack per host-process for now

Debugger Options
WinDbg
GUI Debugger Source and/or Assembly level debugging UMDF debugger extension available Can work as user-mode or kernel-mode debugger See resources slide to find download location

Visual Studio Debugger
WDK and Visual Studio aren?t currently integrated UMDF Debugger extension not available Must copy mspdb71.dll from WDK to use it We?re concentrating support on WinDbg

CDB & KD
If you prefer command line debugging, these work

User-Mode or Kernel-Mode Debugging
Can debug UMDF with UM or KM debugger
You can use WinDbg to debug either way

UM Debugger
Simpler and more familiar Have to attach to each host process when it starts

KM Debugging
Requires a second computer to run debugger More complex, but quite powerful
Stops entire computer – no UMDF timeouts

Can be always running
Catch UMDF Verifier problems like JIT debugger

Can debug and set breakpoints in host process
Use “.process /i <process object address>” to break into running host

See additional slides for KM Debugging tips

Enabling the Debugger
Host process started by Driver Manager service
You can?t attach debugger until after initialization

Host Process supports an “initial breakpoint” (IB)
Host waits N seconds for debugger to attach
Breaks into debugger once detected Continues running once N seconds elapse

Timeout (in seconds) configured under UMDF_Host key

HostProcessDbgBreakOnStart = N Enabling IB disables other UMDF timeouts
Like those on PnP operations

Initial Breakpoint is for UM Debugger (by default)
Can be configured to watch for both UM & KM debugger Set high-bit in the timeout value
0x8000000 attempts once to break into either debugger

Attaching the UM Debugger
Cannot connect UM Debugger until host starts Enable the Initial Breakpoint Attach the device to the system
Or enable it in the device manager

If you have a single device attached
Run “windbg –pn WUDFHost.exe” Repeat until it finds a host process to debug

If you have multiple devices attached
Find out process ID (PID) of the new host
Use tasklist.exe before & after to find new host process

Run “windbg –p PID”

UMDF Debugger Extension
WudfExt.dll
Copy into your path “!load WudfExt.dll” debugger command loads the extension Names are case sensitive

Command
!devstack !dumpirps !umirp !wdfdriverinfo !wdfdevicequeue !wdfqueue !wdfrequest !wdfitf2obj

Description
Shows device stacks in the host process Shows UM IRPs in the host process Shows a host IRP Shows info about a UM driver Shows the I/O queues for a device Shows an IoQueue Shows an IoRequest Converts an interface pointer to an object address for above extensions.

Interesting UMDF Breakpoints (BP)
Hopefully, this will get you started Event to debug Host attempts to load driver Driver Load Breakpoint (BP)
OLE32!CoCreateInstance Watch for your CLSID

MyDriver!DllMain Invoked first time whe

n your DLL is loaded
Called after that too, so clear the BP once it hits

Creation of CMyDriver

Driver attaches device to stack

MyDriver!DllGetClassObject Invoked to get your class factory MyDriver!CMyDriver::CMyDriver Invoked when the factory calls new MyDriver!CMyDriver::OnDeviceAdd Driver creates a device to attach to the stack

Tracing in Your UM Driver
Recommend using WPP tracing for debug output
Lightweight & always available, printf-style tracing Easily captured to disk, screen or (kernel) debugger

Skeleton contains some basic tracing code
See MSDN documentation on Event Tracing

Collect output with tracelog.exe or traceview.exe
Tracelog comes with Windows Traceview comes with WDK

For more information see:
“Collecting & Viewing Traces” in additional slides MSDN & DDK documentation

What Do I Do When It Crashes? (Summary)
Check for configuration problems
Is there a PNP problem code? Is there a host process running?

Is there a .dmp file WUDF log file directory?
%SystemRoot%\LogFiles\WUDF\*.dmp

Attach a debugger to the host as it starts
Or always enable the kernel debugger

Watch for UMDF Verifier failures Walk through initialization
Use list of interesting breakpoints

Get debug output with WPP tracing

Plug and Play / Power Management

UMDF Design Goals for PnP/PM
Coordinate I/O delivery to driver with PnP/PM events The framework handles complexities of PnP/PM
Allow drivers to participate with optional callbacks

Support FDO and filter driver scenarios
No bus driver support for version 1

Same design as kernel mode WDF PnP/PM

UMDF PnP/PM Design
Implemented with a state machine
Consumes PnP/Power messages from the reflector Suspends and resumes I/O queues as needed Calls the driver if desired through a set of driver provided callback functions Driver callbacks are logically grouped into interfaces
IDevicePnpHardware IDevicePnp IDevicePnpSelfManagedIo

Driver “opts-in” by implementing one or more callback interfaces
Software-only drivers generally don?t need any of these interfaces Most drivers will only need IDevicePnpHardware

UMDF PnP/PM Interfaces
IDevicePnpHardware
First time hardware initialization / de-initialization OnPrepareHardware() OnReleaseHardware()

IDevicePnp
Device state change notifications OnD0Entry() OnD0Exit() OnSurpriseRemoval() OnQueryRemove() OnQueryStop()

IDevicePnpSelfManagedIo
Custom I/O processing notifications OnSelfManagedIoCleanup() OnSelfManagedIoFlush() OnSelfManagedIoInit() OnSelfManagedIoSuspend() OnSelfManagedIoRestart()

Device Driver Interface (DDI)
IDriverEntry::OnDeviceAdd
Driver must implement this interface Called when framework receives “Add Device” message Driver should perform initialization that does not require access to hardware or lower level drivers Driver also creates a device object and device callback object (beyond the scope of this talk)
HRESULT CMyDriver::OnDeviceAdd( IWDFDriver* pDriver, IWDFDeviceInitialize* pDeviceInit ) { // Read in driver properties INa

medPropertyStore * pPropStore = NULL; hr = pDeviceInit->GetDevicePropertyStore( &pPropStore ); ... }

IDevicePnpHardware
OnPrepareHardware
Called when device is first started Driver establishes connection to the device and performs one-time initialization HRESULT CMyDevice::OnPrepareHardware( IWDFDevice* pDevice ) { ... // Open the device hr = pDevice->GetDeviceName( pDeviceName, … ) m_Handle = CreateFile( pDeviceName, … ) ... // Initialize the device and look for endpoints if (WinUsb_Initialize( m_Handle, &m_UsbHandle )) { return DiscoverBulkEndpoints(); }

IDevicePnpHardware
OnReleaseHardware
Called when device is removed or stopped Driver should essentially undo anything it did in OnPrepareHardware
HRESULT CDevice::OnReleaseHardware( IWDFDevice* pDevice ) { // Close the USB handle and the device’s file // handle if ( m_UsbHandle ) { WinUsb_Free( m_UsbHandle ); } if ( m_Handle ) { CloseHandle( m_Handle ); } return S_OK; }

IDevicePnp
OnD0Exit
Called each time device should power down Also called before the device is removed
Stop device?s I/O target with “leave pending I/O” flag
hr = m_pIoTarget-> Stop( WdfIoTargetLeaveSentIoPending );

Save device state Set the device into low power state

OnD0Entry
Called each time device should power up Also called when the device starts up
Set the device into working power state Restore any previously saved state Restart device?s I/O target
hr = m_pIoTarget->Start();

IDevicePnp
OnSurpriseRemoval
Called when the device has unexpectedly detached from the PC Stop device?s I/O target with cancel flag
hr = m_pIoTarget->Stop( WdfIoTargetCancelSentIo )

OnQueryRemove
Allows driver to veto a device removal request
HRESULT CDevice::OnQueryRemove( IWDFDevice* pDevice ) { return S_OK; // Allow device removal }

OnQueryStop
Allows driver to veto a device stop request
HRESULT CDevice::OnQueryStop( IWDFDevice* pDevice ) { return E_FAIL; // Disallow device stop }

IDevicePnpSelfManagedIo
Notifications to drivers that perform I/O dispatching unmanaged by the framework
OnSelfManagedIoInit()
Start I/O dispatching

OnSelfManagedIoSuspend()
Pause I/O dispatching

OnSelfManagedIoRestart()
Resume I/O dispatching

OnSelfManagedIoFlush()
Cancel or complete all pending I/O

OnSelfManagedIoCleanup()
Free I/O dispatching mechanisms

PnP/PM Driver Callback Example

Start Device
OnPrepareHardware()

Device Driver

Framework

Start Device

Off

On

Off

Start Device
OnD0Entry()

Device Driver

Framework

Start Device

Off

On

Off

Device Operational
Device Driver

Framework

On

On

Off

Suspend Device
OnD0Exit()

Device Driver

Framework

Power Down

On

On

Off

Resume Device
OnD0Entry()

Device Driver

Framework

Power Up

On

On

Off

Remove Device
OnD0Exit()

Device Driver

Framework

Remove Device

On

On

Off

Remove Device
OnReleaseHardware()

Device Driver

Framework

Remove Device

On

On

Off

WDM Message to UMDF Callback Mapping
Start -> Query Remove -> Remove
IRP_MN_START_DEVICE:
OnPrepareHard

ware() OnD0Entry() OnSelfManagedIoInit()

IRP_MN_QUERY_REMOVE_DEVICE:
OnQueryRemove()

IRP_MN_REMOVE_DEVICE:
OnSelfManagedIoSuspend() OnD0Exit() OnSelfManagedIoFlush() OnReleaseHardware() OnSelfManagedIoCleanup()

WDM Message to UMDF Callback Mapping
Start -> Surprise Removal -> Remove
IRP_MN_START_DEVICE:
OnPrepareHardware() OnD0Entry() OnSelfManagedIoInit()

IRP_MN_SURPRISE_REMOVAL:
OnSurpriseRemoval() OnSelfManagedIoSuspend() OnReleaseHardware() OnSelfManagedIoFlush()

IRP_MN_REMOVE_DEVICE:
OnSelfManagedIoCleanup()

PnP/PM Timeouts
Each WDM PnP/PM message has a timeout
Currently, this timeout is set to 1 minute The reflector will abort the host process if this timeout is exceeded

Each WDM Pnp/PM message can produce multiple driver callbacks, for example:
“AddDevice” results in:
OnInitialize OnDeviceAdd 1 minute

IRP_MN_START results in:
OnPrepareHardware OnD0Entry OnSelfManagedIoInit 1 minute

Supplemental Slides

Example: DllMain
BOOL DllMain( HINSTANCE ModuleHandle, DWORD Reason, PVOID Reserved ) { if (DLL_PROCESS_ATTACH == Reason) { WPP_INIT_TRACING(“Microsoft\\UMDF\\UMDFSkeleton”); g_ModuleHandle = ModuleHandle; } else if (DLL_PROCESS_DETACH) == Reason) { WPP_CLEANUP(); } return TRUE; }

See Skeleton\Host.cpp

Example: DllGetClassObject
HRESULT DllGetClassObject( REFCLSID ClassId, REFIID InterfaceId, PVOID *Interface ) { PCClassFactory factory; HRESULT hr; *Interface = NULL; if (!IsEqualCLSID( ClassId, __uuidof(MyDriverCoClass) )) { return CLASS_E_NOTAVAILABLE; } hr = CClassFactory::CreateInstance(&factory); if (S_OK == hr) { hr = factory->QueryInterface(InterfaceId, Interface); factory->Release(); } return hr; }

Example: DllRegisterServer & DllCanUnloadNow
HRESULT DllRegisterServer() { return UpdateCOMRegistration( g_ModuleHandle, IDR_MYDRIVER_CLASSINFO, true, __uuidof( MyDriverCoClass ), L“UMDF Skeleton Sample Driver” ); } HRESULT DllUnregisterServer() { return UpdateCOMRegistration(..., false, ...) } HRESULT DllCanUnloadNow() { return S_FALSE; }

Example: CUnknown Definition
class CUnknown : public IUnknown { LONG m_RefCount; public: CUnknown() { m_RefCount = 1; } virtual ~CUnknown() { return; } IUnknown *QueryIUnknown(){ AddRef(); return (IUnknown *)this; } ULONG AddRef(); ULONG Release(); HRESULT QueryInterface( REFIID InterfaceId, PVOID *Interface ); };

Example: CUnknown Implementation
ULONG CUnknown::AddRef(){ return InterlockedIncrement(&m_RefCount); }

ULONG CUnknown::Release() { ULONG count = InterlockedIncrement(&m_RefCount); if (count == 0) { delete this; } return count; }
HRESULT CUnknown:QueryInterface(...) { if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) { *Interface = QueryIUnknown(); return S_OK; } *Interface = NULL; return E_NOINTERFACE; }

Example: CClassFactory Definition
class CClassFactory : public CUnknown, public IClassFactory { public: IClassFactory *QueryIClassFactory() {...} // IUnknown AddRef() {return __super::AddRef()} Release() {return __super::Release()} QueryInterface(...); // IClas

sFactory HRESULT CreateInstance( IUnknown *Outer, REFIID InterfaceId, PVOID *Object ); HRESULT LockServer(BOOL Lock) { return S_OK; }

};

Example: CClassFactory Implementation
HRESULT CClassFactory::QueryInterface(...) { if(IsEqualIID(Interface, __uuidof(IClassFactory)) { *Object = QueryIClassFactory(); return S_OK; } else { return CUnknown::QueryInterface(...); } } HRESULT CClassFactory::CreateInstance(...) { PCMyDriver driver; HRESULT hr = CMyDriver::CreateInstance(&driver); if (S_OK == hr) { hr = driver->QueryInterface(InterfaceId, Object); driver->Release(); } return hr;

}

Debugging with WinDbg
Source Level GUI debugger (Most) commands work on addresses or symbols
ModuleName!FunctionName ModuleName!ClassName::MethodName
Best to always use fully resolved names

Setting Breakpoints
“bp <addr>” sets an excution breakpoint
Use bu if the function?s module isn?t loaded yet

?ba [w|r] [1|2|4|8] <addr>? sets a watchpoint
ba r 4 MyDriver!g_MyArrayLength

Dumping Memory
d<type> [address] [L<length>]
type = byte, word, char, unicode, dword, quadword, string
dd MyMyDriver!g_MyArrayLength L1

dv dumps local variable names

Dumping Types
dt <variable name> dumps a specific local dt <addr> <typename> dumps an address or symbol as a type
dt ??? MyDriver!CMyDevice

See the WinDbg help for more details

Debugging with a Kernel Debugger
WinDbg can be used as a kernel debugger Must point Kernel debugger to host process
Automatic if the process requests a kernel break-in Manually through the .process command
“!process 0 0” will list all process object addresses

Must reload user-mode symbols after attaching
“.reload /user”
Or the stack trace won?t have any symbols

Can set breakpoints on user-mode addresses
Must load user symbols first

Cannot break into a running host process
Must wait for a breakpoint

UMDF “Verifier” will break into KD if attached
Last chance to debug before process termination

Collecting & Viewing Traces
TraceLog.exe lets you control trace sessions
To start a session
Tracelog.exe -start MyLogger -guid MyDriver.ctl -level 255 -flag 65535 -f MyLogFile.etl

To end a session
Tracelog.exe -stop MyLogger

To print a session
TraceFmt –o MyLogFile.txt -p symbols.pri/TraceFormat MyLogFile.etl

Or use the GUI “TraceView” tool
Use in place of TraceLog or TraceFmt

Resources:
“WPP Software Tracing” page in DDK documentation MSDN online page for these tools:
http://msdn.microsoft.com/library/default.asp?url=/library/enus/ddtools/hh/ddtools/tracetools_8eccb8f7-6f29-4683-87bdfa83618c32eb.xml.asp

How to Develop a UMDF Driver: Part 3

Outline
I/O Processing Overview I/O Queues File Objects Driver Layering I/O Targets Cancellation

Goals
A better understanding of:
How to incorporate I/O processing in a UMDF driver Framework objects involved with I/O Request processing

Knowledge of where to find resources for UMDF

I/O Request Processing Overview

I/O Request Processing in UMDF
You?ve seen WDF Driver and Devi

ce objects
These are used to configure a device stack

I/O processing involves many more objects for:
Flow control and internal request routing Per request context and callbacks Connections to other drivers in the stack and/or system

And some concepts that span across objects:
Driver Layering Cancellation

Framework Objects
Driver Device Request Memory (Input)

Memory (Output)
Queue File I/O Target

Framework Objects
These objects are associated with request processing
All derive from IWDFObject Object
Device Request

Description
The information associated with a single layer in a device stack An I/O operation Either sent to the driver or initiated by the driver to a lower device A flow control mechanism for Requests An open handle to the device and any context the driver needs to store with it Another driver to which the Driver can send Requests Either another user-mode layer in the device stack, the kernel-mode portion of the device stack, or the top of another device stack entirely. A buffer associated with a request

Queue File I/O Target

Memory

I/O Request Processing – A Bird’s Eye view
Request

I/O Queue Driver Complete

I/O Target

I/O Request Object
Request

I/O Queue Driver Complete

I/O Target

I/O Request Object
Represents a request
Sent to the driver by a client
An application or another UM driver

Generated by a driver Types of Requests presented to driver
Create Read / Write / DeviceIoControl Cleanup Close

Request Parameters can be obtained from IWDFIoRequest interface

I/O Queues

I/O Queues
Request

I/O Queue Driver Complete

I/O Target

I/O Queues
Queues provide flow control for I/O Requests
All requests dispatched to driver through I/O Queues

Driver can configure I/O routing for a device
Create one or more queues for a device Configure routing for a type of I/O to a particular queue “Default queue” handles any remaining I/O types

I/O Queue Dispatch Types
Dispatch Type controls how requests are presented to driver Queues allow following modes of dispatching:
Automatic: Queue presents requests via callbacks (Push Model) Manual: Requests are retrieved by driver (Pull Model)

Dispatch type is set at Queue creation time
It is a per-Queue property

Automatic Dispatch
Queue presents request through driver implemented callback interfaces
IQueueCallbackCreateClose IQueueCallback[Read | Write | DeviceIoControl]

Automatic Dispatch Types
Sequential: allows at most one outstanding request at a time
New Request not presented until current request is completed

Parallel: allows multiple outstanding requests
New Request can be presented even when previously presented requests are not completed The number of parallel requests presented is bounded
Driver should minimize blocking in presentation callbacks

Manual Dispatch
Driver pulls requests from the queue
Typically starts in response to Queue callback IQueueCallbackStateChange
Empty to non-empty transition

Continues to pump I/O until “done”
No more I/O, bookmark r

equest retrieved, error, etc...

Starts again on next Queue state change
HRESULT RetrieveNextRequest( OUT IWDFIoRequest** ppRequest );

It is possible for driver to pull requests from an Automatic Queue

Callback Constraints
Callback constraints specify locking model for Queue callbacks Callback constraints options
Device Level: Callbacks invoked with device level lock held None: Callbacks invoked with no lock held

Specified at device creation time via
IWDFDeviceInitialize::SetLockingConstraint Set before creating the WDF Device object Per device property – applies to all queues

Callback Constraints (con’t)
Constraints apply only to Queue Callbacks Queue callbacks include
Automatic Dispatch Callbacks Queue state change callback Request cancellation callback

If Device Level locking is used:
The above callbacks are synchronized Request Completion is a not a Queue Callback – not synchronized

Unsynchronized code can call IWDFObject::AcquireLock
Call on object that matches your synchronization scope

Dispatch Type vs. Locking Model
Combining Dispatch Type and Locking Model provides several modes of operation For example:
Sequential Queue Device Level Locking
Request1

Parallel Queue Device Level Locking
Request1 Request2

Parallel Queue No Locking
Request1 Request2

Req1 Complete
Request2 Req2 Complete

Req1 Complete Req2 Complete

Req1 Complete Req2 Complete

UMDF OSR USB Sample Walk-through
Requests and Queue Usage in the sample driver (src\umdf\usb\driver)
Callback locking constraint used
(CMyDevice::Initialize in Device.cpp)

Dispatch type used
(CMyQueue::Initialize in Queue.cpp)

Queue callbacks used
(CMyQueue in Queue.h and Queue.cpp)

File Objects

File Object
File Object represents open connection to device It is the session context for I/O All requests associated with a File Object in UMDF
KMDF and WDM requests sometimes don?t have one

File object for a request obtained using IWDFIoRequest::GetFileObject Trailing name used by client while opening connection is available via IWDFFile::GetFileName

File Object (con’t)
Device File1 Request1 Request2

File2 Request1 Request2

File Object Lifetime
File Object?s lifetime spans
Create: File Object gets created in response to a connection being opened Cleanup: Notification of connection being torn down and that Close is pending Close: All I/O pertaining to this File Object has now ceased. File Object is now disposed.

File Object is created and destroyed by the Framework All I/O operations happen in the context of File object
i.e., they happen between Create and Close These operations are: Read / Write / DeviceIoControl

File Object Lifetime Illustrated
Example of I/O sequence between App and Driver
Application
hFile = CreateFile(… …
Async/Sync Read/Write/IoCtl


Driver
Create Request
Read/Write/IoCtl Requests …

… CloseHandle(hFile);

Cleanup
… Any remaining Requests drain …

Close

Cleanup Handling in Driver
Cleanup received when client closes connection No

tification for driver to flush I/O for File Object
Cancel or complete outstanding I/O as soon as possible Close will not come until all I/O is finished Cleanup is a “critical” operation in UMDF
Cannot fail, subject to timeout

Cleanup is not the end of I/O operations
That?s the Close Request I/O received after a Cleanup should be cancelled/completed immediately

UMDF OSR USB Sample Walk-through
File usage in the sample driver (src\umdf\usb\driver)
(Queue.cpp) CMyQueue::OnRead CMyQueue::OnCreateFile CMyQueue::OnCleanupFile CMyQueue::OnCloseFile

Driver Layering

Driver Layering
UMDF supports driver layering
Multiple drivers build a device stack “Function” driver provides core device behavior “Filter” drivers modify aspects of device behavior

Filter is a property set at device creation time All Framework Objects are per layer
Each layer works only with its own objects e.g., each layer gets a Request object to complete

Driver sends request to next layer using I/O Target
Represents the next driver in the stack That driver may be in user mode or kernel mode

Driver Layering Diagram
Framework
Device Queue File Request

Framework
Device

Queue

File

Request

Framework
Device Queue File Request

Device Stack

Request Completion
When Driver receives a Request it can
Complete the Request synchronously Forward it to an I/O Target or an I/O Queue Hold on to it to complete later

Driver must complete a Request it receives
e.g., while forwarding request to I/O Target
Driver must register request-completion-callback object Framework invokes callback when target completes request Callback must complete request or arrange for completion

UM IRP not complete until all layers complete their Request objects

Completion callback is not a device level event
Runs outside driver?s callback locking constraints

Request Completion Illustrated
Request Completion Routine

Request

Completion Routine

Request

I/O Target

I/O Target
Request

I/O Queue Driver Complete

I/O Target

I/O Target Framework Object
Provides a way to send requests to another device Local I/O Target represents:
The next device in the stack
Another UM Driver, or the KM portion of the stack

Driver doesn?t need to care which it is

Remote I/O Target represents
Some other UM or KM device stack Need feedback to prioritize this for Longhorn

I/O Target is responsible for
Sending I/O request to lower device Detecting completion and invoking callback interface

Local I/O Target
Application

Device
Device Device

I/O Target
I/O Target I/O Target

User Mode

Kernel Mode Up Device Down Device
Device Device Reflector

Device Stack

I/O Target Functionality
State based I/O handling
Driver can start and stop the I/O target
In Response to a PnP Transition For any driver specific reason (e.g., reconfigure after reset)

Supports two I/O modes:
Synchronous for short-term operations Asynchronous with callback for long-term operations

Supports request timeout
Outstanding request is cance

lled when timeout expires

Tracks sent requests for the driver
Allows automatic purge or flush on I/O target stop

Coordinates completion and cancellation

Bridging UM and KM stacks
I/O Target provides bridge between KM and UM drivers
Bottom-most I/O Target sends requests to kernel-mode stack

Driver could also “escape” to the Platform API
Send I/O using Win32 File I/O API directly

Advantages of using I/O Target
Handles complexity of coordinating completion, cancellation and cleanup Allows for filtering and layered stacks transparently Allows routing of request to kernel mode in mode neutral way Offers rich functionality

In Beta 1
Bottom-most I/O Target uses Win32 File I/O API internally No way to use specific API (e.g., WinUSB)
Makes the escape necessary in such cases

UMDF OSR USB Sample Walk-through
I/O Target usage in the sample filter (src\umdf\usb\filter)
Obtaining default I/O Target
(CMyQueue::Initialize in Queue.cpp)

Forwarding request down the stack
(CMyQueue::OnWrite in Queue.cpp) (CMyQueue::ForwardRequest in Queue.cpp)

Request Cancellation

Request Cancellation
Application can cancel a request at any time by
Using CancelIo[Ex] API Exiting application, etc.

Higher layer driver can cancel sent requests Cancel tells driver to complete request soon
But not necessarily immediately Driver should abort any long operations
Short synchronous requests can just be allowed to complete normally

Cancel is a critical operation
Cannot be failed, subject to timeout, etc… Cancellation is part of good user experience

Cancellation Overview
Request Owner can register a cancel callback Cancel callback follows locking constraints On Cancel:
Request?s internal state is marked as cancelled
Any callback registered after this will run immediately

Registered cancel callback is cleared then invoked

In the cancellation callback
Owner arranges to cancel and complete request

Remove callback before transferring ownership
e.g., when forwarding or completing the Request

Request Ownership
Request ownership starts with I/O Queue Request ownership moves from:
Queue to Driver – Driver receives the Request Driver to Queue – Driver forwards Request to Queue Driver to I/O Target – Driver forwards Request to I/O Target

Queue or I/O Target handle cancellation when they own request
I/O Target notifies you through completion callback

Driver must handle cancel when it owns request
If it holds on to the request for a long time

Cancellation Handling in Driver
When driver receives a Request, it may:
Complete it soon Shortly send it to I/O Target Queue it back to Framework I/O Queue Hold on to it (not using Framework I/O Queue) Do (potentially) lengthy sync/asynch processing

Driver needs to handle cancellation only in the last two cases

Cancellation Handling in Driver (con’t)
Driver may register a cancel notification callback
void IWDFIoRequest::MarkCancelable( IRequestCallbackCancel* pCancelCallback );

In callback it should cancel/complete the

request
As soon as possible

Unregister callback when transferring ownership
Before sending request to I/O target or completing it
HRESULT IWdfIoRequest::UnmarkCancelable();

Failure return value indicates request has been canceled
Cancel routine has run or will run soon

Owner must ensure Request is completed only once

Cancellation Illustrated
Let us take the example of OSR USB Driver
This driver uses device level locking It submits I/O requests to WinUSB The internal completion routine manually uses device level lock Request state is stored in Request context

There are the following possibilities:
1. Request completes without cancellation 2. Request is cancelled
2a. Cancel callback runs before completion callback 2b. Cancel callback runs after completion callback

The driver makes sure that:
Request is completed only once Request is not completed until both completion and cancellation callback are done with it

Cancellation Illustrated (1)
OnRead* … Req->MarkCancelable … WinUSB_ReadPipe … OnCancel* … if (ctx->state == RequestCompleted) { CompleteRequest } else { CancelIoEx ctx->state = CancelInvoked; } * Invoked under DeviceLock OnUSBReadComplete … DeviceLock->AcquireLock(); if (Req->UnmarkCancelable()) { DeviceLock->ReleaseLock(); CompleteRequest } else { if (ctx->state == CancelInvoked) { DeviceLock->ReleaseLock(); CompleteRequest } else { ctx->state = RequestCompleted; DeviceLock->ReleaseLock(); } }

Cancellation Illustrated (2a)
OnRead* … Req->MarkCancelable … WinUSB_ReadPipe … OnCancel* OnUSBReadComplete … DeviceLock->AcquireLock(); if (Req->UnmarkCancelable()) { DeviceLock->ReleaseLock(); CompleteRequest } else { if (ctx->state == CancelInvoked) { DeviceLock->ReleaseLock(); CompleteRequest } else { ctx->state = RequestCompleted; DeviceLock->ReleaseLock(); } }

… if (ctx->state == RequestCompleted) { CompleteRequest } else { CancelIoEx ctx->state = CancelInvoked; }
* Invoked under DeviceLock

Cancellation Illustrated (2b)
OnRead* … Req->MarkCancelable … WinUSB_ReadPipe … OnCancel* OnUSBReadComplete … DeviceLock->AcquireLock(); if (Req->UnmarkCancelable()) { DeviceLock->ReleaseLock(); CompleteRequest } else { if (ctx->state == CancelInvoked) { DeviceLock->ReleaseLock(); CompleteRequest } else { ctx->state = RequestCompleted; DeviceLock->ReleaseLock(); } }

… if (ctx->state == RequestCompleted) { CompleteRequest } else { CancelIoEx ctx->state = CancelInvoked; }
* Invoked under DeviceLock

UMDF OSR USB Sample Walk-through
Cancellation walk-through in the sample driver (src\umdf\usb\driver)
(Queue.cpp) CMyQueue::OnRead CMyQueue::OnCancel CMyQueue::CompletionThread

Putting It Together
You?ve seen the following portions of the sample:
Driver (Driver.cpp)
CMyDriver::OnDeviceAdd

Device (Device.cpp)
CMyDevice::OnPrepareHardware CMyDevice::OnReleaseHardware

Queue (Queue.cpp)
CMyQueue::OnCreateFile CMyQueue::OnCleanupFile CMyQueue::OnRead / CQueue::OnWrite CMyQueue::OnCancel CMyQueue::CompletionThread

Call

to Action
Install the Windows Driver Kit Join the WDF Beta Program
At http://beta.microsoft.com Guest ID: Guest4WDF

Evaluate UMDF for your driver projects
Consider development time, customer support for system crashes, etc.

Send Us Feedback – We want to know
If UMDF will meet your needs What stops you from writing your drivers with UMDF

Additional Resources
Email
umdffdbk @ microsoft.com

Web Resources:
WDF Information:
http://www.microsoft.com/whdc/driver/wdf/default.mspx

Windows Debugger:
http://www.microsoft.com/whdc/devtools/debugging/default.mspx

External Resources
“Introduction to the Windows Driver Foundation: How To Develop Device Drivers Using the Kernel Mode Driver Framework” from OSR Press
Release date is September 2005 Focuses on KMDF but provides general WDF information as well

? 2005 Microsoft Corporation. All rights reserved.
This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.


网站首页网站地图 站长统计
All rights reserved Powered by 海文库
copyright ©right 2010-2011。
文档资料库内容来自网络,如有侵犯请联系客服。zhit326@126.com