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

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

Слайд 3

Goals

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

are structured

Goals An understanding of UMDF infrastructure An understanding of the UMDF DDIs and

Слайд 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

Architectural Goals Stability Driver failures should NOT bring down the system Build on

Слайд 5

Device Stack

Device Stack

Architectural Block Diagram

Windows Kernel
(I/O Mgr, PnP)

Reflector

Driver
Manager

Kernel Driver
(e.g., WinUSB)

Application(s)

Kernel Driver 2

User

Kernel

Host

Process

UM
Driver

Host Process

WinSock

Reflector

UM
Driver

Device Stack Device Stack Architectural Block Diagram Windows Kernel (I/O Mgr, PnP) Reflector

Слайд 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

Reflector

Driver
Manager

Host Process

UM
Driver

UMDF Components Driver manager Global, system-wide Windows Service Responsible for host process lifetime

Слайд 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

Reflector

Driver
Manager

Host Process

UM
Driver

UMDF Components Reflector Nucleus of UMDF Installed with each device stack Proxy for

Слайд 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

Reflector

Driver
Manager

UMDF Components : Host Process Child process of the UM Driver Manager Unit

Слайд 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

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

Слайд 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

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

Слайд 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

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

Слайд 12

Driver Loading

Windows Kernel
(I/O Mgr, PnP)

Driver
Manager

Reflector

Kernel Driver

1

3

Add Device

2

Driver Loading Windows Kernel (I/O Mgr, PnP) Driver Manager Reflector Kernel Driver 1

Слайд 13

Driver Loading (Layered UM Drivers)

Add Device

Driver Loading (Layered UM Drivers) Add Device

Слайд 14

Driver Loading (Host Process)

UM Driver

Host
Runtime

Framework

Driver Loading (Host Process) UM Driver Host Runtime Framework

Слайд 15

Host Process

I/O Data Flow

Kernel driver

Windows Kernel

“Up” Device
Object

Application

UM Filter
Driver

UM I/O Mgr

“Down” Device
Object

Reflector

Device

Stack

Framework

UM Driver

Framework

Host Process I/O Data Flow Kernel driver Windows Kernel “Up” Device Object Application

Слайд 16

I/O in Host Process

UM Driver

Run-time

Framework

Device Stack

Invoke driver callback
passing in I/O request

UM Irp

Host File

Object returned as context to the reflector.

IPC Message

Host
File Object

UM
IRP

Driver can return without
completing i/o (asynch)

Driver eventually
completes i/o.

I/O in Host Process UM Driver Run-time Framework Device Stack Invoke driver callback

Слайд 17

Device Removal and Cleanup

UM Driver

Run-time

Framework

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

Device Removal and Cleanup UM Driver Run-time Framework Device Remove Message path similar

Слайд 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

When Driver or Application Crashes When the UM driver crashes: Reflector gets notification

Слайд 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

Timeout Policy UMDF enforces timeouts on “critical” operations Operations that run under system

Слайд 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;

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

Слайд 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

Using Impersonation Application controls the allowed level Specified in QOS settings in CreateFile

Слайд 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)

UMDF Verifier Built-in verification Checks for problems in framework code Checks for problems

Слайд 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

UMDF Verifier Failures Driver failures will “Bugcheck” the host Bugcheck is NOT the

Слайд 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

UMDF Error Reporting Current driver failure reports are hard to analyze Too much

Слайд 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

Types of Error Reports UMDF will report the following problems : UM Driver

Слайд 26

Device Driver Interfaces (DDI) and Programming Patterns

Device Driver Interfaces (DDI) and Programming Patterns

Слайд 27

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

Framework Object Model

Framework objects have a hierarchical relationship WDF Driver is the root object Child

Слайд 28

Key Framework Objects

Key Framework Objects

Слайд 29

Parent-Child Object Hierarchy

Device

I/O Queue

I/O Request

I/O Target

Driver

File

Applies to lifetime management
Lifetime of child is scoped

within that of the parent
Child is cleaned up when the parent goes away

