How to Develop a UMDF Driver Part 1
Outline
Goals
Architectural Goals
Architectural Block Diagram
UMDF Components
UMDF Components
UMDF Components : Host Process
Host Process - Framework
IPC : Message Passing
Processing Messages
Driver Loading
Driver Loading (Layered UM Drivers)
Driver Loading (Host Process)
I/O Data Flow
I/O in Host Process
Device Removal and Cleanup
When Driver or Application Crashes
Timeout Policy
Impersonation
Using Impersonation
UMDF Verifier
UMDF Verifier Failures
UMDF Error Reporting
Types of Error Reports
Device Driver Interfaces (DDI) and Programming Patterns
Framework Object Model
Key Framework Objects
Parent-Child Object Hierarchy
Framework Object Model
Framework Object Model
DDI Design
DDI : COM Interfaces
All You Need to Know about COM …
Device Driver Interfaces (DDI)
Device Driver Interfaces (DDI)
Device Driver Interfaces (DDI)
Driver Entry
Callback Objects
Callback Objects (con’t)
Callback Objects (con’t)
Callback Objects (con’t)
Summary
How to Develop a UMDF Driver Part 2
Outline
Goals
Writing Your Driver
What is a User-Mode Driver?
UMDF Driver DLL Exports
Common Driver Classes
UMDF Skeleton Driver
Example: CMyDriver Definition (Driver.h)
Example: CMyDriver Implementation (Driver.cpp)
Example: CMyDriver Implementation (con’t)
Example: CMyDevice Definition (Device.h)
Writing Your Driver (Summary)
Installing Your Driver
Registry Locations
Use UMDF CoInstaller
Register Driver DLLs
Configure the Driver List
Setup UM Driver Key
Adding the Reflector Driver
Installing Your Driver (Summary)
Debugging Your Driver
Debugging Overview
Debugger Options
User-Mode or Kernel-Mode Debugging
Enabling the Debugger
Attaching the UM Debugger
UMDF Debugger Extension
Interesting UMDF Breakpoints (BP)
Tracing in Your UM Driver
What Do I Do When It Crashes? (Summary)
Plug and Play / Power Management
UMDF Design Goals for PnP/PM
UMDF PnP/PM Design
UMDF PnP/PM Interfaces
Device Driver Interface (DDI)
IDevicePnpHardware
IDevicePnpHardware
IDevicePnp
IDevicePnp
IDevicePnpSelfManagedIo
PnP/PM Driver Callback Example
WDM Message to UMDF Callback Mapping
WDM Message to UMDF Callback Mapping
PnP/PM Timeouts
Example: DllMain
Example: DllGetClassObject
Example: DllRegisterServer & DllCanUnloadNow
Example: CUnknown Definition
Example: CUnknown Implementation
Example: CClassFactory Definition
Example: CClassFactory Implementation
Debugging with WinDbg
Debugging with a Kernel Debugger
Collecting & Viewing Traces
How to Develop a UMDF Driver: Part 3
Outline
Goals
I/O Request Processing Overview
I/O Request Processing in UMDF
Framework Objects
Framework Objects
I/O Request Processing – A Bird’s Eye view
I/O Request Object
I/O Request Object
I/O Queues
I/O Queues
I/O Queues
I/O Queue Dispatch Types
Automatic Dispatch
Manual Dispatch
Callback Constraints
Callback Constraints (con’t)
Dispatch Type vs. Locking Model
UMDF OSR USB Sample Walk-through
File Objects
File Object
File Object (con’t)
File Object Lifetime
File Object Lifetime Illustrated
Cleanup Handling in Driver
UMDF OSR USB Sample Walk-through
Driver Layering
Driver Layering
Driver Layering Diagram
Request Completion
Request Completion Illustrated
I/O Target
I/O Target
I/O Target Framework Object
Local I/O Target
I/O Target Functionality
Bridging UM and KM stacks
UMDF OSR USB Sample Walk-through
Request Cancellation
Request Cancellation
Cancellation Overview
Request Ownership
Cancellation Handling in Driver
Cancellation Handling in Driver (con’t)
Cancellation Illustrated
Cancellation Illustrated (1)
Cancellation Illustrated (2a)
Cancellation Illustrated (2b)
UMDF OSR USB Sample Walk-through
Putting It Together
Call to Action
Additional Resources
1.37M
Category: informaticsinformatics

How to Develop a UMDF Driver Part 1

1. How to Develop a UMDF Driver Part 1

2. 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

3. Goals

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

4. 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

5. Architectural Block Diagram

Application(s)
Driver
Manager
Host Process
Host Process
UM
Driver
UM
Driver
WinSock
User
Kernel
Reflector
Windows Kernel
(I/O Mgr, PnP)
Reflector
Kernel Driver
(e.g., WinUSB)
Provided by:
Microsoft
ISV
IHV
Kernel Driver 2
Device Stack
Device Stack

6. 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
Host Process
Driver
Manager
UM
Driver
Reflector

7. 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
Host Process
Driver
Manager
UM
Driver
Reflector

8. 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
Reflector
Framework
DDI
UM
Driver

