summaryrefslogtreecommitdiff
path: root/pofx/WDF/App
diff options
context:
space:
mode:
Diffstat (limited to 'pofx/WDF/App')
-rw-r--r--pofx/WDF/App/PowerFxApp.cpp592
-rw-r--r--pofx/WDF/App/PowerFxApp.vcxproj192
-rw-r--r--pofx/WDF/App/PowerFxApp.vcxproj.Filters25
-rw-r--r--pofx/WDF/App/UserInput.cpp201
-rw-r--r--pofx/WDF/App/include.h95
5 files changed, 1105 insertions, 0 deletions
diff --git a/pofx/WDF/App/PowerFxApp.cpp b/pofx/WDF/App/PowerFxApp.cpp
new file mode 100644
index 00000000..c628d366
--- /dev/null
+++ b/pofx/WDF/App/PowerFxApp.cpp
@@ -0,0 +1,592 @@
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Module Name:
+
+ PowerFxApp.cpp
+
+Abstract:
+
+ This application can be used to exercise KMDF sample drivers for the
+ new power framework. See application "usage" details for more information.
+
+Environment:
+
+ user mode only
+
+--*/
+
+#include "include.h"
+
+int __cdecl
+wmain(
+ _In_ int argc,
+ _In_reads_(argc) PWSTR argv[]
+ )
+{
+ DWORD err;
+ WCHAR devicePath[MAX_DEVPATH_LENGTH] = {UNICODE_NULL};
+ HANDLE hDevice = INVALID_HANDLE_VALUE;
+ HANDLE hCompletionPort = NULL;
+
+
+ //
+ // Process user input.
+ //
+ err = ProcessUserInput(argc, argv);
+ if (ERROR_SUCCESS != err)
+ {
+ goto clean0;
+ }
+
+ if ( !GetDevicePath(
+ (LPGUID) &GUID_DEVINTERFACE_POWERFX,
+ devicePath,
+ COUNT_OF(devicePath)))
+ {
+ printf("Unable to get device path. Has the device driver been installed? \n");
+ err = ERROR_OPEN_FAILED;
+ goto clean0;
+ }
+
+ hDevice = CreateFile(devicePath,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL );
+
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ err = GetLastError();
+ printf("Failed to open device. Error %d.\n",err);
+ goto clean0;
+ }
+
+ hCompletionPort = CreateIoCompletionPort(hDevice, NULL, 1, 0);
+ if (hCompletionPort == NULL) {
+ err = GetLastError();
+ printf("Cannot open completion port %d.\n",err);
+ goto clean0;
+ }
+
+ err = SendIO(hDevice,
+ hCompletionPort,
+ GetSetting(COMPONENT),
+ GetSetting(MAX_OUTSTANDING_IO),
+ GetSetting(DELAY),
+ (BOOLEAN)GetSetting(CANCEL));
+ if (ERROR_SUCCESS != err)
+ {
+ goto clean0;
+ }
+
+clean0:
+ if (INVALID_HANDLE_VALUE != hDevice)
+ {
+ CloseHandle(hDevice);
+ }
+ if (NULL != hCompletionPort)
+ {
+ CloseHandle(hCompletionPort);
+ }
+ return err;
+}
+
+DWORD Initialize(
+ _In_ ULONG Count,
+ _Out_ LPOVERLAPPED *pOverlappedPtr,
+ _Out_ PPOWERFX_READ_COMPONENT_INPUT *pInput,
+ _Out_ PPOWERFX_READ_COMPONENT_OUTPUT *pOutput
+ )
+{
+ PPOWERFX_READ_COMPONENT_INPUT inputBuffer = NULL;
+ PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer = NULL;
+ LPOVERLAPPED pOverlapped = NULL;
+ DWORD err = ERROR_SUCCESS;
+
+ pOverlapped = new OVERLAPPED[Count];
+ if (NULL == pOverlapped)
+ {
+ err = ERROR_OUTOFMEMORY;
+ goto clean0;
+ }
+
+ inputBuffer = new POWERFX_READ_COMPONENT_INPUT[Count];
+ if (NULL == inputBuffer)
+ {
+ err = ERROR_OUTOFMEMORY;
+ goto clean0;
+ }
+
+ outputBuffer = new POWERFX_READ_COMPONENT_OUTPUT[Count];
+ if (NULL == outputBuffer)
+ {
+ err = ERROR_OUTOFMEMORY;
+ goto clean0;
+ }
+
+ ZeroMemory(pOverlapped,
+ sizeof(OVERLAPPED)*Count);
+
+ for (UINT i = 0; i < Count; i++)
+ {
+ //
+ // When the component number is set to UNUSED it indicates
+ // that a request has not been issued (or has completed)
+ // using this input buffer. Hence the buffer along with the
+ // overlapped structure at the corresponding index is available
+ // for issuing a request.
+ //
+ inputBuffer[i].ComponentNumber = UNUSED;
+ }
+
+ ZeroMemory(outputBuffer,
+ sizeof(POWERFX_READ_COMPONENT_OUTPUT)*Count);
+
+clean0:
+ if (err != ERROR_SUCCESS)
+ {
+ delete[] pOverlapped;
+ delete[] inputBuffer;
+ delete[] outputBuffer;
+ }
+ else
+ {
+ *pOverlappedPtr = pOverlapped;
+ *pInput = inputBuffer;
+ *pOutput = outputBuffer;
+ }
+ return err;
+}
+
+/*++
+
+Routine Description:
+
+ This function sends requests to the driver based on the settings passed
+ in the arguments. The requests are sent indefinitely until an error occurs.
+
+ Depending on the number of maximum outstanding I/O requests,
+ an array of overlapped structures and input/output buffers is allocated.
+ The method then loops through the overlapped structure array
+ to issue asynchronous requests. When a request completes, the
+ overlapped structure for that request is not immediately re-used to issue
+ a new request. Instead the method goes in-order through the array to
+ ensure that each issued request is completed in a reasonable amount
+ of time and it is able to detect if one or more requests do not complete
+ at all (or within the specified timeout).
+
+--*/
+DWORD SendIO(
+ _In_ HANDLE DeviceHandle,
+ _In_ HANDLE CompletionPortHandle,
+ _In_ ULONG Component,
+ _In_ ULONG MaxOutstandingIo,
+ _In_ ULONG Delay,
+ _In_ BOOLEAN Cancel
+ )
+{
+ LPOVERLAPPED pOverlapped = NULL;
+ LPOVERLAPPED pOv = NULL;
+ PPOWERFX_READ_COMPONENT_INPUT inputBuffer = NULL;
+ PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer = NULL;
+ DWORD err = ERROR_SUCCESS;
+ UINT outstandingIoCount = 0;
+ UINT index = 0;
+
+ srand((DWORD)GetTickCount64());
+
+ err = Initialize(MaxOutstandingIo,
+ &pOverlapped,
+ &inputBuffer,
+ &outputBuffer);
+ if (ERROR_SUCCESS != err)
+ {
+ goto clean0;
+ }
+
+ UINT k = 0;
+
+ for (;;k++)
+ {
+ k = k % MaxOutstandingIo;
+
+ if (UNUSED == inputBuffer[k].ComponentNumber)
+ {
+ //
+ // This indicates the input buffer and corresponding overlapped
+ // structure is available to issue a new request.
+ //
+ pOv = &pOverlapped[k];
+ }
+ else
+ {
+ //
+ // Wait for request #k to complete.
+ //
+ DWORD completionStatus;
+ ULONGLONG startTime = GetTickCount64();
+
+ for(;;)
+ {
+ ULONG_PTR completedRequestIndex;
+
+ err = WaitForIoCompletion(CompletionPortHandle,
+ &pOv,
+ &completionStatus);
+ if (ERROR_SUCCESS != err) {
+ goto clean0;
+ }
+
+ completedRequestIndex = pOv-pOverlapped;
+
+ printf(" Request %d completed with status 0x%X.\n",
+ (DWORD)completedRequestIndex, completionStatus);
+
+ if (ERROR_SUCCESS != completionStatus)
+ {
+ if (!Cancel ||
+ ERROR_OPERATION_ABORTED != completionStatus)
+ {
+ //
+ // If there is a setting to cancel requests it is ok for
+ // the requests to complete with aborted status.
+ //
+ err = completionStatus;
+ printf(" Unexpected completion status %d. \n",
+ completionStatus);
+ goto clean0;
+ }
+ }
+ else
+ {
+ //
+ // If request completed successfully verify the contents of the buffer.
+ //
+ if (! VerifyRequest(&inputBuffer[completedRequestIndex],
+ &outputBuffer[completedRequestIndex]))
+ {
+ printf(" Request completed with unexpected data in"
+ " output buffer. \n");
+ err = ERROR_INVALID_DATA;
+ goto clean0;
+ }
+ }
+
+ inputBuffer[completedRequestIndex].ComponentNumber = UNUSED;
+ outstandingIoCount--;
+
+ if (k == completedRequestIndex)
+ {
+ //
+ // The request we are looking for has completed.
+ //
+ pOv = &pOverlapped[k];
+ break;
+ }
+ else if (GetTickCount64() - startTime > REQUEST_TIMEOUT)
+ {
+ //
+ // The request we are looking for did not complete on time.
+ //
+ err = ERROR_TIMEOUT;
+ printf(" Request %d did not complete within the expected"
+ " time. \n", k);
+ assert(0);
+ goto clean0;
+ }
+ }
+
+ }
+
+ //
+ // We now have an overlapped structure to use. Set the input buffer
+ // to the target component and send the request.
+ //
+ ZeroMemory(pOv, sizeof(OVERLAPPED));
+ inputBuffer[k].ComponentNumber = (Component == RANDOM_COMPONENT) ?
+ (rand() % COMPONENT_COUNT):
+ Component;
+
+ if (0 != Delay)
+ {
+ //
+ // If there is a setting to introduce a delay, sleep and then send the
+ // request.
+ //
+ Sleep(rand() % Delay);
+ }
+
+ err = SendRequest(DeviceHandle,
+ pOv,
+ &inputBuffer[k],
+ &outputBuffer[k]);
+ if (ERROR_SUCCESS != err)
+ {
+ goto clean0;
+ }
+
+ outstandingIoCount++;
+
+ printf(" Request number %d sent to component %d.\n", k,
+ inputBuffer[k].ComponentNumber);
+
+ if (Cancel)
+ {
+ //
+ // If there is a setting to cancel the request then cancel it after
+ // issuing it.
+ //
+ CancelIoEx(DeviceHandle,
+ pOv);
+ }
+ }
+
+clean0:
+ if (outstandingIoCount > 0)
+ {
+ CancelIo(DeviceHandle);
+ for (index=0; index < outstandingIoCount; index++)
+ {
+ WaitForIoCompletion(CompletionPortHandle,
+ NULL,
+ NULL);
+ }
+ }
+ delete[] pOverlapped;
+ delete[] inputBuffer;
+ delete[] outputBuffer;
+ return err;
+}
+
+BOOLEAN
+VerifyRequest(
+ _In_ PPOWERFX_READ_COMPONENT_INPUT input,
+ _In_ PPOWERFX_READ_COMPONENT_OUTPUT output)
+{
+ return (output->ComponentData == ~input->ComponentNumber);
+}
+
+DWORD
+SendRequest(
+ _In_ HANDLE DeviceHandle,
+ _In_ LPOVERLAPPED OverlappedPtr,
+ _In_ PPOWERFX_READ_COMPONENT_INPUT inputBuffer,
+ _In_ PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer)
+{
+
+ BOOL bResult = FALSE;
+ DWORD err = ERROR_SUCCESS;
+
+ bResult = DeviceIoControl(DeviceHandle,
+ (DWORD) IOCTL_POWERFX_READ_COMPONENT,
+ (PVOID)inputBuffer,
+ sizeof(POWERFX_READ_COMPONENT_INPUT),
+ (PVOID)outputBuffer,
+ sizeof(POWERFX_READ_COMPONENT_OUTPUT),
+ NULL,
+ OverlappedPtr);
+ if (FALSE == bResult)
+ {
+ err = GetLastError();
+ if (ERROR_IO_PENDING == err)
+ {
+ //
+ // This is not really an error.
+ //
+ err = ERROR_SUCCESS;
+ }
+ else
+ {
+ printf("Unable to send request. DeviceIoControl failed with "
+ "error 0x%X. \n", err);
+ goto clean0;
+ }
+ }
+clean0:
+ return err;
+}
+
+DWORD
+WaitForIoCompletion(
+ _In_ HANDLE CompletionPortHandle,
+ _In_opt_ LPOVERLAPPED* POvPtr,
+ _Out_opt_ PDWORD CompletionStatus)
+{
+ BOOL bResult;
+ DWORD err;
+ DWORD numBytes;
+ ULONG_PTR completionKey;
+ LPOVERLAPPED ovPtr;
+ DWORD completionStatus;
+
+ //
+ // Assume successful completion of I/O request
+ //
+ completionStatus = ERROR_SUCCESS;
+
+ //
+ // Dequeue a completion packet
+ //
+ bResult = GetQueuedCompletionStatus(CompletionPortHandle,
+ &numBytes,
+ &completionKey,
+ &ovPtr,
+ REQUEST_TIMEOUT);
+ if (FALSE == bResult)
+ {
+ err = GetLastError();
+ if (NULL == ovPtr)
+ {
+ printf("Could not dequeue a completion packet. "
+ "GetQueuedCompletionStatus failed with error 0x%X.",
+ err);
+ assert(0);
+ goto clean0;
+ }
+
+ //
+ // We dequeued a completion packet for an I/O operation that failed.
+ // Make a note of the failure status, but we need to return success from
+ // this function because we got a completion packet (even though it was
+ // for a failed I/O operation).
+ //
+ completionStatus = err;
+ err = ERROR_SUCCESS;
+ }
+
+ if (NULL != POvPtr) {
+ *POvPtr = ovPtr;
+ }
+
+ if (NULL != CompletionStatus) {
+ *CompletionStatus = completionStatus;
+ }
+
+ err = ERROR_SUCCESS;
+
+clean0:
+ return err;
+}
+
+BOOL
+GetDevicePath(
+ IN LPGUID InterfaceGuid,
+ _Out_writes_(BufLen) PWSTR DevicePath,
+ _In_ size_t BufLen
+ )
+{
+ HDEVINFO HardwareDeviceInfo;
+ SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
+ ULONG Length, RequiredLength = 0;
+ BOOL bResult;
+ HRESULT hr;
+
+ HardwareDeviceInfo = SetupDiGetClassDevs(
+ InterfaceGuid,
+ NULL,
+ NULL,
+ (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+
+ if (HardwareDeviceInfo == INVALID_HANDLE_VALUE) {
+ printf("SetupDiGetClassDevs failed!\n");
+ return FALSE;
+ }
+
+ DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
+ 0,
+ InterfaceGuid,
+ 0,
+ &DeviceInterfaceData);
+
+ if (bResult == FALSE) {
+
+ LPVOID lpMsgBuf;
+
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR) &lpMsgBuf,
+ 0,
+ NULL
+ )) {
+
+ printf("SetupDiEnumDeviceInterfaces failed: %ws", (LPTSTR)lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
+
+ printf("SetupDiEnumDeviceInterfaces failed.\n");
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ return FALSE;
+ }
+
+ SetupDiGetDeviceInterfaceDetail(
+ HardwareDeviceInfo,
+ &DeviceInterfaceData,
+ NULL,
+ 0,
+ &RequiredLength,
+ NULL
+ );
+
+ DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, RequiredLength);
+
+ if (DeviceInterfaceDetailData == NULL) {
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ printf("Failed to allocate memory.\n");
+ return FALSE;
+ }
+
+ DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+ Length = RequiredLength;
+
+ bResult = SetupDiGetDeviceInterfaceDetail(
+ HardwareDeviceInfo,
+ &DeviceInterfaceData,
+ DeviceInterfaceDetailData,
+ Length,
+ &RequiredLength,
+ NULL);
+
+ if (bResult == FALSE) {
+
+ LPVOID lpMsgBuf;
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ printf("Error in SetupDiGetDeviceInterfaceDetail: %ws\n", (LPWSTR)lpMsgBuf);
+ LocalFree(DeviceInterfaceDetailData);
+ LocalFree(lpMsgBuf);
+ return FALSE;
+ }
+
+ hr = StringCchCopy(DevicePath,
+ BufLen,
+ DeviceInterfaceDetailData->DevicePath) ;
+
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo); // It must be executed in both success and failure traces
+ LocalFree(DeviceInterfaceDetailData);
+
+ return ( !FAILED(hr) ); // Result depends on StringCchCopy()
+}
+
+
diff --git a/pofx/WDF/App/PowerFxApp.vcxproj b/pofx/WDF/App/PowerFxApp.vcxproj
new file mode 100644
index 00000000..32b104c3
--- /dev/null
+++ b/pofx/WDF/App/PowerFxApp.vcxproj
@@ -0,0 +1,192 @@
+<?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>{3E233D0A-F988-4C9D-B15A-49B54025E11F}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{11455AB9-264E-4853-AE1E-615C1C5CA620}</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 />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</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" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>PowerFxApp</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>PowerFxApp</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>PowerFxApp</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>PowerFxApp</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="PowerFxApp.cpp" />
+ <ClCompile Include="UserInput.cpp" />
+ </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/pofx/WDF/App/PowerFxApp.vcxproj.Filters b/pofx/WDF/App/PowerFxApp.vcxproj.Filters
new file mode 100644
index 00000000..8d16d12b
--- /dev/null
+++ b/pofx/WDF/App/PowerFxApp.vcxproj.Filters
@@ -0,0 +1,25 @@
+<?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>{C8B06C0E-8C3C-4875-8327-4C592F8FD738}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{8091FCE2-2451-4561-B199-CB021902EA1B}</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>{CC2C62EE-9135-480E-9DF9-5DB6BEB61DE8}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="PowerFxApp.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="UserInput.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/pofx/WDF/App/UserInput.cpp b/pofx/WDF/App/UserInput.cpp
new file mode 100644
index 00000000..dcd3ca75
--- /dev/null
+++ b/pofx/WDF/App/UserInput.cpp
@@ -0,0 +1,201 @@
+#include "include.h"
+
+
+//
+// The supported settings with their default values.
+//
+CONFIGURATION g_UserSettings[] = {
+ {COMPONENT ,0},
+ {MAX_OUTSTANDING_IO ,1},
+ {DELAY ,0},
+ {CANCEL ,0}
+};
+
+DWORD
+ProcessUserInput(
+ _In_ int argc,
+ _In_reads_(argc) PWSTR argv[]
+ )
+{
+ DWORD err = ERROR_SUCCESS;
+
+ for (int i=1; i < argc; i++)
+ {
+ PWSTR arg = argv[i];
+
+ //
+ // Setting must begin with / or -
+ //
+ if (arg[0] != L'-' && arg[0] != L'/')
+ {
+ printf("\n Invalid command-line argument %ws. \n", arg);
+ err = ERROR_INVALID_PARAMETER;
+ goto clean0;
+ }
+
+ if (L'?' == arg[1])
+ {
+ err = ERROR_INVALID_PARAMETER;
+ goto clean0;
+ }
+
+ //
+ // Setting must contain ':' as the seperator.
+ //
+ PWSTR settingName = arg + 1;
+ PWSTR settingValue = NULL;
+ PWSTR seperator = wcschr(settingName, L':');
+ if (seperator == NULL)
+ {
+ printf("\n Invalid command-line argument %ws. \n", arg);
+ err = ERROR_INVALID_PARAMETER;
+ goto clean0;
+ }
+
+ settingValue = seperator + 1;
+ *seperator = L'\0';
+
+ //
+ // Store the value of the setting in the appropriate location.
+ //
+ err = ProcessSwitch(settingName, settingValue);
+ if (err != ERROR_SUCCESS)
+ {
+ goto clean0;
+ }
+ }
+
+clean0:
+
+ if (ERROR_SUCCESS != err)
+ {
+ PrintUsage(argv);
+ }
+ return err;
+}
+
+
+PCONFIGURATION
+LookupSwitch(
+ _In_ PWSTR Param)
+{
+ for (UINT i=0; i < COUNT_OF(g_UserSettings); i++)
+ {
+ if (_wcsicmp(Param, g_UserSettings[i].Option) == 0)
+ {
+ return &g_UserSettings[i];
+ }
+ }
+
+ return NULL;
+}
+
+ULONG
+GetSetting(
+ _In_ PWSTR Switch)
+{
+ return LookupSwitch(Switch)->Value;
+}
+
+DWORD
+ProcessSwitch(
+ _In_ PWSTR Param,
+ _In_ PWSTR Value)
+{
+ PCONFIGURATION config;
+
+ config = LookupSwitch(Param);
+ if (NULL == config)
+ {
+ printf("\n '%ws' is not a valid switch", Param);
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if (0 == _wcsicmp(Param, COMPONENT))
+ {
+ if (0 == _wcsicmp(Value, L"*"))
+ {
+ config->Value = RANDOM_COMPONENT;
+ }
+ else
+ {
+ config->Value = _wtoi(Value);
+ if (config->Value >= COMPONENT_COUNT)
+ {
+ printf("Invalid component count '%ws' specified. "
+ "Component count must be less than %d. \n", Value, COMPONENT_COUNT);
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ }
+ else if (0 == _wcsicmp(Param, CANCEL))
+ {
+ if (0 == _wcsicmp(Value, L"yes"))
+ {
+ config->Value = TRUE;
+ }
+ else if (0 == _wcsicmp(Value, L"no"))
+ {
+ config->Value = FALSE;
+ }
+ else
+ {
+ printf("'%ws' is not a valid option for '%ws'. Must be 'yes' or 'no'. \n",
+ Value, Param);
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ //
+ // For MaxOutstandingIo or Delay this is sufficient.
+ //
+ config->Value = _wtoi(Value);
+ if (0 == config->Value)
+ {
+ printf("'%ws' is not a valid option for '%ws'", Value, Param);
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+void PrintUsage(
+ _In_ PWSTR argv[]
+ )
+{
+ printf("\n This application can be used to send IO requests to a specified component");
+ printf("\n of the WDF Power Fx sample driver. The requests will be sent indefinitely ");
+ printf("\n until a request fails or the user terminates the execution with ^C");
+ printf("\n More details on the driver and application are in the associated help file.");
+ printf("\n ");
+ printf("\n Usage:");
+ printf("\n %ws [/<SettingName>:<SettingValue> ...]", argv[0]);
+ printf("\n ");
+ printf("\n Available settings are:");
+ printf("\n ");
+ printf("\n /Component:<Number>");
+ printf("\n Where <Number> can be a specific component number, or if you are running with");
+ printf("\n the multi-component sample driver you can specify '*'(without quotes) and ");
+ printf("\n each request will be sent to a random component between 0 and ");
+ printf("\n (COMPONENT_COUNT-1). Default value is component 0.");
+ printf("\n ");
+ printf("\n /Delay:<DelayInMilliSeconds>");
+ printf("\n There is an approximate delay between 0 and <DelayInMilliSeconds> ms");
+ printf("\n between each request. Default value is 0 (no delay).");
+ printf("\n ");
+ printf("\n /MaxOutstandingIO:<NumberOfRequests>");
+ printf("\n The maximum number of I/O requests that can be outstanding at any point.");
+ printf("\n Default value is 1 (equivalent to synchronously sending requests).");
+ printf("\n ");
+ printf("\n /Cancel:<YesNo>");
+ printf("\n Can be 'yes' or 'no' (without quotes).");
+ printf("\n When set to 'yes' the application will attempt to cancel the requests once ");
+ printf("\n sent. Default value is 'no'.");
+ printf("\n ");
+ return;
+}
+
diff --git a/pofx/WDF/App/include.h b/pofx/WDF/App/include.h
new file mode 100644
index 00000000..29f0cb5e
--- /dev/null
+++ b/pofx/WDF/App/include.h
@@ -0,0 +1,95 @@
+/*++
+
+
+--*/
+#include <DriverSpecs.h>
+ _Analysis_mode_(_Analysis_code_type_user_code_)
+
+#define INITGUID
+
+#include <windows.h>
+#include <strsafe.h>
+#include <setupapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <devioctl.h>
+#include <assert.h>
+#include "AppInterface.h"
+
+#define COUNT_OF(x) sizeof(x)/sizeof(x[0])
+
+#define MAX_DEVPATH_LENGTH 256
+
+#define COMPONENT L"Component"
+#define MAX_OUTSTANDING_IO L"MaxOutStandingIO"
+#define DELAY L"Delay"
+#define CANCEL L"Cancel"
+
+typedef struct _CONFIGURATION {
+ PWSTR Option;
+ ULONG Value;
+} CONFIGURATION, *PCONFIGURATION;
+
+#define RANDOM_COMPONENT (DWORD)-1
+#define UNUSED COMPONENT_COUNT
+#define REQUEST_TIMEOUT 10000
+#define MAX_DEVPATH_LENGTH 256
+
+PCONFIGURATION
+LookupSwitch(
+ _In_ PWSTR Param);
+
+DWORD
+ProcessUserInput(
+ _In_ int argc,
+ _In_reads_(argc) PWSTR argv[]
+ );
+
+ULONG
+GetSetting(
+ _In_ PWSTR Switch);
+
+DWORD
+ProcessSwitch(
+ _In_ PWSTR Param,
+ _In_ PWSTR Value);
+
+void PrintUsage(
+ _In_ PWSTR argv[]
+ );
+
+BOOL
+GetDevicePath(
+ IN LPGUID InterfaceGuid,
+ _Out_writes_(BufLen) PWCHAR DevicePath,
+ _In_ size_t BufLen
+ );
+
+
+DWORD SendIO(
+ _In_ HANDLE DeviceHandle,
+ _In_ HANDLE CompletionPortHandle,
+ _In_ ULONG Component,
+ _In_ ULONG MaxOutstandingIo,
+ _In_ ULONG Delay,
+ _In_ BOOLEAN Cancel
+ );
+
+DWORD
+WaitForIoCompletion(
+ _In_ HANDLE CompletionPortHandle,
+ _In_opt_ LPOVERLAPPED* POvPtr,
+ _Out_opt_ PDWORD CompletionStatus);
+
+BOOLEAN
+VerifyRequest(
+ _In_ PPOWERFX_READ_COMPONENT_INPUT input,
+ _In_ PPOWERFX_READ_COMPONENT_OUTPUT output);
+
+DWORD
+SendRequest(
+ _In_ HANDLE DeviceHandle,
+ _In_ LPOVERLAPPED OverlappedPtr,
+ _In_ PPOWERFX_READ_COMPONENT_INPUT inputBuffer,
+ _In_ PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer);
+