How to Develop a UMDF Driver Part 1 Outline Architectural Goals Architectural Description Core components Driver Manager, Reflector, Host Process, and Drivers Driver startup and teardown I/O flow Layered drivers Driver Programming Model WDF object model COM-lite UMDF DDIs Goals An understanding of UMDF infrastructure An understanding of the UMDF DDIs and how they are structured Architectural Goals Stability Driver failures should NOT bring down the system Build on Windows NT I/O model Applications are transparent to driver runtime environment – User or Kernel mode Asynchronous, layered drivers, and packet based Integrate into PnP for device installs, driver load/unload Security Driver failures should NOT compromise the system Driver runs in “LocalService” account Shared model between KMDF and UMDF Shared model != same DDIs or data structures Architectural Block Diagram Application(s) Driver Manager Host Process Host Process UM Driver UM Driver WinSock User Kernel Reflector Windows Kernel (I/O Mgr, PnP) Reflector Kernel Driver (e.g., WinUSB) Provided by: Microsoft ISV IHV Kernel Driver 2 Device Stack Device Stack UMDF Components Driver manager Global, system-wide Windows Service Responsible for host process lifetime Responds to messages from reflector Always running Started during installation of the first UMDF device Host Process Driver Manager UM Driver Reflector UMDF Components Reflector Nucleus of UMDF Installed with each device stack Proxy for UM device stack in kernel Forwards I/O, Power, and PnP messages from kernel to host process Ties the UM device stack to KM side Ensures “good behavior” of UM drivers Proper responses to messages Timely completion of critical system messages Tracks all outstanding kernel resources Host Process Driver Manager UM Driver Reflector UMDF Components : Host Process Child process of the UM Driver Manager Unit of isolation for the device stack Driver crash will not affect other device stacks Container for Framework and UM driver(s) Runtime environment for framework and driver I/O dispatching, driver loading, driver layering, thread pool Handles messages from reflector and driver manager Driver Manager Runtime Reflector Framework DDI UM Driver Host Process - Framework Implements all of the WDF model Queues, Request, I/O target, etc Implements default behavior Reduces vendor written code Exposes DDI Implemented as DLL Runtime Framework DDI UM Driver IPC : Message Passing Requirements Packet-based and asynchronous Cancelable Fail-safe Efficient data transfer Secure Several potential solution Pending I/O, synchronous message passing Windows codenamed “Longhorn” solution: ALPC Standard Windows OS Component Processing Messages KM drivers handle I/O in caller’s thread Obviously not a option for UMDF Host has a thread pool processing messages Dedicated thread for “critical” operations To ensure I/O doesn’t block 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 Driver Loading 5 Driver Manager 3 Host Runtime 2 Windows Kernel (I/O Mgr, PnP) Provided by: Microsoft IHV 1 Add Device 6 Framework 4 UM Driver IPC Channel Reflector Kernel Driver Driver Loading (Layered UM Drivers) 7 Driver Manager 3 Host Runtime 8 5 6 2 Windows Kernel (I/O Mgr, PnP) Provided by: Microsoft IHV 1 Add Device UM Filter Driver Framework Framework 4 UM Driver IPC Channel Reflector Kernel Driver Driver Loading (Host Process) Add Device Host Runtime Add Device Driver creates WDF Device Framework UM Driver Driver creates WDF Queue Driver creates WDF Queue Add Device Provided by: Microsoft IHV I/O Data Flow UM Filter Driver Framework UM I/O Mgr 1 5 Host Process Application 4 Device Stack 6 7 9 8 Win32 I/O API Framework 10 11 3 UM Driver 12 IPC Message Windows Kernel 2 IRP “Up” Device Object “Down” Device Object Reflector Provided by: Microsoft ISV IHV Kernel driver I/O in Host Process Invoke driver callback passing in I/O request Run-time Host File Object UM IRP UM Irp Framework Device Stack IPC Message Host File Object returned as context to the reflector. Provided by: Microsoft ISV IHV Driver can return without completing i/o (asynch) Driver eventually completes i/o. UM Driver Device Removal and Cleanup Run-time Framework UM Driver Device Remove Message path similar to “add device” path Driver gets several PnP notifications for remove UM driver may unload when remove finishes Host process may exit when all drivers are unloaded Host lifetime controlled by the driver manager When Driver or Application Crashes When the UM driver crashes: Reflector gets notification from OS Reflector tracks outstanding I/O in the host. Completed with STATUS_DRIVER_PROCESS_TERMINATED Win32 apps will see ERROR_DRIVER_PROCESS_TERMINATED The kernel drivers for the device stack are unloaded Device is disabled (yellow bang in device manager) When the application crashes: Reflectors gets IRP_MJ_CLEANUP Sent to host on the “cancel” IPC channel Host/UM driver complete pending I/O requests Timeout Policy UMDF enforces timeouts on “critical” operations Operations that run under system wide locks Operations that affect user experience If operations do not complete on time Host is forcibly terminated and error report is generated Critical operations include PnP and PM operations These run under a system-wide PnP lock Blocks other PnP operations I/O Cancellation Long term operations must be cancelable Adversely affects user experience (application hangs) In WinHEC release, time out = 1 minute Will adjust based on feedback & failure report data for RTM Impersonation Driver runs in LocalService security context Drivers can impersonate the client process Only for I/O requests Not for PnP or other system messages typedef enum _SECURITY_IMPERSONATION_LEVEL { SecurityAnonymous, SecurityIdentification, SecurityImpersonation, SecurityDelegation } SECURITY_IMPERSONATION_LEVEL; Using Impersonation Application controls the allowed level Specified in QOS settings in CreateFile API See dwFlagsAndAttributes parameter in MSDN INF sets the driver’s maximum desired level Stored in registry during device installation Set this as low as possible for your driver Reduces chance of “elevation of privilege” attack Driver requests impersonation for given request Specifies desired level and a callback Isolate impersonated code Do minimal work to reduce the attack surface UMDF Verifier Built-in verification Checks for problems in framework code Checks for problems in device driver code Always enabled & always fatal Unless you have a debugger attached DDI misusage result in verifier failure Passing incorrect parameters, including NULL, in DDI Incorrect DDI call sequence More aggressive checks planned for Beta 2 Verifier failure causes a UMDF “Bugcheck” Generates Memory Dump Generates Error Report Sends Error Report to Microsoft (opt-in) UMDF Verifier Failures Driver failures will “Bugcheck” the host Bugcheck is NOT the “Blue Screen of Death” We will pick a less scary name in Beta 2 Bugcheck will: Save memory dump to log file directory %windir%\System32\LogFiles\WUDF\xxx.dmp Create an error report to report to Microsoft (opt-in) Break into debugger if present Prints out error message Developer can continue…but that may lead to another crash Terminate the host process and disable the device UMDF Error Reporting Current driver failure reports are hard to analyze Too much information in the running kernel Not enough fits into a minidump User-Mode Drivers reports can be better Compartmentalized – less information to collect Specialized – not mixed with irrelevant state Better collection – we’re not limited by crash dump UMDF reports problems through Windows Error Reporting (WER) UMDF queues reports for later approval and upload WER provides for a global “opt-in” to upload quicker No modal crash dialogs Bubble on the task bar indicating an incident has occurred Please upload error reports for Beta 1 Even if you think it’s your driver We need data to refine what we’re collecting Types of Error Reports UMDF will report the following problems : UM Driver Verifier failure Unhandled Exception in host process Unexpected Host Termination Failure or Timeout of “Critical” Operation Error Report may contain: Memory dump of the host process Copy of UMDF’s internal trace log Configuration information about the device Device name, manufacturer, drivers installed Driver binary versions Internal analysis of the problem Address of the last driver to framework call (or vice versa) Problem code, exception info, etc... Report contents depend on the problem detected Device Driver Interfaces (DDI) and Programming Patterns Framework Object Model Framework objects have a hierarchical relationship WDF Driver is the root object Child lifetime scoped by parent Every WDF object is defined by Methods: actions on objects Properties: are object attributes Events: notifications from Framework objects to the driver WDF Driver WDF Device WDF Queue WDF Queue Key Framework Objects Object Driver Device I/O Request I/O Queue File I/O Target Description Supports one or more devices One per driver per host process Tracks PnP/PM state changes and notifies driver Represents application’s I/O request Controls I/O request flow into driver Provides per-handle context for driver Represents next lower device in stack Encapsulates driver to driver communication Parent-Child Object Hierarchy Applies to lifetime management Lifetime of child is scoped within that of the parent Child is cleaned up when the parent goes away Driver Device I/O Queue File I/O Request I/O Target Framework Object Model Framework Driver WDF Driver MyDriver MyDevice WDF Device WDF Queue WDF Queue WDF Objects Provided by: Microsoft IHV MyRead Queue MyWrite Queue Driver implemented Callback Objects Framework Object Model Framework Driver 1 MyDriver1 WDF Driver MyDevice1 WDF Device WDF Queue WDF Queue WDF Driver Device Stack WDF Device WDF Queue WDF Queue MyWrite Queue1 MyDevice2 MyRead Queue2 MyRead Queue1 MyDriver2 MyWrite Queue2 Driver 2 Each driver in the stack has its own set of framework objects DDI Design Common object model with KMDF Driver writers familiar with KMDF can quickly come up to speed with UMDF Interface based programming model UM developers are familiar with C++ and OOP Interfaces allow logical grouping of functions making it easy to navigate through the DDI Facilitates opt-in programming Built-in extensibility C++ is the supported language in the first version Uses a small subset of COM (COM-Lite) COM complexity is in COM RTL features Threading Model, Automation, etc... UMDF doesn’t depend on COM RTL DDI : COM Interfaces Problems solved by Interfaces Allows us to evolve the DDI without changing exported functions Older drivers do not need to be rebuilt No C++ name mangling No C++ fragile base class problem COM facilitates this Well understood Existing tools like ATL We don’t want to invent another model C++ facilitates this Interfaces are just abstract base classes With only pure virtual functions Compiler implements interface as function pointer table (V-Table) All You Need to Know about COM … COM interfaces, by convention, start with “I” e.g., IUnknown All COM interfaces are derived from IUknown QueryInterface, AddRef, Release Lifetime management of COM objects AddRef: takes a reference on Framework object WDF object model simplifies ref-counting Release: drops ref-count on Framework object Driver should release interfaces retrieved from Fx when done Query Interface (QI): allows discovery of “interfaces” supported by the driver Device Driver Interfaces (DDI) UMDF DDI is in wudfddi.idl interface IWDFObject : IUnknown { HRESULT DeleteWdfObject(); ... VOID AcquireLock(); VOID ReleaseLock(); }; Simplified C++ equivalent generated by MIDL struct IWDFObject : public IUnknown { virtual HRESULT DeleteWdfObject() = 0; ... virtual VOID AcquireLock() = 0; virtual VOID ReleaseLock() = 0; }; IWDFObject is base interface for all WDF objects Device Driver Interfaces (DDI) DDIs are grouped into 2 types of interfaces Functionality exported by Framework By convention these begin with IWDF E.g., IWDFDriver, IWDFDevice, IWDFIoQueue Callbacks exported by Driver These are of the form I<WdfObject><Function> e.g., IQueueCallbackRead, IRequestCallbackCancel Methods on callback interfaces begin with “On” interface IQueueCallbackRead : IUnknown { void OnRead ( IWDFIoQueue* pWdfQueue, IWDFIoRequest* pWdfRequest, SIZE_T NumOfBytesToRead ); }; Device Driver Interfaces (DDI) KMDF and UMDF DDI are similar Tuned to language and runtime environment KMDF NTSTATUS WdfDeviceConfigureRequestDispatching( WDFDEVICE Device, WDFQUEUE Queue, WDF_REQUEST_TYPE RequestType, BOOLEAN Forward ); UMDF HRESULT IWDFDevice::ConfigureRequestDispatching( IWDFIoQueue * pQueue, WDF_REQUEST_TYPE RequestType, BOOL Forward ); Device parameter is implicit in C++ Driver Entry IDriverEntry is the top driver-exported interface interface IDriverEntry::IUnknown { HRESULT OnInitialize( IWDFDriver* pWdfDriver ); HRESULT OnDeviceAdd( IWDFDriver* pWdfDriver, IWDFDeviceInitialize* pWdfDeviceInit ); VOID OnDeinitialize(); }; OnInitialize and OnDeinitialize Do driver-wide initialization and cleanup OnDeviceAdd Invoked once for each new device detected by Windows Callback Objects Callback objects = Callbacks + Context Example: Creating Device Object HRESULT CMyDriver::OnDeviceAdd( IWDFDriver* pDriver, IWDFDeviceInitialize* pDeviceInit ) { IUnknown *pDeviceCallback = NULL; ... // Create callback object hr = CMyDevice::CreateInstance( &pDeviceCallback, 1 pDeviceInit, completionPort ); ... // Create WDF Device hr = pDriver->CreateDevice( pDeviceInit, pDeviceCallback, 2 &pIWDFDevice ); ... } Callback Objects (con’t) class CMyDevice : public IDevicePnpHardware { private: HANDLE WINUSB_INTERFACE HANDLE UCHAR ULONG ... public: virtual HRESULT stdcall // Callback interface exposed to // framework. m_CompletionPort; m_UsbHandle; m_BulkOutPipe; m_BulkOutMaxPacket; OnPrepareHardware( IWDFDevice* pDevice ); STDMETHOD( OnReleaseHardware )( IWDFDevice *pDevice ); // Factory method static HRESULT CreateInstance( IUnknown *pUnknown, IWDFDeviceInitialize *pDeviceInit, HANDLE CompletionPort ); ... }; Context Callback Callback Objects (con’t) static HRESULT CreateInstance( IUnknown **ppUnknown, IWDFDeviceInitialize *pDeviceInit, HANDLE CompletionPort ) { ... // Allocate our callback context 1 CMyDevice *pMyDevice = new CMyDevice(); ... // Get our callback interface 2 hr = pMyDevice->QueryInterface( __uuidof(IUnknown), (void **) ppUnknown ); ... return hr; } Callback Objects (con’t) 1 OnDeviceAdd IDriverEntry Callback Object WDF Driver 2 IWDFDriver::CreateDevice( … ) 3 WDF Device 5 Framework Provided by: Microsoft IHV IUnknown MyDevice 4 QueryInterface for • IDevicePnP • IDevicePnPHardware ---- IDevicePnpHardware Driver Summary Discussed driver loading/unloading, I/O data flow Driver installation and setup are same as WDM drivers Keep in the mind the “timeout” polices in reflector Built-in verifier checks Error reporting via WER Discussed driver programming model KMDF and UMDF share same model UMDF DDI is based on C++ and COM-lite Callback objects = Context + Callbacks How to Develop a UMDF Driver Part 2 Outline Goals Getting Started Writing your Driver Installing your Driver Debugging the Driver Plug and Play / Power Management Design goals Design overview Device Driver Interface (DDI) PnP/PM driver callback example Goals How to start writing and debugging a UMDF driver How to interact with UMDF’s Plug And Play and Power Management support The basics of creating and configuring a device driver Writing Your Driver What is a User-Mode Driver? User-Mode (UM) Drivers are DLLs Provide driver’s “callback object” classes Use COM programming pattern, not runtime At least, not very much of the runtime Expose standard COM entry points DllGetClassObject, DllRegisterServer, DllUnregisterServer Can write UM Drivers in C or C++ Implementing COM objects is easier in C++ Can use ATL with C++ for additional COM support WDF Supplement CD contains several examples This talk references the “Skeleton” driver UMDF Driver DLL Exports DllMain Called when DLL loads (and unloads) Construct global objects, initialize tracing Dll[Un]RegisterServer Called by CoInstaller during device installation Skeleton sample uses ATL Rather than write another implementation DllGetClassObject Called on device arrival by COM to get “class factory” DllCanUnloadNow Just return S_FALSE Common Driver Classes COM objects must implement IUnknown Independently, or with help from CUnknown base class UMDF driver implements these classes CClassFactory Instantiates your driver event handler CMyDriver Your Driver-Callback Class Must implement IDriverEntry Paired with an IWDFDriver object CMyDevice Your Device-Callback Class May implement IDevicePnpHardware and/or IDevicePnp Paired with an IWDFDevice object UMDF Skeleton Driver Example code based on UMDF Skeleton sample Code in slides should not be used as-is UMDF Skeleton does just enough to get loaded Boilerplate code found in all UM Drivers Minimal callback objects for driver and device Description of files ComSup.h & ComSup.cpp COM Support code – provides classes for IUnknown & IClassFactory DllSup.h & DllSup.cpp DLL Support code – provides implementation of required exports Depends on COM support code Driver.h & Driver.cpp Driver-Callback Class 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 Example: CMyDriver Definition (Driver.h) class CMyDriver: public CUnknown, public IDriverEntry { IDriverEntry *QueryIDriverEntry(); HRESULT Initialize(); public: static HRESULT CreateInstance( PCMyDriver *Driver ); HRESULT OnInitialize( IWDFDriver *FxDriver ){ return S_OK; } HRESULT OnDeviceAdd(IWDFDriver *FxDriver, IWDFDeviceInitialize *FxDeviceInit); HRESULT OnDeinitialize( IWDFDriver *FxDriver ) { return S_OK; } ... // IUnknown methods, etc... }; Example: CMyDriver Implementation (Driver.cpp) HRESULT CMyDriver::CreateInstance( CMyDriver **Driver ) { CMyDriver *driver = new CMyDriver(); if (driver == NULL) { return E_OUTOFMEMORY; } HRESULT hr = driver->Initialize(); if (S_OK == hr) { *Driver = driver; } else { driver->Release(); } return hr; } HRESULT CMyDriver::Initialize() { HRESULT hr = S_OK; ... // Do any initialization that could fail here return hr; } Example: CMyDriver Implementation (con’t) HRESULT CMyDriver::OnDeviceAdd(...) { CMyDevice *deviceCallback; IWDFDevice *fxDevice; HRESULT hr = CMyDevice::CreateInstance( FxDeviceInit, &device ); if (S_OK == hr) { ... // Call SetLockingModel(), SetFilter(), etc... hr = FxWdfDevice->CreateDevice( FxDeviceInit, deviceCallback->QueryIUnknown(), &fxDevice ); // Release Reference from QueryIUnknown() deviceCallback->Release(); } if (S_OK == hr) {fxDevice->Release();} if (NULL != deviceCallback) {deviceCallback->Release();} return hr; } Example: CMyDevice Definition (Device.h) class CMyDevice : public CUnknown { HRESULT Initialize( IWDFDeviceInitialize *DeviceInit ) { return S_OK; } static HRESULT CreateInstance( IWdfDeviceInitialize *FxDeviceInit, CMyDevice **Device ); // Add IUnknown methods here } Writing Your Driver (Summary) Create the common code Required DLL Exports COM support classes Copy from skeleton, use existing ones (ATL), or write your own Implement CMyDriver class Including the OnDeviceAdd() method Allocate and initialize a CMyDevice object Create IWDFDevice object & connect to CMyDevice callbacks Implement CMyDevice class Add Device-Callback interfaces later Your driver should now load But can’t talk to your device or do I/O Next two talks will address that Installing Your Driver INF Based Installation Just like WDM and kernel-mode WDF drivers Device Matching, Driver Signing, etc... work normally User-Mode Driver’s INF does extra work Use UMDF CoInstaller Register Driver DLLs Configure the Driver List Setup UM Driver Key Add the Reflector driver We plan to simplify the installation for Beta 2 Still INF based, but more support from CoInstaller Registry Locations UMDF keeps information in several registry keys We’ll refer to them using these names as we go Defined in the [Strings] section of the Skeleton INF Key Name Location %UMDF_Software% HKLM \ Software \ Microsoft \ Windows NT \ CurrentVersion \ WUDF %UMDF_Services% %UMDF_Software% \ Services %UMDF_Host% %UMDF_Services% \ {193a1820-d9ac-4997-8c55-be817523f6aa} Use UMDF CoInstaller System provided CoInstaller Sets Driver Manager to start automatically WUDFCoInstaller.dll is already installed No need to copy the file Driver’s INF must reference this CoInstaller [Skeleton.CoInstallers] AddReg = Skeleton.CoInstallers_AddReg [Skeleton.CoInstallers_AddReg] HKR,,CoInstallers32,0x00010000,“WUDFCoInstaller.dll” Without the CoInstaller your driver may not start Driver can’t start if the Driver Manager isn’t running Problem code 37 in device manager Register Driver DLLs UMDF uses CoCreateInstance to load drivers This requires the driver to be “registered” INF must register any user-mode drivers it copies Do this in the [DDInstall] section [Skeleton] CopyFiles=DriverCopy RegisterDlls=Skeleton.RegisterDlls [Skeleton.RegisterDlls] 11,,WUDFSkeleton.dll,1 Unregistered drivers will not load Problem code 43 in the device manager Configure the Driver List UMDF loads drivers by “Driver Name” We recommend the binary name (without extension) UMDF Maintains its own driver list Lists drivers in order of attachment to the stack Drivers are listed by “Driver Name” User-Mode drivers load above kernel-mode drivers MultiString stored under the device node’s key [Skeleton_AddReg] HKR, “WUDF”, “DriverList”, 0x00010000, “WUDFSkeleton” If this is missing Problem 43 in device manager Setup UM Driver Key Create an entry under UMDF Services Key One for each driver installed Key name is the Device Name Contains UMDF-Specific Driver Information: The Driver’s CLSID Configure this in the INF Replace CLSID with your driver’s class ID. [Skeleton_AddReg] HKLM, %WUDF_Services%\WUDFSkeleton, “ComCLSID”, 0, “{CLSID}” Without this: Problem 43 in device manager Adding the Reflector Driver Reflector driver is WUDFRd.sys Already installed on the system Your INF must make this the top-most kernel driver If you’re writing a UM function driver Assign reflector as service with AddService directive You’ll need a service install section too If you’re writing a UM Upper-Level filter driver Assign reflector as top-most Upper Device Filter Without this UMDF is never loaded Device may start, but no host process Installing Your Driver (Summary) Use the UMDF CoInstaller Register your Driver DLLs with COM Configure the Driver List Setup UM Driver Key Record your driver’s CLSID Add Reflector driver to the kernel drivers If it doesn’t work: Is Driver Manager started? Does device manager show a problem code? Is WUDFHost.exe (host process) running ? Debugging Your Driver Debugging Overview Similar to service debugging UM Drivers cannot be started by the debugger No Just-In-Time debugging Host process starts when device is installed Plug & Replug the device to restart Or disable & re-enable in device manager Each device stack runs in host process WUDFHost.exe Child of Driver Manager service One stack per host-process for now Debugger Options WinDbg GUI Debugger Source and/or Assembly level debugging UMDF debugger extension available Can work as user-mode or kernel-mode debugger See resources slide to find download location Visual Studio Debugger WDK and Visual Studio aren’t currently integrated UMDF Debugger extension not available Must copy mspdb71.dll from WDK to use it We’re concentrating support on WinDbg CDB & KD If you prefer command line debugging, these work User-Mode or Kernel-Mode Debugging Can debug UMDF with UM or KM debugger You can use WinDbg to debug either way UM Debugger Simpler and more familiar Have to attach to each host process when it starts KM Debugging Requires a second computer to run debugger More complex, but quite powerful Stops entire computer – no UMDF timeouts Can be always running Catch UMDF Verifier problems like JIT debugger Can debug and set breakpoints in host process Use “.process /i <process object address>” to break into running host See additional slides for KM Debugging tips Enabling the Debugger Host process started by Driver Manager service You can’t attach debugger until after initialization Host Process supports an “initial breakpoint” (IB) Host waits N seconds for debugger to attach Breaks into debugger once detected Continues running once N seconds elapse Timeout (in seconds) configured under UMDF_Host key HostProcessDbgBreakOnStart = N Enabling IB disables other UMDF timeouts Like those on PnP operations Initial Breakpoint is for UM Debugger (by default) Can be configured to watch for both UM & KM debugger Set high-bit in the timeout value 0x8000000 attempts once to break into either debugger Attaching the UM Debugger Cannot connect UM Debugger until host starts Enable the Initial Breakpoint Attach the device to the system Or enable it in the device manager If you have a single device attached Run “windbg –pn WUDFHost.exe” Repeat until it finds a host process to debug If you have multiple devices attached Find out process ID (PID) of the new host Use tasklist.exe before & after to find new host process Run “windbg –p PID” UMDF Debugger Extension WudfExt.dll Copy into your path “!load WudfExt.dll” debugger command loads the extension Names are case sensitive Command !devstack !dumpirps !umirp !wdfdriverinfo !wdfdevicequeue !wdfqueue !wdfrequest !wdfitf2obj Description Shows device stacks in the host process Shows UM IRPs in the host process Shows a host IRP Shows info about a UM driver Shows the I/O queues for a device Shows an IoQueue Shows an IoRequest Converts an interface pointer to an object address for above extensions. Interesting UMDF Breakpoints (BP) Hopefully, this will get you started Event to debug Host attempts to load driver Driver Load Breakpoint (BP) OLE32!CoCreateInstance Watch for your CLSID MyDriver!DllMain Invoked first time when your DLL is loaded Called after that too, so clear the BP once it hits Creation of CMyDriver Driver attaches device to stack MyDriver!DllGetClassObject Invoked to get your class factory MyDriver!CMyDriver::CMyDriver Invoked when the factory calls new MyDriver!CMyDriver::OnDeviceAdd Driver creates a device to attach to the stack Tracing in Your UM Driver Recommend using WPP tracing for debug output Lightweight & always available, printf-style tracing Easily captured to disk, screen or (kernel) debugger Skeleton contains some basic tracing code See MSDN documentation on Event Tracing Collect output with tracelog.exe or traceview.exe Tracelog comes with Windows Traceview comes with WDK For more information see: “Collecting & Viewing Traces” in additional slides MSDN & DDK documentation What Do I Do When It Crashes? (Summary) Check for configuration problems Is there a PNP problem code? Is there a host process running? Is there a .dmp file WUDF log file directory? %SystemRoot%\LogFiles\WUDF\*.dmp Attach a debugger to the host as it starts Or always enable the kernel debugger Watch for UMDF Verifier failures Walk through initialization Use list of interesting breakpoints Get debug output with WPP tracing Plug and Play / Power Management UMDF Design Goals for PnP/PM Coordinate I/O delivery to driver with PnP/PM events The framework handles complexities of PnP/PM Allow drivers to participate with optional callbacks Support FDO and filter driver scenarios No bus driver support for version 1 Same design as kernel mode WDF PnP/PM UMDF PnP/PM Design Implemented with a state machine Consumes PnP/Power messages from the reflector Suspends and resumes I/O queues as needed Calls the driver if desired through a set of driver provided callback functions Driver callbacks are logically grouped into interfaces IDevicePnpHardware IDevicePnp IDevicePnpSelfManagedIo Driver “opts-in” by implementing one or more callback interfaces Software-only drivers generally don’t need any of these interfaces Most drivers will only need IDevicePnpHardware UMDF PnP/PM Interfaces IDevicePnpHardware First time hardware initialization / de-initialization OnPrepareHardware() OnReleaseHardware() IDevicePnp Device state change notifications OnD0Entry() OnD0Exit() OnSurpriseRemoval() OnQueryRemove() OnQueryStop() IDevicePnpSelfManagedIo Custom I/O processing notifications OnSelfManagedIoCleanup() OnSelfManagedIoFlush() OnSelfManagedIoInit() OnSelfManagedIoSuspend() OnSelfManagedIoRestart() Device Driver Interface (DDI) IDriverEntry::OnDeviceAdd Driver must implement this interface Called when framework receives “Add Device” message Driver should perform initialization that does not require access to hardware or lower level drivers Driver also creates a device object and device callback object (beyond the scope of this talk) HRESULT CMyDriver::OnDeviceAdd( IWDFDriver* pDriver, IWDFDeviceInitialize* pDeviceInit ) { // Read in driver properties INamedPropertyStore * pPropStore = NULL; hr = pDeviceInit->GetDevicePropertyStore( &pPropStore ); ... } IDevicePnpHardware OnPrepareHardware Called when device is first started Driver establishes connection to the device and performs one-time initialization HRESULT CMyDevice::OnPrepareHardware( IWDFDevice* pDevice ) { ... // Open the device hr = pDevice->GetDeviceName( pDeviceName, … ) m_Handle = CreateFile( pDeviceName, … ) ... // Initialize the device and look for endpoints if (WinUsb_Initialize( m_Handle, &m_UsbHandle )) { return DiscoverBulkEndpoints(); } IDevicePnpHardware OnReleaseHardware Called when device is removed or stopped Driver should essentially undo anything it did in OnPrepareHardware HRESULT CDevice::OnReleaseHardware( IWDFDevice* pDevice ) { // Close the USB handle and the device’s file // handle if ( m_UsbHandle ) { WinUsb_Free( m_UsbHandle ); } if ( m_Handle ) { CloseHandle( m_Handle ); } return S_OK; } IDevicePnp OnD0Exit Called each time device should power down Also called before the device is removed Stop device’s I/O target with “leave pending I/O” flag hr = m_pIoTarget-> Stop( WdfIoTargetLeaveSentIoPending ); Save device state Set the device into low power state OnD0Entry Called each time device should power up Also called when the device starts up Set the device into working power state Restore any previously saved state Restart device’s I/O target hr = m_pIoTarget->Start(); IDevicePnp OnSurpriseRemoval Called when the device has unexpectedly detached from the PC Stop device’s I/O target with cancel flag hr = m_pIoTarget->Stop( WdfIoTargetCancelSentIo ) OnQueryRemove Allows driver to veto a device removal request HRESULT CDevice::OnQueryRemove( IWDFDevice* pDevice ) { return S_OK; // Allow device removal } OnQueryStop Allows driver to veto a device stop request HRESULT CDevice::OnQueryStop( IWDFDevice* pDevice ) { return E_FAIL; // Disallow device stop } IDevicePnpSelfManagedIo Notifications to drivers that perform I/O dispatching unmanaged by the framework OnSelfManagedIoInit() Start I/O dispatching OnSelfManagedIoSuspend() Pause I/O dispatching OnSelfManagedIoRestart() Resume I/O dispatching OnSelfManagedIoFlush() Cancel or complete all pending I/O OnSelfManagedIoCleanup() Free I/O dispatching mechanisms PnP/PM Driver Callback Example Start Device OnPrepareHardware() Device Driver Framework Start Device Off On Off Start Device OnD0Entry() Device Driver Framework Start Device Off On Off Device Operational Device Driver Framework On On Off Suspend Device OnD0Exit() Device Driver Framework Power Down On On Off Resume Device OnD0Entry() Device Driver Framework Power Up On On Off Remove Device OnD0Exit() Device Driver Framework Remove Device On On Off Remove Device OnReleaseHardware() Device Driver Framework Remove Device On On Off WDM Message to UMDF Callback Mapping Start -> Query Remove -> Remove IRP_MN_START_DEVICE: 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 -> Surprise Removal -> Remove IRP_MN_START_DEVICE: OnPrepareHardware() OnD0Entry() OnSelfManagedIoInit() IRP_MN_SURPRISE_REMOVAL: OnSurpriseRemoval() OnSelfManagedIoSuspend() OnReleaseHardware() OnSelfManagedIoFlush() IRP_MN_REMOVE_DEVICE: OnSelfManagedIoCleanup() PnP/PM Timeouts Each WDM PnP/PM message has a timeout Currently, this timeout is set to 1 minute The reflector will abort the host process if this timeout is exceeded Each WDM Pnp/PM message can produce multiple driver callbacks, for example: “AddDevice” results in: OnInitialize OnDeviceAdd 1 minute IRP_MN_START results in: OnPrepareHardware OnD0Entry OnSelfManagedIoInit 1 minute Supplemental Slides Example: DllMain BOOL DllMain( HINSTANCE ModuleHandle, DWORD Reason, PVOID Reserved ) { if (DLL_PROCESS_ATTACH == Reason) { WPP_INIT_TRACING(“Microsoft\\UMDF\\UMDFSkeleton”); g_ModuleHandle = ModuleHandle; } else if (DLL_PROCESS_DETACH) == Reason) { WPP_CLEANUP(); } return TRUE; } See Skeleton\Host.cpp Example: DllGetClassObject HRESULT DllGetClassObject( REFCLSID ClassId, REFIID InterfaceId, PVOID *Interface ) { PCClassFactory factory; HRESULT hr; *Interface = NULL; if (!IsEqualCLSID( ClassId, __uuidof(MyDriverCoClass) )) { return CLASS_E_NOTAVAILABLE; } hr = CClassFactory::CreateInstance(&factory); if (S_OK == hr) { hr = factory->QueryInterface(InterfaceId, Interface); factory->Release(); } return hr; } Example: DllRegisterServer & DllCanUnloadNow HRESULT DllRegisterServer() { return UpdateCOMRegistration( g_ModuleHandle, IDR_MYDRIVER_CLASSINFO, true, __uuidof( MyDriverCoClass ), L“UMDF Skeleton Sample Driver” ); } HRESULT DllUnregisterServer() { return UpdateCOMRegistration(..., false, ...) } HRESULT DllCanUnloadNow() { return S_FALSE; } Example: CUnknown Definition class CUnknown : public IUnknown { LONG m_RefCount; public: CUnknown() { m_RefCount = 1; } virtual ~CUnknown() { return; } IUnknown *QueryIUnknown(){ AddRef(); return (IUnknown *)this; } ULONG AddRef(); ULONG Release(); HRESULT QueryInterface( REFIID InterfaceId, PVOID *Interface ); }; Example: CUnknown Implementation ULONG CUnknown::AddRef(){ return InterlockedIncrement(&m_RefCount); } ULONG CUnknown::Release() { ULONG count = InterlockedIncrement(&m_RefCount); if (count == 0) { delete this; } return count; } HRESULT CUnknown:QueryInterface(...) { if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) { *Interface = QueryIUnknown(); return S_OK; } *Interface = NULL; return E_NOINTERFACE; } Example: CClassFactory Definition class CClassFactory : public CUnknown, public IClassFactory { public: IClassFactory *QueryIClassFactory() {...} // IUnknown AddRef() {return __super::AddRef()} Release() {return __super::Release()} QueryInterface(...); // IClassFactory HRESULT CreateInstance( IUnknown *Outer, REFIID InterfaceId, PVOID *Object ); HRESULT LockServer(BOOL Lock) { return S_OK; } }; Example: CClassFactory Implementation HRESULT CClassFactory::QueryInterface(...) { if(IsEqualIID(Interface, __uuidof(IClassFactory)) { *Object = QueryIClassFactory(); return S_OK; } else { return CUnknown::QueryInterface(...); } } HRESULT CClassFactory::CreateInstance(...) { PCMyDriver driver; HRESULT hr = CMyDriver::CreateInstance(&driver); if (S_OK == hr) { hr = driver->QueryInterface(InterfaceId, Object); driver->Release(); } return hr; } Debugging with WinDbg Source Level GUI debugger (Most) commands work on addresses or symbols ModuleName!FunctionName ModuleName!ClassName::MethodName Best to always use fully resolved names Setting Breakpoints “bp <addr>” sets an excution breakpoint Use bu if the function’s module isn’t loaded yet ‘ba [w|r] [1|2|4|8] <addr>’ sets a watchpoint ba r 4 MyDriver!g_MyArrayLength Dumping Memory d<type> [address] [L<length>] type = byte, word, char, unicode, dword, quadword, string dd MyMyDriver!g_MyArrayLength L1 dv dumps local variable names Dumping Types dt <variable name> dumps a specific local dt <addr> <typename> dumps an address or symbol as a type dt ??? MyDriver!CMyDevice See the WinDbg help for more details Debugging with a Kernel Debugger WinDbg can be used as a kernel debugger Must point Kernel debugger to host process Automatic if the process requests a kernel break-in Manually through the .process command “!process 0 0” will list all process object addresses Must reload user-mode symbols after attaching “.reload /user” Or the stack trace won’t have any symbols Can set breakpoints on user-mode addresses Must load user symbols first Cannot break into a running host process Must wait for a breakpoint UMDF “Verifier” will break into KD if attached Last chance to debug before process termination Collecting & Viewing Traces TraceLog.exe lets you control trace sessions To start a session Tracelog.exe -start MyLogger -guid MyDriver.ctl -level 255 -flag 65535 -f MyLogFile.etl To end a session Tracelog.exe -stop MyLogger To print a session TraceFmt –o MyLogFile.txt -p symbols.pri/TraceFormat MyLogFile.etl Or use the GUI “TraceView” tool Use in place of TraceLog or TraceFmt Resources: “WPP Software Tracing” page in DDK documentation MSDN online page for these tools: http://msdn.microsoft.com/library/default.asp?url=/library/enus/ddtools/hh/ddtools/tracetools_8eccb8f7-6f29-4683-87bdfa83618c32eb.xml.asp How to Develop a UMDF Driver: Part 3 Outline I/O Processing Overview I/O Queues File Objects Driver Layering I/O Targets Cancellation Goals A better understanding of: How to incorporate I/O processing in a UMDF driver Framework objects involved with I/O Request processing Knowledge of where to find resources for UMDF I/O Request Processing Overview I/O Request Processing in UMDF You’ve seen WDF Driver and 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 Framework Objects Driver Device Request Memory (Input) Memory (Output) Queue File I/O Target Framework Objects These objects are associated with request processing All derive from IWDFObject Object Description Device The information associated with a single layer in a device stack Request An I/O operation Either sent to the driver or initiated by the driver to a lower device A flow control mechanism for Requests An open handle to the device and any context the driver needs to store with it Another driver to which the Driver can send Requests Either another user-mode layer in the device stack, the kernel-mode portion of the device stack, or the top of another device stack entirely. Queue File I/O Target Memory A buffer associated with a request I/O Request Processing – A Bird’s Eye view Request I/O Queue Driver I/O Target Complete I/O Request Object Request I/O Queue Driver I/O Target Complete I/O Request Object Represents a request Sent to the driver by a client An application or another UM driver Generated by a driver Types of Requests presented to driver Create Read / Write / DeviceIoControl Cleanup Close Request Parameters can be obtained from IWDFIoRequest interface I/O Queues I/O Queues Request I/O Queue Driver I/O Target Complete I/O Queues Queues provide flow control for I/O Requests All requests dispatched to driver through I/O Queues Driver can configure I/O routing for a device Create one or more queues for a device Configure routing for a type of I/O to a particular queue “Default queue” handles any remaining I/O types I/O Queue Dispatch Types Dispatch Type controls how requests are presented to driver Queues allow following modes of dispatching: Automatic: Queue presents requests via callbacks (Push Model) Manual: Requests are retrieved by driver (Pull Model) Dispatch type is set at Queue creation time It is a per-Queue property Automatic Dispatch Queue presents request through driver implemented callback interfaces IQueueCallbackCreateClose IQueueCallback[Read | Write | DeviceIoControl] Automatic Dispatch Types Sequential: allows at most one outstanding request at a time New Request not presented until current request is completed Parallel: allows multiple outstanding requests New Request can be presented even when previously presented requests are not completed The number of parallel requests presented is bounded Driver should minimize blocking in presentation callbacks Manual Dispatch Driver pulls requests from the queue Typically starts in response to Queue callback IQueueCallbackStateChange Empty to non-empty transition Continues to pump I/O until “done” No more I/O, bookmark 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 Callback Constraints Callback constraints specify locking model for Queue callbacks Callback constraints options Device Level: Callbacks invoked with device level lock held None: Callbacks invoked with no lock held Specified at device creation time via IWDFDeviceInitialize::SetLockingConstraint Set before creating the WDF Device object Per device property – applies to all queues Callback Constraints (con’t) Constraints apply only to Queue Callbacks Queue callbacks include Automatic Dispatch Callbacks Queue state change callback Request cancellation callback If Device Level locking is used: The above callbacks are synchronized Request Completion is a not a Queue Callback – not synchronized Unsynchronized code can call IWDFObject::AcquireLock Call on object that matches your synchronization scope Dispatch Type vs. Locking Model Combining Dispatch Type and Locking Model provides several modes of operation For example: Sequential Queue Device Level Locking Parallel Queue Device Level Locking Request1 Request1 Req1 Complete Request2 Request2 Req2 Complete Req1 Complete Req2 Complete Parallel Queue No Locking Request1 Request2 Req1 Complete Req2 Complete UMDF OSR USB Sample Walk-through Requests and Queue Usage in the sample driver (src\umdf\usb\driver) Callback locking constraint used (CMyDevice::Initialize in Device.cpp) Dispatch type used (CMyQueue::Initialize in Queue.cpp) Queue callbacks used (CMyQueue in Queue.h and Queue.cpp) File Objects File Object File Object represents open connection to device It is the session context for I/O All requests associated with a File Object in UMDF KMDF and WDM requests sometimes don’t have one File object for a request obtained using IWDFIoRequest::GetFileObject Trailing name used by client while opening connection is available via IWDFFile::GetFileName File Object (con’t) Device File1 Request1 Request2 File2 Request1 Request2 File Object Lifetime File Object’s lifetime spans Create: File Object gets created in response to a connection being opened Cleanup: Notification of connection being torn down and that Close is pending Close: All I/O pertaining to this File Object has now ceased. File Object is now disposed. File Object is created and destroyed by the Framework All I/O operations happen in the context of File object i.e., they happen between Create and Close These operations are: Read / Write / DeviceIoControl File Object Lifetime Illustrated Example of I/O sequence between App and Driver Application hFile = CreateFile(… … Async/Sync Read/Write/IoCtl … CloseHandle(hFile); Driver Create Request … Read/Write/IoCtl Requests … Cleanup … Any remaining Requests drain … Close 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 UMDF OSR USB Sample Walk-through File usage in the sample driver (src\umdf\usb\driver) (Queue.cpp) CMyQueue::OnRead CMyQueue::OnCreateFile CMyQueue::OnCleanupFile CMyQueue::OnCloseFile Driver Layering Driver Layering UMDF supports driver layering Multiple drivers build a device stack “Function” driver provides core device behavior “Filter” drivers modify aspects of device behavior Filter is a property set at device creation time All Framework Objects are per layer Each layer works only with its own objects e.g., each layer gets a Request object to complete Driver sends request to next layer using I/O Target Represents the next driver in the stack That driver may be in user mode or kernel mode Driver Layering Diagram Framework Device Queue File Request Framework Device Queue File Request Framework Device Device Stack Queue File Request Request Completion When Driver receives a Request it can Complete the Request synchronously Forward it to an I/O Target or an I/O Queue Hold on to it to complete later Driver must complete a Request it receives e.g., while forwarding request to I/O Target Driver must register request-completion-callback object Framework invokes callback when target completes request Callback must complete request or arrange for completion UM IRP not complete until all layers complete their Request objects Completion callback is not a device level event Runs outside driver’s callback locking constraints Request Completion Illustrated Request Completion Routine Request Completion Routine Request I/O Target I/O Target Request I/O Queue Driver I/O Target Complete I/O Target Framework Object Provides a way to send requests to another device Local I/O Target represents: The next device in the stack Another UM Driver, or the KM portion of the stack Driver doesn’t need to care which it is Remote I/O Target represents Some other UM or KM device stack Need feedback to prioritize this for Longhorn I/O Target is responsible for Sending I/O request to lower device Detecting completion and invoking callback interface Local I/O Target Application Device I/O Target Device I/O Target Device I/O Target User Mode Kernel Mode Up Device Down Device Device Device Device Stack Reflector 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 Bridging UM and KM stacks I/O Target provides bridge between KM and UM drivers Bottom-most I/O Target sends requests to kernel-mode stack Driver could also “escape” to the Platform API Send I/O using Win32 File I/O API directly Advantages of using I/O Target Handles complexity of coordinating completion, cancellation and cleanup Allows for filtering and layered stacks transparently Allows routing of request to kernel mode in mode neutral way Offers rich functionality In Beta 1 Bottom-most I/O Target uses Win32 File I/O API internally No way to use specific API (e.g., WinUSB) Makes the escape necessary in such cases UMDF OSR USB Sample Walk-through I/O Target usage in the sample filter (src\umdf\usb\filter) Obtaining default I/O Target (CMyQueue::Initialize in Queue.cpp) Forwarding request down the stack (CMyQueue::OnWrite in Queue.cpp) (CMyQueue::ForwardRequest in Queue.cpp) Request Cancellation Request Cancellation Application can cancel a request at any time by Using CancelIo[Ex] API Exiting application, etc. Higher layer driver can cancel sent requests Cancel tells driver to complete request soon But not necessarily immediately Driver should abort any long operations Short synchronous requests can just be allowed to complete normally Cancel is a critical operation Cannot be failed, subject to timeout, etc… Cancellation is part of good user experience Cancellation Overview Request Owner can register a cancel callback Cancel callback follows locking constraints On Cancel: Request’s internal state is marked as cancelled Any callback registered after this will run immediately Registered cancel callback is cleared then invoked In the cancellation callback Owner arranges to cancel and complete request Remove callback before transferring ownership e.g., when forwarding or completing the Request Request Ownership Request ownership starts with I/O Queue Request ownership moves from: Queue to Driver – Driver receives the Request Driver to Queue – Driver forwards Request to Queue Driver to I/O Target – Driver forwards Request to I/O Target Queue or I/O Target handle cancellation when they own request I/O Target notifies you through completion callback Driver must handle cancel when it owns request If it holds on to the request for a long time Cancellation Handling in Driver When driver receives a Request, it may: Complete it soon Shortly send it to I/O Target Queue it back to Framework I/O Queue Hold on to it (not using Framework I/O Queue) Do (potentially) lengthy sync/asynch processing Driver needs to handle cancellation only in the last two cases Cancellation Handling in Driver (con’t) Driver may register a cancel notification callback void IWDFIoRequest::MarkCancelable( IRequestCallbackCancel* pCancelCallback ); In callback it should cancel/complete the request As soon as possible Unregister callback when transferring ownership Before sending request to I/O target or completing it HRESULT IWdfIoRequest::UnmarkCancelable(); Failure return value indicates request has been canceled Cancel routine has run or will run soon Owner must ensure Request is completed only once Cancellation Illustrated Let us take the example of OSR USB Driver This driver uses device level locking It submits I/O requests to WinUSB The internal completion routine manually uses device level lock Request state is stored in Request context There are the following possibilities: 1. Request completes without cancellation 2. Request is cancelled 2a. Cancel callback runs before completion callback 2b. Cancel callback runs after completion callback The driver makes sure that: Request is completed only once Request is not completed until both completion and cancellation callback are done with it Cancellation Illustrated (1) OnRead* … Req->MarkCancelable … WinUSB_ReadPipe … OnCancel* … if (ctx->state == RequestCompleted) { CompleteRequest } else { CancelIoEx ctx->state = CancelInvoked; } * Invoked under DeviceLock OnUSBReadComplete … DeviceLock->AcquireLock(); if (Req->UnmarkCancelable()) { DeviceLock->ReleaseLock(); CompleteRequest } else { if (ctx->state == CancelInvoked) { DeviceLock->ReleaseLock(); CompleteRequest } else { ctx->state = RequestCompleted; DeviceLock->ReleaseLock(); } } Cancellation Illustrated (2a) OnRead* … Req->MarkCancelable … WinUSB_ReadPipe … OnCancel* … if (ctx->state == RequestCompleted) { CompleteRequest } else { CancelIoEx ctx->state = CancelInvoked; } * Invoked under DeviceLock OnUSBReadComplete … DeviceLock->AcquireLock(); if (Req->UnmarkCancelable()) { DeviceLock->ReleaseLock(); CompleteRequest } else { if (ctx->state == CancelInvoked) { DeviceLock->ReleaseLock(); CompleteRequest } else { ctx->state = RequestCompleted; DeviceLock->ReleaseLock(); } } Cancellation Illustrated (2b) OnRead* … Req->MarkCancelable … WinUSB_ReadPipe … OnCancel* … if (ctx->state == RequestCompleted) { CompleteRequest } else { CancelIoEx ctx->state = CancelInvoked; } * Invoked under DeviceLock OnUSBReadComplete … DeviceLock->AcquireLock(); if (Req->UnmarkCancelable()) { DeviceLock->ReleaseLock(); CompleteRequest } else { if (ctx->state == CancelInvoked) { DeviceLock->ReleaseLock(); CompleteRequest } else { ctx->state = RequestCompleted; DeviceLock->ReleaseLock(); } } UMDF OSR USB Sample Walk-through Cancellation walk-through in the sample driver (src\umdf\usb\driver) (Queue.cpp) CMyQueue::OnRead CMyQueue::OnCancel CMyQueue::CompletionThread Putting It Together You’ve seen the following portions of the sample: Driver (Driver.cpp) CMyDriver::OnDeviceAdd Device (Device.cpp) CMyDevice::OnPrepareHardware CMyDevice::OnReleaseHardware Queue (Queue.cpp) CMyQueue::OnCreateFile CMyQueue::OnCleanupFile CMyQueue::OnRead / CQueue::OnWrite CMyQueue::OnCancel CMyQueue::CompletionThread Call to Action Install the Windows Driver Kit Join the WDF Beta Program At http://beta.microsoft.com Guest ID: Guest4WDF Evaluate UMDF for your driver projects Consider development time, customer support for system crashes, etc. Send Us Feedback – We want to know If UMDF will meet your needs What stops you from writing your drivers with UMDF Additional Resources Email umdffdbk @ microsoft.com Web Resources: WDF Information: http://www.microsoft.com/whdc/driver/wdf/default.mspx Windows Debugger: http://www.microsoft.com/whdc/devtools/debugging/default.mspx External Resources “Introduction to the Windows Driver Foundation: How To Develop Device Drivers Using the Kernel Mode Driver Framework” from OSR Press Release date is September 2005 Focuses on KMDF but provides general WDF information as well © 2005 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
© Copyright 2024