Parent-Child Object Hierarchy Device I/O Queue I/O Request I/O Target Driver File Applies

Слайд 30

Framework Object Model

MyDriver

MyRead
Queue

MyWrite
Queue

Framework

Driver

Driver implemented Callback Objects

WDF Objects

MyDevice

Framework Object Model MyDriver MyRead Queue MyWrite Queue Framework Driver Driver implemented Callback

Слайд 31

Framework Object Model

MyDriver1

MyDevice1

MyRead
Queue1

MyWrite
Queue1

Framework

Driver 1

WDF Driver

WDF Device

WDF Queue

WDF Queue

WDF Driver

WDF Queue

WDF

Device

WDF Queue

Driver 2

MyDevice2

MyDriver2

MyWrite
Queue2

MyRead
Queue2

Device Stack

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

Framework Object Model MyDriver1 MyDevice1 MyRead Queue1 MyWrite Queue1 Framework Driver 1 WDF

Слайд 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

DDI Design Common object model with KMDF Driver writers familiar with KMDF can

Слайд 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)

DDI : COM Interfaces Problems solved by Interfaces Allows us to evolve the

Слайд 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

All You Need to Know about COM … COM interfaces, by convention, start

Слайд 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

Device Driver Interfaces (DDI) UMDF DDI is in wudfddi.idl interface IWDFObject : IUnknown

Слайд 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
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) DDIs are grouped into 2 types of interfaces Functionality

Слайд 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++

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

Слайд 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

Driver Entry IDriverEntry is the top driver-exported interface interface IDriverEntry::IUnknown { HRESULT OnInitialize(

Слайд 39

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,
pDeviceInit,
completionPort );
...
// Create WDF Device
hr = pDriver->CreateDevice( pDeviceInit,
pDeviceCallback,
&pIWDFDevice );
...
}

Callback Objects

1

2

Callback objects = Callbacks + Context Example: Creating Device Object HRESULT CMyDriver::OnDeviceAdd( IWDFDriver*

Слайд 40

Callback Objects (con’t)

class CMyDevice :
public IDevicePnpHardware // Callback interface exposed to

// framework.
{
private:
HANDLE m_CompletionPort;
WINUSB_INTERFACE HANDLE m_UsbHandle;
UCHAR m_BulkOutPipe;
ULONG m_BulkOutMaxPacket;
...
public:
virtual HRESULT stdcall OnPrepareHardware(
IWDFDevice* pDevice
);
STDMETHOD( OnReleaseHardware )( IWDFDevice *pDevice );
// Factory method
static HRESULT CreateInstance(
IUnknown *pUnknown,
IWDFDeviceInitialize *pDeviceInit,
HANDLE CompletionPort
);
...
};

Context

Callback

Callback Objects (con’t) class CMyDevice : public IDevicePnpHardware // Callback interface exposed to

Слайд 41

Callback Objects (con’t)

static HRESULT CreateInstance(
IUnknown **ppUnknown,
IWDFDeviceInitialize *pDeviceInit,
HANDLE CompletionPort

) {
...
// Allocate our callback context
CMyDevice *pMyDevice = new CMyDevice();
...
// Get our callback interface
hr = pMyDevice->QueryInterface(
__uuidof(IUnknown),
(void **) ppUnknown
);
...
return hr;
}

1

2

Callback Objects (con’t) static HRESULT CreateInstance( IUnknown **ppUnknown, IWDFDeviceInitialize *pDeviceInit, HANDLE CompletionPort )

Слайд 42


Callback Objects (con’t)

WDF Driver

Framework

Driver

IDriverEntry

5

Callback Objects (con’t) WDF Driver Framework Driver IDriverEntry 5

Слайд 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

Summary Discussed driver loading/unloading, I/O data flow Driver installation and setup are same

Слайд 44

How to Develop a UMDF Driver Part 2

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

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

Слайд 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

Goals How to start writing and debugging a UMDF driver How to interact

Слайд 47

Writing Your Driver

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

What is a User-Mode Driver? User-Mode (UM) Drivers are DLLs Provide driver’s “callback

Слайд 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

UMDF Driver DLL Exports DllMain Called when DLL loads (and unloads) Construct global

Слайд 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

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

Слайд 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

UMDF Skeleton Driver Example code based on UMDF Skeleton sample Code in slides

Слайд 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...
};

