summaryrefslogtreecommitdiff
path: root/pofx/WDF/Driver/SingleComp
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /pofx/WDF/Driver/SingleComp
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'pofx/WDF/Driver/SingleComp')
-rw-r--r--pofx/WDF/Driver/SingleComp/HwSim.c265
-rw-r--r--pofx/WDF/Driver/SingleComp/HwSim.h74
-rw-r--r--pofx/WDF/Driver/SingleComp/SingleComponentFStateDriver.vcxproj176
-rw-r--r--pofx/WDF/Driver/SingleComp/SingleComponentFStateDriver.vcxproj.Filters37
-rw-r--r--pofx/WDF/Driver/SingleComp/SingleComponentFStateSample.inx105
-rw-r--r--pofx/WDF/Driver/SingleComp/driver.c1243
-rw-r--r--pofx/WDF/Driver/SingleComp/driver.h150
-rw-r--r--pofx/WDF/Driver/SingleComp/include.h3
8 files changed, 2053 insertions, 0 deletions
diff --git a/pofx/WDF/Driver/SingleComp/HwSim.c b/pofx/WDF/Driver/SingleComp/HwSim.c
new file mode 100644
index 00000000..26f8faf0
--- /dev/null
+++ b/pofx/WDF/Driver/SingleComp/HwSim.c
@@ -0,0 +1,265 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ HwSim.c
+
+Abstract:
+ This module implements a simple hardware simulator that simulates reading of
+ data from the device's components. In this sample, the "data" that is read
+ is simply the bitwise complement of the component number. In other words,
+ the data for component number 'X' is simply '~X'.
+
+ The hardware simulator also verifies that when a component is read, the
+ device is in D0 and the component is in F0. If not, it breaks into the
+ debugger.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "include.h"
+#include "HwSim.h"
+#include "HwSim.tmh"
+
+NTSTATUS
+HwSimInitialize(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine initializes the hardware simulator
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES objectAttributes;
+ PHWSIM_CONTEXT devCtx;
+
+ //
+ // Allocate our context for this device
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes,
+ HWSIM_CONTEXT);
+ status = WdfObjectAllocateContext((WDFOBJECT) Device,
+ &objectAttributes,
+ (PVOID*) &devCtx);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfObjectAllocateContext failed with %!status!",
+ status);
+ goto exit;
+ }
+
+ devCtx->FirstD0Entry = TRUE;
+
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+VOID
+HwSimD0Entry(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine simulates the device entering D0
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ None
+
+--*/
+{
+ PHWSIM_CONTEXT devCtx;
+
+ devCtx = HwSimGetDeviceContext(Device);
+
+ if (devCtx->FirstD0Entry) {
+ devCtx->FirstD0Entry = FALSE;
+
+ //
+ // On the first D0 entry component is in F0 state
+ //
+ devCtx->ComponentFState = 0;
+ }
+
+ devCtx->DevicePoweredOn = TRUE;
+
+ return;
+}
+
+VOID
+HwSimD0Exit(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine simulates the device exiting D0
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ None
+
+--*/
+{
+ PHWSIM_CONTEXT devCtx;
+
+ devCtx = HwSimGetDeviceContext(Device);
+
+ devCtx->DevicePoweredOn = FALSE;
+
+ return;
+}
+
+VOID
+HwSimFStateChange(
+ _In_ WDFDEVICE Device,
+ _In_ ULONG State
+ )
+/*++
+Routine Description:
+
+ This routine simulates a component changing its F-state
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ State - New F-state for the component
+
+Return Value:
+
+ None
+
+--*/
+{
+ PHWSIM_CONTEXT devCtx;
+
+ devCtx = HwSimGetDeviceContext(Device);
+
+ //
+ // Verify that the device is powered on
+ //
+ if (FALSE == devCtx->DevicePoweredOn) {
+ //
+ // This means that our driver is handling an F state transition while
+ // device is not in D0.
+ //
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - Expected device to be powered on, but it was not.");
+
+ WdfVerifierDbgBreakPoint();
+ }
+
+ ASSERT(devCtx->DevicePoweredOn);
+
+ //
+ // Put the component in the requested F-state
+ //
+ devCtx->ComponentFState = State;
+
+ //
+ // For an actual hardware, save any hardware state on Fx transition
+ // and restore state on F0 transition.
+ //
+
+ return;
+}
+
+ULONG
+HwSimReadComponent(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine simulates the reading of data from a component
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ Component - Component from which data is being read
+
+Return Value:
+
+ A ULONG value representing the data that was read from the component
+
+--*/
+{
+ ULONG componentData;
+ PHWSIM_CONTEXT devCtx;
+ ULONG component = 0;
+
+ devCtx = HwSimGetDeviceContext(Device);
+
+ //
+ // Verify that the device is powered on
+ //
+ if (FALSE == devCtx->DevicePoweredOn) {
+ //
+ // This means that our driver is attempting to read from the component
+ // while the device is not powered on.
+ //
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - Expected device to be powered on, but it was not.");
+
+ WdfVerifierDbgBreakPoint();
+ }
+
+ //
+ // Verify that the component is in F0
+ //
+ if (0 != devCtx->ComponentFState) {
+ //
+ // This means that our driver is attempting to read from the component
+ // while the component is not in F0.
+ //
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - Expected component to be in F0, but it was in F%d.",
+ devCtx->ComponentFState);
+
+ WdfVerifierDbgBreakPoint();
+ }
+
+ ASSERT(devCtx->DevicePoweredOn);
+ ASSERT(0 == devCtx->ComponentFState);
+
+ //
+ // In this sample, component data is just a bit-wise complement of the
+ // component number.
+ //
+ componentData = ~component;
+ return componentData;
+}
diff --git a/pofx/WDF/Driver/SingleComp/HwSim.h b/pofx/WDF/Driver/SingleComp/HwSim.h
new file mode 100644
index 00000000..a43223fb
--- /dev/null
+++ b/pofx/WDF/Driver/SingleComp/HwSim.h
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ HwSim.h
+
+Abstract:
+ Header file for the hardware simulation module of the KMDF sample driver for
+ a single-component device.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#pragma once
+
+NTSTATUS
+HwSimInitialize(
+ _In_ WDFDEVICE Device
+ );
+
+VOID
+HwSimD0Entry(
+ _In_ WDFDEVICE Device
+ );
+
+VOID
+HwSimD0Exit(
+ _In_ WDFDEVICE Device
+ );
+
+VOID
+HwSimFStateChange(
+ _In_ WDFDEVICE Device,
+ _In_ ULONG State
+ );
+
+ULONG
+HwSimReadComponent(
+ _In_ WDFDEVICE Device
+ );
+
+//
+// This structure represents the hardware simulation module's device context
+// space
+//
+typedef struct _HWSIM_CONTEXT {
+ //
+ // F-state of the component
+ //
+ ULONG ComponentFState;
+
+ //
+ // The following member tracks whether or not the device is in D0
+ //
+ BOOLEAN DevicePoweredOn;
+
+ //
+ // The following member tracks whether or not we have previously entered the
+ // D0 state for this device
+ //
+ BOOLEAN FirstD0Entry;
+} HWSIM_CONTEXT, *PHWSIM_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(HWSIM_CONTEXT, HwSimGetDeviceContext)
diff --git a/pofx/WDF/Driver/SingleComp/SingleComponentFStateDriver.vcxproj b/pofx/WDF/Driver/SingleComp/SingleComponentFStateDriver.vcxproj
new file mode 100644
index 00000000..3f0b05c0
--- /dev/null
+++ b/pofx/WDF/Driver/SingleComp/SingleComponentFStateDriver.vcxproj
@@ -0,0 +1,176 @@
+<?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>{17F25816-A09C-44DF-99A3-16D0FF5FCD66}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{D3CED862-FD94-4428-9E76-0D63654856A3}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</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="driver.c; HwSim.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppScanConfigurationData>driver.h</WppScanConfigurationData>
+ </ClCompile>
+ <Inf Include=".\SingleComponentFStateSample.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\SingleComponentFStateSample.inf</CopyOutput>
+ </Inf>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>SingleComponentFStateDriver</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>SingleComponentFStateDriver</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>SingleComponentFStateDriver</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>SingleComponentFStateDriver</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <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/pofx/WDF/Driver/SingleComp/SingleComponentFStateDriver.vcxproj.Filters b/pofx/WDF/Driver/SingleComp/SingleComponentFStateDriver.vcxproj.Filters
new file mode 100644
index 00000000..a8eba88d
--- /dev/null
+++ b/pofx/WDF/Driver/SingleComp/SingleComponentFStateDriver.vcxproj.Filters
@@ -0,0 +1,37 @@
+<?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>{C09CD711-AD25-4CEA-8535-7051049866B9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{8C669253-AA2C-4BA8-970C-BE8E4A5BEB6C}</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>{2086162C-ED1C-4446-9A17-03967584AA37}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{ACF33661-8D77-4D77-ACD7-ABC80DD52BE0}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="driver.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="HwSim.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\SingleComponentFStateSample.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include=".\SingleComponentFStateSample.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/pofx/WDF/Driver/SingleComp/SingleComponentFStateSample.inx b/pofx/WDF/Driver/SingleComp/SingleComponentFStateSample.inx
new file mode 100644
index 00000000..1c555f11
--- /dev/null
+++ b/pofx/WDF/Driver/SingleComp/SingleComponentFStateSample.inx
@@ -0,0 +1,105 @@
+;/*++
+;
+;Copyright (c) 1990-2000 Microsoft Corporation
+;
+;Module Name:
+; SingleComponentFStateSample.INF
+;
+;Abstract:
+; INF file for installing SingleComponentFStateSample Driver
+;
+;Installation Notes:
+; Using Devcon: Type "devcon install SingleComponentFStateSample.inf root\SingleComponentFStateDevice" to install
+;
+;--*/
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=Sample
+ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}
+Provider=%MSFT%
+CatalogFile=KmdfSamples.cat
+
+[DestinationDirs]
+DefaultDestDir = 12
+
+; ================= Class section =====================
+
+[ClassInstall32]
+Addreg=SampleClassReg
+
+[SampleClassReg]
+HKR,,,0,%ClassName%
+HKR,,Icon,,-5
+
+[SourceDisksNames]
+1 = %DiskId1%,,,""
+
+[SourceDisksFiles]
+SingleComponentFStateDriver.sys = 1,,
+
+;*****************************************
+; SingleComponentFStateDevice Install Section
+;*****************************************
+
+[Manufacturer]
+%StdMfg%=Standard,NT$ARCH$
+
+; Decorated model section take precedence over undecorated
+; ones on XP and later.
+[Standard.NT$ARCH$]
+%SingleComponentFStateDevice.DeviceDesc%=SingleComponentFStateDevice, root\SingleComponentFStateDevice
+
+[SingleComponentFStateDevice.NT]
+CopyFiles=Drivers_Dir
+
+[Drivers_Dir]
+SingleComponentFStateDriver.sys
+
+
+;-------------- Service installation
+[SingleComponentFStateDevice.NT.Services]
+AddService = SingleComponentFStateSvc,%SPSVCINST_ASSOCSERVICE%, SingleComponentFStateSvc_Service_Inst
+
+; -------------- SingleComponentFStateDevice driver install sections
+[SingleComponentFStateSvc_Service_Inst]
+DisplayName = %SingleComponentFStateSvc.SVCDESC%
+ServiceType = 1 ; SERVICE_KERNEL_DRIVER
+StartType = 3 ; SERVICE_DEMAND_START
+ErrorControl = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary = %12%\SingleComponentFStateDriver.sys
+
+;
+;--- SingleComponentFStateDevice Coinstaller installation ------
+;
+
+[DestinationDirs]
+SingleComponentFStateDevice_CoInstaller_CopyFiles = 11
+
+[SingleComponentFStateDevice.NT.CoInstallers]
+AddReg=SingleComponentFStateDevice_CoInstaller_AddReg
+CopyFiles=SingleComponentFStateDevice_CoInstaller_CopyFiles
+
+[SingleComponentFStateDevice_CoInstaller_AddReg]
+HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
+
+[SingleComponentFStateDevice_CoInstaller_CopyFiles]
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
+
+[SourceDisksFiles]
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
+
+[SingleComponentFStateDevice.NT.Wdf]
+KmdfService = SingleComponentFStateSvc, SingleComponentFStateDevice_wdfsect
+[SingleComponentFStateDevice_wdfsect]
+KmdfLibraryVersion = $KMDFVERSION$
+
+
+[Strings]
+SPSVCINST_ASSOCSERVICE= 0x00000002
+MSFT = "Microsoft"
+StdMfg = "(Standard system devices)"
+DiskId1 = "WDF Sample SingleComponentFStateDevice Installation Disk #1"
+SingleComponentFStateDevice.DeviceDesc = "Single comp F State Device"
+SingleComponentFStateSvc.SVCDESC = "Single comp F State Service"
+ClassName = "Sample Device"
diff --git a/pofx/WDF/Driver/SingleComp/driver.c b/pofx/WDF/Driver/SingleComp/driver.c
new file mode 100644
index 00000000..cd7b6dd1
--- /dev/null
+++ b/pofx/WDF/Driver/SingleComp/driver.c
@@ -0,0 +1,1243 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Driver.c
+
+Abstract:
+ This module implements a KMDF sample driver for a single-component device.
+ The driver uses the power framework to manage the power state of the
+ component that represents device.
+
+ The device used in this sample is a root-enumerated device whose components
+ are simulated entirely in software. The simulation of the components is
+ implemented in HwSim.h and HwSim.c.
+
+ This driver works only on Win8 and above.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "include.h"
+#include "hwsim.h"
+
+#include <initguid.h>
+#include "AppInterface.h"
+
+#include "driver.tmh"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text (INIT, DriverEntry)
+#pragma alloc_text (PAGE, SingleCompEvtDriverCleanup)
+#pragma alloc_text (PAGE, SingleCompEvtDeviceAdd)
+#pragma alloc_text (PAGE, SingleCompEvtDeviceD0Exit)
+#pragma alloc_text (PAGE, AssignS0IdleSettings)
+#pragma alloc_text (PAGE, AssignPowerFrameworkSettings)
+#pragma alloc_text (PAGE, SingleCompWdmEvtDeviceWdmPostPoFxRegisterDevice)
+#pragma alloc_text (PAGE, SingleCompWdmEvtDeviceWdmPrePoFxUnregisterDevice)
+#endif
+
+NTSTATUS
+DriverEntry(
+ _In_ PDRIVER_OBJECT DriverObject,
+ _In_ PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+
+ Driver initialization entry point. This entry point is called directly by
+ the I/O system.
+
+Arguments:
+
+ DriverObject - pointer to the driver object
+
+ RegistryPath - pointer to a unicode string representing the path to the
+ driver-specific key in the registry.
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ WDF_DRIVER_CONFIG config;
+ WDF_OBJECT_ATTRIBUTES attributes;
+
+ WPP_INIT_TRACING(DriverObject, RegistryPath);
+
+ //
+ // Initiialize driver config to control the attributes that are global to
+ // the driver. Note that framework by default provides a driver unload
+ // routine. If DriverEntry creates any resources that require clean-up in
+ // driver unload, you can manually override the default by supplying a
+ // pointer to the EvtDriverUnload callback in the config structure. In
+ // general xxx_CONFIG_INIT macros are provided to initialize most commonly
+ // used members.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.EvtCleanupCallback = SingleCompEvtDriverCleanup;
+ WDF_DRIVER_CONFIG_INIT(
+ &config,
+ SingleCompEvtDeviceAdd
+ );
+
+ //
+ // Create a framework driver object to represent our driver.
+ //
+ status = WdfDriverCreate(DriverObject,
+ RegistryPath,
+ &attributes, // Driver Attributes
+ &config, // Driver Config Info
+ WDF_NO_HANDLE
+ );
+
+ if (FALSE == NT_SUCCESS(status)) {
+ KdPrint( ("WdfDriverCreate failed with status 0x%x\n", status));
+ WPP_CLEANUP(DriverObject);
+ }
+
+ return status;
+}
+
+VOID
+SingleCompEvtDriverCleanup(
+ _In_ WDFOBJECT Driver
+ )
+{
+ PAGED_CODE();
+
+ WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER) Driver));
+}
+
+NTSTATUS
+SingleCompEvtDeviceAdd(
+ _In_ WDFDRIVER Driver,
+ _Inout_ PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+Routine Description:
+
+ EvtDeviceAdd is called by the KMDF in response to AddDevice call from
+ the PnP manager.
+
+Arguments:
+
+ Driver - Handle to the KMDF driver object created in DriverEntry
+
+ DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ WDFDEVICE device;
+ WDF_IO_QUEUE_CONFIG queueConfig;
+ FDO_DATA *fdoContext = NULL;
+ ULONG queueIndex = 0;
+ WDF_OBJECT_ATTRIBUTES objectAttributes;
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
+
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, FDO_DATA);
+
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);
+ pnpCallbacks.EvtDeviceD0Entry = SingleCompEvtDeviceD0Entry;
+ pnpCallbacks.EvtDeviceD0Exit = SingleCompEvtDeviceD0Exit;
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks);
+
+ status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device);
+ if (!NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceCreate failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ fdoContext = FdoGetContext(device);
+
+ //
+ // Our initial state is active
+ //
+ fdoContext->IsActive = TRUE;
+
+ //
+ // Create three power-managed queues, one each for read, write and IOCTL
+ // requests. The handles to these power-managed queues are stored in an
+ // array in the device object context space. When the component becomes idle
+ // we need to stop our power-managed queues. When the component becomes
+ // active we need to start them. In those situations, we go through this
+ // array of power-managed queues and stop or start each queue as
+ // appropriate. Handles to non-power-managed queues should not be stored in
+ // this array.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
+ WdfIoQueueDispatchParallel);
+ queueConfig.EvtIoDeviceControl = SingleCompEvtIoDeviceControl;
+
+ //
+ // By default, Static Driver Verifier (SDV) displays a warning if it
+ // doesn't find the EvtIoStop callback on a power-managed queue.
+ // The 'assume' below causes SDV to suppress this warning. If the driver
+ // has not explicitly set PowerManaged to WdfFalse, the framework creates
+ // power-managed queues when the device is not a filter driver. Normally
+ // the EvtIoStop is required for power-managed queues, but for this driver
+ // it is not needed b/c the driver doesn't hold on to the requests or
+ // forward them to other drivers. This driver completes the requests
+ // directly in the queue's handlers. If the EvtIoStop callback is not
+ // implemented, the framework waits for all driver-owned requests to be
+ // done before moving in the Dx/sleep states or before removing the
+ // device, which is the correct behavior for this type of driver.
+ // If the requests were taking an indeterminate amount of time to complete,
+ // or if the driver forwarded the requests to a lower driver/another stack,
+ // the queue should have an EvtIoStop/EvtIoResume.
+ //
+ __analysis_assume(queueConfig.EvtIoStop != 0);
+ status = WdfIoQueueCreate(device,
+ &queueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &(fdoContext->Queues[queueIndex]));
+ __analysis_assume(queueConfig.EvtIoStop == 0);
+
+ if (FALSE == NT_SUCCESS (status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfIoQueueCreate for IoDeviceControl failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ status = WdfDeviceConfigureRequestDispatching(device,
+ fdoContext->Queues[queueIndex],
+ WdfRequestTypeDeviceControl);
+ if (FALSE == NT_SUCCESS (status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceConfigureRequestDispatching for "
+ "WdfRequestTypeDeviceControl failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ ++queueIndex;
+
+ WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
+ WdfIoQueueDispatchParallel);
+ queueConfig.EvtIoRead = SingleCompEvtIoRead;
+
+ //
+ // By default, Static Driver Verifier (SDV) displays a warning if it
+ // doesn't find the EvtIoStop callback on a power-managed queue.
+ // The 'assume' below causes SDV to suppress this warning. If the driver
+ // has not explicitly set PowerManaged to WdfFalse, the framework creates
+ // power-managed queues when the device is not a filter driver. Normally
+ // the EvtIoStop is required for power-managed queues, but for this driver
+ // it is not needed b/c the driver doesn't hold on to the requests or
+ // forward them to other drivers. This driver completes the requests
+ // directly in the queue's handlers. If the EvtIoStop callback is not
+ // implemented, the framework waits for all driver-owned requests to be
+ // done before moving in the Dx/sleep states or before removing the
+ // device, which is the correct behavior for this type of driver.
+ // If the requests were taking an indeterminate amount of time to complete,
+ // or if the driver forwarded the requests to a lower driver/another stack,
+ // the queue should have an EvtIoStop/EvtIoResume.
+ //
+ __analysis_assume(queueConfig.EvtIoStop != 0);
+ status = WdfIoQueueCreate(device,
+ &queueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &(fdoContext->Queues[queueIndex]));
+ __analysis_assume(queueConfig.EvtIoStop == 0);
+
+ if (FALSE == NT_SUCCESS (status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfIoQueueCreate for IoRead failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ status = WdfDeviceConfigureRequestDispatching(device,
+ fdoContext->Queues[queueIndex],
+ WdfRequestTypeRead);
+ if (FALSE == NT_SUCCESS (status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceConfigureRequestDispatching for "
+ "WdfRequestTypeRead failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ ++queueIndex;
+
+ WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
+ WdfIoQueueDispatchParallel);
+ queueConfig.EvtIoWrite = SingleCompEvtIoWrite;
+
+ //
+ // By default, Static Driver Verifier (SDV) displays a warning if it
+ // doesn't find the EvtIoStop callback on a power-managed queue.
+ // The 'assume' below causes SDV to suppress this warning. If the driver
+ // has not explicitly set PowerManaged to WdfFalse, the framework creates
+ // power-managed queues when the device is not a filter driver. Normally
+ // the EvtIoStop is required for power-managed queues, but for this driver
+ // it is not needed b/c the driver doesn't hold on to the requests or
+ // forward them to other drivers. This driver completes the requests
+ // directly in the queue's handlers. If the EvtIoStop callback is not
+ // implemented, the framework waits for all driver-owned requests to be
+ // done before moving in the Dx/sleep states or before removing the
+ // device, which is the correct behavior for this type of driver.
+ // If the requests were taking an indeterminate amount of time to complete,
+ // or if the driver forwarded the requests to a lower driver/another stack,
+ // the queue should have an EvtIoStop/EvtIoResume.
+ //
+ __analysis_assume(queueConfig.EvtIoStop != 0);
+ status = WdfIoQueueCreate(device,
+ &queueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &(fdoContext->Queues[queueIndex]));
+ __analysis_assume(queueConfig.EvtIoStop == 0);
+
+ if (FALSE == NT_SUCCESS (status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfIoQueueCreate for IoWrite failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ status = WdfDeviceConfigureRequestDispatching(device,
+ fdoContext->Queues[queueIndex],
+ WdfRequestTypeWrite);
+ if (FALSE == NT_SUCCESS (status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceConfigureRequestDispatching for "
+ "WdfRequestTypeWrite failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ ++queueIndex;
+
+ ASSERT(queueIndex == QUEUE_COUNT);
+
+ status = AssignS0IdleSettings(device);
+ if (!NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ //
+ // If you need to talk to hardware to figure out what F-states are
+ // applicable this can be done in EvtSelfManagedIoInit
+ // (but no later than that). EvtSelfManagedIoInit gets invoked after
+ // EvtPrepareHardware so you'd have chance to initialize your hardware.
+ //
+ status = AssignPowerFrameworkSettings(device);
+ if (!NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ //
+ // Create a device interface so that applications can open a handle to this
+ // device.
+ //
+ status = WdfDeviceCreateDeviceInterface(device,
+ &GUID_DEVINTERFACE_POWERFX,
+ NULL /* ReferenceString */);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceCreateDeviceInterface failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ //
+ // Initialize the hardware simulator
+ //
+ status = HwSimInitialize(device);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+exit:
+ return status;
+}
+
+NTSTATUS
+SingleCompEvtDeviceD0Entry(
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE PreviousState
+ )
+/*++
+Routine Description:
+
+ KMDF calls this routine when the device has entered D0.
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ PreviousState - Previous device power state
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(PreviousState);
+
+ HwSimD0Entry(Device);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+SingleCompEvtDeviceD0Exit(
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE TargetState
+ )
+/*++
+Routine Description:
+
+ KMDF calls this routine when the device is about to leave D0.
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ TargetState - Device power state that the device is about to enter
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(TargetState);
+
+ HwSimD0Exit(Device);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+SingleCompWdmEvtDeviceWdmPostPoFxRegisterDevice(
+ _In_ WDFDEVICE Device,
+ _In_ POHANDLE PoHandle
+ )
+/*++
+Routine Description:
+
+ KMDF calls this routine after it has registered with the Power Framework
+ and supplies the registration handle that driver can use directly.
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ PoHandle - Handle of registration with Power Framework.
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ FDO_DATA *fdoContext = NULL;
+
+ PAGED_CODE();
+
+ //
+ // Get the device context
+ //
+ fdoContext = FdoGetContext(Device);
+
+ //
+ // Save the POHANDLE
+ //
+ fdoContext->PoHandle = PoHandle;
+
+ //
+ // Set latency and residency hints so that the power framework chooses lower
+ // powered F-states when we are idle.
+ // The values used here are for illustration purposes only. The driver
+ // should use values that are appropriate for its device.
+ //
+ PoFxSetComponentLatency(
+ PoHandle,
+ 0, // Component
+ (WDF_ABS_TIMEOUT_IN_MS(DEEPEST_FSTATE_LATENCY_IN_MS) + 1)
+ );
+ PoFxSetComponentResidency(
+ PoHandle,
+ 0, // Component
+ (WDF_ABS_TIMEOUT_IN_SEC(DEEPEST_FSTATE_RESIDENCY_IN_SEC) + 1)
+ );
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+SingleCompWdmEvtDeviceWdmPrePoFxUnregisterDevice(
+ _In_ WDFDEVICE Device,
+ _In_ POHANDLE PoHandle
+ )
+/*++
+Routine Description:
+
+ KMDF calls this routine when it is about to unregister with the Power
+ Framework. After returning from this routine driver must not use the
+ supplied registration handle anymore.
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ PoHandle - Handle of registration with Power Framework.
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ FDO_DATA *fdoContext = NULL;
+
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(PoHandle);
+
+ //
+ // Get the device context
+ //
+ fdoContext = FdoGetContext(Device);
+
+ //
+ // Reset the POHANDLE
+ //
+ fdoContext->PoHandle = NULL;
+
+ return;
+}
+
+_IRQL_requires_same_
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS
+AssignS0IdleSettings(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ Helper function to assign S0 idle settings for the device
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS powerPolicy;
+
+ PAGED_CODE();
+
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&powerPolicy,
+ IdleCannotWakeFromS0);
+ powerPolicy.IdleTimeoutType = SystemManagedIdleTimeout;
+
+ status = WdfDeviceAssignS0IdleSettings(Device, &powerPolicy);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceAssignS0IdleSettings failed with %!status!.",
+ status);
+ }
+ return status;
+}
+
+_IRQL_requires_same_
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS
+AssignPowerFrameworkSettings(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ Helper function to assign Power Framework related settings for the device
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ WDF_POWER_FRAMEWORK_SETTINGS poFxSettings;
+ PO_FX_COMPONENT component;
+ PO_FX_COMPONENT_IDLE_STATE idleStates[FSTATE_COUNT];
+
+ //
+ // Note that we initialize the 'idleStates' array below based on the
+ // assumption that MAX_FSTATE_COUNT is 4.
+ // If we increase the value of MAX_FSTATE_COUNT, we need to initialize those
+ // additional F-states below. If we decrease the value of MAX_FSTATE_COUNT,
+ // we need to remove the corresponding initializations below.
+ //
+ C_ASSERT(FSTATE_COUNT == 4);
+
+ PAGED_CODE();
+
+ //
+ // Initialization
+ //
+ RtlZeroMemory(&component, sizeof(component));
+ RtlZeroMemory(idleStates, sizeof(idleStates));
+
+ //
+ // The transition latency and residency requirement values used here are for
+ // illustration purposes only. The driver should use values that are
+ // appropriate for its device.
+ //
+
+ //
+ // F0
+ //
+ idleStates[0].TransitionLatency = 0;
+ idleStates[0].ResidencyRequirement = 0;
+ idleStates[0].NominalPower = 0;
+
+ //
+ // F1
+ //
+ idleStates[1].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(200);
+ idleStates[1].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(3);
+ idleStates[1].NominalPower = 0;
+
+ //
+ // F2
+ //
+ idleStates[2].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(400);
+ idleStates[2].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(6);
+ idleStates[2].NominalPower = 0;
+
+ //
+ // F3
+ //
+ idleStates[3].TransitionLatency =
+ WDF_ABS_TIMEOUT_IN_MS(DEEPEST_FSTATE_LATENCY_IN_MS);
+ idleStates[3].ResidencyRequirement =
+ WDF_ABS_TIMEOUT_IN_SEC(DEEPEST_FSTATE_RESIDENCY_IN_SEC);
+ idleStates[3].NominalPower = 0;
+
+ //
+ // Component 0 (the only component)
+ //
+ component.IdleStateCount = FSTATE_COUNT;
+ component.IdleStates = idleStates;
+
+ WDF_POWER_FRAMEWORK_SETTINGS_INIT(&poFxSettings);
+
+ poFxSettings.EvtDeviceWdmPostPoFxRegisterDevice =
+ SingleCompWdmEvtDeviceWdmPostPoFxRegisterDevice;
+ poFxSettings.EvtDeviceWdmPrePoFxUnregisterDevice =
+ SingleCompWdmEvtDeviceWdmPrePoFxUnregisterDevice;
+
+ poFxSettings.Component = &component;
+ poFxSettings.ComponentActiveConditionCallback =
+ SingleCompWdmActiveConditionCallback;
+ poFxSettings.ComponentIdleConditionCallback =
+ SingleCompWdmIdleConditionCallback;
+ poFxSettings.ComponentIdleStateCallback =
+ SingleCompWdmIdleStateCallback;
+ poFxSettings.PoFxDeviceContext = (PVOID) Device;
+
+ status = WdfDeviceWdmAssignPowerFrameworkSettings(Device, &poFxSettings);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceWdmAssignPowerFrameworkSettings failed with "
+ "%!status!.",
+ status);
+ }
+ return status;
+}
+
+_IRQL_requires_same_
+_IRQL_requires_max_(DISPATCH_LEVEL)
+BOOLEAN
+F0Entry(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ Helper function invoked when component (representing the whole device) is
+ requested to enter F0.
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ BOOLEAN indicating whether F0 transition has completed.
+
+--*/
+{
+ //
+ // Change the F-state of the component
+ // This includes hardware-specific operations such as:
+ // * enabling DMA capabilities associated with the component
+ // * enabling interrupts associated with the component
+ // * restoring component state
+ //
+ //
+ HwSimFStateChange(Device, 0);
+ return TRUE;
+}
+
+_IRQL_requires_same_
+_IRQL_requires_max_(DISPATCH_LEVEL)
+BOOLEAN
+F0Exit(
+ _In_ WDFDEVICE Device,
+ _In_ ULONG State
+ )
+/*++
+Routine Description:
+
+ Helper function invoked when component (representing the whole device) is
+ requested to exit F0.
+
+Arguments:
+
+ Device - Handle to the framework device object
+ State - The new F-state to be entered
+
+Return Value:
+
+ BOOLEAN indicating whether Fx transition has completed.
+
+--*/
+{
+ //
+ // Change the F-state of the component
+ // This includes hardware-specific operations such as:
+ // * disabling DMA capabilities associated with the component
+ // * disabling interrupts associated with the component
+ // * saving component state
+ //
+ HwSimFStateChange(Device, State);
+ return TRUE;
+}
+
+VOID
+SingleCompWdmIdleStateCallback(
+ _In_ PVOID Context,
+ _In_ ULONG Component,
+ _In_ ULONG State
+ )
+/*++
+Routine Description:
+
+ This callback is invoked by Power Framework to notify driver about any
+ F-state transition.
+
+Arguments:
+
+ Context - Context supplied to Power Framework. KMDF supplies WDFDEVICE as
+ the context while registering with Power Framework. Hence Context
+ contains the KMDF device object.
+
+ Component - Component for which F state transition is requested. Since we
+ have only one component this value is always 0.
+
+Return Value:
+
+ BOOLEAN indicating whether Fx transition has completed.
+
+--*/
+{
+ WDFDEVICE device = NULL;
+ FDO_DATA *fdoContext = NULL;
+ BOOLEAN transitionComplete = TRUE;
+
+ //
+ // We have only component 0
+ //
+ if (0 != Component) {
+ Trace(TRACE_LEVEL_ERROR,"%!FUNC! - Unexpected component %d",Component);
+ ASSERT(FALSE);
+ }
+
+ //
+ // Get the device
+ //
+ device = (WDFDEVICE) Context;
+
+ //
+ // Get the device context
+ //
+ fdoContext = FdoGetContext(device);
+
+ //
+ // Note the new F-state
+ //
+ switch (State) {
+ case 0: {
+ transitionComplete = F0Entry(device);
+ }
+ break;
+
+ //
+ // PEP may make us go to any of the F-states directly, hence we execute
+ // F0Exit code for all of the Fx states.
+ //
+ // Transition to any Fx state happens from F0 (and not another
+ // Fx state)
+ //
+ default: {
+ ASSERT(State < FSTATE_COUNT);
+
+ transitionComplete = F0Exit(device, State);
+ }
+ break;
+ }
+
+ if (transitionComplete) {
+ PoFxCompleteIdleState(fdoContext->PoHandle, 0 /* Component */);
+ }
+}
+
+VOID
+SingleCompEvtIoDeviceControl(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength,
+ _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode
+ )
+/*++
+Routine Description:
+
+ Callback invoked by WDFQUEUE for a Device Io Control request.
+
+Arguments:
+
+ Queue - Device I/O control queue
+
+ Request - Device I/O control request
+
+ OutputBufferLength - Output buffer length for the I/O control
+
+ InputBufferLength - Input buffer length for the I/O control
+
+ IoControlCode - I/O control code
+
+--*/
+{
+ NTSTATUS status;
+ PPOWERFX_READ_COMPONENT_INPUT inputBuffer = NULL;
+ PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer = NULL;
+ WDFDEVICE device = NULL;
+ ULONG componentData;
+ ULONG_PTR information = 0;
+ FDO_DATA *fdoContext = NULL;
+
+ //
+ // When we complete the request, make sure we don't get the I/O manager to
+ // copy any more data to the client address space than what we write to the
+ // output buffer. The only data that we write to the output buffer is the
+ // component data and the C_ASSERT below ensures that the output buffer does
+ // not have room to contain anything other than that.
+ //
+ C_ASSERT(sizeof(componentData) == sizeof(*outputBuffer));
+
+ //
+ // This is a power-managed queue. So our queue stop/start logic should have
+ // ensured that we are in the active condition when a request is dispatched
+ // from this queue.
+ //
+ device = WdfIoQueueGetDevice(Queue);
+ fdoContext = FdoGetContext(device);
+ if (FALSE == fdoContext->IsActive) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - IOCTL %d was dispatched from WDFQUEUE %p when the "
+ "component was not in an active condition.",
+ IOCTL_POWERFX_READ_COMPONENT,
+ Queue);
+ WdfVerifierDbgBreakPoint();
+ }
+
+ //
+ // Validate Ioctl code
+ //
+ if (IOCTL_POWERFX_READ_COMPONENT != IoControlCode) {
+ status = STATUS_NOT_SUPPORTED;
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! -Unsupported IoControlCode. Expected: %d. Actual: %d."
+ " %!status!.",
+ IOCTL_POWERFX_READ_COMPONENT,
+ IoControlCode,
+ status);
+ goto exit;
+ }
+
+ //
+ // Validate input buffer length
+ //
+ if (InputBufferLength != sizeof(*inputBuffer)) {
+ status = STATUS_INVALID_PARAMETER;
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! -Invalid output buffer size. Expected: %d. Actual: %I64u."
+ " %!status!.",
+ sizeof(*inputBuffer),
+ InputBufferLength,
+ status);
+ goto exit;
+ }
+
+ //
+ // Validate output buffer length
+ //
+ if (OutputBufferLength != sizeof(*outputBuffer)) {
+ status = STATUS_INVALID_PARAMETER;
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! -Invalid input buffer size. Expected: %d. Actual: %I64u."
+ " %!status!.",
+ sizeof(*outputBuffer),
+ OutputBufferLength,
+ status);
+ goto exit;
+ }
+
+ //
+ // Get the output buffer
+ //
+ status = WdfRequestRetrieveOutputBuffer(Request,
+ sizeof(*outputBuffer),
+ (PVOID*) &outputBuffer,
+ NULL // Length
+ );
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfRequestRetrieveOutputBuffer failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ //
+ // Read the data from the component
+ //
+ componentData = HwSimReadComponent(device);
+ outputBuffer->ComponentData = componentData;
+ information = sizeof(*outputBuffer);
+
+ status = STATUS_SUCCESS;
+
+exit:
+ //
+ // Complete the request
+ //
+ WdfRequestCompleteWithInformation(Request, status, information);
+ return;
+}
+
+//
+// Read and write queues are only for illustration purposes - on how to stop
+// multiple queues. Currently app doesn't send Read/Write to the driver.
+//
+VOID
+SingleCompEvtIoRead(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength
+ )
+/*++
+Routine Description:
+
+ Callback invoked by WDFQUEUE for a read request.
+
+Arguments:
+
+ Queue - Read queue
+
+ Request - Read request
+
+ OutputBufferLength - Length of read
+
+--*/
+{
+ NTSTATUS status;
+
+ UNREFERENCED_PARAMETER(Queue);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ status = STATUS_NOT_SUPPORTED;
+
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! -Reads are currently not supported: %!status!.",
+ status);
+
+ WdfRequestComplete(Request, status);
+}
+
+VOID
+SingleCompEvtIoWrite(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t InputBufferLength
+ )
+/*++
+Routine Description:
+
+ Callback invoked by WDFQUEUE for a write request.
+
+Arguments:
+
+ Queue - Write queue
+
+ Request - Write request
+
+ InputBufferLength - Length of write
+
+--*/
+{
+ NTSTATUS status;
+
+ UNREFERENCED_PARAMETER(Queue);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+
+ status = STATUS_NOT_SUPPORTED;
+
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! -Writes are currently not supported: %!status!.",
+ status);
+
+ WdfRequestComplete(Request, status);
+}
+
+VOID
+SingleCompWdmActiveConditionCallback(
+ _In_ PVOID Context,
+ _In_ ULONG Component
+ )
+/*++
+Routine Description:
+
+ This callback is invoked by Power Framework to notify driver that one of its
+ components has become active.
+
+Arguments:
+
+ Context - Context that we supplied when calling
+ WdfDeviceWdmAssignPowerFrameworkSettings.
+
+ Component - Component that have become active. Since we have only one
+ component this value is always 0.
+
+Return Value:
+
+ None
+
+--*/
+{
+ WDFDEVICE device;
+ FDO_DATA *fdoContext = NULL;
+ UCHAR i = 0;
+
+ //
+ // We have only component 0
+ //
+ if (0 != Component) {
+ Trace(TRACE_LEVEL_ERROR,"%!FUNC! - Unexpected component %d",Component);
+ ASSERT(FALSE);
+ }
+
+ //
+ // Get the device
+ //
+ device = (WDFDEVICE) Context;
+
+ //
+ // Get the device context
+ //
+ fdoContext = FdoGetContext(device);
+
+ //
+ // Mark ourselves as active
+ //
+ fdoContext->IsActive = TRUE;
+
+ //
+ // Start power-managed queues
+ //
+ for (i = 0; i < QUEUE_COUNT; i++) {
+ WdfIoQueueStart(fdoContext->Queues[i]);
+ }
+
+ return;
+}
+
+VOID
+SingleCompWdmIdleConditionCallback(
+ _In_ PVOID Context,
+ _In_ ULONG Component
+ )
+/*++
+Routine Description:
+ This callback is invoked by Power Framework to notify driver that one of its
+ components has become idle.
+
+Arguments:
+
+ Context - Context that we supplied when calling
+ WdfDeviceWdmAssignPowerFrameworkSettings.
+
+ Component - Component that have become idle. Since we have only one
+ component this value is always 0.
+
+Return Value:
+
+ None
+
+--*/
+{
+ WDFDEVICE device;
+ FDO_DATA *fdoContext = NULL;
+ UCHAR i = 0;
+
+ //
+ // We have only component 0
+ //
+ if (0 != Component) {
+ Trace(TRACE_LEVEL_ERROR,"%!FUNC! - Unexpected component %d",Component);
+ ASSERT(FALSE);
+ }
+
+ //
+ // Get the device
+ //
+ device = (WDFDEVICE) Context;
+
+ //
+ // Get the device context
+ //
+ fdoContext = FdoGetContext(device);
+
+ //
+ // Initialize the count of queues to be stopped.
+ //
+ // Until we complete this idle transition there cannot be other idle
+ // transitions, which is only where we use this count. Thus nothing races
+ // with it.
+ //
+ // If you have other code that stops/starts queues, it may be simpler
+ // to queue a work-item from this callback which stops all the queues
+ // synchronously. Synchronous queue stop cannot be done from here since
+ // this callback may be called at DISPATCH_LEVEL.
+ //
+ fdoContext->QueueStopCount = QUEUE_COUNT;
+
+ //
+ // Stop power-managed queues
+ //
+ for (i = 0; i < QUEUE_COUNT; i++) {
+#pragma warning(suppress: 6387) // passing NULL Context parameter is safe in this instance
+ WdfIoQueueStop(fdoContext->Queues[i],
+ SingleCompEvtQueueStopComplete,
+ NULL /* Context */);
+ }
+
+ //
+ // The idle transition will complete asynchronously. We'll call
+ // PoFxCompleteIdleCondition to complete it when all the queues have been
+ // stopped.
+ //
+ // IMPORTANT NOTE
+ // ==============
+ // Given that the idle transition does not complete until all the power-
+ // managed queues have been stopped, it is extremely important for the
+ // driver to ensure that stopping of power-managed queues is reasonably
+ // quick. If the driver fails to ensure this, the power framework can remain
+ // stuck in the idle transition for a long time, which could hamper its
+ // ability to put the component in a low-power F-state. This could
+ // negatively impact any power savings that can be gained via component
+ // power management.
+ //
+ // In order to ensure that idle transitions can complete quickly, the driver
+ // should quickly process any requests that are dispatched to it via a
+ // power-managed queue. If the driver forwards a request (that was received
+ // via a power-managed queue) to an I/O target that might keep the request
+ // pending for a long time, then the driver should cancel the request when
+ // the component idle condition callback is invoked. This is because the
+ // power-managed queue cannot be stopped while the request is pending in the
+ // I/O target.
+ //
+ return;
+}
+
+VOID
+SingleCompEvtQueueStopComplete(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFCONTEXT Context
+ )
+/*++
+Routine Description:
+
+ Callback invoked by KMDF when stop transiton of the supplied queue has
+ completed.
+
+Arguments:
+
+ Queue - Queue whose stop transition has completed
+
+ Context - The context we supply while calling WdfIoQueueStop.
+
+Return value:
+ None
+--*/
+{
+ PFDO_DATA fdoContext;
+ WDFDEVICE device;
+
+ UNREFERENCED_PARAMETER(Context);
+
+ device = WdfIoQueueGetDevice(Queue);
+
+ fdoContext = WdfObjectGetTypedContext(device, FDO_DATA);
+
+ if (0 == InterlockedDecrement(&(fdoContext->QueueStopCount))) {
+ //
+ // All the queues have been stopped. Mark ourselves as idle and complete
+ // the idle transition.
+ //
+ fdoContext->IsActive = FALSE;
+ PoFxCompleteIdleCondition(fdoContext->PoHandle, 0 /* Component */);
+ }
+}
diff --git a/pofx/WDF/Driver/SingleComp/driver.h b/pofx/WDF/Driver/SingleComp/driver.h
new file mode 100644
index 00000000..850657c0
--- /dev/null
+++ b/pofx/WDF/Driver/SingleComp/driver.h
@@ -0,0 +1,150 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Driver.h
+
+Abstract:
+ Header file for the KMDF sample driver for a single-component device.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#define QUEUE_COUNT 3
+#define FSTATE_COUNT 4
+#define DEEPEST_FSTATE_LATENCY_IN_MS 800
+#define DEEPEST_FSTATE_RESIDENCY_IN_SEC 12
+
+//
+// This structure represents the driver's device context space
+//
+typedef struct _FDO_DATA
+{
+ //
+ // Handle of registration with Power Framework
+ //
+ POHANDLE PoHandle;
+
+ //
+ // Power-managed queues used for the device.
+ // We track them here so that we can stop/start them on active/idle
+ // transitions.
+ //
+ WDFQUEUE Queues[QUEUE_COUNT];
+
+ //
+ // Count of queues to be stopped.
+ //
+ // It is initialized to QUEUE_COUNT at the beginning of a transition to an
+ // idle condition. It is decremented everytime a queue completes stop
+ // transition.
+ //
+ // When this count reaches 0 we can transition device into an idle
+ // condition.
+ //
+ LONG QueueStopCount;
+
+ //
+ // Tracks the active/idle state of the component
+ //
+ BOOLEAN IsActive;
+} FDO_DATA, *PFDO_DATA;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_DATA, FdoGetContext)
+
+//
+// Driver's KMDF callbacks
+//
+
+DRIVER_INITIALIZE DriverEntry;
+
+EVT_WDF_DRIVER_DEVICE_ADD SingleCompEvtDeviceAdd;
+EVT_WDF_OBJECT_CONTEXT_CLEANUP SingleCompEvtDriverCleanup;
+
+EVT_WDF_DEVICE_D0_ENTRY SingleCompEvtDeviceD0Entry;
+EVT_WDF_DEVICE_D0_EXIT SingleCompEvtDeviceD0Exit;
+
+
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SingleCompEvtIoDeviceControl;
+EVT_WDF_IO_QUEUE_IO_READ SingleCompEvtIoRead;
+EVT_WDF_IO_QUEUE_IO_WRITE SingleCompEvtIoWrite;
+EVT_WDF_IO_QUEUE_STATE SingleCompEvtQueueStopComplete;
+
+EVT_WDFDEVICE_WDM_POST_PO_FX_REGISTER_DEVICE SingleCompWdmEvtDeviceWdmPostPoFxRegisterDevice;
+EVT_WDFDEVICE_WDM_PRE_PO_FX_UNREGISTER_DEVICE SingleCompWdmEvtDeviceWdmPrePoFxUnregisterDevice;
+
+//
+// Driver's power framework callbacks
+//
+PO_FX_COMPONENT_ACTIVE_CONDITION_CALLBACK SingleCompWdmActiveConditionCallback;
+PO_FX_COMPONENT_IDLE_CONDITION_CALLBACK SingleCompWdmIdleConditionCallback;
+PO_FX_COMPONENT_IDLE_STATE_CALLBACK SingleCompWdmIdleStateCallback;
+
+//
+// Helper functions
+//
+
+_IRQL_requires_same_
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS
+AssignS0IdleSettings(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_same_
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS
+AssignPowerFrameworkSettings(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_same_
+_IRQL_requires_max_(DISPATCH_LEVEL)
+BOOLEAN
+F0Entry(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_same_
+_IRQL_requires_max_(DISPATCH_LEVEL)
+BOOLEAN
+F0Exit(
+ _In_ WDFDEVICE Device,
+ _In_ ULONG State
+ );
+
+//
+// Define the tracing flags.
+//
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ MyDriverTraceControl, (f9eb5c3a,c292,4c69,8b52,ccf043c25ab0), \
+ \
+ 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
+//
diff --git a/pofx/WDF/Driver/SingleComp/include.h b/pofx/WDF/Driver/SingleComp/include.h
new file mode 100644
index 00000000..d80fa458
--- /dev/null
+++ b/pofx/WDF/Driver/SingleComp/include.h
@@ -0,0 +1,3 @@
+#include <ntddk.h>
+#include <wdf.h>
+#include "driver.h" \ No newline at end of file