summaryrefslogtreecommitdiff
path: root/usb/umdf_filter_umdf
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /usb/umdf_filter_umdf
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'usb/umdf_filter_umdf')
-rw-r--r--usb/umdf_filter_umdf/Package/package.VcxProj91
-rw-r--r--usb/umdf_filter_umdf/Package/package.VcxProj.Filters21
-rw-r--r--usb/umdf_filter_umdf/ReadMe.md57
-rw-r--r--usb/umdf_filter_umdf/inc/WUDFOsrUsbPublic.h32
-rw-r--r--usb/umdf_filter_umdf/inc/list.h77
-rw-r--r--usb/umdf_filter_umdf/inc/public.h217
-rw-r--r--usb/umdf_filter_umdf/inc/usb_hw.h233
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/ControlQueue.cpp564
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/ControlQueue.h101
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/Device.cpp2087
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/Device.h604
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/Driver.cpp220
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/Driver.h149
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/OsrUsbFx2.ctl1
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/OsrUsbFx2.rc21
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/ReadWriteQueue.cpp425
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/ReadWriteQueue.h163
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/WUDFOsrUsbFx2.vcxproj270
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/WUDFOsrUsbFx2.vcxproj.Filters52
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/comsup.cpp344
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/comsup.h215
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/dllsup.cpp202
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/exports.def4
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/internal.h170
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/queue.cpp147
-rw-r--r--usb/umdf_filter_umdf/umdf_driver/queue.h93
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/OsrUsbFilter.rc17
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilter.vcxproj287
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilter.vcxproj.Filters51
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilterOnUmFx2Driver.inx114
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/comsup.cpp351
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/comsup.h215
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/device.cpp243
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/device.h114
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/dllsup.cpp183
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/driver.cpp207
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/driver.h145
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/exports.def4
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/internal.h111
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/queue.cpp538
-rw-r--r--usb/umdf_filter_umdf/umdf_filter/queue.h253
-rw-r--r--usb/umdf_filter_umdf/umdf_filter_umdf.sln59
42 files changed, 9452 insertions, 0 deletions
diff --git a/usb/umdf_filter_umdf/Package/package.VcxProj b/usb/umdf_filter_umdf/Package/package.VcxProj
new file mode 100644
index 00000000..b9b377e9
--- /dev/null
+++ b/usb/umdf_filter_umdf/Package/package.VcxProj
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="PropertySheets">
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Utility</ConfigurationType>
+ <DriverType>Package</DriverType>
+ <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
+ <Configuration>Debug</Configuration>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{92A41A0C-EC0F-4D98-B4DE-4899B375FD49}</ProjectGuid>
+ <SampleGuid>{ECED2BAF-D334-46B0-A7A9-734224614A21}</SampleGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup>
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <ImportToStore>False</ImportToStore>
+ <InstallMode>None</InstallMode>
+ <HardwareIdString />
+ <CommandLine />
+ <ScriptPath />
+ <DeployFiles />
+ <ScriptName />
+ <ScriptDeviceQuery>%PathToInf%</ScriptDeviceQuery>
+ <EnableVerifier>False</EnableVerifier>
+ <AllDrivers>False</AllDrivers>
+ <VerifyProjectOutput>True</VerifyProjectOutput>
+ <VerifyDrivers />
+ <VerifyFlags>133563</VerifyFlags>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <!--Inf Include="DriverInf.inv" /-->
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\umdf_driver\WUDFOsrUsbFx2.vcxproj">
+ <Project>{0D3781C2-2236-46B0-806D-387999E500AB}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\umdf_filter\WUDFOsrUsbFilter.vcxproj">
+ <Project>{E62A4AAA-870E-4D58-AA10-D9604A2E52E8}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/usb/umdf_filter_umdf/Package/package.VcxProj.Filters b/usb/umdf_filter_umdf/Package/package.VcxProj.Filters
new file mode 100644
index 00000000..a96565c8
--- /dev/null
+++ b/usb/umdf_filter_umdf/Package/package.VcxProj.Filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{4E330348-D3BC-4378-9E28-1C0E89913E9C}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{F5D9FE78-6B2A-4C19-91B7-49A3D081DA74}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{32502152-33D3-42BC-8DC3-DBCEC24AAC1F}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{82F51BD2-E3F4-4E26-9787-497F73C1EC82}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/usb/umdf_filter_umdf/ReadMe.md b/usb/umdf_filter_umdf/ReadMe.md
new file mode 100644
index 00000000..56eb02db
--- /dev/null
+++ b/usb/umdf_filter_umdf/ReadMe.md
@@ -0,0 +1,57 @@
+Sample UMDF Filter above UMDF Function Driver for OSR USB-FX2 (UMDF Version 1)
+==============================================================================
+
+The umdf\_filter\_umdf sample demonstrates how to load a User-Mode Driver Framework (UMDF) filter driver as an upper filter driver above the umdf\_fx2 sample driver.
+
+This sample is written for the OSR USB-FX2 Learning Kit. The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>.
+
+Overview
+--------
+
+Here is the overview of the device:
+
+- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to query toggle switch states.
+- Interrupt Endpoint:
+ - Sends an 8-bit value that represents the state of the switches.
+ - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
+ - Firmware does not de-bounce the switch pack.
+ - One switch change can result in multiple bytes being sent.
+ - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
+- Bulk Endpoints are configured for loopback:
+ - The device moves data from IN endpoint to OUT endpoint.
+ - The device does not change the values of the data it receives nor does it internally create any data.
+ - Endpoints are always double buffered.
+ - Maximum packet size depends on speed (64 full speed, 512 high speed).
+
+Testing the driver
+------------------
+
+You can test this sample either by using the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample application, or by using the osrusbfx2.exe test application. For information on how to build and use the osrusbfx2.exe application, see the test instructions for the [umdf\_fx2](http://msdn.microsoft.com/en-us/library/windows/hardware/) sample.
+
+Sample Contents
+---------------
+
+<table>
+<colgroup>
+<col width="50%" />
+<col width="50%" />
+</colgroup>
+<thead>
+<tr class="header">
+<th align="left">Folder
+Description</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td align="left">usb\umdf_filter_umdf\umdf_driver
+This directory contains source code for the umdf_fx2 sample driver.</td>
+<td align="left">usb\umdf_filter_umdf\umdf_filter
+This directory contains the UMDF filter driver.</td>
+</tr>
+</tbody>
+</table>
+
+
diff --git a/usb/umdf_filter_umdf/inc/WUDFOsrUsbPublic.h b/usb/umdf_filter_umdf/inc/WUDFOsrUsbPublic.h
new file mode 100644
index 00000000..6681fa14
--- /dev/null
+++ b/usb/umdf_filter_umdf/inc/WUDFOsrUsbPublic.h
@@ -0,0 +1,32 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ WUDFOsrUsbPublic.h
+
+Abstract:
+
+ This module contains the common declarations shared by driver
+ and user applications for the UMDF OSR device sample.
+
+ Note that this driver does NOT use the same device interface GUID
+ as the KMDF OSR USB sample.
+
+Environment:
+
+ user and kernel
+
+--*/
+
+#pragma once
+
+//
+// Define an Interface Guid so that app can find the device and talk to it.
+//
+
+// {573E8C73-0CB4-4471-A1BF-FAB26C31D384}
+DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2,
+ 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);
+
diff --git a/usb/umdf_filter_umdf/inc/list.h b/usb/umdf_filter_umdf/inc/list.h
new file mode 100644
index 00000000..38d0b1e9
--- /dev/null
+++ b/usb/umdf_filter_umdf/inc/list.h
@@ -0,0 +1,77 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ list.h
+
+Abstract:
+
+ This module contains doubly linked list macros
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+
+FORCEINLINE
+VOID
+InitializeListHead(
+ IN PLIST_ENTRY ListHead
+ )
+{
+ ListHead->Flink = ListHead->Blink = ListHead;
+}
+
+FORCEINLINE
+BOOLEAN
+RemoveEntryList(
+ IN PLIST_ENTRY Entry
+ )
+{
+ PLIST_ENTRY Blink;
+ PLIST_ENTRY Flink;
+
+ Flink = Entry->Flink;
+ Blink = Entry->Blink;
+ Blink->Flink = Flink;
+ Flink->Blink = Blink;
+ return (BOOLEAN)(Flink == Blink);
+}
+
+FORCEINLINE
+VOID
+InsertHeadList(
+ IN PLIST_ENTRY ListHead,
+ IN PLIST_ENTRY Entry
+ )
+{
+ PLIST_ENTRY Flink;
+
+ Flink = ListHead->Flink;
+ Entry->Flink = Flink;
+ Entry->Blink = ListHead;
+ Flink->Blink = Entry;
+ ListHead->Flink = Entry;
+}
+
+FORCEINLINE
+VOID
+InsertTailList(
+ IN PLIST_ENTRY ListHead,
+ IN PLIST_ENTRY Entry
+ )
+{
+ PLIST_ENTRY Blink;
+
+ Blink = ListHead->Blink;
+ Entry->Flink = ListHead;
+ Entry->Blink = Blink;
+ Blink->Flink = Entry;
+ ListHead->Blink = Entry;
+}
diff --git a/usb/umdf_filter_umdf/inc/public.h b/usb/umdf_filter_umdf/inc/public.h
new file mode 100644
index 00000000..22f6cb6d
--- /dev/null
+++ b/usb/umdf_filter_umdf/inc/public.h
@@ -0,0 +1,217 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ public.h
+
+Abstract:
+
+ Public definitions for the OSR_FX2 device operations.
+
+Environment:
+
+ User & Kernel mode
+
+--*/
+
+#ifndef _PUBLIC_H
+#define _PUBLIC_H
+
+#include <initguid.h>
+
+#include "WudfOsrUsbPublic.h"
+
+
+//
+// Define the structures that will be used by the IOCTL
+// interface to the driver
+//
+
+//
+// BAR_GRAPH_STATE
+//
+// BAR_GRAPH_STATE is a bit field structure with each
+// bit corresponding to one of the bar graph on the
+// OSRFX2 Development Board
+//
+#include <pshpack1.h>
+
+#pragma warning( push )
+#pragma warning( disable : 4201 ) // nameless struct/union
+#pragma warning( disable : 4214 ) // bit-field type other than int
+
+typedef struct _BAR_GRAPH_STATE {
+
+ union {
+
+ struct {
+ //
+ // Individual bars starting from the
+ // top of the stack of bars
+ //
+ // NOTE: There are actually 10 bars,
+ // but the very top two do not light
+ // and are not counted here
+ //
+ UCHAR Bar1 : 1;
+ UCHAR Bar2 : 1;
+ UCHAR Bar3 : 1;
+ UCHAR Bar4 : 1;
+ UCHAR Bar5 : 1;
+ UCHAR Bar6 : 1;
+ UCHAR Bar7 : 1;
+ UCHAR Bar8 : 1;
+ };
+
+ //
+ // The state of all the bar graph as a single
+ // UCHAR
+ //
+ UCHAR BarsAsUChar;
+
+ };
+
+}BAR_GRAPH_STATE, *PBAR_GRAPH_STATE;
+
+//
+// SWITCH_STATE
+//
+// SWITCH_STATE is a bit field structure with each
+// bit corresponding to one of the switches on the
+// OSRFX2 Development Board
+//
+typedef struct _SWITCH_STATE {
+
+ union {
+ struct {
+ //
+ // Individual switches starting from the
+ // left of the set of switches
+ //
+ UCHAR Switch1 : 1;
+ UCHAR Switch2 : 1;
+ UCHAR Switch3 : 1;
+ UCHAR Switch4 : 1;
+ UCHAR Switch5 : 1;
+ UCHAR Switch6 : 1;
+ UCHAR Switch7 : 1;
+ UCHAR Switch8 : 1;
+ };
+
+ //
+ // The state of all the switches as a single
+ // UCHAR
+ //
+ UCHAR SwitchesAsUChar;
+
+ };
+
+
+}SWITCH_STATE, *PSWITCH_STATE;
+
+//
+// Seven segment display bit values.
+//
+
+//
+// Undefine conflicting MFC constant
+//
+#undef SS_CENTER
+#undef SS_LEFT
+#undef SS_RIGHT
+
+#define SS_TOP 0x01
+#define SS_TOP_LEFT 0x40
+#define SS_TOP_RIGHT 0x02
+#define SS_CENTER 0x20
+#define SS_BOTTOM_LEFT 0x10
+#define SS_BOTTOM_RIGHT 0x04
+#define SS_BOTTOM 0x80
+#define SS_DOT 0x08
+
+//
+// FILE_PLAYBACK
+//
+// FILE_PLAYBACK structure contains the parameters for the PLAY_FILE I/O Control.
+//
+
+typedef struct _FILE_PLAYBACK
+{
+ //
+ // The delay between changes in the display, in milliseconds.
+ //
+
+ USHORT Delay;
+
+ //
+ // The data file path.
+ //
+
+ WCHAR Path[1];
+} FILE_PLAYBACK, *PFILE_PLAYBACK;
+
+#include <poppack.h>
+
+#define IOCTL_INDEX 0x800
+#define FILE_DEVICE_OSRUSBFX2 0x65500
+
+#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 1, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 3, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
+ IOCTL_INDEX + 4, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+
+#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
+ IOCTL_INDEX + 5, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+
+#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 6, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+
+#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 7, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+
+#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 8, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
+ IOCTL_INDEX + 9, \
+ METHOD_OUT_DIRECT, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_PLAY_FILE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 10, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#pragma warning(pop)
+
+#endif
+
diff --git a/usb/umdf_filter_umdf/inc/usb_hw.h b/usb/umdf_filter_umdf/inc/usb_hw.h
new file mode 100644
index 00000000..d6e983f1
--- /dev/null
+++ b/usb/umdf_filter_umdf/inc/usb_hw.h
@@ -0,0 +1,233 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ Usb.h
+
+Abstract:
+
+ Contains prototypes for interfacing with a USB connected device. These
+ are copied from the KMDF WDFUSB.H header file (but with the WDF specific
+ portions removed)
+
+Environment:
+
+ kernel mode only
+
+--*/
+
+#pragma once
+
+typedef enum _WINUSB_BMREQUEST_DIRECTION {
+ BmRequestHostToDevice = BMREQUEST_HOST_TO_DEVICE,
+ BmRequestDeviceToHost = BMREQUEST_DEVICE_TO_HOST,
+} WINUSB_BMREQUEST_DIRECTION;
+
+typedef enum _WINUSB_BMREQUEST_TYPE {
+ BmRequestStandard = BMREQUEST_STANDARD,
+ BmRequestClass = BMREQUEST_CLASS,
+ BmRequestVendor = BMREQUEST_VENDOR,
+} WINUSB_BMREQUEST_TYPE;
+
+typedef enum _WINUSB_BMREQUEST_RECIPIENT {
+ BmRequestToDevice = BMREQUEST_TO_DEVICE,
+ BmRequestToInterface = BMREQUEST_TO_INTERFACE,
+ BmRequestToEndpoint = BMREQUEST_TO_ENDPOINT,
+ BmRequestToOther = BMREQUEST_TO_OTHER,
+} WINUSB_BMREQUEST_RECIPIENT;
+
+typedef enum _WINUSB_DEVICE_TRAITS {
+ WINUSB_DEVICE_TRAIT_SELF_POWERED = 0x00000001,
+ WINUSB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE = 0x00000002,
+ WINUSB_DEVICE_TRAIT_AT_HIGH_SPEED = 0x00000004,
+} WINUSB_DEVICE_TRAITS;
+
+typedef enum _WdfUsbTargetDeviceSelectInterfaceType {
+ WdfUsbTargetDeviceSelectInterfaceTypeInterface = 0x10,
+ WdfUsbTargetDeviceSelectInterfaceTypeUrb = 0x11,
+} WdfUsbTargetDeviceSelectInterfaceType;
+
+
+
+typedef union _WINUSB_CONTROL_SETUP_PACKET {
+ struct {
+ union {
+ #pragma warning(disable:4214) // bit field types other than int
+ struct {
+ //
+ // Valid values are BMREQUEST_TO_DEVICE, BMREQUEST_TO_INTERFACE,
+ // BMREQUEST_TO_ENDPOINT, BMREQUEST_TO_OTHER
+ //
+ BYTE Recipient:2;
+
+ BYTE Reserved:3;
+
+ //
+ // Valid values are BMREQUEST_STANDARD, BMREQUEST_CLASS,
+ // BMREQUEST_VENDOR
+ //
+ BYTE Type:2;
+
+ //
+ // Valid values are BMREQUEST_HOST_TO_DEVICE,
+ // BMREQUEST_DEVICE_TO_HOST
+ //
+ BYTE Dir:1;
+ } Request;
+ #pragma warning(default:4214) // bit field types other than int
+ BYTE Byte;
+ } bm;
+
+ BYTE bRequest;
+
+ union {
+ struct {
+ BYTE LowByte;
+ BYTE HiByte;
+ } Bytes;
+ USHORT Value;
+ } wValue;
+
+ union {
+ struct {
+ BYTE LowByte;
+ BYTE HiByte;
+ } Bytes;
+ USHORT Value;
+ } wIndex;
+
+ USHORT wLength;
+ } Packet;
+
+ struct {
+ BYTE Bytes[8];
+ } Generic;
+
+ WINUSB_SETUP_PACKET WinUsb;
+
+} WINUSB_CONTROL_SETUP_PACKET, *PWINUSB_CONTROL_SETUP_PACKET;
+
+VOID
+FORCEINLINE
+WINUSB_CONTROL_SETUP_PACKET_INIT(
+ PWINUSB_CONTROL_SETUP_PACKET Packet,
+ WINUSB_BMREQUEST_DIRECTION Direction,
+ WINUSB_BMREQUEST_RECIPIENT Recipient,
+ BYTE Request,
+ USHORT Value,
+ USHORT Index
+ )
+{
+ RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET));
+
+ Packet->Packet.bm.Request.Dir = (BYTE) Direction;
+ Packet->Packet.bm.Request.Type = (BYTE) BmRequestStandard;
+ Packet->Packet.bm.Request.Recipient = (BYTE) Recipient;
+
+ Packet->Packet.bRequest = Request;
+ Packet->Packet.wValue.Value = Value;
+ Packet->Packet.wIndex.Value = Index;
+
+ // Packet->Packet.wLength will be set by the formatting function
+}
+
+VOID
+FORCEINLINE
+WINUSB_CONTROL_SETUP_PACKET_INIT_CLASS(
+ PWINUSB_CONTROL_SETUP_PACKET Packet,
+ WINUSB_BMREQUEST_DIRECTION Direction,
+ WINUSB_BMREQUEST_RECIPIENT Recipient,
+ BYTE Request,
+ USHORT Value,
+ USHORT Index
+ )
+{
+ RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET));
+
+ Packet->Packet.bm.Request.Dir = (BYTE) Direction;
+ Packet->Packet.bm.Request.Type = (BYTE) BmRequestClass;
+ Packet->Packet.bm.Request.Recipient = (BYTE) Recipient;
+
+ Packet->Packet.bRequest = Request;
+ Packet->Packet.wValue.Value = Value;
+ Packet->Packet.wIndex.Value = Index;
+
+ // Packet->Packet.wLength will be set by the formatting function
+}
+
+VOID
+FORCEINLINE
+WINUSB_CONTROL_SETUP_PACKET_INIT_VENDOR(
+ PWINUSB_CONTROL_SETUP_PACKET Packet,
+ WINUSB_BMREQUEST_DIRECTION Direction,
+ WINUSB_BMREQUEST_RECIPIENT Recipient,
+ BYTE Request,
+ USHORT Value,
+ USHORT Index
+ )
+{
+ RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET));
+
+ Packet->Packet.bm.Request.Dir = (BYTE) Direction;
+ Packet->Packet.bm.Request.Type = (BYTE) BmRequestVendor;
+ Packet->Packet.bm.Request.Recipient = (BYTE) Recipient;
+
+ Packet->Packet.bRequest = Request;
+ Packet->Packet.wValue.Value = Value;
+ Packet->Packet.wIndex.Value = Index;
+
+ // Packet->Packet.wLength will be set by the formatting function
+}
+
+VOID
+FORCEINLINE
+WINUSB_CONTROL_SETUP_PACKET_INIT_FEATURE(
+ PWINUSB_CONTROL_SETUP_PACKET Packet,
+ WINUSB_BMREQUEST_RECIPIENT BmRequestRecipient,
+ USHORT FeatureSelector,
+ USHORT Index,
+ BOOLEAN SetFeature
+ )
+{
+ RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET));
+
+ Packet->Packet.bm.Request.Dir = (BYTE) BmRequestHostToDevice;
+ Packet->Packet.bm.Request.Type = (BYTE) BmRequestStandard;
+ Packet->Packet.bm.Request.Recipient = (BYTE) BmRequestRecipient;
+
+ if (SetFeature) {
+ Packet->Packet.bRequest = USB_REQUEST_SET_FEATURE;
+ }
+ else {
+ Packet->Packet.bRequest = USB_REQUEST_CLEAR_FEATURE;
+ }
+
+ Packet->Packet.wValue.Value = FeatureSelector;
+ Packet->Packet.wIndex.Value = Index;
+
+ // Packet->Packet.wLength will be set by the formatting function
+}
+
+VOID
+FORCEINLINE
+WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS(
+ PWINUSB_CONTROL_SETUP_PACKET Packet,
+ WINUSB_BMREQUEST_RECIPIENT BmRequestRecipient,
+ USHORT Index
+ )
+{
+ RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET));
+
+ Packet->Packet.bm.Request.Dir = (BYTE) BmRequestDeviceToHost;
+ Packet->Packet.bm.Request.Type = (BYTE) BmRequestStandard;
+ Packet->Packet.bm.Request.Recipient = (BYTE) BmRequestRecipient;
+
+ Packet->Packet.bRequest = USB_REQUEST_GET_STATUS;
+ Packet->Packet.wIndex.Value = Index;
+ Packet->Packet.wValue.Value = 0;
+
+ // Packet->Packet.wLength will be set by the formatting function
+}
+
diff --git a/usb/umdf_filter_umdf/umdf_driver/ControlQueue.cpp b/usb/umdf_filter_umdf/umdf_driver/ControlQueue.cpp
new file mode 100644
index 00000000..f4058941
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/ControlQueue.cpp
@@ -0,0 +1,564 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ControlQueue.cpp
+
+Abstract:
+
+ This file implements the I/O queue interface and performs
+ the ioctl operations.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+
+#include "winioctl.h"
+
+#include "ControlQueue.tmh"
+
+CMyControlQueue::CMyControlQueue(
+ _In_ PCMyDevice Device
+ ) : CMyQueue(Device)
+{
+
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CMyControlQueue::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+Routine Description:
+
+
+ Query Interface
+
+Aruments:
+
+ Follows COM specifications
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ HRESULT hr;
+
+
+ if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackDeviceIoControl)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackDeviceIoControl();
+
+ }
+ else
+ {
+ hr = CMyQueue::QueryInterface(InterfaceId, Object);
+ }
+
+ return hr;
+}
+
+//
+// Initialize
+//
+
+HRESULT
+CMyControlQueue::CreateInstance(
+ _In_ PCMyDevice Device,
+ _Out_ PCMyControlQueue *Queue
+ )
+/*++
+
+Routine Description:
+
+
+ CreateInstance creates an instance of the queue object.
+
+Aruments:
+
+ ppUkwn - OUT parameter is an IUnknown interface to the queue object
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ PCMyControlQueue queue = NULL;
+ HRESULT hr = S_OK;
+
+ queue = new CMyControlQueue(Device);
+
+ if (NULL == queue)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // Call the queue callback object to initialize itself. This will create
+ // its partner queue framework object.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = queue->Initialize();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *Queue = queue;
+ }
+ else
+ {
+ SAFE_RELEASE(queue);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyControlQueue::Initialize(
+ VOID
+ )
+{
+ HRESULT hr;
+
+ //
+ // First initialize the base class. This will create the partner FxIoQueue
+ // object and setup automatic forwarding of I/O controls.
+ //
+
+ //
+ // The framework (UMDF) will not deliver a
+ // request to the driver that arrives on a power-managed queue, unless
+ // the device is in a powered-up state. If you receive a request on a
+ // power-managed queue after the device has idled out,
+ // the framework will not be able to power-up and present the request
+ // to the driver unless it is the power policy owner (PPO).
+ // Since this driver is the PPO it can use power managed queues
+ //
+
+ hr = __super::Initialize(WdfIoQueueDispatchSequential,
+ false,
+ true /* use power managed queue */);
+
+ //
+ // return the status.
+ //
+
+ return hr;
+}
+
+VOID
+STDMETHODCALLTYPE
+CMyControlQueue::OnDeviceIoControl(
+ _In_ IWDFIoQueue *FxQueue,
+ _In_ IWDFIoRequest *FxRequest,
+ _In_ ULONG ControlCode,
+ _In_ SIZE_T InputBufferSizeInBytes,
+ _In_ SIZE_T OutputBufferSizeInBytes
+ )
+/*++
+
+Routine Description:
+
+
+ DeviceIoControl dispatch routine
+
+Aruments:
+
+ FxQueue - Framework Queue instance
+ FxRequest - Framework Request instance
+ ControlCode - IO Control Code
+ InputBufferSizeInBytes - Lenth of input buffer
+ OutputBufferSizeInBytes - Lenth of output buffer
+
+ Always succeeds DeviceIoIoctl
+Return Value:
+
+ VOID
+
+--*/
+{
+ UNREFERENCED_PARAMETER(FxQueue);
+
+ IWDFMemory *memory = NULL;
+ PVOID buffer;
+
+ SIZE_T bigBufferCb;
+
+ ULONG information = 0;
+
+ bool completeRequest = true;
+
+ HRESULT hr = S_OK;
+
+ switch (ControlCode)
+ {
+ case IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR:
+ {
+ //
+ // Get the output buffer.
+ //
+
+ FxRequest->GetOutputMemory(&memory );
+
+ //
+ // request the descriptor.
+ //
+
+ ULONG bufferCb;
+
+ //
+ // Get the buffer address then release the memory object.
+ // The memory object remains valid until the request is
+ // completed.
+ //
+
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ if (bigBufferCb > ULONG_MAX)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ break;
+ }
+ else
+ {
+ bufferCb = (ULONG) bigBufferCb;
+ }
+
+ hr = m_Device->GetUsbTargetDevice()->RetrieveDescriptor(
+ USB_CONFIGURATION_DESCRIPTOR_TYPE,
+ 0,
+ 0,
+ &bufferCb,
+ (PUCHAR) buffer
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ information = bufferCb;
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY:
+ {
+ //
+ // Make sure the buffer is big enough to hold the result of the
+ // control transfer.
+ //
+
+ if (OutputBufferSizeInBytes < sizeof(BAR_GRAPH_STATE))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetOutputMemory(&memory );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ hr = m_Device->GetBarGraphDisplay((PBAR_GRAPH_STATE) buffer);
+ }
+
+ //
+ // If that worked then record how many bytes of data we're
+ // returning.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ information = sizeof(BAR_GRAPH_STATE);
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY:
+ {
+ //
+ // Make sure the buffer is big enough to hold the input for the
+ // control transfer.
+ //
+
+ if (InputBufferSizeInBytes < sizeof(BAR_GRAPH_STATE))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetInputMemory(&memory);
+ }
+
+ //
+ // Get the data buffer and use it to set the bar graph on the
+ // device.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ hr = m_Device->SetBarGraphDisplay((PBAR_GRAPH_STATE) buffer);
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY:
+ {
+ //
+ // Make sure the buffer is big enough to hold the result of the
+ // control transfer.
+ //
+
+ if (OutputBufferSizeInBytes < sizeof(SEVEN_SEGMENT))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetOutputMemory(&memory );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+ hr = m_Device->GetSevenSegmentDisplay((PSEVEN_SEGMENT) buffer);
+ }
+
+ //
+ // If that worked then record how many bytes of data we're
+ // returning.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ information = sizeof(SEVEN_SEGMENT);
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY:
+ {
+ //
+ // Make sure the buffer is big enough to hold the input for the
+ // control transfer.
+ //
+
+ if (InputBufferSizeInBytes < sizeof(SEVEN_SEGMENT))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetInputMemory(&memory );
+ }
+
+ //
+ // Get the data buffer and use it to set the bar graph on the
+ // device.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ hr = m_Device->SetSevenSegmentDisplay((PSEVEN_SEGMENT) buffer);
+ }
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_READ_SWITCHES:
+ {
+ //
+ // Make sure the buffer is big enough to hold the input for the
+ // control transfer.
+ //
+
+ if (OutputBufferSizeInBytes < sizeof(SWITCH_STATE))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetOutputMemory(&memory );
+ }
+
+ //
+ // Get the data buffer and use it to set the bar graph on the
+ // device.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ hr = m_Device->ReadSwitchState((PSWITCH_STATE) buffer);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ information = sizeof(SWITCH_STATE);
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE:
+ {
+ //
+ // Make sure the buffer is big enough to hold the switch
+ // state.
+ //
+
+ if (OutputBufferSizeInBytes < sizeof(SWITCH_STATE))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ //
+ // Forward the request to the switch state change queue.
+ //
+
+ hr = FxRequest->ForwardToIoQueue(
+ m_Device->GetSwitchChangeQueue()
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ completeRequest = false;
+ }
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_RESET_DEVICE:
+ case IOCTL_OSRUSBFX2_REENUMERATE_DEVICE:
+ {
+ //
+ // WinUSB does not allow us to reset or re-enumerate the device.
+ // Return not-supported for the error in both of these cases.
+ //
+
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_PLAY_FILE:
+ {
+ //
+ // This IOCTL demonstrates how to use impersonation to access
+ // resources using the credentials provided by the client. Note
+ // that for impersonation to work it has to be enabled in the device
+ // INF and the client must allow impersonation when they open the
+ // device.
+ //
+ // This IOCTL opens a file using the path provided by the client
+ // and then plays the characters in that file out to the seven segment
+ // display in a worker thread.
+ //
+
+ PFILE_PLAYBACK playback;
+ SIZE_T playbackCb;
+ size_t realPlaybackCb;
+
+ FxRequest->GetInputMemory(&memory);
+
+ if (memory == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ break;
+ }
+
+ //
+ // Get the playback structure from the input buffer.
+ //
+
+ playback = (PFILE_PLAYBACK) memory->GetDataBuffer(&playbackCb);
+
+ memory->Release();
+
+ //
+ // Make sure the length is at least as big as the fixed portion
+ // of the input structure.
+ //
+
+ if (playbackCb < (FIELD_OFFSET(FILE_PLAYBACK, Path)))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ break;
+ }
+
+ //
+ // Make sure the file name is at least one character long.
+ //
+
+ playbackCb -= FIELD_OFFSET(FILE_PLAYBACK, Path);
+
+ if (playbackCb < sizeof(WCHAR))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ break;
+ }
+
+ //
+ // Verify that the string provided is valid.
+ //
+
+ hr = StringCbLength(playback->Path,
+ min(playbackCb, (STRSAFE_MAX_CCH * sizeof(WCHAR))),
+ &realPlaybackCb);
+
+ if (FAILED(hr))
+ {
+ break;
+ }
+
+ hr = m_Device->PlaybackFile(playback, FxRequest);
+
+ break;
+ }
+
+
+
+ default:
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
+ break;
+ }
+ }
+
+ if (completeRequest)
+ {
+ FxRequest->CompleteWithInformation(hr, information);
+ }
+
+ return;
+}
diff --git a/usb/umdf_filter_umdf/umdf_driver/ControlQueue.h b/usb/umdf_filter_umdf/umdf_driver/ControlQueue.h
new file mode 100644
index 00000000..251521e1
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/ControlQueue.h
@@ -0,0 +1,101 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ControlQueue.h
+
+Abstract:
+
+ This file defines the queue callback object for handling device I/O
+ control requests. This is a serialized queue.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Queue Callback Object.
+//
+
+class CMyControlQueue : public IQueueCallbackDeviceIoControl,
+ public CMyQueue
+{
+ HRESULT
+ Initialize(
+ VOID
+ );
+
+public:
+
+ CMyControlQueue(
+ _In_ PCMyDevice Device
+ );
+
+ virtual
+ ~CMyControlQueue(
+ VOID
+ )
+ {
+ return;
+ }
+
+ static
+ HRESULT
+ CreateInstance(
+ _In_ PCMyDevice Device,
+ _Out_ PCMyControlQueue *Queue
+ );
+
+ HRESULT
+ Configure(
+ VOID
+ )
+ {
+ return S_OK;
+ }
+
+ IQueueCallbackDeviceIoControl *
+ QueryIQueueCallbackDeviceIoControl(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackDeviceIoControl *>(this);
+ }
+
+ //
+ // IUnknown
+ //
+
+ STDMETHOD_(ULONG,AddRef) (VOID) {return CUnknown::AddRef();}
+
+ _At_(this, __drv_freesMem(object))
+ STDMETHOD_(ULONG,Release) (VOID) {return CUnknown::Release();}
+
+ STDMETHOD_(HRESULT, QueryInterface)(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+
+ //
+ // Wdf Callbacks
+ //
+
+ //
+ // IQueueCallbackDeviceIoControl
+ //
+ STDMETHOD_ (void, OnDeviceIoControl)(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ ULONG ControlCode,
+ _In_ SIZE_T InputBufferSizeInBytes,
+ _In_ SIZE_T OutputBufferSizeInBytes
+ );
+};
+
diff --git a/usb/umdf_filter_umdf/umdf_driver/Device.cpp b/usb/umdf_filter_umdf/umdf_driver/Device.cpp
new file mode 100644
index 00000000..2ebf4079
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/Device.cpp
@@ -0,0 +1,2087 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ Device.cpp
+
+Abstract:
+
+ This module contains the implementation of the UMDF OSR Fx2 driver's
+ device callback object.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+#include "internal.h"
+#include "initguid.h"
+#include "usb_hw.h"
+#include <devpkey.h>
+
+#include "device.tmh"
+#define CONCURRENT_READS 2
+
+CMyDevice::~CMyDevice(
+ )
+{
+ SAFE_RELEASE(m_pIoTargetInterruptPipeStateMgmt);
+}
+
+HRESULT
+CMyDevice::CreateInstance(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize * FxDeviceInit,
+ _Out_ PCMyDevice *Device
+ )
+/*++
+
+ Routine Description:
+
+ This method creates and initializs an instance of the OSR Fx2 driver's
+ device callback object.
+
+ Arguments:
+
+ FxDeviceInit - the settings for the device.
+
+ Device - a location to store the referenced pointer to the device object.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ PCMyDevice device;
+ HRESULT hr;
+
+ //
+ // Allocate a new instance of the device class.
+ //
+
+ device = new CMyDevice();
+
+ if (NULL == device)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ //
+ // Initialize the instance.
+ //
+
+ hr = device->Initialize(FxDriver, FxDeviceInit);
+
+ if (SUCCEEDED(hr))
+ {
+ *Device = device;
+ }
+ else
+ {
+ device->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::Initialize(
+ _In_ IWDFDriver * FxDriver,
+ _In_ IWDFDeviceInitialize * FxDeviceInit
+ )
+/*++
+
+ Routine Description:
+
+ This method initializes the device callback object and creates the
+ partner device object.
+
+ The method should perform any device-specific configuration that:
+ * could fail (these can't be done in the constructor)
+ * must be done before the partner object is created -or-
+ * can be done after the partner object is created and which aren't
+ influenced by any device-level parameters the parent (the driver
+ in this case) might set.
+
+ Arguments:
+
+ FxDeviceInit - the settings for this device.
+
+ Return Value:
+
+ status.
+
+--*/
+{
+ IWDFDevice2 *fxDevice = NULL;
+
+ HRESULT hr = S_OK;
+
+ //
+ // TODO: Any per-device initialization which must be done before
+ // creating the partner object.
+ //
+
+ //
+ // Set no locking unless you need an automatic callbacks synchronization
+ //
+
+ FxDeviceInit->SetLockingConstraint(None);
+
+ //
+ // TODO: If you're writing a filter driver then indicate that here.
+ // And then don't claim power policy ownership below
+ //
+ // FxDeviceInit->SetFilter();
+ //
+
+ //
+ // Set the Fx2 driver as the power policy owner.
+ //
+
+ FxDeviceInit->SetPowerPolicyOwnership(TRUE);
+
+ //
+ // Create a new FX device object and assign the new callback object to
+ // handle any device level events that occur.
+ //
+
+ //
+ // QueryIUnknown references the IUnknown interface that it returns
+ // (which is the same as referencing the device). We pass that to
+ // CreateDevice, which takes its own reference if everything works.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ IUnknown *unknown = this->QueryIUnknown();
+ IWDFDevice* device1;
+
+ hr = FxDriver->CreateDevice(FxDeviceInit, unknown, &device1);
+
+ //
+ // Convert the interface to version 2
+ //
+
+ if (SUCCEEDED(hr)) {
+ device1->QueryInterface(IID_PPV_ARGS(&fxDevice));
+ _Analysis_assume_(fxDevice != NULL);
+ device1->Release();
+ }
+
+ unknown->Release();
+ }
+
+ //
+ // If that succeeded then set our FxDevice member variable.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ m_FxDevice = fxDevice;
+
+ //
+ // Drop the reference we got from CreateDevice. Since this object
+ // is partnered with the framework object they have the same
+ // lifespan - there is no need for an additional reference.
+ //
+
+ fxDevice->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::Configure(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method is called after the device callback object has been initialized
+ and returned to the driver. It would setup the device's queues and their
+ corresponding callback objects.
+
+ Arguments:
+
+ FxDevice - the framework device object for which we're handling events.
+
+ Return Value:
+
+ status
+
+--*/
+{
+ HRESULT hr = S_OK;
+
+ //
+ // Get the bus type GUID for the device and confirm that we're attached to
+ // USB.
+ //
+ // NOTE: Since this device only supports USB we'd normally trust our INF
+ // to ensure this.
+ //
+ // But if the device also supported 1394 then we could
+ // use this to determine which type of bus we were attached to.
+ //
+
+ hr = GetBusTypeGuid();
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ //
+ // Create the read-write queue.
+ //
+
+ hr = CMyReadWriteQueue::CreateInstance(this, &m_ReadWriteQueue);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ //
+ // We use default queue for read/write
+ //
+
+ hr = m_ReadWriteQueue->Configure();
+
+ m_ReadWriteQueue->Release();
+
+ //
+ // Create the control queue and configure forwarding for IOCTL requests.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CMyControlQueue::CreateInstance(this, &m_ControlQueue);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_ControlQueue->Configure();
+ if (SUCCEEDED(hr))
+ {
+ m_FxDevice->ConfigureRequestDispatching(
+ m_ControlQueue->GetFxQueue(),
+ WdfRequestDeviceIoControl,
+ true
+ );
+ }
+ m_ControlQueue->Release();
+ }
+ }
+
+ //
+ // Create a manual I/O queue to hold requests for notification when
+ // the switch state changes.
+ //
+
+ hr = m_FxDevice->CreateIoQueue(NULL,
+ FALSE,
+ WdfIoQueueDispatchManual,
+ FALSE,
+ FALSE,
+ &m_SwitchChangeQueue);
+
+
+ //
+ // Release creation reference as object tree will keep a reference
+ //
+
+ m_SwitchChangeQueue->Release();
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_FxDevice->CreateDeviceInterface(&GUID_DEVINTERFACE_OSRUSBFX2,
+ NULL);
+ }
+
+ //
+ // Mark the interface as restricted to allow access to applications bound
+ // using device metadata. Failures here are not fatal so we log them but
+ // ignore them otherwise.
+ //
+ if (SUCCEEDED(hr))
+ {
+ WDF_PROPERTY_STORE_ROOT RootSpecifier;
+ IWDFUnifiedPropertyStoreFactory * pUnifiedPropertyStoreFactory = NULL;
+ IWDFUnifiedPropertyStore * pUnifiedPropertyStore = NULL;
+ DEVPROP_BOOLEAN isRestricted = DEVPROP_TRUE;
+ HRESULT hrSetProp;
+
+ hrSetProp = m_FxDevice->QueryInterface(IID_PPV_ARGS(&pUnifiedPropertyStoreFactory));
+
+ WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrSetProp));
+
+ RootSpecifier.LengthCb = sizeof(RootSpecifier);
+ RootSpecifier.RootClass = WdfPropertyStoreRootClassDeviceInterfaceKey;
+ RootSpecifier.Qualifier.DeviceInterfaceKey.InterfaceGUID = &GUID_DEVINTERFACE_OSRUSBFX2;
+ RootSpecifier.Qualifier.DeviceInterfaceKey.ReferenceString = NULL;
+
+ hrSetProp = pUnifiedPropertyStoreFactory->RetrieveUnifiedDevicePropertyStore(&RootSpecifier,
+ &pUnifiedPropertyStore);
+
+ if (SUCCEEDED(hrSetProp))
+ {
+ hrSetProp = pUnifiedPropertyStore->SetPropertyData(&DEVPKEY_DeviceInterface_Restricted,
+ 0, // Lcid
+ 0, // Flags
+ DEVPROP_TYPE_BOOLEAN,
+ sizeof(isRestricted),
+ &isRestricted);
+ }
+
+ if (FAILED(hrSetProp))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Could not set restricted property %!HRESULT!",
+ hrSetProp
+ );
+ }
+
+ SAFE_RELEASE(pUnifiedPropertyStoreFactory);
+ SAFE_RELEASE(pUnifiedPropertyStore);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method is called to get a pointer to one of the object's callback
+ interfaces.
+
+ Arguments:
+
+ InterfaceId - the interface being requested
+
+ Object - a location to store the interface pointer if successful
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ HRESULT hr;
+
+ if (IsEqualIID(InterfaceId, __uuidof(IPnpCallbackHardware)))
+ {
+ *Object = QueryIPnpCallbackHardware();
+ hr = S_OK;
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IPnpCallback)))
+ {
+ *Object = QueryIPnpCallback();
+ hr = S_OK;
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IPnpCallbackSelfManagedIo)))
+ {
+ *Object = QueryIPnpCallbackSelfManagedIo();
+ hr = S_OK;
+ }
+ else if(IsEqualIID(InterfaceId, __uuidof(IUsbTargetPipeContinuousReaderCallbackReadersFailed)))
+ {
+ *Object = QueryContinousReaderFailureCompletion();
+ hr = S_OK;
+ }
+ else if(IsEqualIID(InterfaceId, __uuidof(IUsbTargetPipeContinuousReaderCallbackReadComplete)))
+ {
+ *Object = QueryContinousReaderCompletion();
+ hr = S_OK;
+ }
+ else
+ {
+ hr = CUnknown::QueryInterface(InterfaceId, Object);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::OnPrepareHardware(
+ _In_ IWDFDevice * /* FxDevice */
+ )
+/*++
+
+Routine Description:
+
+ This routine is invoked to ready the driver
+ to talk to hardware. It opens the handle to the
+ device and talks to it using the WINUSB interface.
+ It invokes WINUSB to discver the interfaces and stores
+ the information related to bulk endpoints.
+
+Arguments:
+
+ FxDevice : Pointer to the WDF device interface
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ PWSTR deviceName = NULL;
+ DWORD deviceNameCch = 0;
+
+ HRESULT hr;
+
+ //
+ // Get the device name.
+ // Get the length to allocate first
+ //
+
+ hr = m_FxDevice->RetrieveDeviceName(NULL, &deviceNameCch);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Cannot get device name %!HRESULT!",
+ hr
+ );
+ }
+
+ //
+ // Allocate the buffer
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ deviceName = new WCHAR[deviceNameCch];
+
+ if (deviceName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ //
+ // Get the actual name
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_FxDevice->RetrieveDeviceName(deviceName, &deviceNameCch);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Cannot get device name %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Device name %S",
+ deviceName
+ );
+ }
+
+ //
+ // Create USB I/O Targets and configure them
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CreateUsbIoTargets();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ULONG length = sizeof(m_Speed);
+
+ hr = m_pIUsbTargetDevice->RetrieveDeviceInformation(DEVICE_SPEED,
+ &length,
+ &m_Speed);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Cannot get usb device speed information %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Speed - %x\n",
+ m_Speed
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ConfigureUsbPipes();
+ }
+
+ // Setup power-management settings on the device.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = SetPowerManagement();
+ }
+
+ //
+ //
+ // Clear the seven segement display to indicate that we're done with
+ // prepare hardware.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IndicateDeviceReady();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ConfigContReaderForInterruptEndPoint();
+ }
+
+ delete[] deviceName;
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::OnReleaseHardware(
+ _In_ IWDFDevice * /* FxDevice */
+ )
+/*++
+
+Routine Description:
+
+ This routine is invoked when the device is being removed or stopped
+ It releases all resources allocated for this device.
+
+Arguments:
+
+ FxDevice - Pointer to the Device object.
+
+Return Value:
+
+ HRESULT - Always succeeds.
+
+--*/
+{
+ //
+ // Delete USB Target Device WDF Object, this will in turn
+ // delete all the children - interface and the pipe objects
+ //
+ // This makes sure that
+ // 1. We drain the the pending read which does not come from an I/O queue
+ // 2. We remove USB target objects from object tree (and thereby free them)
+ // before any potential subsequent OnPrepareHardware creates new ones
+ //
+ // m_pIUsbTargetDevice could be NULL if OnPrepareHardware failed so we need
+ // to guard against that
+ //
+
+ if (m_pIUsbTargetDevice)
+ {
+ m_pIUsbTargetDevice->DeleteWdfObject();
+ }
+
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::CreateUsbIoTargets(
+ )
+/*++
+
+Routine Description:
+
+ This routine creates Usb device, interface and pipe objects
+
+Arguments:
+
+ None
+
+Return Value:
+
+ HRESULT
+--*/
+{
+ HRESULT hr;
+ UCHAR NumEndPoints = 0;
+ IWDFUsbTargetFactory * pIUsbTargetFactory = NULL;
+ IWDFUsbTargetDevice * pIUsbTargetDevice = NULL;
+ IWDFUsbInterface * pIUsbInterface = NULL;
+ IWDFUsbTargetPipe * pIUsbPipe = NULL;
+
+ hr = m_FxDevice->QueryInterface(IID_PPV_ARGS(&pIUsbTargetFactory));
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Cannot get usb target factory %!HRESULT!",
+ hr
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pIUsbTargetFactory->CreateUsbTargetDevice(
+ &pIUsbTargetDevice);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to create USB Device I/O Target %!HRESULT!",
+ hr
+ );
+ }
+ else
+ {
+ m_pIUsbTargetDevice = pIUsbTargetDevice;
+
+ //
+ // Release the creation reference as object tree will maintain a reference
+ //
+
+ pIUsbTargetDevice->Release();
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ UCHAR NumInterfaces = pIUsbTargetDevice->GetNumInterfaces();
+
+ WUDF_TEST_DRIVER_ASSERT(1 == NumInterfaces);
+
+ hr = pIUsbTargetDevice->RetrieveUsbInterface(0, &pIUsbInterface);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to retrieve USB interface from USB Device I/O Target %!HRESULT!",
+ hr
+ );
+ }
+ else
+ {
+ m_pIUsbInterface = pIUsbInterface;
+
+ pIUsbInterface->Release(); //release creation reference
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ NumEndPoints = pIUsbInterface->GetNumEndPoints();
+
+ if (NumEndPoints != NUM_OSRUSB_ENDPOINTS) {
+ hr = E_UNEXPECTED;
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Has %d endpoints, expected %d, returning %!HRESULT! ",
+ NumEndPoints,
+ NUM_OSRUSB_ENDPOINTS,
+ hr
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ for (UCHAR PipeIndex = 0; PipeIndex < NumEndPoints; PipeIndex++)
+ {
+ hr = pIUsbInterface->RetrieveUsbPipeObject(PipeIndex,
+ &pIUsbPipe);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to retrieve USB Pipe for PipeIndex %d, %!HRESULT!",
+ PipeIndex,
+ hr
+ );
+ }
+ else
+ {
+ if ( pIUsbPipe->IsInEndPoint() )
+ {
+ if ( UsbdPipeTypeInterrupt == pIUsbPipe->GetType() )
+ {
+ m_pIUsbInterruptPipe = pIUsbPipe;
+
+ WUDF_TEST_DRIVER_ASSERT (m_pIoTargetInterruptPipeStateMgmt == NULL);
+
+ hr = m_pIUsbInterruptPipe->QueryInterface(__uuidof(
+ IWDFIoTargetStateManagement),
+ reinterpret_cast<void**>(&m_pIoTargetInterruptPipeStateMgmt)
+ );
+ if (FAILED(hr))
+ {
+ m_pIoTargetInterruptPipeStateMgmt = NULL;
+ }
+ }
+ else if ( UsbdPipeTypeBulk == pIUsbPipe->GetType() )
+ {
+ m_pIUsbInputPipe = pIUsbPipe;
+ }
+ else
+ {
+ pIUsbPipe->DeleteWdfObject();
+ }
+ }
+ else if ( pIUsbPipe->IsOutEndPoint() && (UsbdPipeTypeBulk == pIUsbPipe->GetType()) )
+ {
+ m_pIUsbOutputPipe = pIUsbPipe;
+ }
+ else
+ {
+ pIUsbPipe->DeleteWdfObject();
+ }
+
+ SAFE_RELEASE(pIUsbPipe); //release creation reference
+ }
+ }
+
+ if (NULL == m_pIUsbInputPipe || NULL == m_pIUsbOutputPipe)
+ {
+ hr = E_UNEXPECTED;
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Input or output pipe not found, returning %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ SAFE_RELEASE(pIUsbTargetFactory);
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::ConfigureUsbPipes(
+ )
+/*++
+
+Routine Description:
+
+ This routine retrieves the IDs for the bulk end points of the USB device.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ HRESULT
+--*/
+{
+ HRESULT hr = S_OK;
+ LONG timeout;
+
+ //
+ // Set timeout policies for input/output pipes
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ timeout = ENDPOINT_TIMEOUT;
+
+ hr = m_pIUsbInputPipe->SetPipePolicy(PIPE_TRANSFER_TIMEOUT,
+ sizeof(timeout),
+ &timeout);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to set timeout policy for input pipe %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ timeout = ENDPOINT_TIMEOUT;
+
+ hr = m_pIUsbOutputPipe->SetPipePolicy(PIPE_TRANSFER_TIMEOUT,
+ sizeof(timeout),
+ &timeout);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to set timeout policy for output pipe %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::IndicateDeviceReady(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method lights the period on the device's seven-segment display to
+ indicate that the driver's PrepareHardware method has completed.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ SEVEN_SEGMENT display = {0};
+
+ HRESULT hr;
+
+ //
+ // First read the contents of the seven segment display.
+ //
+
+ hr = GetSevenSegmentDisplay(&display);
+
+ if (SUCCEEDED(hr))
+ {
+ display.Segments |= 0x08;
+
+ hr = SetSevenSegmentDisplay(&display);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::GetBarGraphDisplay(
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously retrieves the bar graph display information
+ from the OSR USB-FX2 device. It uses the buffers in the FxRequest
+ to hold the data it retrieves.
+
+ Arguments:
+
+ FxRequest - the request for the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesReturned;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Zero the contents of the buffer - the controller OR's in every
+ // light that's set.
+ //
+
+ BarGraphState->BarsAsUChar = 0;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_BARGRAPH_DISPLAY,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) BarGraphState,
+ sizeof(BAR_GRAPH_STATE),
+ &bytesReturned
+ );
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::SetBarGraphDisplay(
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously sets the bar graph display on the OSR USB-FX2
+ device using the buffers in the FxRequest as input.
+
+ Arguments:
+
+ FxRequest - the request to set the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesTransferred;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestHostToDevice,
+ BmRequestToDevice,
+ USBFX2LK_SET_BARGRAPH_DISPLAY,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) BarGraphState,
+ sizeof(BAR_GRAPH_STATE),
+ &bytesTransferred
+ );
+
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::GetSevenSegmentDisplay(
+ _In_ PSEVEN_SEGMENT SevenSegment
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously retrieves the bar graph display information
+ from the OSR USB-FX2 device. It uses the buffers in the FxRequest
+ to hold the data it retrieves.
+
+ Arguments:
+
+ FxRequest - the request for the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesReturned;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Zero the output buffer - the device will or in the bits for
+ // the lights that are set.
+ //
+
+ SevenSegment->Segments = 0;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_7SEGMENT_DISPLAY,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) SevenSegment,
+ sizeof(SEVEN_SEGMENT),
+ &bytesReturned
+ );
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::SetSevenSegmentDisplay(
+ _In_ PSEVEN_SEGMENT SevenSegment
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously sets the bar graph display on the OSR USB-FX2
+ device using the buffers in the FxRequest as input.
+
+ Arguments:
+
+ FxRequest - the request to set the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesTransferred;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestHostToDevice,
+ BmRequestToDevice,
+ USBFX2LK_SET_7SEGMENT_DISPLAY,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) SevenSegment,
+ sizeof(SEVEN_SEGMENT),
+ &bytesTransferred
+ );
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::ReadSwitchState(
+ _In_ PSWITCH_STATE SwitchState
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously retrieves the bar graph display information
+ from the OSR USB-FX2 device. It uses the buffers in the FxRequest
+ to hold the data it retrieves.
+
+ Arguments:
+
+ FxRequest - the request for the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesReturned;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Zero the output buffer - the device will or in the bits for
+ // the lights that are set.
+ //
+
+ SwitchState->SwitchesAsUChar = 0;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_SWITCHES,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) SwitchState,
+ sizeof(SWITCH_STATE),
+ &bytesReturned
+ );
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::SendControlTransferSynchronously(
+ _In_ PWINUSB_SETUP_PACKET SetupPacket,
+ _Inout_updates_(BufferLength) PBYTE Buffer,
+ _In_ ULONG BufferLength,
+ _Out_ PULONG LengthTransferred
+ )
+{
+ HRESULT hr = S_OK;
+ HRESULT hrRequest = S_OK;
+ IWDFIoRequest *pWdfRequest = NULL;
+ IWDFDriver * FxDriver = NULL;
+ IWDFMemory * FxMemory = NULL;
+ IWDFRequestCompletionParams * FxComplParams = NULL;
+ IWDFUsbRequestCompletionParams * FxUsbComplParams = NULL;
+
+ *LengthTransferred = 0;
+
+ hr = m_FxDevice->CreateRequest( NULL, //pCallbackInterface
+ NULL, //pParentObject
+ &pWdfRequest);
+ hrRequest = hr;
+
+ if (SUCCEEDED(hr))
+ {
+ m_FxDevice->GetDriver(&FxDriver);
+
+ hr = FxDriver->CreatePreallocatedWdfMemory( Buffer,
+ BufferLength,
+ NULL, //pCallbackInterface
+ pWdfRequest, //pParetObject
+ &FxMemory );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_pIUsbTargetDevice->FormatRequestForControlTransfer( pWdfRequest,
+ SetupPacket,
+ FxMemory,
+ NULL); //TransferOffset
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pWdfRequest->Send( m_pIUsbTargetDevice,
+ WDF_REQUEST_SEND_OPTION_SYNCHRONOUS,
+ 0); //Timeout
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ pWdfRequest->GetCompletionParams(&FxComplParams);
+
+ hr = FxComplParams->GetCompletionStatus();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ HRESULT hrQI = FxComplParams->QueryInterface(IID_PPV_ARGS(&FxUsbComplParams));
+ WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI));
+
+ WUDF_TEST_DRIVER_ASSERT( WdfUsbRequestTypeDeviceControlTransfer ==
+ FxUsbComplParams->GetCompletedUsbRequestType() );
+
+ FxUsbComplParams->GetDeviceControlTransferParameters( NULL,
+ LengthTransferred,
+ NULL,
+ NULL );
+ }
+
+ SAFE_RELEASE(FxUsbComplParams);
+ SAFE_RELEASE(FxComplParams);
+ SAFE_RELEASE(FxMemory);
+
+ if (SUCCEEDED(hrRequest))
+ {
+ pWdfRequest->DeleteWdfObject();
+ }
+ SAFE_RELEASE(pWdfRequest);
+
+ SAFE_RELEASE(FxDriver);
+
+ return hr;
+}
+
+WDF_IO_TARGET_STATE
+CMyDevice::GetTargetState(
+ IWDFIoTarget * pTarget
+ )
+{
+ IWDFIoTargetStateManagement * pStateMgmt = NULL;
+ WDF_IO_TARGET_STATE state;
+
+ HRESULT hrQI = pTarget->QueryInterface(IID_PPV_ARGS(&pStateMgmt));
+ WUDF_TEST_DRIVER_ASSERT((SUCCEEDED(hrQI) && pStateMgmt));
+
+ state = pStateMgmt->GetState();
+
+ SAFE_RELEASE(pStateMgmt);
+
+ return state;
+}
+
+VOID
+CMyDevice::ServiceSwitchChangeQueue(
+ _In_ SWITCH_STATE NewState,
+ _In_ HRESULT CompletionStatus,
+ _In_opt_ IWDFFile *SpecificFile
+ )
+/*++
+
+ Routine Description:
+
+ This method processes switch-state change notification requests as
+ part of reading the OSR device's interrupt pipe. As each read completes
+ this pulls all pending I/O off the switch change queue and completes
+ each request with the current switch state.
+
+ Arguments:
+
+ NewState - the state of the switches
+
+ CompletionStatus - all pending operations are completed with this status.
+
+ SpecificFile - if provided only requests for this file object will get
+ completed.
+
+ Return Value:
+
+ None
+
+--*/
+{
+ IWDFIoRequest *fxRequest;
+
+ HRESULT enumHr = S_OK;
+
+ do
+ {
+ HRESULT hr;
+
+ //
+ // Get the next request.
+ //
+
+ if (NULL != SpecificFile)
+ {
+ enumHr = m_SwitchChangeQueue->RetrieveNextRequestByFileObject(
+ SpecificFile,
+ &fxRequest
+ );
+ }
+ else
+ {
+ enumHr = m_SwitchChangeQueue->RetrieveNextRequest(&fxRequest);
+ }
+
+ //
+ // if we got one then complete it.
+ //
+
+ if (SUCCEEDED(enumHr))
+ {
+ if (SUCCEEDED(CompletionStatus))
+ {
+ IWDFMemory *fxMemory;
+
+ //
+ // First copy the result to the request buffer.
+ //
+
+ fxRequest->GetOutputMemory(&fxMemory );
+
+ hr = fxMemory->CopyFromBuffer(0,
+ &NewState,
+ sizeof(SWITCH_STATE));
+ fxMemory->Release();
+ }
+ else
+ {
+ hr = CompletionStatus;
+ }
+
+ //
+ // Complete the request with the status of the copy (or the completion
+ // status if that was an error).
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ fxRequest->CompleteWithInformation(hr, sizeof(SWITCH_STATE));
+ }
+ else
+ {
+ fxRequest->Complete(hr);
+ }
+
+ fxRequest->Release();
+ }
+ }
+ while (SUCCEEDED(enumHr));
+}
+
+HRESULT
+CMyDevice::SetPowerManagement(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method enables the idle and wake functionality
+ using UMDF. UMDF has been set as the power policy
+ owner (PPO) for the device stack and we are using power
+ managed queues.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ HRESULT hr;
+
+ //
+ // Enable USB selective suspend on the device.
+ //
+
+ hr = m_FxDevice->AssignS0IdleSettings( IdleUsbSelectiveSuspend,
+ PowerDeviceMaximum,
+ IDLE_TIMEOUT_IN_MSEC,
+ IdleAllowUserControl,
+ WdfUseDefault);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to assign S0 idle settings for the device %!HRESULT!",
+ hr
+ );
+ }
+
+ //
+ // Enable Sx wake settings
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_FxDevice->AssignSxWakeSettings( PowerDeviceMaximum,
+ WakeAllowUserControl,
+ WdfUseDefault);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to set Sx Wake Settings for the device %!HRESULT!",
+ hr
+ );
+ }
+
+ }
+
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::OnD0Entry(
+ _In_ IWDFDevice* pWdfDevice,
+ _In_ WDF_POWER_DEVICE_STATE previousState
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ UNREFERENCED_PARAMETER(previousState);
+
+ //
+ // Start/Stop the I/O target if you support a continuous reader.
+ // The rest of the I/O is fed through power managed queues. The queue
+ // itself will stop feeding I/O to targets (and will wait for any pending
+ // I/O to complete before going into low power state), hence targets
+ // don�t need to be stopped/started. The continuous reader I/O is outside
+ // of power managed queues so we need to Stop the I/O target on D0Exit and
+ // start it on D0Entry. Please note that bulk pipe target doesn't need to
+ // be stopped/started because I/O submitted to this pipe comes from power
+ // managed I/O queue, which delivers I/O only in power on state.
+ //
+
+ m_pIoTargetInterruptPipeStateMgmt->Start();
+
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnD0Exit(
+ _In_ IWDFDevice* pWdfDevice,
+ _In_ WDF_POWER_DEVICE_STATE previousState
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ UNREFERENCED_PARAMETER(previousState);
+
+ //
+ // Stop the I/O target always succeedes.
+ //
+ m_pIoTargetInterruptPipeStateMgmt->Stop(WdfIoTargetCancelSentIo);
+ return S_OK;
+}
+
+void
+CMyDevice::OnSurpriseRemoval(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return;
+}
+
+HRESULT
+CMyDevice::OnQueryRemove(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnQueryStop(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+//
+// Self Managed Io Callbacks
+//
+
+VOID
+CMyDevice::OnSelfManagedIoCleanup(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return;
+}
+
+VOID
+CMyDevice::OnSelfManagedIoFlush(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+
+ //
+ // Complete every switch change operation with an error.
+ //
+ ServiceSwitchChangeQueue(m_SwitchState,
+ HRESULT_FROM_WIN32(ERROR_DEVICE_REMOVED),
+ NULL);
+
+ return;
+}
+
+HRESULT
+CMyDevice::OnSelfManagedIoInit(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnSelfManagedIoRestart(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnSelfManagedIoStop(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnSelfManagedIoSuspend(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+
+
+HRESULT
+CMyDevice::ConfigContReaderForInterruptEndPoint(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine configures a continuous reader on the
+ interrupt endpoint. It's called from the PrepareHarware event.
+
+Arguments:
+
+
+Return Value:
+
+ HRESULT value
+
+--*/
+{
+ HRESULT hr, hrQI;
+ IUsbTargetPipeContinuousReaderCallbackReadComplete *pOnCompletionCallback = NULL;
+ IUsbTargetPipeContinuousReaderCallbackReadersFailed *pOnFailureCallback= NULL;
+ IWDFUsbTargetPipe2 * pIUsbInterruptPipe2;
+
+ hrQI = this->QueryInterface(IID_PPV_ARGS(&pOnCompletionCallback));
+ WUDF_TEST_DRIVER_ASSERT((SUCCEEDED(hrQI) && pOnCompletionCallback));
+
+ hrQI = this->QueryInterface(IID_PPV_ARGS(&pOnFailureCallback));
+ WUDF_TEST_DRIVER_ASSERT((SUCCEEDED(hrQI) && pOnFailureCallback));
+
+ hrQI = m_pIUsbInterruptPipe->QueryInterface(IID_PPV_ARGS(&pIUsbInterruptPipe2));
+ WUDF_TEST_DRIVER_ASSERT((SUCCEEDED(hrQI) && pIUsbInterruptPipe2));
+
+ //
+ // Reader requests are not posted to the target automatically.
+ // Driver must explictly call WdfIoTargetStart to kick start the
+ // reader. In this sample, it's done in D0Entry.
+ // By defaut, framework queues two requests to the target
+ // endpoint. Driver can configure up to 10 requests with the
+ // parameter CONCURRENT_READS
+ //
+ hr = pIUsbInterruptPipe2->ConfigureContinuousReader( sizeof(m_SwitchStateBuffer),
+ 0,//header
+ 0,//trailer
+ CONCURRENT_READS,
+ NULL,
+ pOnCompletionCallback,
+ m_pIUsbInterruptPipe,
+ pOnFailureCallback
+ );
+
+ if (FAILED(hr)) {
+ TraceEvents(TRACE_LEVEL_ERROR, TEST_TRACE_DEVICE,
+ "OsrFxConfigContReaderForInterruptEndPoint failed %!HRESULT!",
+ hr);
+ }
+
+ SAFE_RELEASE(pOnCompletionCallback);
+ SAFE_RELEASE(pOnFailureCallback);
+ SAFE_RELEASE(pIUsbInterruptPipe2);
+
+ return hr;
+}
+
+
+BOOL
+CMyDevice::OnReaderFailure(
+ IWDFUsbTargetPipe * pPipe,
+ HRESULT hrCompletion
+ )
+{
+ UNREFERENCED_PARAMETER(pPipe);
+
+ m_InterruptReadProblem = hrCompletion;
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Failure completed with %!HRESULT!",
+ hrCompletion
+ );
+
+ ServiceSwitchChangeQueue(m_SwitchState,
+ hrCompletion,
+ NULL);
+
+ return TRUE;
+}
+
+VOID
+CMyDevice::OnReaderCompletion(
+ IWDFUsbTargetPipe * pPipe,
+ IWDFMemory * pMemory,
+ SIZE_T NumBytesTransferred,
+ PVOID Context
+ )
+{
+ WUDF_TEST_DRIVER_ASSERT(pPipe == (IWDFUsbTargetPipe *)Context);
+
+ //
+ // Make sure that there is data in the read packet. Depending on the device
+ // specification, it is possible for it to return a 0 length read in
+ // certain conditions.
+ //
+
+ if (NumBytesTransferred == 0) {
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Zero length read occured on the Interrupt Pipe's "
+ "Continuous Reader\n"
+ );
+ return;
+ }
+
+ WUDF_TEST_DRIVER_ASSERT(NumBytesTransferred == sizeof(m_SwitchState));
+
+ //
+ // Get the switch state
+ //
+
+ PVOID pBuff = pMemory->GetDataBuffer(NULL);
+
+ CopyMemory(&m_SwitchState, pBuff, sizeof(m_SwitchState));
+
+
+ //
+ // Satisfy application request for switch change notification
+ //
+
+ ServiceSwitchChangeQueue(m_SwitchState,
+ S_OK,
+ NULL);
+
+ //
+ // Make sure that the request that got completed is the one that we reuse
+ // Don't Delete the request because it gets reused
+ //
+}
+
+
+HRESULT
+CMyDevice::GetBusTypeGuid(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This routine gets the device instance ID then invokes SetupDi to
+ retrieve the bus type guid for the device. The bus type guid is
+ stored in object.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ ULONG instanceIdCch = 0;
+ PWSTR instanceId = NULL;
+
+ HDEVINFO deviceInfoSet = NULL;
+ SP_DEVINFO_DATA deviceInfo = {sizeof(SP_DEVINFO_DATA)};
+
+ HRESULT hr;
+
+ //
+ // Retrieve the device instance ID.
+ //
+
+ hr = m_FxDevice->RetrieveDeviceInstanceId(NULL, &instanceIdCch);
+
+ if (FAILED(hr))
+ {
+ goto Exit;
+ }
+
+ instanceId = new WCHAR[instanceIdCch];
+
+ if (instanceId == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ hr = m_FxDevice->RetrieveDeviceInstanceId(instanceId, &instanceIdCch);
+
+ if (FAILED(hr))
+ {
+ goto Exit2;
+ }
+
+ //
+ // Call SetupDI to open the device info.
+ //
+
+ deviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
+
+ if (deviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Exit2;
+ }
+
+ if (SetupDiOpenDeviceInfo(deviceInfoSet,
+ instanceId,
+ NULL,
+ 0,
+ &deviceInfo) == FALSE)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Exit3;
+ }
+
+ if (SetupDiGetDeviceRegistryProperty(deviceInfoSet,
+ &deviceInfo,
+ SPDRP_BUSTYPEGUID,
+ NULL,
+ (PBYTE) &m_BusTypeGuid,
+ sizeof(m_BusTypeGuid),
+ NULL) == FALSE)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Exit3;
+ }
+
+Exit3:
+ SetupDiDestroyDeviceInfoList(deviceInfoSet);
+
+Exit2:
+
+ delete[] instanceId;
+
+Exit:
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::PlaybackFile(
+ _In_ PFILE_PLAYBACK PlayInfo,
+ _In_ IWDFIoRequest *FxRequest
+ )
+/*++
+
+ Routine Description:
+
+ This method impersonates the caller, opens the file and prints each
+ character to the seven segement display.
+
+ Arguments:
+
+ PlayInfo - the playback info from the request.
+
+ FxRequest - the request (used for impersonation)
+
+ Return Value:
+
+ Status
+
+--*/
+
+{
+ PLAYBACK_IMPERSONATION_CONTEXT context = {PlayInfo, NULL, S_OK};
+ IWDFIoRequest2* fxRequest2;
+
+ HRESULT hr;
+
+ // Convert FxRequest to FxRequest2. No error can occur here.
+ FxRequest->QueryInterface(IID_PPV_ARGS(&fxRequest2));
+ _Analysis_assume_(fxRequest2 != NULL);
+
+ //
+ // Impersonate and open the playback file.
+ //
+
+ hr = FxRequest->Impersonate(
+ SecurityImpersonation,
+ this->QueryIImpersonateCallback(),
+ &context
+ );
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ //
+ // Release the reference that was added in QueryIImpersonateCallback()
+ //
+ this->Release();
+
+ hr = context.Hr;
+
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ //
+ // The impersonation callback succeeded - tell code analysis that the
+ // file handle is non-null
+ //
+
+ _Analysis_assume_(context.FileHandle != NULL);
+
+ //
+ // Read from the file one character at a time until we hit
+ // EOF or the request is cancelled.
+ //
+
+ do
+ {
+ UCHAR c;
+ ULONG bytesRead;
+
+ //
+ // Check for cancellation.
+ //
+
+ if (fxRequest2->IsCanceled())
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
+ }
+ else
+ {
+ BOOL result;
+
+ //
+ // Read a character from the file and see if we can
+ // encode it on the display.
+ //
+
+ result = ReadFile(context.FileHandle,
+ &c,
+ sizeof(c),
+ &bytesRead,
+ NULL);
+
+ if (result)
+ {
+ SEVEN_SEGMENT segment;
+ BAR_GRAPH_STATE barGraph;
+
+ if (bytesRead > 0)
+ {
+ #pragma prefast(suppress:__WARNING_USING_UNINIT_VAR,"Above this->Release() method does not actually free 'this'")
+ if(EncodeSegmentValue(c, &segment) == true)
+ {
+ barGraph.BarsAsUChar = c;
+
+ SetSevenSegmentDisplay(&segment);
+ SetBarGraphDisplay(&barGraph);
+ }
+
+ Sleep(PlayInfo->Delay);
+ }
+ else
+ {
+ hr = S_OK;
+ break;
+ }
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+
+ } while(SUCCEEDED(hr));
+
+ CloseHandle(context.FileHandle);
+
+exit:
+
+ fxRequest2->Release();
+ return hr;
+}
+
+VOID
+CMyDevice::OnImpersonate(
+ _In_ PVOID Context
+ )
+/*++
+
+ Routine Description:
+
+ This routine handles the impersonation for the PLAY FILE I/O control.
+
+ Arguments:
+
+ Context - pointer to the impersonation context
+
+ Return Value:
+
+ None
+
+--*/
+{
+ PPLAYBACK_IMPERSONATION_CONTEXT context;
+
+ context = (PPLAYBACK_IMPERSONATION_CONTEXT) Context;
+
+ context->FileHandle = CreateFile(context->PlaybackInfo->Path,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (context->FileHandle == INVALID_HANDLE_VALUE)
+ {
+ DWORD error = GetLastError();
+ context->Hr = HRESULT_FROM_WIN32(error);
+ }
+ else
+ {
+ context->Hr = S_OK;
+ }
+
+ return;
+}
+
+#define SS_LEFT (SS_TOP_LEFT | SS_BOTTOM_LEFT)
+#define SS_RIGHT (SS_TOP_RIGHT | SS_BOTTOM_RIGHT)
+
+bool
+CMyDevice::EncodeSegmentValue(
+ _In_ UCHAR Character,
+ _Out_ SEVEN_SEGMENT *SevenSegment
+ )
+{
+ UCHAR letterMap[] = {
+ (SS_TOP | SS_BOTTOM_LEFT | SS_RIGHT | SS_CENTER | SS_BOTTOM), // a
+ (SS_LEFT | SS_CENTER | SS_BOTTOM | SS_BOTTOM_RIGHT), // b
+ (SS_CENTER | SS_BOTTOM_LEFT | SS_BOTTOM), // c
+ (SS_BOTTOM_LEFT | SS_CENTER | SS_BOTTOM | SS_RIGHT), // d
+ (SS_LEFT | SS_TOP | SS_CENTER | SS_BOTTOM), // e
+ (SS_LEFT | SS_TOP | SS_CENTER), // f
+ (SS_TOP | SS_TOP_LEFT | SS_CENTER | SS_BOTTOM | SS_RIGHT), // g
+ (SS_LEFT | SS_RIGHT | SS_CENTER), // h
+ (SS_BOTTOM_LEFT), // i
+ (SS_BOTTOM | SS_RIGHT), // j
+ (SS_LEFT | SS_CENTER | SS_BOTTOM), // k
+ (SS_LEFT | SS_BOTTOM), // l
+ (SS_LEFT | SS_TOP | SS_RIGHT), // m
+ (SS_BOTTOM_LEFT | SS_CENTER | SS_BOTTOM_RIGHT), // n
+ (SS_BOTTOM_LEFT | SS_BOTTOM_RIGHT | SS_CENTER | SS_BOTTOM), // o
+ (SS_LEFT | SS_TOP | SS_CENTER | SS_TOP_RIGHT), // p
+ (SS_TOP_LEFT | SS_TOP | SS_CENTER | SS_RIGHT), // q
+ (SS_BOTTOM_LEFT | SS_CENTER), // r
+ (SS_TOP_LEFT |
+ SS_TOP | SS_CENTER | SS_BOTTOM |
+ SS_BOTTOM_RIGHT), // s
+ (SS_TOP | SS_RIGHT), // t
+ (SS_LEFT | SS_RIGHT | SS_BOTTOM), // u
+ (SS_BOTTOM_LEFT | SS_BOTTOM | SS_BOTTOM_RIGHT), // v
+ (SS_LEFT | SS_BOTTOM | SS_BOTTOM_RIGHT), // w
+ (SS_LEFT | SS_CENTER | SS_RIGHT), // x
+ (SS_TOP_LEFT | SS_CENTER | SS_RIGHT), // y
+ (SS_TOP_RIGHT |
+ SS_TOP | SS_CENTER | SS_BOTTOM |
+ SS_BOTTOM_LEFT), // z
+ };
+
+ UCHAR numberMap[] = {
+ (SS_LEFT | SS_TOP | SS_BOTTOM | SS_RIGHT | SS_DOT), // 0
+ (SS_RIGHT | SS_DOT), // 1
+ (SS_TOP |
+ SS_TOP_RIGHT | SS_CENTER | SS_BOTTOM_LEFT |
+ SS_BOTTOM | SS_DOT), // 2
+ (SS_TOP | SS_CENTER | SS_BOTTOM | SS_RIGHT | SS_DOT), // 3
+ (SS_TOP_LEFT | SS_CENTER | SS_RIGHT | SS_DOT), // 4
+ (SS_TOP_LEFT |
+ SS_TOP | SS_CENTER | SS_BOTTOM |
+ SS_BOTTOM_RIGHT | SS_DOT), // 5
+ (SS_TOP | SS_CENTER | SS_BOTTOM |
+ SS_LEFT | SS_BOTTOM_RIGHT | SS_DOT), // 6
+ (SS_TOP | SS_RIGHT | SS_DOT), // 7
+ (SS_TOP | SS_BOTTOM | SS_CENTER |
+ SS_LEFT | SS_RIGHT | SS_DOT), // 8
+ (SS_TOP_LEFT | SS_TOP | SS_CENTER | SS_RIGHT | SS_DOT), // 9
+ };
+
+ if (((Character >= 'a') && (Character <= 'z')) ||
+ ((Character >= 'A') && (Character <= 'Z')))
+ {
+ SevenSegment->Segments = letterMap[tolower(Character) - 'a'];
+ return true;
+ }
+ else if ((Character >= '0') && (Character <= '9'))
+ {
+ SevenSegment->Segments = numberMap[Character - '0'];
+ return true;
+ }
+ else
+ {
+ SevenSegment->Segments = 0;
+ return false;
+ }
+}
+
diff --git a/usb/umdf_filter_umdf/umdf_driver/Device.h b/usb/umdf_filter_umdf/umdf_driver/Device.h
new file mode 100644
index 00000000..641a04de
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/Device.h
@@ -0,0 +1,604 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Device.h
+
+Abstract:
+
+ This module contains the type definitions for the UMDF OSR Fx2 sample
+ driver's device callback class.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+#include "internal.h"
+
+#define ENDPOINT_TIMEOUT 10000
+#define NUM_OSRUSB_ENDPOINTS 3
+
+//
+// Define the vendor commands supported by our device
+//
+#define USBFX2LK_READ_7SEGMENT_DISPLAY 0xD4
+#define USBFX2LK_READ_SWITCHES 0xD6
+#define USBFX2LK_READ_BARGRAPH_DISPLAY 0xD7
+#define USBFX2LK_SET_BARGRAPH_DISPLAY 0xD8
+#define USBFX2LK_IS_HIGH_SPEED 0xD9
+#define USBFX2LK_REENUMERATE 0xDA
+#define USBFX2LK_SET_7SEGMENT_DISPLAY 0xDB
+
+typedef struct {
+ UCHAR Segments;
+} SEVEN_SEGMENT, *PSEVEN_SEGMENT;
+
+//
+// Context for the impersonation callback.
+//
+
+typedef struct
+{
+ PFILE_PLAYBACK PlaybackInfo;
+
+ HANDLE FileHandle;
+
+ HRESULT Hr;
+} PLAYBACK_IMPERSONATION_CONTEXT, *PPLAYBACK_IMPERSONATION_CONTEXT;
+
+//
+// Class for the driver.
+//
+
+class CMyDevice :
+ public CUnknown,
+ public IPnpCallbackHardware,
+ public IPnpCallback,
+ public IPnpCallbackSelfManagedIo,
+ public IUsbTargetPipeContinuousReaderCallbackReadersFailed,
+ public IUsbTargetPipeContinuousReaderCallbackReadComplete,
+ public IImpersonateCallback
+{
+//
+// Private data members.
+//
+private:
+ //
+ // Weak reference to framework device
+ // Use IWDFDevice2 so we can set power policy settings
+ //
+ IWDFDevice2 *m_FxDevice;
+
+ //
+ // Weak reference to the control queue
+ //
+ PCMyReadWriteQueue m_ReadWriteQueue;
+
+ //
+ // Weak reference to the control queue
+ //
+ PCMyControlQueue m_ControlQueue;
+
+ //
+ // The bus type for this device (used here for
+ // illustrative purposes only)
+ //
+
+ GUID m_BusTypeGuid;
+
+ //
+ // USB Device I/O Target
+ //
+ IWDFUsbTargetDevice * m_pIUsbTargetDevice;
+
+ //
+ // USB Interface
+ //
+ IWDFUsbInterface * m_pIUsbInterface;
+
+ //
+ // USB Input pipe for Reads
+ //
+ IWDFUsbTargetPipe * m_pIUsbInputPipe;
+
+ //
+ // USB Output pipe for writes
+ //
+ IWDFUsbTargetPipe * m_pIUsbOutputPipe;
+
+ //
+ // USB interrupt pipe
+ //
+ IWDFUsbTargetPipe * m_pIUsbInterruptPipe;
+
+ //
+ // Use I/O target state management interfaces if you are going to
+ // support a continuous reader.
+ //
+
+ //
+ // USB interrupt pipe state management
+ //
+ IWDFIoTargetStateManagement * m_pIoTargetInterruptPipeStateMgmt;
+
+ //
+ // Device Speed (Low, Full, High)
+ //
+ UCHAR m_Speed;
+
+ //
+ // Current switch state
+ //
+ SWITCH_STATE m_SwitchState;
+
+ //
+ // Request to be used for pending reads from interrupt pipe
+ // (to get switch state change notifications)
+ //
+
+ IWDFIoRequest * m_RequestForPendingRead;
+
+ //
+ // If reads stopped because of a transient problem, the error status
+ // is stored here.
+ //
+
+ HRESULT m_InterruptReadProblem;
+
+ //
+ // Switch state buffer - this might hold the transient value
+ // m_SwitchState holds stable value of the switch state
+ //
+ SWITCH_STATE m_SwitchStateBuffer;
+
+ //
+ // A manual queue to hold requests for changes in the I/O switch state.
+ //
+
+ IWDFIoQueue * m_SwitchChangeQueue;
+
+//
+// Private methods.
+//
+
+private:
+
+ CMyDevice(
+ VOID
+ ) :
+ m_FxDevice(NULL),
+ m_ControlQueue(NULL),
+ m_ReadWriteQueue(NULL),
+ m_SwitchChangeQueue(NULL),
+ m_pIUsbTargetDevice(NULL),
+ m_pIUsbInterface(NULL),
+ m_pIUsbInputPipe(NULL),
+ m_pIUsbOutputPipe(NULL),
+ m_pIUsbInterruptPipe(NULL),
+ m_Speed(0),
+ m_InterruptReadProblem(S_OK),
+ m_RequestForPendingRead(NULL),
+ m_pIoTargetInterruptPipeStateMgmt(NULL)
+ {
+ ZeroMemory(&m_BusTypeGuid, sizeof(m_BusTypeGuid));
+ }
+
+ ~CMyDevice(
+ );
+
+ HRESULT
+ Initialize(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ );
+
+ //
+ // Helper methods
+ //
+
+ HRESULT
+ GetBusTypeGuid(
+ VOID
+ );
+
+ HRESULT
+ CreateUsbIoTargets(
+ VOID
+ );
+
+
+ HRESULT
+ ConfigureUsbPipes(
+ );
+
+ HRESULT
+ SetPowerManagement(
+ VOID
+ );
+
+ HRESULT
+ IndicateDeviceReady(
+ VOID
+ );
+
+ //
+ // Helper functions
+ //
+
+ HRESULT
+ SendControlTransferSynchronously(
+ _In_ PWINUSB_SETUP_PACKET SetupPacket,
+ _Inout_updates_(BufferLength) PBYTE Buffer,
+ _In_ ULONG BufferLength,
+ _Out_ PULONG LengthTransferred
+ );
+
+ static
+ WDF_IO_TARGET_STATE
+ GetTargetState(
+ IWDFIoTarget * pTarget
+ );
+
+ VOID
+ ServiceSwitchChangeQueue(
+ _In_ SWITCH_STATE NewState,
+ _In_ HRESULT CompletionStatus,
+ _In_opt_ IWDFFile *SpecificFile
+ );
+
+//
+// Public methods
+//
+public:
+
+ //
+ // The factory method used to create an instance of this driver.
+ //
+
+ static
+ HRESULT
+ CreateInstance(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit,
+ _Out_ PCMyDevice *Device
+ );
+
+ IWDFDevice *
+ GetFxDevice(
+ VOID
+ )
+ {
+ return m_FxDevice;
+ }
+
+ HRESULT
+ Configure(
+ VOID
+ );
+
+ IPnpCallback *
+ QueryIPnpCallback(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IPnpCallback *>(this);
+ }
+
+ IPnpCallbackHardware *
+ QueryIPnpCallbackHardware(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IPnpCallbackHardware *>(this);
+ }
+
+ IPnpCallbackSelfManagedIo *
+ QueryIPnpCallbackSelfManagedIo(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IPnpCallbackSelfManagedIo *>(this);
+ }
+
+
+ IUsbTargetPipeContinuousReaderCallbackReadersFailed *
+ QueryContinousReaderFailureCompletion(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IUsbTargetPipeContinuousReaderCallbackReadersFailed *>(this);
+ }
+
+ IUsbTargetPipeContinuousReaderCallbackReadComplete *
+ QueryContinousReaderCompletion(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IUsbTargetPipeContinuousReaderCallbackReadComplete *>(this);
+ }
+
+ IImpersonateCallback *
+ QueryIImpersonateCallback(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IImpersonateCallback *>(this);
+ }
+
+ HRESULT
+ GetBarGraphDisplay(
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ );
+
+ HRESULT
+ SetBarGraphDisplay(
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ );
+
+ HRESULT
+ GetSevenSegmentDisplay(
+ _In_ PSEVEN_SEGMENT SevenSegment
+ );
+
+ HRESULT
+ SetSevenSegmentDisplay(
+ _In_ PSEVEN_SEGMENT SevenSegment
+ );
+
+ HRESULT
+ ReadSwitchState(
+ _In_ PSWITCH_STATE SwitchState
+ );
+
+ bool
+ EncodeSegmentValue(
+ _In_ UCHAR Character,
+ _Out_ SEVEN_SEGMENT *SevenSegment
+ );
+
+ HRESULT
+ PlaybackFile(
+ _In_ PFILE_PLAYBACK PlaybackInfo,
+ _In_ IWDFIoRequest *FxRequest
+ );
+
+ //
+ //returns a weak reference to the target USB device
+ //DO NOT release it
+ //
+ IWDFUsbTargetDevice *
+ GetUsbTargetDevice(
+ )
+ {
+ return m_pIUsbTargetDevice;
+ }
+
+ //
+ //returns a weak reference to input pipe
+ //DO NOT release it
+ //
+ IWDFUsbTargetPipe *
+ GetInputPipe(
+ )
+ {
+ return m_pIUsbInputPipe;
+ }
+
+ //
+ //returns a weak reference to output pipe
+ //DO NOT release it
+ //
+ IWDFUsbTargetPipe *
+ GetOutputPipe(
+ )
+ {
+ return m_pIUsbOutputPipe;
+ }
+
+ IWDFIoQueue *
+ GetSwitchChangeQueue(
+ VOID
+ )
+ {
+ return m_SwitchChangeQueue;
+ }
+
+ PSWITCH_STATE
+ GetCurrentSwitchState(
+ VOID
+ )
+ {
+ return &m_SwitchState;
+ }
+
+
+ HRESULT
+ ConfigContReaderForInterruptEndPoint(
+ VOID
+ );
+//
+// COM methods
+//
+public:
+
+ //
+ // IUnknown methods.
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+
+ //
+ // IPnpCallbackHardware
+ //
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnPrepareHardware(
+ _In_ IWDFDevice *FxDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnReleaseHardware(
+ _In_ IWDFDevice *FxDevice
+ );
+
+
+ //
+ // IPnpCallback
+ //
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnD0Entry(
+ _In_ IWDFDevice* pWdfDevice,
+ _In_ WDF_POWER_DEVICE_STATE previousState
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnD0Exit(
+ _In_ IWDFDevice* pWdfDevice,
+ _In_ WDF_POWER_DEVICE_STATE previousState
+ );
+
+ virtual
+ void
+ STDMETHODCALLTYPE
+ OnSurpriseRemoval(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnQueryRemove(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnQueryStop(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ //
+ // IPnpCallbackSelfManagedIo
+ //
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnSelfManagedIoCleanup(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnSelfManagedIoFlush(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnSelfManagedIoInit(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnSelfManagedIoRestart(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnSelfManagedIoStop(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnSelfManagedIoSuspend(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ //
+ // IUsbTargetPipeContinuousReaderCallbackReadersFailed
+ //
+ virtual
+ BOOL
+ STDMETHODCALLTYPE
+ OnReaderFailure(
+ IWDFUsbTargetPipe * pPipe,
+ HRESULT hrCompletion
+ );
+
+ //
+ // IUsbTargetPipeContinuousReaderCallbackReadComplete
+ //
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnReaderCompletion(
+ IWDFUsbTargetPipe * pPipe,
+ IWDFMemory * pMemory,
+ SIZE_T NumBytesTransferred,
+ PVOID Context
+ );
+
+ // IImpersonateCallback
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnImpersonate(
+ _In_ PVOID Context
+ );
+};
+
diff --git a/usb/umdf_filter_umdf/umdf_driver/Driver.cpp b/usb/umdf_filter_umdf/umdf_driver/Driver.cpp
new file mode 100644
index 00000000..d6635242
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/Driver.cpp
@@ -0,0 +1,220 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ Driver.cpp
+
+Abstract:
+
+ This module contains the implementation of the UMDF OSR Fx2 driver's
+ core driver callback object.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "driver.tmh"
+
+HRESULT
+CMyDriver::CreateInstance(
+ _Out_ PCMyDriver *Driver
+ )
+/*++
+
+ Routine Description:
+
+ This static method is invoked in order to create and initialize a new
+ instance of the driver class. The caller should arrange for the object
+ to be released when it is no longer in use.
+
+ Arguments:
+
+ Driver - a location to store a referenced pointer to the new instance
+
+ Return Value:
+
+ S_OK if successful, or error otherwise.
+
+--*/
+{
+ PCMyDriver driver;
+ HRESULT hr;
+
+ //
+ // Allocate the callback object.
+ //
+
+ driver = new CMyDriver();
+
+ if (NULL == driver)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ //
+ // Initialize the callback object.
+ //
+
+ hr = driver->Initialize();
+
+ if (SUCCEEDED(hr))
+ {
+ //
+ // Store a pointer to the new, initialized object in the output
+ // parameter.
+ //
+
+ *Driver = driver;
+ }
+ else
+ {
+
+ //
+ // Release the reference on the driver object to get it to delete
+ // itself.
+ //
+
+ driver->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDriver::Initialize(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method is called to initialize a newly created driver callback object
+ before it is returned to the creator. Unlike the constructor, the
+ Initialize method contains operations which could potentially fail.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None
+
+--*/
+{
+ return S_OK;
+}
+
+HRESULT
+CMyDriver::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Interface
+ )
+/*++
+
+ Routine Description:
+
+ This method returns a pointer to the requested interface on the callback
+ object..
+
+ Arguments:
+
+ InterfaceId - the IID of the interface to query/reference
+
+ Interface - a location to store the interface pointer.
+
+ Return Value:
+
+ S_OK if the interface is supported.
+ E_NOINTERFACE if it is not supported.
+
+--*/
+{
+ if (IsEqualIID(InterfaceId, __uuidof(IDriverEntry)))
+ {
+ *Interface = QueryIDriverEntry();
+ return S_OK;
+ }
+ else
+ {
+ return CUnknown::QueryInterface(InterfaceId, Interface);
+ }
+}
+
+HRESULT
+CMyDriver::OnDeviceAdd(
+ _In_ IWDFDriver *FxWdfDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ )
+/*++
+
+ Routine Description:
+
+ The FX invokes this method when it wants to install our driver on a device
+ stack. This method creates a device callback object, then calls the Fx
+ to create an Fx device object and associate the new callback object with
+ it.
+
+ Arguments:
+
+ FxWdfDriver - the Fx driver object.
+
+ FxDeviceInit - the initialization information for the device.
+
+ Return Value:
+
+ status
+
+--*/
+{
+ HRESULT hr;
+
+ PCMyDevice device = NULL;
+
+ //
+ // TODO: Do any per-device initialization (reading settings from the
+ // registry for example) that's necessary before creating your
+ // device callback object here. Otherwise you can leave such
+ // initialization to the initialization of the device event
+ // handler.
+ //
+
+ //
+ // Create a new instance of our device callback object
+ //
+
+ hr = CMyDevice::CreateInstance(FxWdfDriver, FxDeviceInit, &device);
+
+ //
+ // TODO: Change any per-device settings that the object exposes before
+ // calling Configure to let it complete its initialization.
+ //
+
+ //
+ // If that succeeded then call the device's construct method. This
+ // allows the device to create any queues or other structures that it
+ // needs now that the corresponding fx device object has been created.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = device->Configure();
+ }
+
+ //
+ // Release the reference on the device callback object now that it's been
+ // associated with an fx device object.
+ //
+
+ if (NULL != device)
+ {
+ device->Release();
+ }
+
+ return hr;
+}
diff --git a/usb/umdf_filter_umdf/umdf_driver/Driver.h b/usb/umdf_filter_umdf/umdf_driver/Driver.h
new file mode 100644
index 00000000..d9cafb4e
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/Driver.h
@@ -0,0 +1,149 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Driver.h
+
+Abstract:
+
+ This module contains the type definitions for the UMDF OSR Fx2 sample's
+ driver callback class.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// This class handles driver events for the OSR Fx2 sample. In particular
+// it supports the OnDeviceAdd event, which occurs when the driver is called
+// to setup per-device handlers for a new device stack.
+//
+
+class CMyDriver : public CUnknown, public IDriverEntry
+{
+//
+// Private data members.
+//
+private:
+
+//
+// Private methods.
+//
+private:
+
+ //
+ // Returns a refernced pointer to the IDriverEntry interface.
+ //
+
+ IDriverEntry *
+ QueryIDriverEntry(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IDriverEntry*>(this);
+ }
+
+ HRESULT
+ Initialize(
+ VOID
+ );
+
+//
+// Public methods
+//
+public:
+
+ //
+ // The factory method used to create an instance of this driver.
+ //
+
+ static
+ HRESULT
+ CreateInstance(
+ _Out_ PCMyDriver *Driver
+ );
+
+//
+// COM methods
+//
+public:
+
+ //
+ // IDriverEntry methods
+ //
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnInitialize(
+ _In_ IWDFDriver *FxWdfDriver
+ )
+ {
+ UNREFERENCED_PARAMETER(FxWdfDriver);
+
+ return S_OK;
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnDeviceAdd(
+ _In_ IWDFDriver *FxWdfDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ );
+
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnDeinitialize(
+ _In_ IWDFDriver *FxWdfDriver
+ )
+ {
+ UNREFERENCED_PARAMETER(FxWdfDriver);
+
+ return;
+ }
+
+ //
+ // IUnknown methods.
+ //
+ // We have to implement basic ones here that redirect to the
+ // base class becuase of the multiple inheritance.
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+};
diff --git a/usb/umdf_filter_umdf/umdf_driver/OsrUsbFx2.ctl b/usb/umdf_filter_umdf/umdf_driver/OsrUsbFx2.ctl
new file mode 100644
index 00000000..4dab56ae
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/OsrUsbFx2.ctl
@@ -0,0 +1 @@
+da5fbdfd-1eae-4ecf-b426-a3818f325ddb WudfOsrUsbFx2TraceGuid
diff --git a/usb/umdf_filter_umdf/umdf_driver/OsrUsbFx2.rc b/usb/umdf_filter_umdf/umdf_driver/OsrUsbFx2.rc
new file mode 100644
index 00000000..36f10ea9
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/OsrUsbFx2.rc
@@ -0,0 +1,21 @@
+//---------------------------------------------------------------------------
+// OsrUsbDevice.rc
+//
+// Copyright (c) Microsoft Corporation, All Rights Reserved
+//---------------------------------------------------------------------------
+
+
+#include <windows.h>
+#include <ntverp.h>
+
+//
+// TODO: Change the file description and file names to match your binary.
+//
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "WDF:UMDF OSR USB Fx2 User-Mode Driver Sample"
+#define VER_INTERNALNAME_STR "WUDFOsrUsbFx2"
+#define VER_ORIGINALFILENAME_STR "WUDFOsrUsbFx2.dll"
+
+#include "common.ver"
diff --git a/usb/umdf_filter_umdf/umdf_driver/ReadWriteQueue.cpp b/usb/umdf_filter_umdf/umdf_driver/ReadWriteQueue.cpp
new file mode 100644
index 00000000..46144829
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/ReadWriteQueue.cpp
@@ -0,0 +1,425 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ queue.cpp
+
+Abstract:
+
+ This file implements the I/O queue interface and performs
+ the read/write/ioctl operations.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "ReadWriteQueue.tmh"
+
+VOID
+CMyReadWriteQueue::OnCompletion(
+ _In_ IWDFIoRequest* pWdfRequest,
+ _In_ IWDFIoTarget* pIoTarget,
+ _In_ IWDFRequestCompletionParams* pParams,
+ _In_ PVOID pContext
+ )
+{
+ UNREFERENCED_PARAMETER(pIoTarget);
+ UNREFERENCED_PARAMETER(pContext);
+
+ pWdfRequest->CompleteWithInformation(
+ pParams->GetCompletionStatus(),
+ pParams->GetInformation()
+ );
+}
+
+void
+CMyReadWriteQueue::ForwardFormattedRequest(
+ _In_ IWDFIoRequest* pRequest,
+ _In_ IWDFIoTarget* pIoTarget
+ )
+{
+ //
+ //First set the completion callback
+ //
+
+ IRequestCallbackRequestCompletion * pCompletionCallback = NULL;
+ HRESULT hrQI = this->QueryInterface(IID_PPV_ARGS(&pCompletionCallback));
+ WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI) && (NULL != pCompletionCallback));
+
+ pRequest->SetCompletionCallback(
+ pCompletionCallback,
+ NULL
+ );
+
+ pCompletionCallback->Release();
+ pCompletionCallback = NULL;
+
+ //
+ //Send down the request
+ //
+
+ HRESULT hrSend = S_OK;
+ hrSend = pRequest->Send(pIoTarget,
+ 0, //flags
+ 0); //timeout
+
+ if (FAILED(hrSend))
+ {
+ pRequest->CompleteWithInformation(hrSend, 0);
+ }
+
+ return;
+}
+
+
+CMyReadWriteQueue::CMyReadWriteQueue(
+ _In_ PCMyDevice Device
+ ) :
+ CMyQueue(Device)
+{
+}
+
+//
+// Queue destructor.
+// Free up the buffer, wait for thread to terminate and
+//
+
+CMyReadWriteQueue::~CMyReadWriteQueue(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+
+ IUnknown implementation of Release
+
+Aruments:
+
+
+Return Value:
+
+ ULONG (reference count after Release)
+
+--*/
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC! Entry"
+ );
+
+}
+
+
+HRESULT
+STDMETHODCALLTYPE
+CMyReadWriteQueue::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+Routine Description:
+
+
+ Query Interface
+
+Aruments:
+
+ Follows COM specifications
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ HRESULT hr;
+
+
+ if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackWrite)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackWrite();
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackRead)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackRead();
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IRequestCallbackRequestCompletion)))
+ {
+ hr = S_OK;
+ *Object = QueryIRequestCallbackRequestCompletion();
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackIoStop)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackIoStop();
+ }
+ else
+ {
+ hr = CMyQueue::QueryInterface(InterfaceId, Object);
+ }
+
+ return hr;
+}
+
+//
+// Initialize
+//
+
+HRESULT
+CMyReadWriteQueue::CreateInstance(
+ _In_ PCMyDevice Device,
+ _Out_ PCMyReadWriteQueue *Queue
+ )
+/*++
+
+Routine Description:
+
+
+ CreateInstance creates an instance of the queue object.
+
+Aruments:
+
+ ppUkwn - OUT parameter is an IUnknown interface to the queue object
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ PCMyReadWriteQueue queue;
+ HRESULT hr = S_OK;
+
+ queue = new CMyReadWriteQueue(Device);
+
+ if (NULL == queue)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // Call the queue callback object to initialize itself. This will create
+ // its partner queue framework object.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = queue->Initialize();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *Queue = queue;
+ }
+ else
+ {
+ SAFE_RELEASE(queue);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyReadWriteQueue::Initialize(
+ )
+{
+ HRESULT hr;
+
+ //
+ // First initialize the base class. This will create the partner FxIoQueue
+ // object and setup automatic forwarding of I/O controls.
+ //
+
+ hr = __super::Initialize(WdfIoQueueDispatchParallel,
+ true,
+ true);
+
+ //
+ // return the status.
+ //
+
+ return hr;
+}
+
+STDMETHODIMP_ (void)
+CMyReadWriteQueue::OnWrite(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ SIZE_T BytesToWrite
+ )
+/*++
+
+Routine Description:
+
+
+ Write dispatch routine
+ IQueueCallbackWrite
+
+Aruments:
+
+ pWdfQueue - Framework Queue instance
+ pWdfRequest - Framework Request instance
+ BytesToWrite - Lenth of bytes in the write buffer
+
+ Allocate and copy data to local buffer
+Return Value:
+
+ VOID
+
+--*/
+{
+ UNREFERENCED_PARAMETER(pWdfQueue);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC!: Queue %p Request %p BytesToTransfer %d\n",
+ this,
+ pWdfRequest,
+ (ULONG)(ULONG_PTR)BytesToWrite
+ );
+
+ HRESULT hr = S_OK;
+ IWDFMemory * pInputMemory = NULL;
+ IWDFUsbTargetPipe * pOutputPipe = m_Device->GetOutputPipe();
+
+ pWdfRequest->GetInputMemory(&pInputMemory);
+
+ hr = pOutputPipe->FormatRequestForWrite(
+ pWdfRequest,
+ NULL, //pFile
+ pInputMemory,
+ NULL, //Memory offset
+ NULL //DeviceOffset
+ );
+
+ if (FAILED(hr))
+ {
+ pWdfRequest->Complete(hr);
+ }
+ else
+ {
+ ForwardFormattedRequest(pWdfRequest, pOutputPipe);
+ }
+
+ SAFE_RELEASE(pInputMemory);
+
+ return;
+}
+
+STDMETHODIMP_ (void)
+CMyReadWriteQueue::OnRead(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ SIZE_T BytesToRead
+ )
+/*++
+
+Routine Description:
+
+
+ Read dispatch routine
+ IQueueCallbackRead
+
+Aruments:
+
+ pWdfQueue - Framework Queue instance
+ pWdfRequest - Framework Request instance
+ BytesToRead - Lenth of bytes in the read buffer
+
+ Copy available data into the read buffer
+Return Value:
+
+ VOID
+
+--*/
+{
+ UNREFERENCED_PARAMETER(pWdfQueue);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC!: Queue %p Request %p BytesToTransfer %d\n",
+ this,
+ pWdfRequest,
+ (ULONG)(ULONG_PTR)BytesToRead
+ );
+
+ HRESULT hr = S_OK;
+ IWDFMemory * pOutputMemory = NULL;
+
+ pWdfRequest->GetOutputMemory(&pOutputMemory);
+
+ hr = m_Device->GetInputPipe()->FormatRequestForRead(
+ pWdfRequest,
+ NULL, //pFile
+ pOutputMemory,
+ NULL, //Memory offset
+ NULL //DeviceOffset
+ );
+
+ if (FAILED(hr))
+ {
+ pWdfRequest->Complete(hr);
+ }
+ else
+ {
+ ForwardFormattedRequest(pWdfRequest, m_Device->GetInputPipe());
+ }
+
+ SAFE_RELEASE(pOutputMemory);
+
+ return;
+}
+
+STDMETHODIMP_ (void)
+CMyReadWriteQueue::OnIoStop(
+ _In_ IWDFIoQueue * pWdfQueue,
+ _In_ IWDFIoRequest * pWdfRequest,
+ _In_ ULONG ActionFlags
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfQueue);
+
+
+ //
+ // The driver owns the request and no locking constraint is safe for
+ // the queue callbacks
+ //
+ if (ActionFlags == WdfRequestStopActionSuspend )
+ {
+ IWDFIoRequest2 * request2 = NULL;
+ HRESULT hr;
+
+ hr = pWdfRequest->QueryInterface(IID_PPV_ARGS(&request2));
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC!: Failed to QI for IWDFIoRequest2: %!hresult!",
+ hr);
+ return;
+ }
+
+ request2->StopAcknowledge(FALSE); //don't requeue
+ SAFE_RELEASE(request2);
+ }
+ else if(ActionFlags == WdfRequestStopActionPurge)
+ {
+ //
+ // Cancel the sent request since we are asked to purge the request
+ //
+
+ pWdfRequest->CancelSentRequest();
+ }
+
+ return;
+}
+
diff --git a/usb/umdf_filter_umdf/umdf_driver/ReadWriteQueue.h b/usb/umdf_filter_umdf/umdf_driver/ReadWriteQueue.h
new file mode 100644
index 00000000..4f1a98c1
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/ReadWriteQueue.h
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ queue.h
+
+Abstract:
+
+ This file defines the queue callback interface.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+
+#define MAX_TRANSFER_SIZE(x) 64*1024*1024
+
+//
+// Queue Callback Object.
+//
+
+class CMyReadWriteQueue :
+ public IQueueCallbackRead,
+ public IQueueCallbackWrite,
+ public IRequestCallbackRequestCompletion,
+ public IQueueCallbackIoStop,
+ public CMyQueue
+{
+protected:
+ HRESULT
+ Initialize(
+ );
+
+ void
+ ForwardFormattedRequest(
+ _In_ IWDFIoRequest* pRequest,
+ _In_ IWDFIoTarget* pIoTarget
+ );
+
+public:
+
+ CMyReadWriteQueue(
+ _In_ PCMyDevice Device
+ );
+
+ virtual ~CMyReadWriteQueue();
+
+ static
+ HRESULT
+ CreateInstance(
+ _In_ PCMyDevice Device,
+ _Out_ PCMyReadWriteQueue *Queue
+ );
+
+ HRESULT
+ Configure(
+ VOID
+ )
+ {
+ return CMyQueue::Configure();
+ }
+
+ IQueueCallbackWrite *
+ QueryIQueueCallbackWrite(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackWrite *>(this);
+ }
+
+ IQueueCallbackRead *
+ QueryIQueueCallbackRead(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackRead *>(this);
+ }
+
+ IRequestCallbackRequestCompletion *
+ QueryIRequestCallbackRequestCompletion(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IRequestCallbackRequestCompletion *>(this);
+ }
+
+ IQueueCallbackIoStop*
+ QueryIQueueCallbackIoStop(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackIoStop *>(this);
+ }
+
+ //
+ // IUnknown
+ //
+
+ STDMETHOD_(ULONG,AddRef) (VOID) {return CUnknown::AddRef();}
+
+ _At_(this, __drv_freesMem(object))
+ STDMETHOD_(ULONG,Release) (VOID) {return CUnknown::Release();}
+
+ STDMETHOD_(HRESULT, QueryInterface)(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+
+
+ //
+ // Wdf Callbacks
+ //
+
+ //
+ // IQueueCallbackWrite
+ //
+ STDMETHOD_ (void, OnWrite)(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ SIZE_T NumOfBytesToWrite
+ );
+
+ //
+ // IQueueCallbackRead
+ //
+ STDMETHOD_ (void, OnRead)(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ SIZE_T NumOfBytesToRead
+ );
+
+ //
+ //IRequestCallbackRequestCompletion
+ //
+
+ STDMETHOD_ (void, OnCompletion)(
+ _In_ IWDFIoRequest* pWdfRequest,
+ _In_ IWDFIoTarget* pIoTarget,
+ _In_ IWDFRequestCompletionParams* pParams,
+ _In_ PVOID pContext
+ );
+
+ //
+ //IQueueCallbackIoStop
+ //
+
+ STDMETHOD_ (void, OnIoStop)(
+ _In_ IWDFIoQueue * pWdfQueue,
+ _In_ IWDFIoRequest * pWdfRequest,
+ _In_ ULONG ActionFlags
+ );
+
+};
diff --git a/usb/umdf_filter_umdf/umdf_driver/WUDFOsrUsbFx2.vcxproj b/usb/umdf_filter_umdf/umdf_driver/WUDFOsrUsbFx2.vcxproj
new file mode 100644
index 00000000..e5b2d207
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/WUDFOsrUsbFx2.vcxproj
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{0D3781C2-2236-46B0-806D-387999E500AB}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <UMDF_VERSION_MAJOR>1</UMDF_VERSION_MAJOR>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <SupportsPackaging>false</SupportsPackaging>
+ <RequiresPackageProject>true</RequiresPackageProject>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{C4216905-C3FE-44F7-A5AD-0987922D565E}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <ClCompile Include="dllsup.cpp; comsup.cpp; driver.cpp; device.cpp; queue.cpp; ControlQueue.cpp; ReadWriteQueue.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppDllMacro>true</WppDllMacro>
+ <WppScanConfigurationData>internal.h</WppScanConfigurationData>
+ </ClCompile>
+ <OtherWpp Include="OsrUsbFx2.rc">
+ <WppEnabled>true</WppEnabled>
+ <WppDllMacro>true</WppDllMacro>
+ <WppScanConfigurationData>internal.h</WppScanConfigurationData>
+ </OtherWpp>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>WUDFOsrUsbFx2</TargetName>
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>WUDFOsrUsbFx2</TargetName>
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>WUDFOsrUsbFx2</TargetName>
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>WUDFOsrUsbFx2</TargetName>
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201</DisableSpecificWarnings>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201</DisableSpecificWarnings>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201</DisableSpecificWarnings>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201</DisableSpecificWarnings>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\setupapi.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\setupapi.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\setupapi.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\setupapi.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ResourceCompile Include="OsrUsbFx2.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/usb/umdf_filter_umdf/umdf_driver/WUDFOsrUsbFx2.vcxproj.Filters b/usb/umdf_filter_umdf/umdf_driver/WUDFOsrUsbFx2.vcxproj.Filters
new file mode 100644
index 00000000..d0c54d1b
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/WUDFOsrUsbFx2.vcxproj.Filters
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{ABA4E4AE-18A0-4313-819F-B0D9DDB54C2E}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{E4C135BD-DEBF-4561-8E32-CA099824DFF6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{2CBEC65A-B61D-4E62-9582-AA80C3C538D0}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{8597CA67-53BC-423A-BF33-07316F805E89}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="comsup.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ControlQueue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="device.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllsup.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="queue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ReadWriteQueue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <None Include="exports.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="OsrUsbFx2.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/usb/umdf_filter_umdf/umdf_driver/comsup.cpp b/usb/umdf_filter_umdf/umdf_driver/comsup.cpp
new file mode 100644
index 00000000..9c9aec3b
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/comsup.cpp
@@ -0,0 +1,344 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ComSup.cpp
+
+Abstract:
+
+ This module contains implementations for the functions and methods
+ used for providing COM support.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+
+#include "comsup.tmh"
+
+//
+// Implementation of CUnknown methods.
+//
+
+CUnknown::CUnknown(
+ VOID
+ ) : m_ReferenceCount(1)
+/*++
+
+ Routine Description:
+
+ Constructor for an instance of the CUnknown class. This simply initializes
+ the reference count of the object to 1. The caller is expected to
+ call Release() if it wants to delete the object once it has been allocated.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None
+
+--*/
+{
+ // do nothing.
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CUnknown::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method provides the basic support for query interface on CUnknown.
+ If the interface requested is IUnknown it references the object and
+ returns an interface pointer. Otherwise it returns an error.
+
+ Arguments:
+
+ InterfaceId - the IID being requested
+
+ Object - a location to store the interface pointer to return.
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ if (IsEqualIID(InterfaceId, __uuidof(IUnknown)))
+ {
+ *Object = QueryIUnknown();
+ return S_OK;
+ }
+ else
+ {
+ *Object = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+IUnknown *
+CUnknown::QueryIUnknown(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This helper method references the object and returns a pointer to the
+ object's IUnknown interface.
+
+ This allows other methods to convert a CUnknown pointer into an IUnknown
+ pointer without a typecast and without calling QueryInterface and dealing
+ with the return value.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ A pointer to the object's IUnknown interface.
+
+--*/
+{
+ AddRef();
+ return static_cast<IUnknown *>(this);
+}
+
+ULONG
+STDMETHODCALLTYPE
+CUnknown::AddRef(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method adds one to the object's reference count.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ The new reference count. The caller should only use this for debugging
+ as the object's actual reference count can change while the caller
+ examines the return value.
+
+--*/
+{
+ return InterlockedIncrement(&m_ReferenceCount);
+}
+
+ULONG
+STDMETHODCALLTYPE
+CUnknown::Release(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method subtracts one to the object's reference count. If the count
+ goes to zero, this method deletes the object.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ The new reference count. If the caller uses this value it should only be
+ to check for zero (i.e. this call caused or will cause deletion) or
+ non-zero (i.e. some other call may have caused deletion, but this one
+ didn't).
+
+--*/
+{
+ ULONG count = InterlockedDecrement(&m_ReferenceCount);
+
+ if (count == 0)
+ {
+ delete this;
+ }
+ return count;
+}
+
+//
+// Implementation of CClassFactory methods.
+//
+
+//
+// Define storage for the factory's static lock count variable.
+//
+
+LONG CClassFactory::s_LockCount = 0;
+
+IClassFactory *
+CClassFactory::QueryIClassFactory(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This helper method references the object and returns a pointer to the
+ object's IClassFactory interface.
+
+ This allows other methods to convert a CClassFactory pointer into an
+ IClassFactory pointer without a typecast and without dealing with the
+ return value QueryInterface.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ A referenced pointer to the object's IClassFactory interface.
+
+--*/
+{
+ AddRef();
+ return static_cast<IClassFactory *>(this);
+}
+
+HRESULT
+CClassFactory::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method attempts to retrieve the requested interface from the object.
+
+ If the interface is found then the reference count on that interface (and
+ thus the object itself) is incremented.
+
+ Arguments:
+
+ InterfaceId - the interface the caller is requesting.
+
+ Object - a location to store the interface pointer.
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ //
+ // This class only supports IClassFactory so check for that.
+ //
+
+ if (IsEqualIID(InterfaceId, __uuidof(IClassFactory)))
+ {
+ *Object = QueryIClassFactory();
+ return S_OK;
+ }
+ else
+ {
+ //
+ // See if the base class supports the interface.
+ //
+
+ return CUnknown::QueryInterface(InterfaceId, Object);
+ }
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CClassFactory::CreateInstance(
+ _In_opt_ IUnknown * /* OuterObject */,
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This COM method is the factory routine - it creates instances of the driver
+ callback class and returns the specified interface on them.
+
+ Arguments:
+
+ OuterObject - only used for aggregation, which our driver callback class
+ does not support.
+
+ InterfaceId - the interface ID the caller would like to get from our
+ new object.
+
+ Object - a location to store the referenced interface pointer to the new
+ object.
+
+ Return Value:
+
+ Status.
+
+--*/
+{
+ HRESULT hr;
+
+ PCMyDriver driver;
+
+ *Object = NULL;
+
+ hr = CMyDriver::CreateInstance(&driver);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = driver->QueryInterface(InterfaceId, Object);
+ driver->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CClassFactory::LockServer(
+ _In_ BOOL Lock
+ )
+/*++
+
+ Routine Description:
+
+ This COM method can be used to keep the DLL in memory. However since the
+ driver's DllCanUnloadNow function always returns false, this has little
+ effect. Still it tracks the number of lock and unlock operations.
+
+ Arguments:
+
+ Lock - Whether the caller wants to lock or unlock the "server"
+
+ Return Value:
+
+ S_OK
+
+--*/
+{
+ if (Lock)
+ {
+ InterlockedIncrement(&s_LockCount);
+ }
+ else
+ {
+ InterlockedDecrement(&s_LockCount);
+ }
+ return S_OK;
+}
+
diff --git a/usb/umdf_filter_umdf/umdf_driver/comsup.h b/usb/umdf_filter_umdf/umdf_driver/comsup.h
new file mode 100644
index 00000000..dedf78c8
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/comsup.h
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ComSup.h
+
+Abstract:
+
+ This module contains classes and functions use for providing COM support
+ code.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Forward type declarations. They are here rather than in internal.h as
+// you only need them if you choose to use these support classes.
+//
+
+typedef class CUnknown *PCUnknown;
+typedef class CClassFactory *PCClassFactory;
+
+//
+// Base class to implement IUnknown. You can choose to derive your COM
+// classes from this class, or simply implement IUnknown in each of your
+// classes.
+//
+
+class CUnknown : public IUnknown
+{
+
+//
+// Private data members and methods. These are only accessible by the methods
+// of this class.
+//
+private:
+
+ //
+ // The reference count for this object. Initialized to 1 in the
+ // constructor.
+ //
+
+ LONG m_ReferenceCount;
+
+//
+// Protected data members and methods. These are accessible by the subclasses
+// but not by other classes.
+//
+protected:
+
+ //
+ // The constructor and destructor are protected to ensure that only the
+ // subclasses of CUnknown can create and destroy instances.
+ //
+
+ CUnknown(
+ VOID
+ );
+
+ //
+ // The destructor MUST be virtual. Since any instance of a CUnknown
+ // derived class should only be deleted from within CUnknown::Release,
+ // the destructor MUST be virtual or only CUnknown::~CUnknown will get
+ // invoked on deletion.
+ //
+ // If you see that your CMyDevice specific destructor is never being
+ // called, make sure you haven't deleted the virtual destructor here.
+ //
+
+ virtual
+ ~CUnknown(
+ VOID
+ )
+ {
+ // Do nothing
+ }
+
+//
+// Public Methods. These are accessible by any class.
+//
+public:
+
+ IUnknown *
+ QueryIUnknown(
+ VOID
+ );
+
+//
+// COM Methods.
+//
+public:
+
+ //
+ // IUnknown methods
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ );
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+};
+
+//
+// Class factory support class. Create an instance of this from your
+// DllGetClassObject method and modify the implementation to create
+// an instance of your driver event handler class.
+//
+
+class CClassFactory : public CUnknown, public IClassFactory
+{
+//
+// Private data members and methods. These are only accessible by the methods
+// of this class.
+//
+private:
+
+ //
+ // The lock count. This is shared across all instances of IClassFactory
+ // and can be queried through the public IsLocked method.
+ //
+
+ static LONG s_LockCount;
+
+//
+// Public Methods. These are accessible by any class.
+//
+public:
+
+ IClassFactory *
+ QueryIClassFactory(
+ VOID
+ );
+
+//
+// COM Methods.
+//
+public:
+
+ //
+ // IUnknown methods
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+
+ //
+ // IClassFactory methods.
+ //
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ CreateInstance(
+ _In_opt_ IUnknown *OuterObject,
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ LockServer(
+ _In_ BOOL Lock
+ );
+};
diff --git a/usb/umdf_filter_umdf/umdf_driver/dllsup.cpp b/usb/umdf_filter_umdf/umdf_driver/dllsup.cpp
new file mode 100644
index 00000000..22dfb3b0
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/dllsup.cpp
@@ -0,0 +1,202 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ dllsup.cpp
+
+Abstract:
+
+ This module contains the implementation of the UMDF OSR Fx2
+ Driver's entry point and its exported functions for providing COM support.
+
+ This module can be copied without modification to a new UMDF driver. It
+ depends on some of the code in comsup.cpp & comsup.h to handle DLL
+ registration and creating the first class factory.
+
+ This module is dependent on the following defines:
+
+ MYDRIVER_TRACING_ID - A wide string passed to WPP when initializing
+ tracing. For example the driver uses
+ L"Microsoft\\UMDF\\OsrUsb"
+
+ MYDRIVER_CLASS_ID - A GUID encoded in struct format used to
+ initialize the driver's ClassID.
+
+ These are defined in internal.h for this sample. If you choose
+ to use a different primary include file, you should ensure they are
+ defined there as well.
+
+Environment:
+
+ WDF User-Mode Driver Framework (WDF:UMDF)
+
+--*/
+
+#include "internal.h"
+#include "dllsup.tmh"
+
+const GUID CLSID_MyDriverCoClass = MYDRIVER_CLASS_ID;
+
+BOOL
+WINAPI
+DllMain(
+ HINSTANCE ModuleHandle,
+ DWORD Reason,
+ PVOID /* Reserved */
+ )
+/*++
+
+ Routine Description:
+
+ This is the entry point and exit point for the I/O trace driver. This
+ does very little as the I/O trace driver has minimal global data.
+
+ This method initializes tracing, and saves the module handle away in a
+ global variable so that it can be referenced should the COM registration
+ code (Dll[Un]RegisterServer) be called.
+
+ Arguments:
+
+ ModuleHandle - the DLL handle for this module.
+
+ Reason - the reason this entry point was called.
+
+ Reserved - unused
+
+ Return Value:
+
+ TRUE
+
+--*/
+{
+ UNREFERENCED_PARAMETER(ModuleHandle);
+
+ if (DLL_PROCESS_ATTACH == Reason)
+ {
+ //
+ // Initialize tracing.
+ //
+
+ WPP_INIT_TRACING(MYDRIVER_TRACING_ID);
+ }
+ else if (DLL_PROCESS_DETACH == Reason)
+ {
+ //
+ // Cleanup tracing.
+ //
+
+ WPP_CLEANUP();
+ }
+
+ return TRUE;
+}
+
+HRESULT
+STDAPICALLTYPE
+DllCanUnloadNow(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ Called by the COM runtime when determining whether or not this module
+ can be unloaded. Our answer is always "no".
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ S_FALSE
+
+--*/
+{
+ return S_FALSE;
+}
+
+HRESULT
+STDAPICALLTYPE
+DllGetClassObject(
+ _In_ REFCLSID ClassId,
+ _In_ REFIID InterfaceId,
+ _Outptr_ LPVOID *Interface
+ )
+/*++
+
+ Routine Description:
+
+ This routine is called by COM in order to instantiate the
+ OSR Fx2 driver callback object and do an initial query interface on it.
+
+ This method only creates an instance of the driver's class factory, as this
+ is the minimum required to support UMDF.
+
+ Arguments:
+
+ ClassId - the CLSID of the object being "gotten"
+
+ InterfaceId - the interface the caller wants from that object.
+
+ Interface - a location to store the referenced interface pointer
+
+ Return Value:
+
+ S_OK if the function succeeds or error indicating the cause of the
+ failure.
+
+--*/
+{
+ PCClassFactory factory;
+
+ HRESULT hr = S_OK;
+
+ *Interface = NULL;
+
+ //
+ // If the CLSID doesn't match that of our "coclass" (defined in the IDL
+ // file) then we can't create the object the caller wants. This may
+ // indicate that the COM registration is incorrect, and another CLSID
+ // is referencing this drvier.
+ //
+
+ if (IsEqualCLSID(ClassId, CLSID_MyDriverCoClass) == false)
+ {
+ Trace(
+ TRACE_LEVEL_ERROR,
+ L"ERROR: Called to create instance of unrecognized class (%!GUID!)",
+ &ClassId
+ );
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+ }
+
+ //
+ // Create an instance of the class factory for the caller.
+ //
+
+ factory = new CClassFactory();
+
+ if (NULL == factory)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // Query the object we created for the interface the caller wants. After
+ // that we release the object. This will drive the reference count to
+ // 1 (if the QI succeeded an referenced the object) or 0 (if the QI failed).
+ // In the later case the object is automatically deleted.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = factory->QueryInterface(InterfaceId, Interface);
+ factory->Release();
+ }
+
+ return hr;
+}
diff --git a/usb/umdf_filter_umdf/umdf_driver/exports.def b/usb/umdf_filter_umdf/umdf_driver/exports.def
new file mode 100644
index 00000000..15f923d3
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/exports.def
@@ -0,0 +1,4 @@
+; WudfOsrUsbDriver.def : Declares the module parameters.
+
+EXPORTS
+ DllGetClassObject PRIVATE
diff --git a/usb/umdf_filter_umdf/umdf_driver/internal.h b/usb/umdf_filter_umdf/umdf_driver/internal.h
new file mode 100644
index 00000000..2d57793d
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/internal.h
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Internal.h
+
+Abstract:
+
+ This module contains the local type definitions for the UMDF OSR Fx2
+ driver sample.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+//
+// Include the WUDF Headers
+//
+
+#include "wudfddi.h"
+
+//
+// Include SetupDi functions.
+//
+
+#include "setupapi.h"
+
+//
+// Use specstrings for in/out annotation of function parameters.
+//
+
+#include "specstrings.h"
+
+//
+// Include the safestring functions.
+//
+
+#include "strsafe.h"
+
+//
+// Get limits on common data types (ULONG_MAX for example)
+//
+
+#include "limits.h"
+
+//
+// We need usb I/O targets to talk to the OSR device.
+//
+
+#include "wudfusb.h"
+
+//
+// Include the header shared between the drivers and the test applications.
+//
+
+#include "public.h"
+
+//
+// Include the header shared between the drivers and the test applications.
+//
+
+#include "WUDFOsrUsbPublic.h"
+
+//
+// Forward definitions of classes in the other header files.
+//
+
+typedef class CMyDriver *PCMyDriver;
+typedef class CMyDevice *PCMyDevice;
+typedef class CMyQueue *PCMyQueue;
+
+typedef class CMyControlQueue *PCMyControlQueue;
+typedef class CMyReadWriteQueue *PCMyReadWriteQueue;
+
+typedef class CCancelCallback *PCCancelCallback;
+
+//
+// Define the tracing flags.
+//
+// TODO: Choose a different trace control GUID
+//
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ WudfOsrUsbFx2TraceGuid, (da5fbdfd,1eae,4ecf,b426,a3818f325ddb), \
+ \
+ WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
+ WPP_DEFINE_BIT(TEST_TRACE_DRIVER) \
+ WPP_DEFINE_BIT(TEST_TRACE_DEVICE) \
+ WPP_DEFINE_BIT(TEST_TRACE_QUEUE) \
+ )
+
+#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
+ WPP_LEVEL_LOGGER(flag)
+
+#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
+ (WPP_LEVEL_ENABLED(flag) && \
+ WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
+
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
+ WPP_LEVEL_LOGGER(flags)
+
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
+ (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
+
+//
+// This comment block is scanned by the trace preprocessor to define our
+// Trace function.
+//
+// begin_wpp config
+// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
+// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
+// end_wpp
+//
+
+//
+// Driver specific #defines
+//
+// TODO: Change these values to be appropriate for your driver.
+//
+
+#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF\\OsrUsb"
+#define MYDRIVER_CLASS_ID {0x0865b2b0, 0x6b73, 0x428f, {0xa3, 0xea, 0x21, 0x72, 0x83, 0x2d, 0x6b, 0xfc}}
+
+//
+// Include the type specific headers.
+//
+
+#include "comsup.h"
+#include "driver.h"
+#include "device.h"
+#include "queue.h"
+#include "ControlQueue.h"
+#include "ReadWriteQueue.h"
+#include "list.h"
+
+__forceinline
+#ifdef _PREFAST_
+__declspec(noreturn)
+#endif
+VOID
+WdfTestNoReturn(
+ VOID
+ )
+{
+ // do nothing.
+}
+
+#define WUDF_TEST_DRIVER_ASSERT(p) \
+{ \
+ if ( !(p) ) \
+ { \
+ DebugBreak(); \
+ WdfTestNoReturn(); \
+ } \
+}
+
+#define SAFE_RELEASE(p) {if ((p)) { (p)->Release(); (p) = NULL; }}
+
+#define IDLE_TIMEOUT_IN_MSEC 10*1000
diff --git a/usb/umdf_filter_umdf/umdf_driver/queue.cpp b/usb/umdf_filter_umdf/umdf_driver/queue.cpp
new file mode 100644
index 00000000..c56b38bb
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/queue.cpp
@@ -0,0 +1,147 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ queue.cpp
+
+Abstract:
+
+ This file implements the I/O queue interface and performs
+ the read/write/ioctl operations.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "queue.tmh"
+
+CMyQueue::CMyQueue(
+ _In_ PCMyDevice Device
+ ) :
+ m_FxQueue(NULL),
+ m_Device(Device)
+{
+}
+
+//
+// Queue destructor.
+// Free up the buffer, wait for thread to terminate and
+//
+
+CMyQueue::~CMyQueue(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+
+ IUnknown implementation of Release
+
+Aruments:
+
+
+Return Value:
+
+ ULONG (reference count after Release)
+
+--*/
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC! Entry"
+ );
+
+}
+
+
+HRESULT
+STDMETHODCALLTYPE
+CMyQueue::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+Routine Description:
+
+
+ Query Interface
+
+Aruments:
+
+ Follows COM specifications
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ HRESULT hr;
+
+ hr = CUnknown::QueryInterface(InterfaceId, Object);
+
+ return hr;
+}
+
+//
+// Initialize
+//
+
+HRESULT
+CMyQueue::Initialize(
+ _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType,
+ _In_ bool Default,
+ _In_ bool PowerManaged
+ )
+{
+ IWDFIoQueue *fxQueue;
+ HRESULT hr;
+
+ //
+ // Create the I/O Queue object.
+ //
+
+ {
+ IUnknown *callback = QueryIUnknown();
+
+ hr = m_Device->GetFxDevice()->CreateIoQueue(
+ callback,
+ Default,
+ DispatchType,
+ PowerManaged,
+ FALSE,
+ &fxQueue
+ );
+ callback->Release();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ m_FxQueue = fxQueue;
+
+ //
+ // Release the creation reference on the queue. This object will be
+ // destroyed before the queue so we don't need to have a reference out
+ // on it.
+ //
+
+ fxQueue->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyQueue::Configure(
+ VOID
+ )
+{
+ return S_OK;
+}
diff --git a/usb/umdf_filter_umdf/umdf_driver/queue.h b/usb/umdf_filter_umdf/umdf_driver/queue.h
new file mode 100644
index 00000000..5659224b
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_driver/queue.h
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ queue.h
+
+Abstract:
+
+ This file defines the queue callback interface.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Queue Callback Object.
+//
+
+class CMyQueue :
+ public CUnknown
+{
+protected:
+ //
+ // Unreferenced pointer to the partner Fx device.
+ //
+
+ IWDFIoQueue *m_FxQueue;
+
+ //
+ // Unreferenced pointer to the parent device.
+ //
+
+ PCMyDevice m_Device;
+
+ HRESULT
+ Initialize(
+ _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType,
+ _In_ bool Default,
+ _In_ bool PowerManaged
+ );
+
+protected:
+
+ CMyQueue(
+ _In_ PCMyDevice Device
+ );
+
+ virtual ~CMyQueue();
+
+ HRESULT
+ Configure(
+ VOID
+ );
+
+public:
+
+ IWDFIoQueue *
+ GetFxQueue(
+ VOID
+ )
+ {
+ return m_FxQueue;
+ }
+
+
+ PCMyDevice
+ GetDevice(
+ VOID
+ )
+ {
+ return m_Device;
+ }
+
+ //
+ // IUnknown
+ //
+
+ STDMETHOD_(ULONG,AddRef) (VOID) {return CUnknown::AddRef();}
+
+ _At_(this, __drv_freesMem(object))
+ STDMETHOD_(ULONG,Release) (VOID) {return CUnknown::Release();}
+
+ STDMETHOD_(HRESULT, QueryInterface)(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+};
diff --git a/usb/umdf_filter_umdf/umdf_filter/OsrUsbFilter.rc b/usb/umdf_filter_umdf/umdf_filter/OsrUsbFilter.rc
new file mode 100644
index 00000000..cec032d9
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/OsrUsbFilter.rc
@@ -0,0 +1,17 @@
+//---------------------------------------------------------------------------
+// OsrUsbFilter.rc
+//
+// Copyright (c) Microsoft Corporation, All Rights Reserved
+//---------------------------------------------------------------------------
+
+
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "WDF:UMDF OsrUsbFilter User-Mode Driver Sample"
+#define VER_INTERNALNAME_STR "OsrUsbFilter"
+#define VER_ORIGINALFILENAME_STR "OsrUsbFilter.dll"
+
+#include "common.ver"
diff --git a/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilter.vcxproj b/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilter.vcxproj
new file mode 100644
index 00000000..4968db88
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilter.vcxproj
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E62A4AAA-870E-4D58-AA10-D9604A2E52E8}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <UMDF_VERSION_MAJOR>1</UMDF_VERSION_MAJOR>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <SupportsPackaging>false</SupportsPackaging>
+ <RequiresPackageProject>true</RequiresPackageProject>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{A09CF05A-0501-47A9-98B5-48C0A9487ECA}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <ClCompile Include="dllsup.cpp; comsup.cpp; driver.cpp; device.cpp; queue.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppDllMacro>true</WppDllMacro>
+ <WppScanConfigurationData>internal.h</WppScanConfigurationData>
+ </ClCompile>
+ <Inf Include="WUDFOsrUsbFilterOnUmFx2Driver.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\WUDFOsrUsbFilterOnUmFx2Driver.Inf</CopyOutput>
+ </Inf>
+ <OtherWpp Include="OsrUsbFilter.rc">
+ <WppEnabled>true</WppEnabled>
+ <WppDllMacro>true</WppDllMacro>
+ <WppScanConfigurationData>internal.h</WppScanConfigurationData>
+ </OtherWpp>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>WUDFOsrUsbFilter</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>WUDFOsrUsbFilter</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>WUDFOsrUsbFilter</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>WUDFOsrUsbFilter</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ResourceCompile Include="OsrUsbFilter.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilter.vcxproj.Filters b/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilter.vcxproj.Filters
new file mode 100644
index 00000000..f92d33fa
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilter.vcxproj.Filters
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{AFBD23B1-572F-4E48-B155-B32902A4661E}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{A72AB5BE-0993-4901-8D44-E3AC062578E8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{3D0316D0-D4C5-4718-8634-6072A187C604}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{10BE8A0E-56B7-4329-8582-2BB1E16F94E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="comsup.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="device.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllsup.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="queue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <None Include="exports.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="WUDFOsrUsbFilterOnUmFx2Driver.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="OsrUsbFilter.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilterOnUmFx2Driver.inx b/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilterOnUmFx2Driver.inx
new file mode 100644
index 00000000..fd920e03
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/WUDFOsrUsbFilterOnUmFx2Driver.inx
@@ -0,0 +1,114 @@
+;
+; WUDFOsrUsbFilterOnUmDriver.inf - Install a UM Filter driver on the OSR
+ USB Device.
+;
+
+[Version]
+Signature="$Windows NT$"
+Class=Sample
+ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}
+Provider=%MSFTUMDF%
+DriverVer=03/25/2005,0.0.0.1
+CatalogFile=wudf.cat
+
+[Manufacturer]
+%MSFTUMDF%=Microsoft,NT$ARCH$
+
+[Microsoft.NT$ARCH$]
+%OsrUsbDeviceName%=OsrUsb_Install, USB\Vid_045e&Pid_94aa&mi_00
+%OsrUsbDeviceName%=OsrUsb_Install, USB\VID_0547&PID_1002
+
+[ClassInstall32]
+AddReg=SampleClass_RegistryAdd
+
+[SampleClass_RegistryAdd]
+HKR,,,,%ClassName%
+HKR,,Icon,,"-10"
+
+[SourceDisksFiles]
+WudfOsrUsbFilter.dll=1
+WudfOsrUsbFx2.dll=1
+WudfUpdate_$UMDFCOINSTALLERVERSION$.dll=1
+
+[SourceDisksNames]
+1 = %MediaDescription%
+
+; =================== UMDF OSR Filter Driver ==================================
+
+[OsrUsb_Install.NT]
+CopyFiles=UMDriverCopy
+Include=WINUSB.INF ; Import sections from WINUSB.INF
+Needs=WINUSB.NT ; Run the CopyFiles & AddReg directives for WinUsb.INF
+
+[OsrUsb_Install.NT.hw]
+AddReg=OsrUsb_AddReg
+
+[OsrUsb_Install.NT.Services]
+AddService=WUDFRd,0x000001fa,WUDFRD_ServiceInstall ; flag 0x2 sets this as the service for the device
+AddService=WinUsb,0x000001f8,WinUsb_ServiceInstall ; this service is installed because its a filter.
+
+[OsrUsb_Install.NT.Wdf]
+KmdfService=WINUSB, WinUsb_Install
+UmdfService=WudfOsrUsbFx2, WudfOsrUsbFx2_Install
+UmdfService=WudfOsrUsbFilter, WudfOsrUsbFilter_Install
+UmdfServiceOrder=WudfOsrUsbFx2, WUDFOsrUsbFilter
+UmdfDispatcher=WinUsb
+
+[OsrUsb_Install.NT.CoInstallers]
+AddReg = CoInstallers_AddReg
+CopyFiles = CoInstallers_CopyFiles
+
+[WinUsb_Install]
+KmdfLibraryVersion=$KMDFVERSION$
+
+[WudfOsrUsbFilter_Install]
+UmdfLibraryVersion=$UMDFVERSION$
+DriverCLSID = "{422d8dbc-520d-4d7e-8f53-920e5c867e6c}"
+ServiceBinary = "%12%\UMDF\WUDFOsrUsbFilter.dll"
+
+[WudfOsrUsbFx2_Install]
+UmdfLibraryVersion=$UMDFVERSION$
+DriverCLSID = "{0865b2b0-6b73-428f-a3ea-2172832d6bfc}"
+ServiceBinary = "%12%\UMDF\WUDFOsrUsbFx2.dll"
+
+[OsrUsb_AddReg]
+HKR,,"LowerFilters",0x00010008,"WinUsb" ; FLG_ADDREG_TYPE_MULTI_SZ | FLG_ADDREG_APPEND
+HKR,,"WinUsbPowerPolicyOwnershipDisabled",0x00010001,1 ; our driver takes ownership of power policy. Tell WINUSB not to
+
+[WUDFRD_ServiceInstall]
+DisplayName = %WudfRdDisplayName%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\WUDFRd.sys
+
+[WinUsb_ServiceInstall]
+DisplayName = %WinUsb_SvcDesc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\WinUSB.sys
+
+[CoInstallers_AddReg]
+HKR,,CoInstallers32,0x00010000,"WudfUpdate_$UMDFCOINSTALLERVERSION$.dll"
+
+[CoInstallers_CopyFiles]
+WudfUpdate_$UMDFCOINSTALLERVERSION$.dll
+
+[DestinationDirs]
+CoInstallers_CopyFiles=11 ; copy to system32
+UMDriverCopy=12,UMDF ; copy to drivers\umdf
+
+[UMDriverCopy]
+WudfOsrUsbFilter.dll
+WudfOsrUsbFx2.dll
+
+; =================== Generic ==================================
+
+[Strings]
+MSFTUMDF="Microsoft Internal (WDF:UMDF)"
+MediaDescription="Microsoft UMDF OSR USB Sample Device Installation Media"
+ClassName="Sample Device"
+OsrUsbDeviceName="Microsoft UMDF OSR Usb Sample Device With Filter on User-mode Driver"
+WinUsb_SvcDesc="WinUSB Driver"
+WudfRdDisplayName="Windows Driver Foundation - User-mode Driver Framework Reflector"
diff --git a/usb/umdf_filter_umdf/umdf_filter/comsup.cpp b/usb/umdf_filter_umdf/umdf_filter/comsup.cpp
new file mode 100644
index 00000000..31257f31
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/comsup.cpp
@@ -0,0 +1,351 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ComSup.cpp
+
+Abstract:
+
+ This module contains implementations for the functions and methods
+ used for providing COM support.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+
+#include "comsup.tmh"
+
+//
+// This is the number of characters in a GUID string including the trailing
+// NULL.
+//
+
+#define GUID_STRING_CCH (sizeof("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"))
+
+//
+// Implementation of CUnknown methods.
+//
+
+CUnknown::CUnknown(
+ VOID
+ ) : m_ReferenceCount(1)
+/*++
+
+ Routine Description:
+
+ Constructor for an instance of the CUnknown class. This simply initializes
+ the reference count of the object to 1. The caller is expected to
+ call Release() if it wants to delete the object once it has been allocated.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None
+
+--*/
+{
+ // do nothing.
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CUnknown::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method provides the basic support for query interface on CUnknown.
+ If the interface requested is IUnknown it references the object and
+ returns an interface pointer. Otherwise it returns an error.
+
+ Arguments:
+
+ InterfaceId - the IID being requested
+
+ Object - a location to store the interface pointer to return.
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ if (IsEqualIID(InterfaceId, __uuidof(IUnknown)))
+ {
+ *Object = QueryIUnknown();
+ return S_OK;
+ }
+ else
+ {
+ *Object = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+IUnknown *
+CUnknown::QueryIUnknown(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This helper method references the object and returns a pointer to the
+ object's IUnknown interface.
+
+ This allows other methods to convert a CUnknown pointer into an IUnknown
+ pointer without a typecast and without calling QueryInterface and dealing
+ with the return value.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ A pointer to the object's IUnknown interface.
+
+--*/
+{
+ AddRef();
+ return static_cast<IUnknown *>(this);
+}
+
+ULONG
+STDMETHODCALLTYPE
+CUnknown::AddRef(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method adds one to the object's reference count.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ The new reference count. The caller should only use this for debugging
+ as the object's actual reference count can change while the caller
+ examines the return value.
+
+--*/
+{
+ return InterlockedIncrement(&m_ReferenceCount);
+}
+
+ULONG
+STDMETHODCALLTYPE
+CUnknown::Release(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method subtracts one to the object's reference count. If the count
+ goes to zero, this method deletes the object.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ The new reference count. If the caller uses this value it should only be
+ to check for zero (i.e. this call caused or will cause deletion) or
+ non-zero (i.e. some other call may have caused deletion, but this one
+ didn't).
+
+--*/
+{
+ ULONG count = InterlockedDecrement(&m_ReferenceCount);
+
+ if (count == 0)
+ {
+ delete this;
+ }
+ return count;
+}
+
+//
+// Implementation of CClassFactory methods.
+//
+
+//
+// Define storage for the factory's static lock count variable.
+//
+
+LONG CClassFactory::s_LockCount = 0;
+
+IClassFactory *
+CClassFactory::QueryIClassFactory(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This helper method references the object and returns a pointer to the
+ object's IClassFactory interface.
+
+ This allows other methods to convert a CClassFactory pointer into an
+ IClassFactory pointer without a typecast and without dealing with the
+ return value QueryInterface.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ A referenced pointer to the object's IClassFactory interface.
+
+--*/
+{
+ AddRef();
+ return static_cast<IClassFactory *>(this);
+}
+
+HRESULT
+CClassFactory::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method attempts to retrieve the requested interface from the object.
+
+ If the interface is found then the reference count on that interface (and
+ thus the object itself) is incremented.
+
+ Arguments:
+
+ InterfaceId - the interface the caller is requesting.
+
+ Object - a location to store the interface pointer.
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ //
+ // This class only supports IClassFactory so check for that.
+ //
+
+ if (IsEqualIID(InterfaceId, __uuidof(IClassFactory)))
+ {
+ *Object = QueryIClassFactory();
+ return S_OK;
+ }
+ else
+ {
+ //
+ // See if the base class supports the interface.
+ //
+
+ return CUnknown::QueryInterface(InterfaceId, Object);
+ }
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CClassFactory::CreateInstance(
+ _In_opt_ IUnknown * /* OuterObject */,
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This COM method is the factory routine - it creates instances of the driver
+ callback class and returns the specified interface on them.
+
+ Arguments:
+
+ OuterObject - only used for aggregation, which our driver callback class
+ does not support.
+
+ InterfaceId - the interface ID the caller would like to get from our
+ new object.
+
+ Object - a location to store the referenced interface pointer to the new
+ object.
+
+ Return Value:
+
+ Status.
+
+--*/
+{
+ HRESULT hr;
+
+ PCMyDriver driver;
+
+ *Object = NULL;
+
+ hr = CMyDriver::CreateInstance(&driver);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = driver->QueryInterface(InterfaceId, Object);
+ driver->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CClassFactory::LockServer(
+ _In_ BOOL Lock
+ )
+/*++
+
+ Routine Description:
+
+ This COM method can be used to keep the DLL in memory. However since the
+ driver's DllCanUnloadNow function always returns false, this has little
+ effect. Still it tracks the number of lock and unlock operations.
+
+ Arguments:
+
+ Lock - Whether the caller wants to lock or unlock the "server"
+
+ Return Value:
+
+ S_OK
+
+--*/
+{
+ if (Lock)
+ {
+ InterlockedIncrement(&s_LockCount);
+ }
+ else
+ {
+ InterlockedDecrement(&s_LockCount);
+ }
+ return S_OK;
+}
+
diff --git a/usb/umdf_filter_umdf/umdf_filter/comsup.h b/usb/umdf_filter_umdf/umdf_filter/comsup.h
new file mode 100644
index 00000000..b96fd982
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/comsup.h
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ComSup.h
+
+Abstract:
+
+ This module contains classes and functions use for providing COM support
+ code.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Forward type declarations. They are here rather than in internal.h as
+// you only need them if you choose to use these support classes.
+//
+
+typedef class CUnknown *PCUnknown;
+typedef class CClassFactory *PCClassFactory;
+
+//
+// Base class to implement IUnknown. You can choose to derive your COM
+// classes from this class, or simply implement IUnknown in each of your
+// classes.
+//
+
+class CUnknown : public IUnknown
+{
+
+//
+// Private data members and methods. These are only accessible by the methods
+// of this class.
+//
+private:
+
+ //
+ // The reference count for this object. Initialized to 1 in the
+ // constructor.
+ //
+
+ LONG m_ReferenceCount;
+
+//
+// Protected data members and methods. These are accessible by the subclasses
+// but not by other classes.
+//
+protected:
+
+ //
+ // The constructor and destructor are protected to ensure that only the
+ // subclasses of CUnknown can create and destroy instances.
+ //
+
+ CUnknown(
+ VOID
+ );
+
+ //
+ // The destructor MUST be virtual. Since any instance of a CUnknown
+ // derived class should only be deleted from within CUnknown::Release,
+ // the destructor MUST be virtual or only CUnknown::~CUnknown will get
+ // invoked on deletion.
+ //
+ // If you see that your CMyDevice specific destructor is never being
+ // called, make sure you haven't deleted the virtual destructor here.
+ //
+
+ virtual
+ ~CUnknown(
+ VOID
+ )
+ {
+ // Do nothing
+ }
+
+//
+// Public Methods. These are accessible by any class.
+//
+public:
+
+ IUnknown *
+ QueryIUnknown(
+ VOID
+ );
+
+//
+// COM Methods.
+//
+public:
+
+ //
+ // IUnknown methods
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ );
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+};
+
+//
+// Class factory support class. Create an instance of this from your
+// DllGetClassObject method and modify the implementation to create
+// an instance of your driver event handler class.
+//
+
+class CClassFactory : public CUnknown, public IClassFactory
+{
+//
+// Private data members and methods. These are only accessible by the methods
+// of this class.
+//
+private:
+
+ //
+ // The lock count. This is shared across all instances of IClassFactory
+ // and can be queried through the public IsLocked method.
+ //
+
+ static LONG s_LockCount;
+
+//
+// Public Methods. These are accessible by any class.
+//
+public:
+
+ IClassFactory *
+ QueryIClassFactory(
+ VOID
+ );
+
+//
+// COM Methods.
+//
+public:
+
+ //
+ // IUnknown methods
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+
+ //
+ // IClassFactory methods.
+ //
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ CreateInstance(
+ _In_opt_ IUnknown *OuterObject,
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ LockServer(
+ _In_ BOOL Lock
+ );
+};
diff --git a/usb/umdf_filter_umdf/umdf_filter/device.cpp b/usb/umdf_filter_umdf/umdf_filter/device.cpp
new file mode 100644
index 00000000..126637ce
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/device.cpp
@@ -0,0 +1,243 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ Device.cpp
+
+Abstract:
+
+ This module contains the implementation of the UMDF OSR USB Sample Filter driver's
+ device callback object.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "device.tmh"
+
+HRESULT
+CMyDevice::CreateInstance(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize * FxDeviceInit,
+ _Out_ PCMyDevice *Device
+ )
+/*++
+
+ Routine Description:
+
+ This method creates and initializs an instance of the OSR USB Sample Filter driver's
+ device callback object.
+
+ Arguments:
+
+ FxDeviceInit - the settings for the device.
+
+ Device - a location to store the referenced pointer to the device object.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ PCMyDevice device;
+ HRESULT hr;
+
+ //
+ // Allocate a new instance of the device class.
+ //
+
+ device = new CMyDevice();
+
+ if (NULL == device)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ //
+ // Initialize the instance.
+ //
+
+ hr = device->Initialize(FxDriver, FxDeviceInit);
+
+ if (SUCCEEDED(hr))
+ {
+ *Device = device;
+ }
+ else
+ {
+ device->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::Initialize(
+ _In_ IWDFDriver * FxDriver,
+ _In_ IWDFDeviceInitialize * FxDeviceInit
+ )
+/*++
+
+ Routine Description:
+
+ This method initializes the device callback object and creates the
+ partner device object.
+
+ The method should perform any device-specific configuration that:
+ * could fail (these can't be done in the constructor)
+ * must be done before the partner object is created -or-
+ * can be done after the partner object is created and which aren't
+ influenced by any device-level parameters the parent (the driver
+ in this case) might set.
+
+ Arguments:
+
+ FxDeviceInit - the settings for this device.
+
+ Return Value:
+
+ status.
+
+--*/
+{
+ IWDFDevice *fxDevice;
+ HRESULT hr;
+
+ //
+ // Configure things like the locking model before we go to create our
+ // partner device.
+ //
+
+ //
+ // We don't need device level locking since we do not keep any state
+ // across the requests
+ //
+
+ FxDeviceInit->SetLockingConstraint(None);
+
+ //
+ // Mark ourselves as a filter
+ //
+
+ FxDeviceInit->SetFilter();
+
+
+ //
+ // We are a filter; we don't want to be the power policy owner
+ //
+
+ FxDeviceInit->SetPowerPolicyOwnership(FALSE);
+
+ //
+ // QueryIUnknown references the IUnknown interface that it returns
+ // (which is the same as referencing the device). We pass that to
+ // CreateDevice, which takes its own reference if everything works.
+ //
+
+ {
+ IUnknown *unknown = this->QueryIUnknown();
+
+ hr = FxDriver->CreateDevice(FxDeviceInit, unknown, &fxDevice);
+
+ unknown->Release();
+ }
+
+ //
+ // If that succeeded then set our FxDevice member variable.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ m_FxDevice = fxDevice;
+
+ //
+ // Drop the reference we got from CreateDevice. Since this object
+ // is partnered with the framework object they have the same
+ // lifespan - there is no need for an additional reference.
+ //
+
+ fxDevice->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::Configure(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method is called after the device callback object has been initialized
+ and returned to the driver. It would setup the device's queues and their
+ corresponding callback objects.
+
+ Arguments:
+
+ FxDevice - the framework device object for which we're handling events.
+
+ Return Value:
+
+ status
+
+--*/
+{
+ PCMyQueue defaultQueue;
+
+ HRESULT hr;
+
+ hr = CMyQueue::CreateInstance(m_FxDevice, &defaultQueue);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = defaultQueue->Configure();
+
+ defaultQueue->Release();
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method is called to get a pointer to one of the object's callback
+ interfaces.
+
+ Since the OSR USB Sample Filter driver doesn't support any of the device events, this
+ method simply calls the base class's BaseQueryInterface.
+
+ If OSR USB Sample Filter is extended to include device event interfaces then this
+ method must be changed to check the IID and return pointers to them as
+ appropriate.
+
+ Arguments:
+
+ InterfaceId - the interface being requested
+
+ Object - a location to store the interface pointer if successful
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ return CUnknown::QueryInterface(InterfaceId, Object);
+}
diff --git a/usb/umdf_filter_umdf/umdf_filter/device.h b/usb/umdf_filter_umdf/umdf_filter/device.h
new file mode 100644
index 00000000..f7a50b1d
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/device.h
@@ -0,0 +1,114 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Device.h
+
+Abstract:
+
+ This module contains the type definitions for the UMDF OSR USB Sample Filter
+ driver's device callback class.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Class for the iotrace driver.
+//
+
+class CMyDevice : public CUnknown
+{
+
+//
+// Private data members.
+//
+private:
+
+ IWDFDevice *m_FxDevice;
+
+//
+// Private methods.
+//
+
+private:
+
+ CMyDevice(
+ VOID
+ )
+ {
+ m_FxDevice = NULL;
+ }
+
+ HRESULT
+ Initialize(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ );
+
+//
+// Public methods
+//
+public:
+
+ //
+ // The factory method used to create an instance of this driver.
+ //
+
+ static
+ HRESULT
+ CreateInstance(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit,
+ _Out_ PCMyDevice *Device
+ );
+
+ HRESULT
+ Configure(
+ VOID
+ );
+
+//
+// COM methods
+//
+public:
+
+ //
+ // IUnknown methods.
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+};
diff --git a/usb/umdf_filter_umdf/umdf_filter/dllsup.cpp b/usb/umdf_filter_umdf/umdf_filter/dllsup.cpp
new file mode 100644
index 00000000..10ef8a78
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/dllsup.cpp
@@ -0,0 +1,183 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ dllsup.cpp
+
+Abstract:
+
+ This module contains the implementation of the OSR USB Sample Filter
+ Driver's entry point and its exported functions for providing COM support.
+
+ This module can be copied without modification to a new UMDF driver. It
+ depends on some of the code in comsup.cpp & comsup.h to handle DLL
+ registration and creating the first class factory.
+
+ This module is dependent on the following defines:
+
+ MYDRIVER_TRACING_ID - A wide string passed to WPP when initializing
+ tracing. For example the skeleton uses
+ L"Microsoft\\UMDF\\Skeleton"
+
+ MYDRIVER_CLASS_ID - A GUID encoded in struct format used to
+ initialize the driver's ClassID.
+
+ These are defined in internal.h for the OSR USB Sample Filter sample. If
+ you choose to use a different primary include file, you should ensure
+ they are defined there as well.
+
+Environment:
+
+ WDF User-Mode Driver Framework (WDF:UMDF)
+
+--*/
+
+#include "internal.h"
+#include "dllsup.tmh"
+
+const GUID CLSID_MyDriverCoClass = MYDRIVER_CLASS_ID;
+
+//
+// Global variable to hold the module handle for this DLL. Initialized during
+// DllMain and never cleared. This is used when registering and unregistering
+// the driver's COM information.
+//
+
+HINSTANCE g_ModuleHandle = NULL;
+
+BOOL
+WINAPI
+DllMain(
+ HINSTANCE /* ModuleHandle */,
+ DWORD Reason,
+ PVOID /* Reserved */
+ )
+/*++
+
+ Routine Description:
+
+ This is the entry point and exit point for the I/O trace driver. This
+ does very little as the I/O trace driver has minimal global data.
+
+ This method initializes tracing.
+
+ Arguments:
+
+ ModuleHandle - the DLL handle for this module.
+
+ Reason - the reason this entry point was called.
+
+ Reserved - unused
+
+ Return Value:
+
+ TRUE
+
+--*/
+{
+
+ if (DLL_PROCESS_ATTACH == Reason)
+ {
+ //
+ // Initialize tracing.
+ //
+
+ WPP_INIT_TRACING(MYDRIVER_TRACING_ID);
+ }
+ else if (DLL_PROCESS_DETACH == Reason)
+ {
+ //
+ // Cleanup tracing.
+ //
+
+ WPP_CLEANUP();
+ }
+
+ return TRUE;
+}
+
+HRESULT
+STDAPICALLTYPE
+DllGetClassObject(
+ _In_ REFCLSID ClassId,
+ _In_ REFIID InterfaceId,
+ _Outptr_ LPVOID *Interface
+ )
+/*++
+
+ Routine Description:
+
+ This routine is called by COM in order to instantiate the OSR USB Sample
+ Filter driver callback object and do an initial query interface on it.
+
+ This method only creates an instance of the driver's class factory, as this
+ is the minimum required to support UMDF.
+
+ Arguments:
+
+ ClassId - the CLSID of the object being "gotten"
+
+ InterfaceId - the interface the caller wants from that object.
+
+ Interface - a location to store the referenced interface pointer
+
+ Return Value:
+
+ S_OK if the function succeeds or error indicating the cause of the
+ failure.
+
+--*/
+{
+ PCClassFactory factory;
+
+ HRESULT hr = S_OK;
+
+ *Interface = NULL;
+
+ //
+ // If the CLSID doesn't match that of our "coclass" (defined in the IDL
+ // file) then we can't create the object the caller wants. This may
+ // indicate that the COM registration is incorrect, and another CLSID
+ // is referencing this drvier.
+ //
+
+ if (IsEqualCLSID(ClassId, CLSID_MyDriverCoClass) == false)
+ {
+ Trace(
+ TRACE_LEVEL_ERROR,
+ L"ERROR: Called to create instance of unrecognized class (%!GUID!)",
+ &ClassId
+ );
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+ }
+
+ //
+ // Create an instance of the class factory for the caller.
+ //
+
+ factory = new CClassFactory();
+
+ if (NULL == factory)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // Query the object we created for the interface the caller wants. After
+ // that we release the object. This will drive the reference count to
+ // 1 (if the QI succeeded an referenced the object) or 0 (if the QI failed).
+ // In the later case the object is automatically deleted.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = factory->QueryInterface(InterfaceId, Interface);
+ factory->Release();
+ }
+
+ return hr;
+}
+
diff --git a/usb/umdf_filter_umdf/umdf_filter/driver.cpp b/usb/umdf_filter_umdf/umdf_filter/driver.cpp
new file mode 100644
index 00000000..c5910c05
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/driver.cpp
@@ -0,0 +1,207 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ Driver.cpp
+
+Abstract:
+
+ This module contains the implementation of the UMDF OSR USB Sample Filter
+ driver's core driver callback object.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "driver.tmh"
+
+HRESULT
+CMyDriver::CreateInstance(
+ _Out_ PCMyDriver *Driver
+ )
+/*++
+
+ Routine Description:
+
+ This static method is invoked in order to create and initialize a new
+ instance of the driver class. The caller should arrange for the object
+ to be released when it is no longer in use.
+
+ Arguments:
+
+ Driver - a location to store a referenced pointer to the new instance
+
+ Return Value:
+
+ S_OK if successful, or error otherwise.
+
+--*/
+{
+ PCMyDriver driver;
+ HRESULT hr;
+
+ //
+ // Allocate the callback object.
+ //
+
+ driver = new CMyDriver();
+
+ if (NULL == driver)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ //
+ // Initialize the callback object.
+ //
+
+ hr = driver->Initialize();
+
+ if (SUCCEEDED(hr))
+ {
+ //
+ // Store a pointer to the new, initialized object in the output
+ // parameter.
+ //
+
+ *Driver = driver;
+ }
+ else
+ {
+
+ //
+ // Release the reference on the driver object to get it to delete
+ // itself.
+ //
+
+ driver->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDriver::Initialize(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method is called to initialize a newly created driver callback object
+ before it is returned to the creator. Unlike the constructor, the
+ Initialize method contains operations which could potentially fail.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None
+
+--*/
+{
+ return S_OK;
+}
+
+HRESULT
+CMyDriver::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Interface
+ )
+/*++
+
+ Routine Description:
+
+ This method returns a pointer to the requested interface on the callback
+ object..
+
+ Arguments:
+
+ InterfaceId - the IID of the interface to query/reference
+
+ Interface - a location to store the interface pointer.
+
+ Return Value:
+
+ S_OK if the interface is supported.
+ E_NOINTERFACE if it is not supported.
+
+--*/
+{
+ if (IsEqualIID(InterfaceId, __uuidof(IDriverEntry)))
+ {
+ *Interface = QueryIDriverEntry();
+ return S_OK;
+ }
+ else
+ {
+ return CUnknown::QueryInterface(InterfaceId, Interface);
+ }
+}
+
+HRESULT
+CMyDriver::OnDeviceAdd(
+ _In_ IWDFDriver *FxWdfDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ )
+/*++
+
+ Routine Description:
+
+ The FX invokes this method when it wants to install our driver on a device
+ stack. This method creates a device callback object, then calls the Fx
+ to create an Fx device object and associate the new callback object with
+ it.
+
+ Arguments:
+
+ FxWdfDriver - the Fx driver object.
+
+ FxDeviceInit - the initialization information for the device.
+
+ Return Value:
+
+ status
+
+--*/
+{
+ HRESULT hr;
+
+ PCMyDevice device = NULL;
+
+ //
+ // Create a new instance of our device callback object
+ //
+
+ hr = CMyDevice::CreateInstance(FxWdfDriver, FxDeviceInit, &device);
+
+ //
+ // If that succeeded then call the device's construct method. This
+ // allows the device to create any queues or other structures that it
+ // needs now that the corresponding fx device object has been created.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = device->Configure();
+ }
+
+ //
+ // Release the reference on the device callback object now that it's been
+ // associated with an fx device object.
+ //
+
+ if (NULL != device)
+ {
+ device->Release();
+ }
+
+ return hr;
+}
diff --git a/usb/umdf_filter_umdf/umdf_filter/driver.h b/usb/umdf_filter_umdf/umdf_filter/driver.h
new file mode 100644
index 00000000..08f36a71
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/driver.h
@@ -0,0 +1,145 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Driver.h
+
+Abstract:
+
+ This module contains the type definitions for the UMDF OSR USB Sample Filter
+ driver's callback class.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// This class handles driver events for the OSR USB Sample Filter driver. In particular
+// it supports the OnDeviceAdd event, which occurs when the driver is called
+// to setup per-device handlers for a new device stack.
+//
+
+class CMyDriver : public CUnknown, public IDriverEntry
+{
+//
+// Private data members.
+//
+private:
+
+//
+// Private methods.
+//
+private:
+
+ //
+ // Returns a refernced pointer to the IDriverEntry interface.
+ //
+
+ IDriverEntry *
+ QueryIDriverEntry(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IDriverEntry*>(this);
+ }
+
+ HRESULT
+ Initialize(
+ VOID
+ );
+
+//
+// Public methods
+//
+public:
+
+ //
+ // The factory method used to create an instance of this driver.
+ //
+
+ static
+ HRESULT
+ CreateInstance(
+ _Out_ PCMyDriver *Driver
+ );
+
+//
+// COM methods
+//
+public:
+
+ //
+ // IDriverEntry methods
+ //
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnInitialize(
+ _In_ IWDFDriver* /*FxWdfDriver*/
+ )
+ {
+ return S_OK;
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnDeviceAdd(
+ _In_ IWDFDriver *FxWdfDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ );
+
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnDeinitialize(
+ _In_ IWDFDriver * /*FxWdfDriver*/
+ )
+ {
+ return;
+ }
+
+ //
+ // IUnknown methods.
+ //
+ // We have to implement basic ones here that redirect to the
+ // base class becuase of the multiple inheritance.
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+};
diff --git a/usb/umdf_filter_umdf/umdf_filter/exports.def b/usb/umdf_filter_umdf/umdf_filter/exports.def
new file mode 100644
index 00000000..0fc42817
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/exports.def
@@ -0,0 +1,4 @@
+; Skeleton.def : Declares the module parameters.
+
+EXPORTS
+ DllGetClassObject PRIVATE
diff --git a/usb/umdf_filter_umdf/umdf_filter/internal.h b/usb/umdf_filter_umdf/umdf_filter/internal.h
new file mode 100644
index 00000000..516f6d7f
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/internal.h
@@ -0,0 +1,111 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Internal.h
+
+Abstract:
+
+ This module contains the local type definitions for the UMDF OSR USB Sample Filter
+ driver.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+//
+// Include the WUDF headers
+//
+
+#include "wudfddi.h"
+
+//
+// Use specstrings for in/out annotation of function parameters.
+//
+
+#include "specstrings.h"
+
+//
+// Forward definitions of classes in the other header files.
+//
+
+typedef class CMyDriver *PCMyDriver;
+typedef class CMyDevice *PCMyDevice;
+typedef class CMyQueue *PCMyQueue;
+
+//
+// Define the tracing flags.
+//
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ MyDriverTraceControl, (73cdcaa5,ce52,43f2,aa2d,5f5a84e22213), \
+ \
+ WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
+ )
+
+#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
+ WPP_LEVEL_LOGGER(flag)
+
+#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
+ (WPP_LEVEL_ENABLED(flag) && \
+ WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
+
+//
+// This comment block is scanned by the trace preprocessor to define our
+// Trace function.
+//
+// begin_wpp config
+// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
+// end_wpp
+//
+
+//
+// Driver specific #defines
+//
+
+#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF\\OsrUsbFilter"
+#define MYDRIVER_COM_DESCRIPTION L"UMDF OSR USB Sample Filter Driver"
+#define MYDRIVER_CLASS_ID {0x422d8dbc, 0x520d, 0x4d7e, {0x8f, 0x53, 0x92, 0x0e, 0x5c, 0x86, 0x7e, 0x6c}}
+
+//
+// Include the type specific headers.
+//
+
+#include "comsup.h"
+#include "driver.h"
+#include "device.h"
+#include "queue.h"
+
+__forceinline
+#ifdef _PREFAST_
+__declspec(noreturn)
+#endif
+VOID
+WdfTestNoReturn(
+ VOID
+ )
+{
+ // do nothing.
+}
+
+#define WUDF_SAMPLE_DRIVER_ASSERT(p) \
+{ \
+ if ( !(p) ) \
+ { \
+ DebugBreak(); \
+ WdfTestNoReturn(); \
+ } \
+}
+
+#define SAFE_RELEASE(p) {if ((p)) { (p)->Release(); (p) = NULL; }}
diff --git a/usb/umdf_filter_umdf/umdf_filter/queue.cpp b/usb/umdf_filter_umdf/umdf_filter/queue.cpp
new file mode 100644
index 00000000..5642ec74
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/queue.cpp
@@ -0,0 +1,538 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ Queue.cpp
+
+Abstract:
+
+ This module contains the implementation of the OSR USB Filter Sample driver's
+ queue callback object.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "queue.h"
+
+#include "queue.tmh"
+
+HRESULT
+CMyQueue::CreateInstance(
+ _In_ IWDFDevice * FxDevice,
+ _Out_ CMyQueue **Queue
+ )
+/*++
+
+ Routine Description:
+
+ This method creates and initializs an instance of the OSR USB Filter Sample driver's
+ device callback object.
+
+ Arguments:
+
+ FxDeviceInit - the settings for the device.
+
+ Device - a location to store the referenced pointer to the device object.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ CMyQueue *queue;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Allocate a new instance of the device class.
+ //
+
+ queue = new CMyQueue();
+
+ if (NULL == queue)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // Initialize the instance.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = queue->Initialize(FxDevice);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ queue->AddRef();
+ *Queue = queue;
+ }
+
+ if (NULL != queue)
+ {
+ queue->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyQueue::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method is called to get a pointer to one of the object's callback
+ interfaces.
+
+ Arguments:
+
+ InterfaceId - the interface being requested
+
+ Object - a location to store the interface pointer if successful
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ HRESULT hr;
+
+
+ if(IsEqualIID(InterfaceId, __uuidof(IQueueCallbackDefaultIoHandler)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackDefaultIoHandler();
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackWrite)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackWrite();
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IRequestCallbackRequestCompletion)))
+ {
+ hr = S_OK;
+ *Object = QueryIRequestCallbackRequestCompletion();
+
+ }
+ else
+ {
+ hr = CUnknown::QueryInterface(InterfaceId, Object);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyQueue::Initialize(
+ _In_ IWDFDevice *FxDevice
+ )
+/*++
+
+ Routine Description:
+
+ This method initializes the device callback object. Any operations which
+ need to be performed before the caller can use the callback object, but
+ which couldn't be done in the constructor becuase they could fail would
+ be placed here.
+
+ Arguments:
+
+ FxDevice - the device which this Queue is for.
+
+ Return Value:
+
+ status.
+
+--*/
+{
+ IWDFIoQueue *fxQueue;
+ HRESULT hr;
+
+ //
+ // Create the framework queue
+ //
+
+ IUnknown *unknown = QueryIUnknown();
+ hr = FxDevice->CreateIoQueue(
+ unknown,
+ TRUE, // bDefaultQueue
+ WdfIoQueueDispatchParallel,
+ FALSE, // bPowerManaged
+ TRUE, // bAllowZeroLengthRequests
+ &fxQueue
+ );
+ if (FAILED(hr))
+ {
+ Trace(
+ TRACE_LEVEL_ERROR,
+ "%!FUNC!: Could not create default I/O queue, %!hresult!",
+ hr
+ );
+ }
+
+ unknown->Release();
+
+ if (SUCCEEDED(hr))
+ {
+ m_FxQueue = fxQueue;
+
+ //
+ // m_FxQueue is kept as a Weak reference to framework Queue object to avoid
+ // circular reference. This object's lifetime is contained within
+ // framework Queue object's lifetime
+ //
+
+ fxQueue->Release();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ FxDevice->GetDefaultIoTarget(&m_FxIoTarget);
+ }
+
+ return hr;
+}
+
+void
+CMyQueue::InvertBits(
+ _Inout_ IWDFMemory* FxMemory,
+ _In_ SIZE_T NumBytes
+ )
+/*++
+
+ Routine Description:
+
+ This helper method inverts bits in the buffer of an FxMemory object
+
+ Arguments:
+
+ FxMemory - Framework memory object whose buffer's bits are to be inverted
+
+ NumBytes - Number of bytes for which bits are to be inverted
+
+ Return Value:
+
+ None
+
+--*/
+{
+ PBYTE Buffer = (PBYTE)
+ FxMemory->GetDataBuffer(NULL);
+
+ for (SIZE_T i = 0; i < NumBytes; i++)
+ {
+ memset(Buffer + i, ~(Buffer[i]), sizeof(*Buffer));
+ }
+}
+
+void
+CMyQueue::OnWrite(
+ _In_ IWDFIoQueue* FxQueue,
+ _In_ IWDFIoRequest* FxRequest,
+ _In_ SIZE_T NumOfBytesToWrite
+ )
+/*++
+
+ Routine Description:
+
+ This method is called by Framework Queue object to deliver the Write request
+ This method inverts the bits in write buffer and forwards the request down the device stack
+ In case of any failure prior to ForwardRequest, it completets the request with failure
+
+ Arguments:
+
+ pWdfQueue - Framework Queue which is delivering the request
+
+ pWdfRequest - Framework Request
+
+ Return Value:
+
+ None
+
+--*/
+{
+ UNREFERENCED_PARAMETER(FxQueue);
+
+ IWDFMemory * FxInputMemory = NULL;
+
+ FxRequest->GetInputMemory(&FxInputMemory);
+
+ //
+ // Invert bits of the buffer to be written to device
+ //
+
+ InvertBits(FxInputMemory, NumOfBytesToWrite);
+
+ //
+ // Forward request down the stack
+ // When the device below completes the request we will get notified in OnComplete
+ // and then we will complete the request
+ //
+
+ ForwardRequest(FxRequest);
+
+ FxInputMemory->Release();
+}
+
+//
+// IQueueCallbackDefaultIoHandler method
+//
+
+void
+CMyQueue::OnDefaultIoHandler(
+ _In_ IWDFIoQueue* FxQueue,
+ _In_ IWDFIoRequest* FxRequest
+ )
+/*++
+
+ Routine Description:
+
+ This method is called by Framework Queue object to deliver all the I/O
+ Requests for which we do not have a specific handler
+ (In our case anything other than Write)
+
+ Arguments:
+
+ pWdfQueue - Framework Queue which is delivering the request
+
+ pWdfRequest - Framework Request
+
+ Return Value:
+
+ None
+
+--*/
+{
+ UNREFERENCED_PARAMETER(FxQueue);
+
+ //
+ // We just forward the request down the stack
+ // When the device below completes the request we will get notified in OnComplete
+ // and then we will complete the request
+ //
+
+ ForwardRequest(FxRequest);
+}
+
+void
+CMyQueue::ForwardRequest(
+ _In_ IWDFIoRequest* FxRequest
+ )
+/*++
+
+ Routine Description:
+
+ This helper method forwards the request down the stack
+
+ Arguments:
+
+ pWdfRequest - Request to be forwarded
+
+ Return Value:
+
+ None
+
+ Remarks:
+
+ The request gets forwarded to the next device in the stack which can be:
+ 1. Next device in user-mode stack
+ 2. Top device in kernel-mode stack (Redirector's Down Device)
+
+ In this routine we:
+ 1. Set a completion callback
+ 2. Copy request parameters to next stack location
+ 3. Asynchronously send the request without any timeout
+
+ When the lower request gets completed we will be notified via the
+ completion callback, where we will complete our request
+
+ In case of failure this routine completes the request
+
+--*/
+{
+ //
+ //First set the completion callback
+ //
+
+ IRequestCallbackRequestCompletion *completionCallback =
+ QueryIRequestCallbackRequestCompletion();
+
+ FxRequest->SetCompletionCallback(
+ completionCallback,
+ NULL //pContext
+ );
+
+ completionCallback->Release();
+
+ //
+ //Copy current i/o stack locations parameters to the next stack location
+ //
+
+ FxRequest->FormatUsingCurrentType(
+ );
+
+ //
+ //Send down the request
+ //
+ HRESULT hrSend = S_OK;
+
+ hrSend = FxRequest->Send(
+ m_FxIoTarget,
+ 0, //No flag
+ 0 //No timeout
+ );
+
+ if (FAILED(hrSend))
+ {
+ //
+ //If send failed we need to complete the request with failure
+ //
+ FxRequest->CompleteWithInformation(hrSend, 0);
+ }
+
+ return;
+}
+
+void
+CMyQueue::HandleReadRequestCompletion(
+ IWDFIoRequest* FxRequest,
+ IWDFIoRequestCompletionParams* CompletionParams
+ )
+/*++
+
+ Routine Description:
+
+ This helper method is called by OnCompletion method to complete Read request
+ We invert the bits in the read buffer
+ This is so that the client reads back the data it wrote since
+ we inverted bits during write to device
+
+ Arguments:
+
+ FxRequest - Request object of our layer
+
+ CompletionParams - Parameters with which the lower Request got completed
+
+ Return Value:
+
+ None
+
+ Remarks:
+
+ This method always completes the request since no one else would get a chance to
+ complete the request
+ In case of failure it completes the request with failure
+
+--*/
+{
+ HRESULT hrCompletion = CompletionParams->GetCompletionStatus();
+ ULONG_PTR BytesRead = CompletionParams->GetInformation();
+
+ //
+ // Check
+ // 1. whether the lower device succeeded the Request (otherwise we will just complete
+ // the Request with failure
+ // 2. If data read is of non-zero length, for us to bother to invert its bits
+ //
+
+ if (SUCCEEDED(hrCompletion) &&
+ (0 != BytesRead)
+ )
+ {
+ IWDFMemory *FxOutputMemory;
+
+ FxRequest->GetOutputMemory(&FxOutputMemory );
+
+ InvertBits(FxOutputMemory, BytesRead);
+
+ FxOutputMemory->Release();
+ }
+
+ //
+ // Complete the request
+ //
+
+ FxRequest->CompleteWithInformation(
+ hrCompletion,
+ BytesRead
+ );
+}
+
+
+void
+CMyQueue::OnCompletion(
+ IWDFIoRequest* FxRequest,
+ IWDFIoTarget* FxIoTarget,
+ IWDFRequestCompletionParams* CompletionParams,
+ PVOID Context
+ )
+/*++
+
+ Routine Description:
+
+ This method is called by Framework I/O Target object when
+ the lower device completets the Request
+
+ Arguments:
+
+ pWdfRequest - Request object of our layer
+
+ pIoTarget - I/O Target object invoking this callback
+
+ pParams - Parameters with which the lower Request got completed
+
+ Return Value:
+
+ None
+
+--*/
+{
+ UNREFERENCED_PARAMETER(FxIoTarget);
+ UNREFERENCED_PARAMETER(Context);
+
+ //
+ // If it is a read request, we invert the bits read since we inverted them during write
+ // so that application would read the same data as it wrote
+ //
+
+ if (WdfRequestRead == FxRequest->GetType())
+ {
+ IWDFIoRequestCompletionParams * IoCompletionParams = NULL;
+ HRESULT hrQI = CompletionParams->QueryInterface(IID_PPV_ARGS(&IoCompletionParams));
+ WUDF_SAMPLE_DRIVER_ASSERT(SUCCEEDED(hrQI));
+
+ HandleReadRequestCompletion(
+ FxRequest,
+ IoCompletionParams
+ );
+
+ SAFE_RELEASE(IoCompletionParams);
+ }
+ else
+ {
+
+ //
+ // Otherwise we just complete our Request object with the same parameters
+ // with which the lower Request got completed
+ //
+
+ FxRequest->CompleteWithInformation(
+ CompletionParams->GetCompletionStatus(),
+ CompletionParams->GetInformation()
+ );
+ }
+}
+
diff --git a/usb/umdf_filter_umdf/umdf_filter/queue.h b/usb/umdf_filter_umdf/umdf_filter/queue.h
new file mode 100644
index 00000000..216264e9
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter/queue.h
@@ -0,0 +1,253 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Queue.h
+
+Abstract:
+
+ This module contains the type definitions for the OSR USB Filter Sample
+ driver's queue callback class.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Class for the queue callbacks.
+// It implements
+// IQueueCallbackDeviceIoControl
+// IRequestCallbackRequestCompletion
+// Queue callbacks
+//
+// This class also implements IRequestCallbackRequestCompletion callback
+// to get the request completion notification when request is sent down the
+// stack. This callback can be implemented on a separate object as well.
+// This callback is implemented here only for conenience.
+//
+class CMyQueue :
+ public CUnknown,
+ public IQueueCallbackWrite,
+ public IQueueCallbackDefaultIoHandler,
+ public IRequestCallbackRequestCompletion
+{
+
+//
+// Private data members.
+//
+private:
+
+ //
+ // Weak reference to framework Queue object which this object implements callbacks for
+ // This is kept as a weak reference to avoid circular reference
+ // This object's lifetime is contained within framework Queue object's lifetime
+ //
+
+ IWDFIoQueue *m_FxQueue;
+
+ //
+ // I/O Target to which we forward requests. Represents next device in the
+ // device stack
+ //
+
+ IWDFIoTarget *m_FxIoTarget;
+
+//
+// Private methods.
+//
+
+private:
+
+ CMyQueue() :
+ m_FxQueue(NULL),
+ m_FxIoTarget(NULL)
+ {
+ }
+
+ virtual ~CMyQueue()
+ {
+ if (NULL != m_FxIoTarget)
+ {
+ m_FxIoTarget->Release();
+ }
+ }
+
+ //
+ // QueryInterface helpers
+ //
+
+ IRequestCallbackRequestCompletion *
+ QueryIRequestCallbackRequestCompletion(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IRequestCallbackRequestCompletion*>(this);
+ }
+
+ IQueueCallbackWrite *
+ QueryIQueueCallbackWrite(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackWrite *>(this);
+ }
+
+ IQueueCallbackDefaultIoHandler *
+ QueryIQueueCallbackDefaultIoHandler(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackDefaultIoHandler *>(this);
+ }
+
+ //
+ // Initialize
+ //
+
+ HRESULT
+ Initialize(
+ _In_ IWDFDevice *FxDevice
+ );
+
+ //
+ // Helper method to forward request down the stack
+ //
+
+ void
+ ForwardRequest(
+ _In_ IWDFIoRequest *pWdfRequest
+ );
+
+ //
+ // Helper method to inverts bits in the buffer of a framework Memory object
+ //
+
+ void
+ InvertBits(
+ _Inout_ IWDFMemory* FxMemory,
+ _In_ SIZE_T NumBytes
+ );
+
+ //
+ // Helper method to handle Read request completion
+ //
+
+ void
+ HandleReadRequestCompletion(
+ IWDFIoRequest* FxRequest,
+ IWDFIoRequestCompletionParams* CompletionParams
+ );
+
+//
+// Public methods
+//
+public:
+
+ //
+ // The factory method used to create an instance of this class
+ //
+
+ static
+ HRESULT
+ CreateInstance(
+ _In_ IWDFDevice *FxDevice,
+ _Out_ CMyQueue **Queue
+ );
+
+
+ HRESULT
+ Configure(
+ VOID
+ )
+ {
+ return S_OK;
+ }
+
+//
+// COM methods
+//
+public:
+
+ //
+ // IUnknown methods.
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+
+ //
+ // IQueueCallbackWrite method
+ //
+
+ virtual
+ void
+ STDMETHODCALLTYPE
+ OnWrite(
+ _In_ IWDFIoQueue* FxQueue,
+ _In_ IWDFIoRequest* FxRequest,
+ _In_ SIZE_T NumOfBytesToWrite
+ );
+
+
+ //
+ // IQueueCallbackDefaultIoHandler method
+ //
+
+ virtual
+ void
+ STDMETHODCALLTYPE
+ OnDefaultIoHandler(
+ _In_ IWDFIoQueue* FxQueue,
+ _In_ IWDFIoRequest* FxRequest
+ );
+
+ //
+ //IRequestCallbackRequestCompletion
+ //
+
+ virtual
+ void
+ STDMETHODCALLTYPE
+ OnCompletion(
+ IWDFIoRequest* FxRequest,
+ IWDFIoTarget* FxIoTarget,
+ IWDFRequestCompletionParams* CompletionParams,
+ PVOID Context
+ );
+};
+
diff --git a/usb/umdf_filter_umdf/umdf_filter_umdf.sln b/usb/umdf_filter_umdf/umdf_filter_umdf.sln
new file mode 100644
index 00000000..50055acd
--- /dev/null
+++ b/usb/umdf_filter_umdf/umdf_filter_umdf.sln
@@ -0,0 +1,59 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 12.0
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{531B99DD-B7DB-431D-A028-6843337B1B2E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Umdf_filter", "Umdf_filter", "{C76583EA-D923-45F8-B74B-A08226D64DE4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Umdf_driver", "Umdf_driver", "{BA612164-8359-46AB-8A21-D2AD9B9EDCA5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "Package\package.VcxProj", "{92A41A0C-EC0F-4D98-B4DE-4899B375FD49}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WUDFOsrUsbFilter", "umdf_filter\WUDFOsrUsbFilter.vcxproj", "{E62A4AAA-870E-4D58-AA10-D9604A2E52E8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WUDFOsrUsbFx2", "umdf_driver\WUDFOsrUsbFx2.vcxproj", "{0D3781C2-2236-46B0-806D-387999E500AB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49}.Debug|Win32.ActiveCfg = Debug|Win32
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49}.Debug|Win32.Build.0 = Debug|Win32
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49}.Release|Win32.ActiveCfg = Release|Win32
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49}.Release|Win32.Build.0 = Release|Win32
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49}.Debug|x64.ActiveCfg = Debug|x64
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49}.Debug|x64.Build.0 = Debug|x64
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49}.Release|x64.ActiveCfg = Release|x64
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49}.Release|x64.Build.0 = Release|x64
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8}.Debug|Win32.Build.0 = Debug|Win32
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8}.Release|Win32.ActiveCfg = Release|Win32
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8}.Release|Win32.Build.0 = Release|Win32
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8}.Debug|x64.ActiveCfg = Debug|x64
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8}.Debug|x64.Build.0 = Debug|x64
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8}.Release|x64.ActiveCfg = Release|x64
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8}.Release|x64.Build.0 = Release|x64
+ {0D3781C2-2236-46B0-806D-387999E500AB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0D3781C2-2236-46B0-806D-387999E500AB}.Debug|Win32.Build.0 = Debug|Win32
+ {0D3781C2-2236-46B0-806D-387999E500AB}.Release|Win32.ActiveCfg = Release|Win32
+ {0D3781C2-2236-46B0-806D-387999E500AB}.Release|Win32.Build.0 = Release|Win32
+ {0D3781C2-2236-46B0-806D-387999E500AB}.Debug|x64.ActiveCfg = Debug|x64
+ {0D3781C2-2236-46B0-806D-387999E500AB}.Debug|x64.Build.0 = Debug|x64
+ {0D3781C2-2236-46B0-806D-387999E500AB}.Release|x64.ActiveCfg = Release|x64
+ {0D3781C2-2236-46B0-806D-387999E500AB}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {92A41A0C-EC0F-4D98-B4DE-4899B375FD49} = {531B99DD-B7DB-431D-A028-6843337B1B2E}
+ {E62A4AAA-870E-4D58-AA10-D9604A2E52E8} = {C76583EA-D923-45F8-B74B-A08226D64DE4}
+ {0D3781C2-2236-46B0-806D-387999E500AB} = {BA612164-8359-46AB-8A21-D2AD9B9EDCA5}
+ EndGlobalSection
+EndGlobal