Example: CMyDriver Definition (Driver.h) class CMyDriver: public CUnknown, public IDriverEntry { IDriverEntry *QueryIDriverEntry();

Слайд 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;
}

Example: CMyDriver Implementation (Driver.cpp) HRESULT CMyDriver::CreateInstance( CMyDriver **Driver ) { CMyDriver *driver =

Слайд 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;
}

Example: CMyDriver Implementation (con’t) HRESULT CMyDriver::OnDeviceAdd(...) { CMyDevice *deviceCallback; IWDFDevice *fxDevice; HRESULT 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
}

Example: CMyDevice Definition (Device.h) class CMyDevice : public CUnknown { HRESULT Initialize( IWDFDeviceInitialize

Слайд 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

Writing Your Driver (Summary) Create the common code Required DLL Exports COM support

Слайд 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

Installing Your Driver INF Based Installation Just like WDM and kernel-mode WDF drivers

Слайд 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

Registry Locations UMDF keeps information in several registry keys We’ll refer to them

Слайд 59

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

Use UMDF CoInstaller

System provided CoInstaller Sets Driver Manager to start automatically WUDFCoInstaller.dll is already installed

Слайд 60

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

Register Driver DLLs

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

Слайд 61

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

Configure the Driver List

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

Слайд 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

Setup UM Driver Key Create an entry under UMDF Services Key One for

Слайд 63

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

Adding the Reflector Driver

Reflector driver is WUDFRd.sys Already installed on the system Your INF must make

Слайд 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 ?

Installing Your Driver (Summary) Use the UMDF CoInstaller Register your Driver DLLs with

Слайд 65

Debugging Your Driver

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

Debugging Overview Similar to service debugging UM Drivers cannot be started by the

Слайд 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

Debugger Options WinDbg GUI Debugger Source and/or Assembly level debugging UMDF debugger extension

Слайд 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 ” to break into running host
See additional slides for KM Debugging tips

User-Mode or Kernel-Mode Debugging Can debug UMDF with UM or KM debugger You

Слайд 69

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

Enabling the Debugger

Host process started by Driver Manager service You can’t attach debugger until after

Слайд 70

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”

Attaching the UM Debugger

Cannot connect UM Debugger until host starts Enable the Initial Breakpoint Attach the

Слайд 71

UMDF Debugger Extension

WudfExt.dll
Copy into your path
“!load WudfExt.dll” debugger command loads the extension
Names are

case sensitive

UMDF Debugger Extension WudfExt.dll Copy into your path “!load WudfExt.dll” debugger command loads

Слайд 72

Interesting UMDF Breakpoints (BP)

Hopefully, this will get you started

Interesting UMDF Breakpoints (BP) Hopefully, this will get you started

Слайд 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

Tracing in Your UM Driver Recommend using WPP tracing for debug output Lightweight

Слайд 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

What Do I Do When It Crashes? (Summary) Check for configuration problems Is

Слайд 75

Plug and Play / Power Management

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

UMDF Design Goals for PnP/PM Coordinate I/O delivery to driver with PnP/PM events

Слайд 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

UMDF PnP/PM Design Implemented with a state machine Consumes PnP/Power messages from the

Слайд 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()

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

Слайд 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 );
...
}

Device Driver Interface (DDI) IDriverEntry::OnDeviceAdd Driver must implement this interface Called when framework

Слайд 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();
}

IDevicePnpHardware OnPrepareHardware Called when device is first started Driver establishes connection to the

Слайд 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;
}

IDevicePnpHardware OnReleaseHardware Called when device is removed or stopped Driver should essentially undo

Слайд 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();

IDevicePnp OnD0Exit Called each time device should power down Also called before the

Слайд 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
}

