diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /usb/umdf_filter_umdf | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'usb/umdf_filter_umdf')
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 |