9. 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

10. 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

11. 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 them
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

12. Driver Loading

5
Driver
Manager
3
Host
Runtime
2
Windows Kernel
(I/O Mgr, PnP)
Provided by:
Microsoft
IHV
1
Add Device
6
Framework
4
UM
Driver
IPC Channel
Reflector
Kernel Driver

13. Driver Loading (Layered UM Drivers)

7
Driver
Manager
3
Host
Runtime
8
5
6
2
Windows Kernel
(I/O Mgr, PnP)
Provided by:
Microsoft
IHV
1
Add Device
UM Filter
Driver
Framework
Framework
4
UM Driver
IPC Channel
Reflector
Kernel Driver

14. Driver Loading (Host Process)

Add Device
Host
Runtime
Add Device
Driver creates WDF Device
Framework
UM Driver
Driver creates WDF Queue
Driver creates WDF Queue
Add Device
Provided by:
Microsoft
IHV

15. I/O Data Flow

UM Filter
Driver
Framework
UM I/O Mgr
1
5
Host Process
Application
4
Device
Stack
6
7
9
8
Win32 I/O
API
Framework
10
11
3
UM Driver
12
IPC Message
Windows Kernel
2
IRP
“Up” Device
Object
“Down” Device
Object
Reflector
Provided by:
Microsoft
ISV
IHV
Kernel driver

16. I/O in Host Process

Invoke driver callback
passing in I/O request
Run-time
Host
File Object
UM
IRP
UM Irp
Framework
Device
Stack
IPC Message Host File Object returned
as context to the reflector.
Provided by:
Microsoft
ISV
IHV
Driver can return without
completing i/o (asynch)
Driver eventually
completes i/o.
UM Driver

17. Device Removal and Cleanup

Run-time
Framework
UM Driver
Device Remove
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

18. 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

19. 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

20. 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;

21. 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

22. 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)

23. 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

24. 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

25. 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

26. Device Driver Interfaces (DDI) and Programming Patterns

27. Framework Object Model

Framework objects have a
hierarchical relationship
WDF Driver is the root object
Child lifetime scoped by parent
Every WDF object is defined by
Methods: actions on objects
Properties: are object attributes
Events: notifications from
Framework objects to the driver
WDF Driver
WDF Device
WDF
Queue
WDF
Queue

28. 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

29. 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

30. Framework Object Model

Framework
Driver
WDF Driver
MyDriver
MyDevice
WDF Device
WDF
Queue
WDF
Queue
WDF Objects
Provided by:
Microsoft
IHV
MyRead
Queue
MyWrite
Queue
Driver implemented
Callback Objects

31. Framework Object Model

Framework
Driver 1
MyDriver1
WDF Driver
MyDevice1
WDF Device
WDF Queue
WDF
Queue
WDF Driver
Device Stack
WDF Device
WDF Queue
WDF Queue
MyWrite
Queue1
MyDevice2
MyRead
Queue2
MyRead
Queue1
MyDriver2
MyWrite
Queue2
Driver 2
Each driver in the stack has its own set of
framework objects

32. 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

33. 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)

34. 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

35. 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

36. 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 );
};

37. 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++

38. 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

39. 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 );
...
}

40. 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;
OnPrepareHardware(
IWDFDevice* pDevice
);
STDMETHOD( OnReleaseHardware )( IWDFDevice *pDevice );
// Factory method
static HRESULT CreateInstance(
IUnknown *pUnknown,
IWDFDeviceInitialize *pDeviceInit,
HANDLE CompletionPort
);
...
};
Context
Callback

41. 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;
}

42. Callback Objects (con’t)

1
OnDeviceAdd
IDriverEntry
Callback Object
WDF Driver
2
IWDFDriver::CreateDevice( … ) 3
WDF Device
5
Framework
Provided by:
Microsoft
IHV
IUnknown
MyDevice
4
QueryInterface for
• IDevicePnP
• IDevicePnPHardware
----
IDevicePnpHardware
Driver

43. 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

44. How to Develop a UMDF Driver Part 2

45. 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

46. 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

47. Writing Your Driver

48. 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

49. 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

50. 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

51. 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
Device.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

52. 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...
};

53. 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;
}

54. 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;
}

55. 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
}

56. 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

57. 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

58. 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
Location
%UMDF_Software%
HKLM \
Software \
Microsoft \
Windows NT \
CurrentVersion \
WUDF
%UMDF_Services%
%UMDF_Software% \
Services
%UMDF_Host%
%UMDF_Services% \
{193a1820-d9ac-4997-8c55-be817523f6aa}

59. 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

60. 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

61. 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

62. 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

63. 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

64. 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 ?

65. Debugging Your Driver

66. 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

67. 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

68. 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

69. 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

70. 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”

71. 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.

72. 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 when 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

73. 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

74. 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

75. Plug and Play / Power Management

76. 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

77.

78. 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

79. 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()

80. 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
INamedPropertyStore * pPropStore = NULL;
hr = pDeviceInit->GetDevicePropertyStore( &pPropStore );
...
}

81. 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();
}

82. 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;
}

83. 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();

84. 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
}