IDevicePnp OnSurpriseRemoval Called when the device has unexpectedly detached from the PC 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

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

Слайд 86

PnP/PM Driver Callback Example

PnP/PM Driver Callback Example

Слайд 87

Device Driver

Off

On

Off

Framework

Start Device

OnPrepareHardware()

Device Driver Off On Off Framework Start Device OnPrepareHardware()

Слайд 88

Device Driver

Off

On

Off

Framework

OnD0Entry()

Start Device

Device Driver Off On Off Framework OnD0Entry() Start Device

Слайд 89

Device Driver

Off

On

On

Device Operational

Framework

Device Driver Off On On Device Operational Framework

Слайд 90

Device Driver

Off

On

On

OnD0Exit()

Suspend Device

Framework

Device Driver Off On On OnD0Exit() Suspend Device Framework

Слайд 91

Device Driver

Off

On

On

OnD0Entry()

Resume Device

Framework

Device Driver Off On On OnD0Entry() Resume Device Framework

Слайд 92

Device Driver

Off

On

On

OnD0Exit()

Remove Device

Framework

Device Driver Off On On OnD0Exit() Remove Device Framework

Слайд 93

Device Driver

Off

On

On

OnReleaseHardware()

Remove Device

Framework

Device Driver Off On On OnReleaseHardware() Remove Device Framework

Слайд 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()

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

Слайд 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()

WDM Message to UMDF Callback Mapping Start -> Surprise Removal -> Remove IRP_MN_START_DEVICE:

Слайд 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
IRP_MN_START results in:
OnPrepareHardware
OnD0Entry
OnSelfManagedIoInit

1 minute

1 minute

PnP/PM Timeouts Each WDM PnP/PM message has a timeout Currently, this timeout is

Слайд 97

Supplemental Slides

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

Example: DllMain BOOL DllMain( HINSTANCE ModuleHandle, DWORD Reason, PVOID Reserved ) { if

Слайд 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;
}

Example: DllGetClassObject HRESULT DllGetClassObject( REFCLSID ClassId, REFIID InterfaceId, PVOID *Interface ) { PCClassFactory

Слайд 100

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: DllRegisterServer & DllCanUnloadNow HRESULT DllRegisterServer() { return UpdateCOMRegistration( g_ModuleHandle, IDR_MYDRIVER_CLASSINFO, true, __uuidof(

Слайд 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 );
};

Example: CUnknown Definition class CUnknown : public IUnknown { LONG m_RefCount; public: CUnknown()

Слайд 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;
}

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

Слайд 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;
}
};

Example: CClassFactory Definition class CClassFactory : public CUnknown, public IClassFactory { public: IClassFactory

Слайд 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;
}

