How to Develop a UMDF Driver Part 1. Outline Architectural Goals Architectural Description Core...
Click here to load reader
-
Upload
alfred-hunt -
Category
Documents
-
view
293 -
download
7
Transcript of How to Develop a UMDF Driver Part 1. Outline Architectural Goals Architectural Description Core...
How to Develop a UMDF DriverPart 1
OutlineOutline
Architectural Goals
Architectural DescriptionCore components
Driver Manager, Reflector, Host Process, and Drivers
Driver startup and teardown
I/O flow
Layered drivers
Driver Programming ModelWDF object model
COM-lite
UMDF DDIs
GoalsGoals
An understanding of UMDF infrastructure
An understanding of the UMDF DDIs and how they are structured
Architectural Goals Architectural Goals
StabilityDriver failures should NOT bring down the system
Build on Windows NT I/O modelApplications 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
SecurityDriver failures should NOT compromise the system
Driver runs in “LocalService” account
Shared model between KMDF and UMDFShared model != same DDIs or data structures
Device StackDevice Stack
Architectural Block DiagramArchitectural Block Diagram
Provided by:Provided by:
MicrosoftMicrosoft
ISVISV
IHVIHV
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
UMDF ComponentsUMDF Components
Driver managerGlobal, 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 ProcessUM
Driver
UMDF ComponentsUMDF Components
ReflectorNucleus 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 ProcessUM
Driver
UMDF Components : Host ProcessUMDF Components : Host Process
Child process of the UM Driver ManagerUnit 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 driverI/O dispatching, driver loading, driver layering, thread pool
Handles messages from reflector and driver manager
Reflector
Driver Manager
UM Driver
Runtime FrameworkDDI
Host Process - FrameworkHost Process - Framework
Implements all of the WDF modelQueues, Request, I/O target, etc
Implements default behaviorReduces vendor written code
Exposes DDI
Implemented as DLL
UM Driver
Runtime Framework DDI
IPC : Message PassingIPC : Message Passing
RequirementsPacket-based and asynchronous
Cancelable
Fail-safe
Efficient data transfer
Secure
Several potential solutionPending I/O, synchronous message passing
Windows codenamed “Longhorn” solution: ALPCStandard Windows OS Component
Processing MessagesProcessing Messages
KM drivers handle I/O in caller’s threadObviously not a option for UMDF
Host has a thread pool processing messagesDedicated 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/OPool could grow or shrink as load changes
Fixed at 2 threads for Beta 1
For long operations the driver should consider using work-items
Driver Loading Driver Loading
Windows Kernel(I/O Mgr, PnP)
Driver Manager
Host Runtime
Reflector
Kernel Driver
1
3
Add Device
Framework6 UM
Driver
5
2 IPC Channel4
Provided by:Provided by:
MicrosoftMicrosoft
IHVIHV
Host Runtime
IPC Channel
Driver Loading (Layered UM Drivers)Driver Loading (Layered UM Drivers)
Windows Kernel(I/O Mgr, PnP)
Driver Manager
Reflector
Kernel Driver
2
3
Add Device
Framework6 UM Driver
5
4
UM FilterDriver
7
Framework8
1
Provided by:Provided by:
MicrosoftMicrosoft
IHVIHV
Driver Loading (Host Process)Driver Loading (Host Process)
UM DriverHost
Runtime Framework
Add Device
Driver creates WDF Device
Add Device
Add Device
Driver creates WDF Queue
Driver creates WDF Queue
Provided by:Provided by:
MicrosoftMicrosoft
IHVIHV
Host Process
I/O Data FlowI/O Data Flow
Kernel driver
Windows Kernel“Up” Device
Object
ApplicationUM Filter
DriverUM I/O Mgr
“Down” Device Object
Reflector
Device Stack
FrameworkUM Driver
IRP2
IPC Message
3
47
8
12
6
5
9
Framework
Win32 I/O API
1
1011
Provided by:Provided by:
MicrosoftMicrosoft
ISVISV
IHVIHV
I/O in Host ProcessI/O in Host Process
UM Driver
Run-time
Framework
Device Stack
Invoke driver callbackpassing in I/O request
UM Irp
Host File Object returned as context to the reflector.
IPC Message
Host File Object
UMIRP
Driver can return without completing i/o (asynch)
Driver eventuallycompletes i/o.
Provided by:Provided by:
MicrosoftMicrosoft
ISVISV
IHVIHV
Device Removal and CleanupDevice Removal and Cleanup
UM DriverRun-time Framework
Device Remove
Message path similar to “add device” pathDriver gets several PnP notifications for remove
UM driver may unload when remove finishes
Host process may exit when all drivers are unloaded
Host lifetime controlled by the driver manager
When Driver or Application CrashesWhen Driver or Application Crashes
When the UM driver crashes:Reflector gets notification from OS
Reflector tracks outstanding I/O in the host. Completed with STATUS_DRIVER_PROCESS_TERMINATED
Win32 apps will see ERROR_DRIVER_PROCESS_TERMINATED
The kernel drivers for the device stack are unloaded
Device is disabled (yellow bang in device manager)
When the application crashes:Reflectors gets IRP_MJ_CLEANUP
Sent to host on the “cancel” IPC channel
Host/UM driver complete pending I/O requests
Timeout PolicyTimeout Policy
UMDF enforces timeouts on “critical” operationsOperations 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 includePnP and PM operations
These run under a system-wide PnP lock
Blocks other PnP operations
I/O CancellationLong term operations must be cancelable
Adversely affects user experience (application hangs)
In WinHEC release, time out = 1 minuteWill adjust based on feedback & failure report data for RTM
ImpersonationImpersonation
Driver runs in LocalService security context
Drivers can impersonate the client processOnly for I/O requests
Not for PnP or other system messages
typedef enum _SECURITY_IMPERSONATION_LEVEL { SecurityAnonymous, SecurityIdentification, SecurityImpersonation, SecurityDelegation } SECURITY_IMPERSONATION_LEVEL;
Using ImpersonationUsing Impersonation
Application controls the allowed levelSpecified in QOS settings in CreateFile API
See dwFlagsAndAttributes parameter in MSDN
INF sets the driver’s maximum desired levelStored 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 requestSpecifies desired level and a callback
Isolate impersonated code Do minimal work to reduce the attack surface
UMDF VerifierUMDF Verifier
Built-in verificationChecks for problems in framework code
Checks for problems in device driver code
Always enabled & always fatalUnless you have a debugger attached
DDI misusage result in verifier failurePassing 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 FailuresUMDF Verifier Failures
Driver failures will “Bugcheck” the hostBugcheck 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 presentPrints out error message
Developer can continue…but that may lead to another crash
Terminate the host process and disable the device
UMDF Error ReportingUMDF Error Reporting
Current driver failure reports are hard to analyzeToo much information in the running kernelNot enough fits into a minidump
User-Mode Drivers reports can be betterCompartmentalized – less information to collectSpecialized – not mixed with irrelevant stateBetter collection – we’re not limited by crash dump
UMDF reports problems through Windows Error Reporting (WER)
UMDF queues reports for later approval and uploadWER provides for a global “opt-in” to upload quicker
No modal crash dialogsBubble on the task bar indicating an incident has occurred
Please upload error reports for Beta 1Even if you think it’s your driverWe need data to refine what we’re collecting
Types of Error ReportsTypes of Error Reports
UMDF will report the following problems :UM Driver Verifier failureUnhandled Exception in host processUnexpected Host TerminationFailure or Timeout of “Critical” Operation
Error Report may contain:Memory dump of the host processCopy of UMDF’s internal trace logConfiguration information about the device
Device name, manufacturer, drivers installedDriver binary versions
Internal analysis of the problemAddress of the last driver to framework call (or vice versa)Problem code, exception info, etc...
Report contents depend on the problem detected
Device Driver Interfaces (DDI)and Programming Patterns
Framework objects have a hierarchical relationship
WDF Driver is the root object
Child lifetime scoped by parent
Every WDF object is defined byMethods: actions on objects
Properties: are object attributes
Events: notifications from Framework objects to the driver
Framework Object ModelFramework Object Model
WDF Driver
WDF Device
WDF Queue
WDF Queue
Key Framework ObjectsKey Framework Objects
Object DescriptionDriver Supports one or more devices
One per driver per host processDevice Tracks PnP/PM state changes and
notifies driverI/O Request Represents application’s I/O requestI/O Queue Controls I/O request flow into driverFile Provides per-handle context for driverI/O Target Represents next lower device in stack
Encapsulates driver to driver communication
Parent-Child Object HierarchyParent-Child Object Hierarchy
Device
I/O Queue
I/O Request
I/O Target
Driver
File
Applies to lifetime managementLifetime of child is scoped within that of the parent
Child is cleaned up when the parent goes away
Framework Object Model Framework Object Model
WDF Driver
WDF Device
WDF Queue
WDF Queue
MyDriver
MyRead Queue MyWrite
Queue
Framework Driver
Driver implemented Callback Objects
WDF Objects
MyDevice
Provided by:Provided by:
MicrosoftMicrosoft
IHVIHV
Framework Object Model Framework Object Model
MyDriver1
MyDevice1
MyRead Queue1MyWrite
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 Queue2MyRead
Queue2Device Stack
Each driver in the stack has its own set of framework objects
DDI DesignDDI Design
Common object model with KMDFDriver writers familiar with KMDF can quickly come up to speed with UMDF
Interface based programming modelUM developers are familiar with C++ and OOP
Interfaces allow logical grouping of functions making it easy to navigate through the DDI
Facilitates opt-in programming
Built-in extensibility
C++ is the supported language in the first version
Uses a small subset of COM (COM-Lite)COM complexity is in COM RTL features
Threading Model, Automation, etc...
UMDF doesn’t depend on COM RTL
DDI : COM InterfacesDDI : COM Interfaces
Problems solved by InterfacesAllows 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 thisWell understood
Existing tools like ATL
We don’t want to invent another model
C++ facilitates thisInterfaces are just abstract base classes
With only pure virtual functions
Compiler implements interface as function pointer table (V-Table)
All You Need to Know about COM …All You Need to Know about COM …
COM interfaces, by convention, start with “I”e.g., IUnknown
All COM interfaces are derived from IUknownQueryInterface, AddRef, Release
Lifetime management of COM objectsAddRef: takes a reference on Framework object
WDF object model simplifies ref-counting
Release: drops ref-count on Framework objectDriver should release interfaces retrieved from Fx when done
Query Interface (QI): allows discovery of “interfaces” supported by the driver
Device Driver Interfaces (DDI)Device Driver Interfaces (DDI)
UMDF DDI is in wudfddi.idlinterface IWDFObject : IUnknown{ HRESULT DeleteWdfObject(); ... VOID AcquireLock(); VOID ReleaseLock();};
Simplified C++ equivalent generated by MIDLstruct 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)Device Driver Interfaces (DDI)
DDIs are grouped into 2 types of interfacesFunctionality exported by Framework
By convention these begin with IWDF
E.g., IWDFDriver, IWDFDevice, IWDFIoQueue
Callbacks exported by DriverThese are of the form I<WdfObject><Function>
e.g., IQueueCallbackRead, IRequestCallbackCancel
Methods on callback interfaces begin with “On”
interface IQueueCallbackRead : IUnknown{ void OnRead ( IWDFIoQueue* pWdfQueue, IWDFIoRequest* pWdfRequest, SIZE_T NumOfBytesToRead );};
Device Driver Interfaces (DDI)Device Driver Interfaces (DDI)
KMDF and UMDF DDI are similarTuned to language and runtime environment
KMDF NTSTATUS WdfDeviceConfigureRequestDispatching( WDFDEVICE Device, WDFQUEUE Queue, WDF_REQUEST_TYPE RequestType, BOOLEAN Forward );
UMDF HRESULT IWDFDevice::ConfigureRequestDispatching( IWDFIoQueue * pQueue, WDF_REQUEST_TYPE RequestType, BOOL Forward );
Device parameter is implicit in C++
Driver EntryDriver 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 OnDeinitializeDo driver-wide initialization and cleanup
OnDeviceAddInvoked once for each new device detected by Windows
Callback objects = Callbacks + ContextExample: 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 ObjectsCallback Objects
1
2
Callback Objects (con’t)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)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) Callback Objects (con’t)
WDF Driver
WDF Device
Framework Driver
IDriverEntryOnDeviceAdd1
IWDFDriver::CreateDevice( … ) 3
4QueryInterface for• IDevicePnP• IDevicePnPHardware
- - - -
5
MyDeviceIUnknown
IDevicePnpHardware
2
Callback Object
Provided by:Provided by:
MicrosoftMicrosoft
IHVIHV
SummarySummary
Discussed driver loading/unloading, I/O data flowDriver 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 modelKMDF and UMDF share same model
UMDF DDI is based on C++ and COM-lite
Callback objects = Context + Callbacks
How to Develop a UMDF DriverPart 2
OutlineOutline
Goals
Getting StartedWriting your Driver
Installing your Driver
Debugging the Driver
Plug and Play / Power ManagementDesign goals
Design overview
Device Driver Interface (DDI)
PnP/PM driver callback example
GoalsGoals
How to start writing and debugging a UMDF driver
How to interact with UMDF’s Plug And Play and Power Management support
The basics of creating and configuring a device driver
Writing Your Driver
What is a User-Mode Driver?What is a User-Mode Driver?
User-Mode (UM) Drivers are DLLsProvide driver’s “callback object” classes
Use COM programming pattern, not runtimeAt least, not very much of the runtime
Expose standard COM entry pointsDllGetClassObject, 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 examplesThis talk references the “Skeleton” driver
UMDF Driver DLL ExportsUMDF Driver DLL Exports
DllMainCalled when DLL loads (and unloads)
Construct global objects, initialize tracing
Dll[Un]RegisterServerCalled by CoInstaller during device installation
Skeleton sample uses ATLRather than write another implementation
DllGetClassObjectCalled on device arrival by COM to get “class factory”
DllCanUnloadNowJust return S_FALSE
Common Driver ClassesCommon Driver Classes
COM objects must implement IUnknownIndependently, or with help from CUnknown base class
UMDF driver implements these classesCClassFactory
Instantiates your driver event handler
CMyDriverYour Driver-Callback Class
Must implement IDriverEntry
Paired with an IWDFDriver object
CMyDeviceYour Device-Callback Class
May implement IDevicePnpHardware and/or IDevicePnp
Paired with an IWDFDevice object
UMDF Skeleton DriverUMDF Skeleton Driver
Example code based on UMDF Skeleton sampleCode in slides should not be used as-is
UMDF Skeleton does just enough to get loadedBoilerplate code found in all UM DriversMinimal callback objects for driver and device
Description of filesComSup.h & ComSup.cpp
COM Support code – provides classes for IUnknown & IClassFactoryDllSup.h & DllSup.cpp
DLL Support code – provides implementation of required exportsDepends on COM support code
Driver.h & Driver.cppDriver-Callback Class
Device.h & Device.cppDevice-Callback Class
“TODO” comments mark where to add your driver codeCOM and DLL support files require no changesThe driver and device files you’ll need to modify for your driver
Example: CMyDriver Definition (Driver.h)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 ImplementationExample: CMyDriver Implementation (Driver.cpp)(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 Example: CMyDriver Implementation (con’t)(con’t)HRESULT CMyDriver::OnDeviceAdd(...) {
CMyDevice *deviceCallback; IWDFDevice *fxDevice;
HRESULT hr = CMyDevice::CreateInstance( FxDeviceInit,
&device );
if (S_OK == hr) {
... // Call SetLockingModel(), SetFilter(), etc...
hr = FxWdfDevice->CreateDevice(
FxDeviceInit,
deviceCallback->QueryIUnknown(),
&fxDevice
);
// Release Reference from QueryIUnknown()
deviceCallback->Release();
}
if (S_OK == hr) {fxDevice->Release();}
if (NULL != deviceCallback) {deviceCallback->Release();}
return hr;
}
Example: CMyDevice Definition (Device.h)Example: CMyDevice Definition (Device.h)class CMyDevice : public CUnknown {
HRESULT Initialize( IWDFDeviceInitialize *DeviceInit ) { return S_OK; }
static HRESULT CreateInstance( IWdfDeviceInitialize *FxDeviceInit, CMyDevice **Device ); // Add IUnknown methods here}
Writing Your Driver (Summary)Writing Your Driver (Summary)
Create the common codeRequired DLL ExportsCOM support classesCopy from skeleton, use existing ones (ATL), or write your own
Implement CMyDriver classIncluding the OnDeviceAdd() method
Allocate and initialize a CMyDevice objectCreate IWDFDevice object & connect to CMyDevice callbacks
Implement CMyDevice classAdd Device-Callback interfaces later
Your driver should now loadBut can’t talk to your device or do I/ONext two talks will address that
Installing Your DriverInstalling Your Driver
INF Based InstallationJust like WDM and kernel-mode WDF drivers
Device Matching, Driver Signing, etc... work normally
User-Mode Driver’s INF does extra workUse 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 2Still INF based, but more support from CoInstaller
Registry LocationsRegistry Locations
UMDF keeps information in several registry keysWe’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}
System provided CoInstallerSets Driver Manager to start automatically
WUDFCoInstaller.dll is already installedNo 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 startDriver can’t start if the Driver Manager isn’t running
Problem code 37 in device manager
Use UMDF CoInstallerUse UMDF CoInstaller
UMDF uses CoCreateInstance to load driversThis requires the driver to be “registered”
INF must register any user-mode drivers it copiesDo this in the [DDInstall] section
[Skeleton]CopyFiles=DriverCopyRegisterDlls=Skeleton.RegisterDlls
[Skeleton.RegisterDlls]11,,WUDFSkeleton.dll,1
Unregistered drivers will not loadProblem code 43 in the device manager
Register Driver DLLsRegister Driver DLLs
UMDF loads drivers by “Driver Name”We recommend the binary name (without extension)
UMDF Maintains its own driver listLists 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 missingProblem 43 in device manager
Configure the Driver ListConfigure the Driver List
Setup UM Driver KeySetup UM Driver Key
Create an entry under UMDF Services KeyOne 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
Reflector driver is WUDFRd.sysAlready installed on the system
Your INF must make this the top-most kernel driver
If you’re writing a UM function driverAssign reflector as service with AddService directive
You’ll need a service install section too
If you’re writing a UM Upper-Level filter driverAssign reflector as top-most Upper Device Filter
Without this UMDF is never loadedDevice may start, but no host process
Adding the Reflector DriverAdding the Reflector Driver
Installing Your Driver (Summary)Installing Your Driver (Summary)
Use the UMDF CoInstaller
Register your Driver DLLs with COM
Configure the Driver List
Setup UM Driver KeyRecord your driver’s CLSID
Add Reflector driver to the kernel drivers
If it doesn’t work:Is Driver Manager started?
Does device manager show a problem code?
Is WUDFHost.exe (host process) running ?
Debugging Your Driver
Debugging OverviewDebugging Overview
Similar to service debuggingUM Drivers cannot be started by the debugger
No Just-In-Time debugging
Host process starts when device is installedPlug & Replug the device to restart
Or disable & re-enable in device manager
Each device stack runs in host processWUDFHost.exe
Child of Driver Manager service
One stack per host-process for now
Debugger OptionsDebugger Options
WinDbgGUI 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 DebuggerWDK 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 & KDIf you prefer command line debugging, these work
User-Mode or Kernel-Mode DebuggingUser-Mode or Kernel-Mode Debugging
Can debug UMDF with UM or KM debuggerYou can use WinDbg to debug either way
UM DebuggerSimpler and more familiarHave to attach to each host process when it starts
KM DebuggingRequires a second computer to run debuggerMore complex, but quite powerful
Stops entire computer – no UMDF timeouts
Can be always runningCatch UMDF Verifier problems like JIT debugger
Can debug and set breakpoints in host processUse “.process /i <process object address>” to break into running host
See additional slides for KM Debugging tips
Host process started by Driver Manager serviceYou 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 timeoutsLike 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 value0x8000000 attempts once to break into either debugger
Enabling the DebuggerEnabling the Debugger
Cannot connect UM Debugger until host starts
Enable the Initial Breakpoint
Attach the device to the systemOr enable it in the device manager
If you have a single device attachedRun “windbg –pn WUDFHost.exe”
Repeat until it finds a host process to debug
If you have multiple devices attachedFind 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 DebuggerAttaching the UM Debugger
UMDF Debugger ExtensionUMDF Debugger Extension
WudfExt.dllCopy into your path
“!load WudfExt.dll” debugger command loads the extension
Names are case sensitive
Command Description!devstack Shows device stacks in the host process
!dumpirps Shows UM IRPs in the host process
!umirp Shows a host IRP
!wdfdriverinfo Shows info about a UM driver
!wdfdevicequeue Shows the I/O queues for a device
!wdfqueue Shows an IoQueue
!wdfrequest Shows an IoRequest
!wdfitf2obj Converts an interface pointer to an object address for above extensions.
Interesting UMDF Breakpoints (BP)Interesting UMDF Breakpoints (BP)
Event to debug Breakpoint (BP)
Host attempts to load driver
OLE32!CoCreateInstance
Watch for your CLSID
Driver Load MyDriver!DllMain
Invoked first time when your DLL is loadedCalled after that too, so clear the BP once it hits
Creation of CMyDriver
MyDriver!DllGetClassObject
Invoked to get your class factory
MyDriver!CMyDriver::CMyDriver
Invoked when the factory calls new
Driver attaches device to stack
MyDriver!CMyDriver::OnDeviceAdd
Driver creates a device to attach to the stack
Hopefully, this will get you started
Tracing in Your UM DriverTracing in Your UM Driver
Recommend using WPP tracing for debug outputLightweight & always available, printf-style tracing
Easily captured to disk, screen or (kernel) debugger
Skeleton contains some basic tracing codeSee MSDN documentation on Event Tracing
Collect output with tracelog.exe or traceview.exeTracelog comes with Windows
Traceview comes with WDK
For more information see:“Collecting & Viewing Traces” in additional slides
MSDN & DDK documentation
What Do I Do When It Crashes? (Summary)What Do I Do When It Crashes? (Summary)
Check for configuration problemsIs 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 startsOr always enable the kernel debugger
Watch for UMDF Verifier failures
Walk through initializationUse list of interesting breakpoints
Get debug output with WPP tracing
Plug and Play / Power Management
UMDF Design Goals for PnP/PMUMDF Design Goals for PnP/PM
Coordinate I/O delivery to driver with PnP/PM events
The framework handles complexities of PnP/PMAllow drivers to participate with optional callbacks
Support FDO and filter driver scenariosNo bus driver support for version 1
Same design as kernel mode WDF PnP/PM
UMDF PnP/PM DesignUMDF PnP/PM Design
Implemented with a state machineConsumes 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 interfacesIDevicePnpHardware
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 InterfacesUMDF PnP/PM Interfaces
IDevicePnpHardwareFirst time hardware initialization / de-initialization
OnPrepareHardware()OnReleaseHardware()
IDevicePnpDevice state change notifications
OnD0Entry()OnD0Exit()OnSurpriseRemoval()OnQueryRemove()OnQueryStop()
IDevicePnpSelfManagedIoCustom I/O processing notifications
OnSelfManagedIoCleanup()OnSelfManagedIoFlush()OnSelfManagedIoInit()OnSelfManagedIoSuspend()OnSelfManagedIoRestart()
Device Driver Interface (DDI)Device Driver Interface (DDI)
IDriverEntry::OnDeviceAddDriver must implement this interfaceCalled when framework receives “Add Device” messageDriver should perform initialization that does not require access to hardware or lower level driversDriver 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 ); ...}
IDevicePnpHardwareIDevicePnpHardware
OnPrepareHardwareCalled when device is first startedDriver 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(); }
IDevicePnpHardwareIDevicePnpHardware
OnReleaseHardwareCalled when device is removed or stoppedDriver 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; }
IDevicePnpIDevicePnpOnD0Exit
Called each time device should power downAlso 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 stateSet the device into low power state
OnD0EntryCalled each time device should power upAlso called when the device starts up
Set the device into working power stateRestore any previously saved stateRestart device’s I/O target
hr = m_pIoTarget->Start();
IDevicePnpIDevicePnpOnSurpriseRemoval
Called when the device has unexpectedly detached from the PCStop device’s I/O target with cancel flag
hr = m_pIoTarget->Stop( WdfIoTargetCancelSentIo )
OnQueryRemoveAllows driver to veto a device removal request
HRESULT CDevice::OnQueryRemove( IWDFDevice* pDevice ) {
return S_OK; // Allow device removal}
OnQueryStopAllows driver to veto a device stop request
HRESULT CDevice::OnQueryStop( IWDFDevice* pDevice ) { return E_FAIL; // Disallow device stop}
IDevicePnpSelfManagedIoIDevicePnpSelfManagedIo
Notifications to drivers that perform I/O dispatching unmanaged by the framework
OnSelfManagedIoInit()Start I/O dispatching
OnSelfManagedIoSuspend()Pause I/O dispatching
OnSelfManagedIoRestart()Resume I/O dispatching
OnSelfManagedIoFlush()Cancel or complete all pending I/O
OnSelfManagedIoCleanup()Free I/O dispatching mechanisms
PnP/PM Driver Callback Example
Device Driver
OffOnOff
Framework
Start Device
Start DeviceStart Device
OnPrepareHardware()
Device Driver
OffOnOff
Framework
Start Device
OnD0Entry()
Start DeviceStart Device
Device Driver
OffOnOn
Device OperationalDevice Operational
Framework
Device Driver
OffOnOn
OnD0Exit()
Suspend DeviceSuspend Device
Framework
Power Down
Device Driver
OffOnOn
OnD0Entry()
Resume DeviceResume Device
Framework
Power Up
Device Driver
OffOnOn
OnD0Exit()
Remove DeviceRemove Device
Framework
Remove Device
Device Driver
OffOnOn
OnReleaseHardware()
Remove DeviceRemove Device
Framework
Remove Device
WDM Message to UMDF Callback MappingWDM Message to UMDF Callback Mapping
Start -> Query Remove -> RemoveIRP_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 MappingWDM Message to UMDF Callback Mapping
Start -> Surprise Removal -> RemoveIRP_MN_START_DEVICE:
OnPrepareHardware()
OnD0Entry()
OnSelfManagedIoInit()
IRP_MN_SURPRISE_REMOVAL:OnSurpriseRemoval()
OnSelfManagedIoSuspend()
OnReleaseHardware()
OnSelfManagedIoFlush()
IRP_MN_REMOVE_DEVICE:OnSelfManagedIoCleanup()
PnP/PM TimeoutsPnP/PM Timeouts
Each WDM PnP/PM message has a timeoutCurrently, 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
Supplemental Slides
Example: DllMainExample: 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: DllGetClassObjectExample: DllGetClassObjectHRESULT DllGetClassObject( REFCLSID ClassId, REFIID InterfaceId, PVOID *Interface ){ PCClassFactory factory; HRESULT hr; *Interface = NULL; if (!IsEqualCLSID( ClassId, __uuidof(MyDriverCoClass) )) { return CLASS_E_NOTAVAILABLE; } hr = CClassFactory::CreateInstance(&factory);
if (S_OK == hr) { hr = factory->QueryInterface(InterfaceId, Interface); factory->Release(); } return hr;}
Example: DllRegisterServer & DllCanUnloadNowExample: DllRegisterServer & DllCanUnloadNow
HRESULT DllRegisterServer() { return UpdateCOMRegistration( g_ModuleHandle, IDR_MYDRIVER_CLASSINFO, true, __uuidof( MyDriverCoClass ), L“UMDF Skeleton Sample Driver” );}
HRESULT DllUnregisterServer() { return UpdateCOMRegistration(..., false, ...)}
HRESULT DllCanUnloadNow() { return S_FALSE;}
Example: CUnknown DefinitionExample: CUnknown Definitionclass 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 ImplementationExample: CUnknown ImplementationULONG CUnknown::AddRef(){ return InterlockedIncrement(&m_RefCount);}
ULONG CUnknown::Release() { ULONG count = InterlockedIncrement(&m_RefCount); if (count == 0) { delete this; } return count;}
HRESULT CUnknown:QueryInterface(...) { if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) { *Interface = QueryIUnknown(); return S_OK; } *Interface = NULL; return E_NOINTERFACE;}
Example: CClassFactory DefinitionExample: CClassFactory Definitionclass 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 ImplementationExample: CClassFactory ImplementationHRESULT CClassFactory::QueryInterface(...) {
if(IsEqualIID(Interface, __uuidof(IClassFactory)) {
*Object = QueryIClassFactory();
return S_OK;
} else {
return CUnknown::QueryInterface(...);
}
}
HRESULT CClassFactory::CreateInstance(...) {
PCMyDriver driver;
HRESULT hr = CMyDriver::CreateInstance(&driver);
if (S_OK == hr) {
hr = driver->QueryInterface(InterfaceId, Object);
driver->Release();
}
return hr;
}
Debugging with WinDbgDebugging with WinDbgSource Level GUI debugger(Most) commands work on addresses or symbols
ModuleName!FunctionNameModuleName!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 Memoryd<type> [address] [L<length>]
type = byte, word, char, unicode, dword, quadword, stringdd MyMyDriver!g_MyArrayLength L1
dv dumps local variable namesDumping Types
dt <variable name> dumps a specific localdt <addr> <typename> dumps an address or symbol as a type
dt ??? MyDriver!CMyDevice
See the WinDbg help for more details
Debugging with a Kernel DebuggerDebugging with a Kernel Debugger
WinDbg can be used as a kernel debuggerMust point Kernel debugger to host process
Automatic if the process requests a kernel break-inManually 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 addressesMust load user symbols first
Cannot break into a running host processMust wait for a breakpoint
UMDF “Verifier” will break into KD if attachedLast chance to debug before process termination
Collecting & Viewing TracesCollecting & Viewing Traces
TraceLog.exe lets you control trace sessionsTo start a session
Tracelog.exe -start MyLogger -guid MyDriver.ctl -level 255 -flag 65535 -f MyLogFile.etl
To end a sessionTracelog.exe -stop MyLogger
To print a sessionTraceFmt –o MyLogFile.txt -p symbols.pri/TraceFormat MyLogFile.etl
Or use the GUI “TraceView” toolUse 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
How to Develop a UMDF Driver: How to Develop a UMDF Driver: Part 3Part 3
OutlineOutline
I/O Processing Overview
I/O Queues
File Objects
Driver Layering
I/O Targets
Cancellation
GoalsGoals
A better understanding of: How to incorporate I/O processing in a UMDF driver
Framework objects involved with I/O Request processing
Knowledge of where to find resources for UMDF
I/O Request Processing OverviewI/O Request Processing Overview
I/O Request Processing in UMDFI/O Request Processing in UMDF
You’ve seen WDF Driver and Device objectsThese 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
Request
Framework ObjectsFramework Objects
Device
Queue
I/O Target
Memory (Input)
Memory (Output)
Driver
File
Framework ObjectsFramework Objects
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
Queue A flow control mechanism for Requests
File An open handle to the device and any context the driver needs to store with it
I/O Target 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.
Memory A buffer associated with a request
These objects are associated with request processingAll derive from IWDFObject
I/O Request Processing – A Bird’s Eye viewI/O Request Processing – A Bird’s Eye view
Request
I/O Queue
Driver
I/O Target
Complete
I/O Request ObjectI/O Request Object
I/O Queue
Driver
I/O Target
Complete
Request
I/O Request ObjectI/O Request Object
Represents a requestSent to the driver by a client
An application or another UM driver
Generated by a driver
Types of Requests presented to driverCreate
Read / Write / DeviceIoControl
Cleanup
Close
Request Parameters can be obtained from IWDFIoRequest interface
I/O QueuesI/O Queues
I/O QueuesI/O Queues
I/O Queue
Driver
I/O Target
Complete
Request
I/O QueuesI/O Queues
Queues provide flow control for I/O RequestsAll requests dispatched to driver through I/O Queues
Driver can configure I/O routing for a deviceCreate one or more queues for a device
Configure routing for a type of I/O to a particular queue
“Default queue” handles any remaining I/O types
I/O Queue Dispatch TypesI/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 timeIt is a per-Queue property
Automatic DispatchAutomatic Dispatch
Queue presents request through driver implemented callback interfaces
IQueueCallbackCreateClose
IQueueCallback[Read | Write | DeviceIoControl]
Automatic Dispatch TypesSequential: allows at most one outstanding request at a time
New Request not presented until current request is completed
Parallel: allows multiple outstanding requestsNew Request can be presented even when previously presented requests are not completed
The number of parallel requests presented is boundedDriver should minimize blocking in presentation callbacks
Manual DispatchManual Dispatch
Driver pulls requests from the queueTypically 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 changeHRESULT RetrieveNextRequest(
OUT IWDFIoRequest** ppRequest
);
It is possible for driver to pull requests from an Automatic Queue
Callback ConstraintsCallback Constraints
Callback constraints specify locking model for Queue callbacks
Callback constraints optionsDevice Level: Callbacks invoked with device level lock held
None: Callbacks invoked with no lock held
Specified at device creation time via IWDFDeviceInitialize::SetLockingConstraint
Set before creating the WDF Device object
Per device property – applies to all queues
Callback Constraints (con’t)Callback Constraints (con’t)
Constraints apply only to Queue Callbacks
Queue callbacks includeAutomatic 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
Sequential Queue
Device Level Locking
Parallel Queue
Device Level Locking
Parallel Queue
No Locking
Dispatch Type vs. Locking ModelDispatch 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:
UMDF OSR USB Sample Walk-throughUMDF OSR USB Sample Walk-through
Requests and Queue Usage in the sample driver (src\umdf\usb\driver)
Callback locking constraint used(CMyDevice::Initialize in Device.cpp)
Dispatch type used(CMyQueue::Initialize in Queue.cpp)
Queue callbacks used(CMyQueue in Queue.h and Queue.cpp)
File ObjectsFile Objects
File ObjectFile Object
File Object represents open connection to device
It is the session context for I/O
All requests associated with a File Object in UMDF
KMDF and WDM requests sometimes don’t have one
File object for a request obtained using IWDFIoRequest::GetFileObject
Trailing name used by client while opening connection is available via IWDFFile::GetFileName
File Object (con’t)File Object (con’t)
Device
File1
Request1
Request2
File2
Request1
Request2
File Object LifetimeFile Object Lifetime
File Object’s lifetime spansCreate: 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 IllustratedFile Object Lifetime Illustrated
Close
…
Any remaining Requests drain
…
CleanupCloseHandle(hFile);
… …Read/Write/IoCtl RequestsAsync/Sync Read/Write/IoCtl
… …Create RequesthFile = CreateFile(…
DriverApplication
Example of I/O sequence between App and Driver
Cleanup Handling in DriverCleanup Handling in Driver
Cleanup received when client closes connectionNotification for driver to flush I/O for File Object
Cancel or complete outstanding I/O as soon as possibleClose will not come until all I/O is finishedCleanup is a “critical” operation in UMDF
Cannot fail, subject to timeout
Cleanup is not the end of I/O operationsThat’s the Close RequestI/O received after a Cleanup should be cancelled/completed immediately
UMDF OSR USB Sample Walk-throughUMDF OSR USB Sample Walk-through
File usage in the sample driver (src\umdf\usb\driver) (Queue.cpp)
CMyQueue::OnRead
CMyQueue::OnCreateFile
CMyQueue::OnCleanupFile
CMyQueue::OnCloseFile
Driver LayeringDriver Layering
Driver LayeringDriver Layering
UMDF supports driver layeringMultiple 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 layerEach 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 DiagramDriver Layering Diagram
Device Queue File Request
Device Queue File Request
Device Queue File Request
Device Stack
Framework
Framework
Framework
Request CompletionRequest Completion
When Driver receives a Request it canComplete 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 receivese.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 eventRuns outside driver’s callback locking constraints
Request Completion IllustratedRequest Completion Illustrated
Request Completion Routine
Request Completion Routine
Request
I/O TargetI/O Target
I/O TargetI/O Target
I/O Queue
Driver
I/O Target
Complete
Request
I/O Target Framework ObjectI/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 representsSome other UM or KM device stack
Need feedback to prioritize this for Longhorn
I/O Target is responsible forSending I/O request to lower device
Detecting completion and invoking callback interface
Device Stack
I/O Target
I/O Target
I/O Target
Device
Device
Device
Local I/O TargetLocal I/O Target
User Mode
Kernel Mode
Device
Device
Down Device
Application
ReflectorUp Device
I/O Target FunctionalityI/O Target Functionality
State based I/O handlingDriver 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 timeoutOutstanding request is cancelled when timeout expires
Tracks sent requests for the driverAllows automatic purge or flush on I/O target stop
Coordinates completion and cancellation
Bridging UM and KM stacksBridging UM and KM stacks
I/O Target provides bridge between KM and UM driversBottom-most I/O Target sends requests to kernel-mode stack
Driver could also “escape” to the Platform APISend I/O using Win32 File I/O API directly
Advantages of using I/O TargetHandles 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 1Bottom-most I/O Target uses Win32 File I/O API internally
No way to use specific API (e.g., WinUSB)Makes the escape necessary in such cases
UMDF OSR USB Sample Walk-throughUMDF OSR USB Sample Walk-through
I/O Target usage in the sample filter (src\umdf\usb\filter)
Obtaining default I/O Target(CMyQueue::Initialize in Queue.cpp)
Forwarding request down the stack(CMyQueue::OnWrite in Queue.cpp)
(CMyQueue::ForwardRequest in Queue.cpp)
Request CancellationRequest Cancellation
Request CancellationRequest Cancellation
Application can cancel a request at any time byUsing CancelIo[Ex] API
Exiting application, etc.
Higher layer driver can cancel sent requests
Cancel tells driver to complete request soonBut not necessarily immediately
Driver should abort any long operationsShort synchronous requests can just be allowed to complete normally
Cancel is a critical operationCannot be failed, subject to timeout, etc…
Cancellation is part of good user experience
Cancellation OverviewCancellation 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 callbackOwner arranges to cancel and complete request
Remove callback before transferring ownershipe.g., when forwarding or completing the Request
Request OwnershipRequest 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 requestIf it holds on to the request for a long time
Cancellation Handling in DriverCancellation Handling in Driver
When driver receives a Request, it may:Complete it soon
Shortly send it to I/O Target
Queue it back to Framework I/O Queue
Hold on to it (not using Framework I/O Queue)
Do (potentially) lengthy sync/asynch processing
Driver needs to handle cancellation only in the last two cases
Cancellation Handling in Driver (con’t)Cancellation Handling in Driver (con’t)
Driver may register a cancel notification callbackvoid IWDFIoRequest::MarkCancelable(
IRequestCallbackCancel* pCancelCallback
);
In callback it should cancel/complete the requestAs soon as possible
Unregister callback when transferring ownershipBefore sending request to I/O target or completing it
HRESULT IWdfIoRequest::UnmarkCancelable();
Failure return value indicates request has been canceledCancel routine has run or will run soon
Owner must ensure Request is completed only once
Cancellation IllustratedCancellation IllustratedLet 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 cancelled2a. 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
OnRead*OnRead*
ctx->state = RequestCompleted;
DeviceLock->ReleaseLock();
}
Cancellation Illustrated (1)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();
OnCancel*
…
if (ctx->state == RequestCompleted) {
CompleteRequest
}
else {
CancelIoEx
ctx->state = CancelInvoked;
}
OnUSBReadComplete
* Invoked under DeviceLock
OnCancel*OnCancel*
OnRead*
}
Cancellation Illustrated (2a)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*
}
Cancellation Illustrated (2b)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
UMDF OSR USB Sample Walk-throughUMDF OSR USB Sample Walk-through
Cancellation walk-through in the sample driver (src\umdf\usb\driver) (Queue.cpp)
CMyQueue::OnRead
CMyQueue::OnCancel
CMyQueue::CompletionThread
Putting It TogetherPutting It Together
You’ve seen the following portions of the sample:Driver (Driver.cpp)
CMyDriver::OnDeviceAdd
Device (Device.cpp)CMyDevice::OnPrepareHardware
CMyDevice::OnReleaseHardware
Queue (Queue.cpp)CMyQueue::OnCreateFile
CMyQueue::OnCleanupFile
CMyQueue::OnRead / CQueue::OnWrite
CMyQueue::OnCancel
CMyQueue::CompletionThread
Call to ActionCall to Action
Install the Windows Driver Kit
Join the WDF Beta ProgramAt http://beta.microsoft.com
Guest ID: Guest4WDF
Evaluate UMDF for your driver projectsConsider development time, customer support for system crashes, etc.
Send Us Feedback – We want to knowIf UMDF will meet your needs
What stops you from writing your drivers with UMDF
Additional ResourcesAdditional Resources
Emailumdffdbk @ 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 2005Focuses on KMDF but provides general WDF information as well
© 2005 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.