85. 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

86. PnP/PM Driver Callback Example

87.

Start Device
OnPrepareHardware()
Device Driver
Framework
Start Device
Off
On
Off

88.

Start Device
OnD0Entry()
Device Driver
Framework
Start Device
Off
On
Off

89.

Device Operational
Device Driver
Framework
On
On
Off

90.

Suspend Device
OnD0Exit()
Device Driver
Framework
Power Down
On
On
Off

91.

Resume Device
OnD0Entry()
Device Driver
Framework
Power Up
On
On
Off

92.

Remove Device
OnD0Exit()
Device Driver
Framework
Remove
Device
On
On
Off

93.

Remove Device
OnReleaseHardware()
Device Driver
Framework
Remove
Device
On
On
Off

94. WDM Message to UMDF Callback Mapping

Start -> Query Remove -> Remove
IRP_MN_START_DEVICE:
OnPrepareHardware()
OnD0Entry()
OnSelfManagedIoInit()
IRP_MN_QUERY_REMOVE_DEVICE:
OnQueryRemove()
IRP_MN_REMOVE_DEVICE:
OnSelfManagedIoSuspend()
OnD0Exit()
OnSelfManagedIoFlush()
OnReleaseHardware()
OnSelfManagedIoCleanup()

95. 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()

96. 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

97.

Supplemental Slides

98. 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

99. 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;
}

100. Example: DllRegisterServer & DllCanUnloadNow

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;
}

101. 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 );
};

102. 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;
}

103. Example: CClassFactory Definition

class CClassFactory : public CUnknown,
public IClassFactory {
public:
IClassFactory *QueryIClassFactory() {...}
// IUnknown
AddRef() {return __super::AddRef()}
Release() {return __super::Release()}
QueryInterface(...);
// IClassFactory
HRESULT CreateInstance(
IUnknown *Outer, REFIID InterfaceId, PVOID *Object
);
HRESULT LockServer(BOOL Lock) {
return S_OK;
}
};

104. 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;
}

105. 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

106. 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

107. Collecting & Viewing Traces

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

108. How to Develop a UMDF Driver: Part 3

109. Outline

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

110. 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

111. I/O Request Processing Overview

112. I/O Request Processing in UMDF

You’ve seen WDF Driver and Device 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

113. Framework Objects

Driver
Device
Request
Memory (Input)
Memory (Output)
Queue
File
I/O Target

114. Framework Objects

These objects are associated with request processing
All derive from IWDFObject
Object
Description
Device
The information associated with a single layer in a device stack
Request
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.
Queue
File
I/O Target
Memory
A buffer associated with a request

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

Request
I/O Queue
Driver
I/O Target
Complete

116. I/O Request Object

Request
I/O Queue
Driver
I/O Target
Complete

117. 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

118. I/O Queues

119. I/O Queues

Request
I/O Queue
Driver
I/O Target
Complete

120. 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

121. 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

122. 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

123. 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 request 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

124. 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

125. 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

126. Dispatch Type vs. Locking Model

Combining Dispatch Type and Locking Model
provides several modes of operation
For example:
Sequential Queue
Device Level Locking
Parallel Queue
Device Level Locking
Request1
Request1
Req1 Complete
Request2
Request2
Req2 Complete
Req1 Complete
Req2 Complete
Parallel Queue
No Locking
Request1
Request2
Req1 Complete
Req2 Complete

127. 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)

128. File Objects

129. 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

130. File Object (con’t)

Device
File1
Request1
Request2
File2
Request1
Request2

131. 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

132. File Object Lifetime Illustrated

Example of I/O sequence between App
and Driver
Application
hFile = CreateFile(…

Async/Sync Read/Write/IoCtl

CloseHandle(hFile);
Driver
Create Request

Read/Write/IoCtl Requests

Cleanup

Any remaining Requests drain

Close

133. Cleanup Handling in Driver

Cleanup received when client closes connection
Notification 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

134. 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

135. Driver Layering

136. 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

137. Driver Layering Diagram

Framework
Device
Queue
File
Request
Framework
Device
Queue
File
Request
Framework
Device
Device Stack
Queue
File
Request

138. 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

139. Request Completion Illustrated

Request
Completion Routine
Request
Completion Routine
Request

140. I/O Target

141. I/O Target

Request
I/O Queue
Driver
I/O Target
Complete

142. 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

143. Local I/O Target

Application
Device
I/O Target
Device
I/O Target
Device
I/O Target
User Mode
Kernel Mode
Up Device
Down Device
Device
Device
Device Stack
Reflector

144. 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 cancelled when timeout expires
Tracks sent requests for the driver
Allows automatic purge or flush on I/O target stop
Coordinates completion and cancellation

145. 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

146. 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)

147. Request Cancellation

148. 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

149. 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

150. 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

151. 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

152. 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

153. 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

154. 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();
}
}

155. Cancellation Illustrated (2a)

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();
}
}

156. Cancellation Illustrated (2b)

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();
}
}

157. 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

158. 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

159. 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

160. 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

161.

© 2005 Microsoft Corporation. All rights reserved.
This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
English     Русский Rules