Example: CClassFactory Implementation HRESULT CClassFactory::QueryInterface(...) { if(IsEqualIID(Interface, __uuidof(IClassFactory)) { *Object = QueryIClassFactory(); return

Слайд 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 ” sets an excution breakpoint
Use bu if the function’s module isn’t loaded yet
‘ba [w|r] [1|2|4|8] ’ sets a watchpoint
ba r 4 MyDriver!g_MyArrayLength
Dumping Memory
d [address] [L]
type = byte, word, char, unicode, dword, quadword, string
dd MyMyDriver!g_MyArrayLength L1
dv dumps local variable names
Dumping Types
dt dumps a specific local
dt dumps an address or symbol as a type
dt ??? MyDriver!CMyDevice
See the WinDbg help for more details

Debugging with WinDbg Source Level GUI debugger (Most) commands work on addresses or

Слайд 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

Debugging with a Kernel Debugger WinDbg can be used as a kernel debugger

Слайд 107

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/en-us/ddtools/hh/ddtools/tracetools_8eccb8f7-6f29-4683-87bd-fa83618c32eb.xml.asp

Collecting & Viewing Traces TraceLog.exe lets you control trace sessions To start a

Слайд 108

How to Develop a UMDF Driver: Part 3

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

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

Goals A better understanding of: How to incorporate I/O processing in a UMDF

Слайд 111

I/O Request Processing Overview

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

I/O Request Processing in UMDF You’ve seen WDF Driver and Device objects These

Слайд 113

Request

Framework Objects

Device

Queue

I/O Target

Memory (Input)

Memory (Output)

Driver

File

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

Слайд 114

Framework Objects

These objects are associated with request processing
All derive from IWDFObject

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

Слайд 115

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

Request

I/O Queue

Driver

I/O Target

Complete

I/O Request Processing – A Bird’s Eye view Request I/O Queue Driver I/O Target Complete

Слайд 116

I/O Request Object

I/O Queue

Driver

I/O Target

Complete

Request

I/O Request Object I/O Queue Driver I/O Target Complete Request

Слайд 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

I/O Request Object Represents a request Sent to the driver by a client

Слайд 118

I/O Queues

I/O Queues

Слайд 119

I/O Queues

I/O Queue

Driver

I/O Target

Complete

Request

I/O Queues I/O Queue Driver I/O Target Complete Request

Слайд 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

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

Слайд 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

I/O Queue Dispatch Types Dispatch Type controls how requests are presented to driver

Слайд 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

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

Слайд 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

Manual Dispatch Driver pulls requests from the queue Typically starts in response to

Слайд 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

Callback Constraints Callback constraints specify locking model for Queue callbacks Callback constraints options

Слайд 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

Callback Constraints (con’t) Constraints apply only to Queue Callbacks Queue callbacks include Automatic

Слайд 126

Dispatch Type vs. Locking Model

Request1

Req1 Complete

Request2

Req2 Complete

Request1

Req1 Complete

Request2

Req2 Complete

Request1

Req1 Complete

Req2 Complete

Request2

Combining Dispatch Type

and Locking Model provides several modes of operation
For example:

Dispatch Type vs. Locking Model Request1 Req1 Complete Request2 Req2 Complete Request1 Req1

Слайд 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)

UMDF OSR USB Sample Walk-through Requests and Queue Usage in the sample driver

Слайд 128

File Objects

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

File Object File Object represents open connection to device It is the session

Слайд 130

File Object (con’t)

Device

File1

Request1

Request2

File2

Request1

Request2

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

File Object Lifetime File Object’s lifetime spans Create: File Object gets created in

Слайд 132

File Object Lifetime Illustrated

Close


Any remaining Requests drain

Cleanup

CloseHandle(hFile);



Read/Write/IoCtl Requests

Async/Sync Read/Write/IoCtl



Create Request

hFile =

CreateFile(…

Driver

Application

Example of I/O sequence between App and Driver

File Object Lifetime Illustrated Close … Any remaining Requests drain … Cleanup CloseHandle(hFile);

Слайд 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

Cleanup Handling in Driver Cleanup received when client closes connection Notification for driver

Слайд 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

UMDF OSR USB Sample Walk-through File usage in the sample driver (src\umdf\usb\driver) (Queue.cpp)

Слайд 135

Driver Layering

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

Driver Layering UMDF supports driver layering Multiple drivers build a device stack “Function”

Слайд 137

Driver Layering Diagram

Device

Queue

File

Request

Device

Queue

File

Request

Device

Queue

File

Request

Device Stack

Framework

Framework

Framework

Driver Layering Diagram Device Queue File Request Device Queue File Request Device Queue

Слайд 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

Request Completion When Driver receives a Request it can Complete the Request synchronously

Слайд 139

Request Completion Illustrated

Request

Completion Routine

Request

Completion Routine

Request

Request Completion Illustrated Request Completion Routine Request Completion Routine Request

Слайд 140

I/O Target

I/O Target

Слайд 141

I/O Target

I/O Queue

Driver

I/O Target

Complete

Request

I/O Target I/O Queue Driver I/O Target Complete Request

Слайд 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

I/O Target Framework Object Provides a way to send requests to another device

Слайд 143

Device Stack

I/O Target

I/O Target

I/O Target

Device

Device

Device

Local I/O Target

User Mode

Kernel Mode

Device

Device

Down Device

Application

Reflector

Up Device

Device Stack I/O Target I/O Target I/O Target Device Device Device Local I/O

Слайд 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

I/O Target Functionality State based I/O handling Driver can start and stop the

Слайд 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

Bridging UM and KM stacks I/O Target provides bridge between KM and UM

Слайд 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)

UMDF OSR USB Sample Walk-through I/O Target usage in the sample filter (src\umdf\usb\filter)

Слайд 147

Request Cancellation

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

Request Cancellation Application can cancel a request at any time by Using CancelIo[Ex]

Слайд 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

Cancellation Overview Request Owner can register a cancel callback Cancel callback follows locking

Слайд 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

Request Ownership Request ownership starts with I/O Queue Request ownership moves from: Queue

Слайд 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

Cancellation Handling in Driver When driver receives a Request, it may: Complete it

Слайд 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

Cancellation Handling in Driver (con’t) Driver may register a cancel notification callback void

Слайд 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

Cancellation Illustrated Let us take the example of OSR USB Driver This driver

Слайд 154

OnRead*

OnRead*

ctx->state = RequestCompleted;
DeviceLock->ReleaseLock();
}

Cancellation Illustrated (1)


WinUSB_ReadPipe


Req->MarkCancelable



OnUSBReadComplete

}

else {

DeviceLock->ReleaseLock();
CompleteRequest
}

if (ctx->state == CancelInvoked) {

else {

DeviceLock->ReleaseLock();
CompleteRequest
}

if (Req->UnmarkCancelable()) {

DeviceLock->AcquireLock();

OnUSBReadComplete

* Invoked under DeviceLock

OnRead* OnRead* ctx->state = RequestCompleted; DeviceLock->ReleaseLock(); } Cancellation Illustrated (1) … WinUSB_ReadPipe …

Слайд 155

OnCancel*

OnCancel*

OnRead*

}

Cancellation Illustrated (2a)


WinUSB_ReadPipe


Req->MarkCancelable



OnUSBReadComplete

if (Req->UnmarkCancelable()) {

DeviceLock->AcquireLock();

}

ctx->state = CancelInvoked;

CancelIoEx

else {

}

CompleteRequest

if (ctx->state ==

RequestCompleted) {


OnUSBReadComplete

ctx->state = RequestCompleted;
DeviceLock->ReleaseLock();
}

DeviceLock->ReleaseLock();
CompleteRequest
}

if (ctx->state == CancelInvoked) {

else {

DeviceLock->ReleaseLock();
CompleteRequest
}

else {

* Invoked under DeviceLock

OnCancel* OnCancel* OnRead* } Cancellation Illustrated (2a) … WinUSB_ReadPipe … Req->MarkCancelable … …

Слайд 156

OnCancel*

OnCancel*

}

Cancellation Illustrated (2b)


WinUSB_ReadPipe


Req->MarkCancelable


OnRead*


OnUSBReadComplete

if (Req->UnmarkCancelable()) {

DeviceLock->AcquireLock();

}

ctx->state = CancelInvoked;

CancelIoEx

else {

}

CompleteRequest

if (ctx->state ==

RequestCompleted) {


OnUSBReadComplete

ctx->state = RequestCompleted;
DeviceLock->ReleaseLock();
}

DeviceLock->ReleaseLock();
CompleteRequest
}

if (ctx->state == CancelInvoked) {

else {

DeviceLock->ReleaseLock();
CompleteRequest
}

else {

* Invoked under DeviceLock

OnCancel* OnCancel* } Cancellation Illustrated (2b) … WinUSB_ReadPipe … Req->MarkCancelable … OnRead* …

Слайд 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

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

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

Слайд 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

Call to Action Install the Windows Driver Kit Join the WDF Beta Program

Слайд 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

Additional Resources Email umdffdbk @ microsoft.com Web Resources: WDF Information: http://www.microsoft.com/whdc/driver/wdf/default.mspx Windows Debugger:

Имя файла: How-to-Develop-a-UMDF-Driver-Part-1.pptx
Количество просмотров: 64
Количество скачиваний: 0