mirror of
https://github.com/ekinnee/SharpCAT.git
synced 2025-12-06 03:31:59 +01:00
Remove VirtualSerial2 directory and all its contents
Co-authored-by: ekinnee <1707617+ekinnee@users.noreply.github.com>
This commit is contained in:
parent
1881bfb8cc
commit
bcbafbf8b3
|
|
@ -1,187 +0,0 @@
|
|||
<?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>{65A037CB-9245-442A-A791-5CFC34E97BF7}</ProjectGuid>
|
||||
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<SampleGuid>{D3E77C62-C6F0-4210-824E-1875C7B48EC5}</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>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>Universal</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>Universal</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>Universal</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" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetName>VirtualSerial2um</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>VirtualSerial2um</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<TargetName>VirtualSerial2um</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<TargetName>VirtualSerial2um</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\device.c" />
|
||||
<ClCompile Include="..\driver.c" />
|
||||
<ClCompile Include="..\queue.c" />
|
||||
<ClCompile Include="..\ringbuffer.c" />
|
||||
<ResourceCompile Include="virtualserial2um.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Exclude="@(Inf)" Include="*.inx" />
|
||||
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
|
||||
</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>
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
<?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>{75562F82-D2DC-4C96-8D1E-01C195D61A2C}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
<UniqueIdentifier>{0748F304-5FE6-4C01-B27A-3CD7B1A268B7}</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>{87F14B94-F7A4-42E8-9931-8ADDA3989EBD}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Driver Files">
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
<UniqueIdentifier>{30F678DB-C12C-461E-8128-CE409AAC9C42}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\device.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\driver.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\queue.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ringbuffer.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="virtualserial2um.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
|
|
@ -1,17 +0,0 @@
|
|||
//---------------------------------------------------------------------------
|
||||
// Virtualserial.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 VirtualSerial User-Mode v2 Driver Sample"
|
||||
#define VER_INTERNALNAME_STR "VirtualSerial2um"
|
||||
#define VER_ORIGINALFILENAME_STR "Virtualserial2um.dll"
|
||||
|
||||
#include "common.ver"
|
||||
Binary file not shown.
|
|
@ -1,17 +0,0 @@
|
|||
//---------------------------------------------------------------------------
|
||||
// FakeModem.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 Fake Modem User-Mode Driver Sample"
|
||||
#define VER_INTERNALNAME_STR "FakeModem2um"
|
||||
#define VER_ORIGINALFILENAME_STR "FakeModem2um.dll"
|
||||
|
||||
#include "common.ver"
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
<?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>{CD78D78F-B132-4E6F-A11F-B62185A6152A}</ProjectGuid>
|
||||
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<SampleGuid>{3E00ED06-5DB5-444F-8FFA-D098A0218DF2}</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>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>Universal</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>Universal</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>Universal</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" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetName>fakemodem2um</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>fakemodem2um</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<TargetName>fakemodem2um</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<TargetName>fakemodem2um</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;_FAKE_MODEM=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)\wdm;..\..\inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\device.c" />
|
||||
<ClCompile Include="..\driver.c" />
|
||||
<ClCompile Include="..\queue.c" />
|
||||
<ClCompile Include="..\ringbuffer.c" />
|
||||
<ResourceCompile Include="fakemodem2um.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Exclude="@(Inf)" Include="*.inx" />
|
||||
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
|
||||
</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>
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
<?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>{5A926099-4361-4BDC-BF0F-D98AD6F55C3A}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
<UniqueIdentifier>{9C5FC831-BCE8-4E84-8BED-0B1182AA7358}</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>{43B83C13-0033-4A5E-A0DB-F0BA1B304FB0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Driver Files">
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
<UniqueIdentifier>{83A3125A-7FA1-4416-B24A-FA9C1EECAAF0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\device.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\driver.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\queue.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ringbuffer.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="fakemodem2um.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
---
|
||||
page_type: sample
|
||||
urlFragment: virtual-serial-driver-sample-v2
|
||||
description: "Demonstrates UMDF version 2 serial drivers and includes a simple virtual serial driver (ComPort) and a controller-less modem driver (FakeModem)."
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows
|
||||
- windows-wdk
|
||||
---
|
||||
|
||||
# Virtual serial driver sample (V2)
|
||||
|
||||
This sample demonstrates these two serial drivers:
|
||||
|
||||
- A simple virtual serial driver (ComPort)
|
||||
|
||||
- A controller-less modem driver (FakeModem).This driver supports sending and receiving AT commands using the ReadFile and WriteFile calls or via a TAPI interface using an application such as, HyperTerminal.
|
||||
|
||||
This sample driver is a minimal driver meant to demonstrate the usage of the User-Mode Driver Framework. It is not intended for use in a production environment.
|
||||
|
||||
For more information, see the [Serial Controller Driver Design Guide](https://docs.microsoft.com/windows-hardware/drivers/serports/).
|
||||
|
||||
## Code tour
|
||||
|
||||
### comsup.cpp and comsup.h
|
||||
|
||||
- COM Support code - specifically base classes which provide implementations for the standard COM interfaces **IUnknown** and **IClassFactory** which are used throughout the sample.
|
||||
|
||||
- The implementation of **IClassFactory** is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file.
|
||||
|
||||
### dllsup.cpp
|
||||
|
||||
- DLL Support code - provides the DLL's entry point as well as the single required export (**DllGetClassObject**).
|
||||
|
||||
- These depend on comsup.cpp to perform the necessary class creation.
|
||||
|
||||
### exports.def
|
||||
|
||||
- This file lists the functions that the driver DLL exports.
|
||||
|
||||
### internal.h
|
||||
|
||||
- This is the main header file for the sample driver.
|
||||
|
||||
### driver.cpp and driver.h
|
||||
|
||||
- Definition and implementation of the driver callback class (CMyDriver) for the sample. This includes **DriverEntry** and events on the framework driver object.
|
||||
|
||||
### device.cpp and driver.h
|
||||
|
||||
- Definition and implementation of the device callback class (CMyDriver) for the sample. This includes events on the framework device object.
|
||||
|
||||
### queue.cpp and queue.h
|
||||
|
||||
- Definition and implementation of the base queue callback class (CMyQueue). This includes events on the framework I/O queue object.
|
||||
|
||||
### VirtualSerial.rc /FakeModem.rc
|
||||
|
||||
- This file defines resource information for the sample driver.
|
||||
|
||||
### VirtualSerial.inf / FakeModem.inf
|
||||
|
||||
- INF file that contains installation information for this driver.
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0
|
||||
MinimumVisualStudioVersion = 12.0
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ComPort", "ComPort", "{F7F21610-DDE7-4709-9C48-68A0ABD1FF65}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FakeModem", "FakeModem", "{704FA9C6-88FA-4381-8FA5-3407E62FAF20}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualSerial2um", "ComPort\VirtualSerial2um.vcxproj", "{65A037CB-9245-442A-A791-5CFC34E97BF7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fakemodem2um", "FakeModem\fakemodem2um.vcxproj", "{CD78D78F-B132-4E6F-A11F-B62185A6152A}"
|
||||
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
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7}.Release|Win32.Build.0 = Release|Win32
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7}.Debug|x64.Build.0 = Debug|x64
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7}.Release|x64.ActiveCfg = Release|x64
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7}.Release|x64.Build.0 = Release|x64
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A}.Release|Win32.Build.0 = Release|Win32
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A}.Debug|x64.Build.0 = Debug|x64
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A}.Release|x64.ActiveCfg = Release|x64
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{65A037CB-9245-442A-A791-5CFC34E97BF7} = {F7F21610-DDE7-4709-9C48-68A0ABD1FF65}
|
||||
{CD78D78F-B132-4E6F-A11F-B62185A6152A} = {704FA9C6-88FA-4381-8FA5-3407E62FAF20}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,449 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, All Rights Reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
Device.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the implementation of the VirtualSerial sample
|
||||
driver's device callback object.
|
||||
|
||||
The VirtualSerial sample device does very little. It does not implement
|
||||
either of the PNP interfaces so once the device is setup, it won't ever get
|
||||
any callbacks until the device is removed.
|
||||
|
||||
Environment:
|
||||
|
||||
Windows Driver Framework
|
||||
|
||||
--*/
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
NTSTATUS
|
||||
DeviceCreate(
|
||||
_In_ WDFDRIVER Driver,
|
||||
_In_ PWDFDEVICE_INIT DeviceInit,
|
||||
_Out_ PDEVICE_CONTEXT *DeviceContext
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This method creates and initializs an instance of the VirtualSerial 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
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDF_OBJECT_ATTRIBUTES deviceAttributes;
|
||||
WDFDEVICE device;
|
||||
PDEVICE_CONTEXT deviceContext;
|
||||
UNREFERENCED_PARAMETER (Driver);
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
|
||||
&deviceAttributes,
|
||||
DEVICE_CONTEXT);
|
||||
|
||||
deviceAttributes.SynchronizationScope = WdfSynchronizationScopeDevice;
|
||||
deviceAttributes.EvtCleanupCallback = EvtDeviceCleanup;
|
||||
|
||||
status = WdfDeviceCreate(&DeviceInit,
|
||||
&deviceAttributes,
|
||||
&device);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfDeviceCreate failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
deviceContext = GetDeviceContext(device);
|
||||
deviceContext->Device = device;
|
||||
|
||||
*DeviceContext = deviceContext;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
DeviceConfigure(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
)
|
||||
/*++
|
||||
|
||||
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
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDFDEVICE device = DeviceContext->Device;
|
||||
WDFKEY key;
|
||||
LPGUID guid;
|
||||
errno_t errorNo;
|
||||
|
||||
DECLARE_CONST_UNICODE_STRING(portName, REG_VALUENAME_PORTNAME);
|
||||
DECLARE_UNICODE_STRING_SIZE (comPort, 10);
|
||||
DECLARE_UNICODE_STRING_SIZE (symbolicLinkName, SYMBOLIC_LINK_NAME_LENGTH);
|
||||
|
||||
#ifdef _FAKE_MODEM
|
||||
//
|
||||
// Compiled as fake modem
|
||||
//
|
||||
guid = (LPGUID) &GUID_DEVINTERFACE_MODEM;
|
||||
#else
|
||||
//
|
||||
// Compiled as virtual serial port
|
||||
//
|
||||
guid = (LPGUID) &GUID_DEVINTERFACE_COMPORT;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Create device interface
|
||||
//
|
||||
status = WdfDeviceCreateDeviceInterface(
|
||||
device,
|
||||
guid,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Cannot create device interface");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Read the COM port number from the registry, which has been automatically
|
||||
// created by "MsPorts!PortsClassInstaller" if INF file says "Class=Ports"
|
||||
//
|
||||
status = WdfDeviceOpenRegistryKey(
|
||||
device,
|
||||
PLUGPLAY_REGKEY_DEVICE,
|
||||
KEY_QUERY_VALUE,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&key);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Failed to retrieve device hardware key root");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
status = WdfRegistryQueryUnicodeString(
|
||||
key,
|
||||
&portName,
|
||||
NULL,
|
||||
&comPort);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Failed to read PortName");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Manually create the symbolic link name. Length is the length in
|
||||
// bytes not including the NULL terminator.
|
||||
//
|
||||
// 6054 and 26035 are code analysis warnings that comPort.Buffer might
|
||||
// not be NULL terminated, while we know that they are.
|
||||
//
|
||||
#pragma warning(suppress: 6054 26035)
|
||||
symbolicLinkName.Length = (USHORT)((wcslen(comPort.Buffer) * sizeof(wchar_t))
|
||||
+ sizeof(SYMBOLIC_LINK_NAME_PREFIX) - sizeof(UNICODE_NULL));
|
||||
|
||||
if (symbolicLinkName.Length >= symbolicLinkName.MaximumLength) {
|
||||
|
||||
Trace(TRACE_LEVEL_ERROR, "Error: Buffer overflow when creating COM port name. Size"
|
||||
" is %d, buffer length is %d", symbolicLinkName.Length, symbolicLinkName.MaximumLength);
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
errorNo = wcscpy_s(symbolicLinkName.Buffer,
|
||||
SYMBOLIC_LINK_NAME_LENGTH,
|
||||
SYMBOLIC_LINK_NAME_PREFIX);
|
||||
|
||||
if (errorNo != 0) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Failed to copy %ws to buffer with error %d",
|
||||
SYMBOLIC_LINK_NAME_PREFIX, errorNo);
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
errorNo = wcscat_s(symbolicLinkName.Buffer,
|
||||
SYMBOLIC_LINK_NAME_LENGTH,
|
||||
comPort.Buffer);
|
||||
|
||||
if (errorNo != 0) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Failed to copy %ws to buffer with error %d",
|
||||
comPort.Buffer, errorNo);
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Create symbolic link
|
||||
//
|
||||
status = WdfDeviceCreateSymbolicLink(
|
||||
device,
|
||||
&symbolicLinkName);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Cannot create symbolic link %ws", symbolicLinkName.Buffer);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
status = DeviceGetPdoName(DeviceContext);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
status = DeviceWriteLegacyHardwareKey(
|
||||
DeviceContext->PdoName,
|
||||
comPort.Buffer,
|
||||
DeviceContext->Device);
|
||||
if (NT_SUCCESS(status)) {
|
||||
DeviceContext->CreatedLegacyHardwareKey = TRUE;
|
||||
}
|
||||
|
||||
status = QueueCreate(DeviceContext);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
DeviceGetPdoName(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDFDEVICE device = DeviceContext->Device;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
WDFMEMORY memory;
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
attributes.ParentObject = device;
|
||||
|
||||
status = WdfDeviceAllocAndQueryProperty(
|
||||
device,
|
||||
DevicePropertyPhysicalDeviceObjectName,
|
||||
NonPagedPoolNx,
|
||||
&attributes,
|
||||
&memory);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Failed to query PDO name");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
DeviceContext->PdoName = (PWCHAR) WdfMemoryGetBuffer(memory, NULL);
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"PDO Name is %ws", DeviceContext->PdoName);
|
||||
|
||||
Exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
DeviceWriteLegacyHardwareKey(
|
||||
_In_ PWSTR PdoName,
|
||||
_In_ PWSTR ComPort,
|
||||
_In_ WDFDEVICE Device
|
||||
)
|
||||
{
|
||||
WDFKEY key = NULL;
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING pdoString = {0};
|
||||
UNICODE_STRING comPort = {0};
|
||||
|
||||
DECLARE_CONST_UNICODE_STRING(deviceSubkey, SERIAL_DEVICE_MAP);
|
||||
|
||||
RtlInitUnicodeString(&pdoString, PdoName);
|
||||
RtlInitUnicodeString(&comPort, ComPort);
|
||||
|
||||
status = WdfDeviceOpenDevicemapKey(Device,
|
||||
&deviceSubkey,
|
||||
KEY_SET_VALUE,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&key);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Failed to open DEVICEMAP\\SERIALCOMM key 0x%x", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = WdfRegistryAssignUnicodeString(key,
|
||||
&pdoString,
|
||||
&comPort);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Failed to write to DEVICEMAP\\SERIALCOMM key 0x%x", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (key != NULL) {
|
||||
WdfRegistryClose(key);
|
||||
key = NULL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
EvtDeviceCleanup(
|
||||
_In_ WDFOBJECT Object
|
||||
)
|
||||
{
|
||||
WDFDEVICE device = (WDFDEVICE) Object;
|
||||
PDEVICE_CONTEXT deviceContext = GetDeviceContext(device);
|
||||
NTSTATUS status;
|
||||
WDFKEY key = NULL;
|
||||
UNICODE_STRING pdoString = {0};
|
||||
|
||||
DECLARE_CONST_UNICODE_STRING(deviceSubkey, SERIAL_DEVICE_MAP);
|
||||
|
||||
if (deviceContext->CreatedLegacyHardwareKey == TRUE) {
|
||||
|
||||
RtlInitUnicodeString(&pdoString, deviceContext->PdoName);
|
||||
|
||||
status = WdfDeviceOpenDevicemapKey(device,
|
||||
&deviceSubkey,
|
||||
KEY_SET_VALUE,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&key);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Failed to open DEVICEMAP\\SERIALCOMM key 0x%x", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = WdfRegistryRemoveValue(key,
|
||||
&pdoString);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Failed to delete %S key, 0x%x", pdoString.Buffer, status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = WdfRegistryRemoveKey(key);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: Failed to delete %S, 0x%x", SERIAL_DEVICE_MAP, status);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (key != NULL) {
|
||||
WdfRegistryClose(key);
|
||||
key = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ULONG
|
||||
GetBaudRate(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
)
|
||||
{
|
||||
return DeviceContext->BaudRate;
|
||||
}
|
||||
|
||||
VOID
|
||||
SetBaudRate(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext,
|
||||
_In_ ULONG BaudRate
|
||||
)
|
||||
{
|
||||
DeviceContext->BaudRate = BaudRate;
|
||||
}
|
||||
|
||||
ULONG *
|
||||
GetModemControlRegisterPtr(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
)
|
||||
{
|
||||
return &DeviceContext->ModemControlRegister;
|
||||
}
|
||||
|
||||
ULONG *
|
||||
GetFifoControlRegisterPtr(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
)
|
||||
{
|
||||
return &DeviceContext->FifoControlRegister;
|
||||
}
|
||||
|
||||
ULONG *
|
||||
GetLineControlRegisterPtr(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
)
|
||||
{
|
||||
return &DeviceContext->LineControlRegister;
|
||||
}
|
||||
|
||||
VOID
|
||||
SetValidDataMask(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext,
|
||||
_In_ UCHAR Mask
|
||||
)
|
||||
{
|
||||
DeviceContext->ValidDataMask = Mask;
|
||||
}
|
||||
|
||||
VOID
|
||||
SetTimeouts(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext,
|
||||
_In_ SERIAL_TIMEOUTS Timeouts
|
||||
)
|
||||
{
|
||||
DeviceContext->Timeouts = Timeouts;
|
||||
}
|
||||
|
||||
VOID
|
||||
GetTimeouts(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext,
|
||||
_Out_ SERIAL_TIMEOUTS *Timeouts
|
||||
)
|
||||
{
|
||||
*Timeouts = DeviceContext->Timeouts;
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
Device.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the type definitions for the VirtualSerial sample
|
||||
driver's device callback class.
|
||||
|
||||
Environment:
|
||||
|
||||
Windows Driver Framework
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SYMBOLIC_LINK_NAME_LENGTH 32
|
||||
#define SYMBOLIC_LINK_NAME_PREFIX L"\\DosDevices\\Global\\"
|
||||
#define REG_PATH_DEVICEMAP L"HARDWARE\\DEVICEMAP"
|
||||
#define SERIAL_DEVICE_MAP L"SERIALCOMM"
|
||||
#define REG_VALUENAME_PORTNAME L"PortName"
|
||||
#define REG_PATH_SERIALCOMM REG_PATH_DEVICEMAP L"\\" SERIAL_DEVICE_MAP
|
||||
|
||||
typedef struct _DEVICE_CONTEXT
|
||||
{
|
||||
WDFDEVICE Device;
|
||||
|
||||
ULONG BaudRate;
|
||||
|
||||
ULONG ModemControlRegister;
|
||||
|
||||
ULONG FifoControlRegister;
|
||||
|
||||
ULONG LineControlRegister;
|
||||
|
||||
UCHAR ValidDataMask;
|
||||
|
||||
SERIAL_TIMEOUTS Timeouts;
|
||||
|
||||
BOOLEAN CreatedLegacyHardwareKey;
|
||||
|
||||
PWSTR PdoName;
|
||||
|
||||
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext);
|
||||
|
||||
|
||||
NTSTATUS
|
||||
DeviceCreate(
|
||||
_In_ WDFDRIVER Driver,
|
||||
_In_ PWDFDEVICE_INIT DeviceInit,
|
||||
_Out_ PDEVICE_CONTEXT *DeviceContext
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DeviceConfigure(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DeviceGetPdoName(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DeviceWriteLegacyHardwareKey(
|
||||
_In_ PWSTR PdoName,
|
||||
_In_ PWSTR ComPort,
|
||||
_In_ WDFDEVICE Device
|
||||
);
|
||||
|
||||
EVT_WDF_DEVICE_CONTEXT_CLEANUP EvtDeviceCleanup;
|
||||
|
||||
ULONG
|
||||
GetBaudRate(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
);
|
||||
|
||||
VOID
|
||||
SetBaudRate(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext,
|
||||
_In_ ULONG BaudRate
|
||||
);
|
||||
|
||||
ULONG *
|
||||
GetModemControlRegisterPtr(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
);
|
||||
|
||||
ULONG *
|
||||
GetFifoControlRegisterPtr(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
);
|
||||
|
||||
ULONG *
|
||||
GetLineControlRegisterPtr(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
);
|
||||
|
||||
VOID
|
||||
SetValidDataMask(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext,
|
||||
_In_ UCHAR Mask
|
||||
);
|
||||
|
||||
VOID
|
||||
SetTimeouts(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext,
|
||||
_In_ SERIAL_TIMEOUTS Timeouts
|
||||
);
|
||||
|
||||
VOID
|
||||
GetTimeouts(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext,
|
||||
_Out_ SERIAL_TIMEOUTS *Timeouts
|
||||
);
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, All Rights Reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
Driver.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the implementation of the VirtualSerial Sample's
|
||||
core driver callback object.
|
||||
|
||||
Environment:
|
||||
|
||||
Windows Driver Framework
|
||||
|
||||
--*/
|
||||
|
||||
#include <initguid.h>
|
||||
#include "internal.h"
|
||||
|
||||
NTSTATUS
|
||||
DriverEntry(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ PUNICODE_STRING RegistryPath
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDF_DRIVER_CONFIG driverConfig;
|
||||
|
||||
WDF_DRIVER_CONFIG_INIT(&driverConfig,
|
||||
EvtDeviceAdd);
|
||||
|
||||
status = WdfDriverCreate(DriverObject,
|
||||
RegistryPath,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&driverConfig,
|
||||
WDF_NO_HANDLE);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfDriverCreate failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
EvtDeviceAdd(
|
||||
_In_ WDFDRIVER Driver,
|
||||
_Inout_ PWDFDEVICE_INIT DeviceInit
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PDEVICE_CONTEXT deviceContext;
|
||||
|
||||
status = DeviceCreate(Driver,
|
||||
DeviceInit,
|
||||
&deviceContext);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = DeviceConfigure(deviceContext);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
Driver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the type definitions for the VirtualSerial sample's
|
||||
driver callback class.
|
||||
|
||||
Environment:
|
||||
|
||||
Windows Driver Framework
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// This class handles driver events for the VirtualSerial 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.
|
||||
//
|
||||
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
EVT_WDF_DRIVER_DEVICE_ADD EvtDeviceAdd;
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
Internal.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the local type definitions for the VirtualSerial
|
||||
driver sample.
|
||||
|
||||
Environment:
|
||||
|
||||
Windows Driver Framework
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
#include <ntddk.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <wdf.h>
|
||||
|
||||
#define _NTDEF_
|
||||
|
||||
//
|
||||
// Include the type specific headers.
|
||||
//
|
||||
#include "serial.h"
|
||||
#include "driver.h"
|
||||
#include "device.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "queue.h"
|
||||
|
||||
//
|
||||
// Tracing and Assert
|
||||
//
|
||||
|
||||
#define Trace(level, _fmt_, ...) \
|
||||
DbgPrintEx(DPFLTR_DEFAULT_ID, level, \
|
||||
_fmt_ "\n", __VA_ARGS__)
|
||||
|
||||
#define TRACE_LEVEL_ERROR DPFLTR_ERROR_LEVEL
|
||||
#define TRACE_LEVEL_INFO DPFLTR_INFO_LEVEL
|
||||
|
||||
#ifndef ASSERT
|
||||
#define ASSERT(exp) { \
|
||||
if (!(exp)) { \
|
||||
RtlAssert(#exp, __FILE__, __LINE__, NULL); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,963 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation, All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
Queue.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This file implements the I/O queue interface and performs
|
||||
the read/write/ioctl operations.
|
||||
|
||||
Environment:
|
||||
|
||||
Windows Driver Framework
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
NTSTATUS
|
||||
QueueCreate(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDFDEVICE device = DeviceContext->Device;
|
||||
WDF_IO_QUEUE_CONFIG queueConfig;
|
||||
WDF_OBJECT_ATTRIBUTES queueAttributes;
|
||||
WDFQUEUE queue;
|
||||
PQUEUE_CONTEXT queueContext;
|
||||
|
||||
//
|
||||
// Create the default queue
|
||||
//
|
||||
|
||||
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
|
||||
&queueConfig,
|
||||
WdfIoQueueDispatchParallel);
|
||||
|
||||
queueConfig.EvtIoRead = EvtIoRead;
|
||||
queueConfig.EvtIoWrite = EvtIoWrite;
|
||||
queueConfig.EvtIoDeviceControl = EvtIoDeviceControl;
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
|
||||
&queueAttributes,
|
||||
QUEUE_CONTEXT);
|
||||
|
||||
status = WdfIoQueueCreate(
|
||||
device,
|
||||
&queueConfig,
|
||||
&queueAttributes,
|
||||
&queue);
|
||||
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfIoQueueCreate failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
queueContext = GetQueueContext(queue);
|
||||
queueContext->Queue = queue;
|
||||
queueContext->DeviceContext = DeviceContext;
|
||||
|
||||
//
|
||||
// Create a manual queue to hold pending read requests. By keeping
|
||||
// them in the queue, framework takes care of cancelling them if the app
|
||||
// exits
|
||||
//
|
||||
|
||||
WDF_IO_QUEUE_CONFIG_INIT(
|
||||
&queueConfig,
|
||||
WdfIoQueueDispatchManual);
|
||||
|
||||
status = WdfIoQueueCreate(
|
||||
device,
|
||||
&queueConfig,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&queue);
|
||||
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfIoQueueCreate manual queue failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
queueContext->ReadQueue = queue;
|
||||
|
||||
//
|
||||
// Create another manual queue to hold pending IOCTL_SERIAL_WAIT_ON_MASK
|
||||
//
|
||||
|
||||
WDF_IO_QUEUE_CONFIG_INIT(
|
||||
&queueConfig,
|
||||
WdfIoQueueDispatchManual);
|
||||
|
||||
status = WdfIoQueueCreate(
|
||||
device,
|
||||
&queueConfig,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&queue);
|
||||
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfIoQueueCreate manual queue failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
queueContext->WaitMaskQueue = queue;
|
||||
|
||||
RingBufferInitialize(&queueContext->RingBuffer,
|
||||
queueContext->Buffer,
|
||||
sizeof(queueContext->Buffer));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
RequestCopyFromBuffer(
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ PVOID SourceBuffer,
|
||||
_In_ size_t NumBytesToCopyFrom
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDFMEMORY memory;
|
||||
|
||||
status = WdfRequestRetrieveOutputMemory(Request, &memory);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfRequestRetrieveOutputMemory failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = WdfMemoryCopyFromBuffer(memory, 0,
|
||||
SourceBuffer, NumBytesToCopyFrom);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfMemoryCopyFromBuffer failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
WdfRequestSetInformation(Request, NumBytesToCopyFrom);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
RequestCopyToBuffer(
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ PVOID DestinationBuffer,
|
||||
_In_ size_t NumBytesToCopyTo
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDFMEMORY memory;
|
||||
|
||||
status = WdfRequestRetrieveInputMemory(Request, &memory);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfRequestRetrieveInputMemory failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = WdfMemoryCopyToBuffer(memory, 0,
|
||||
DestinationBuffer, NumBytesToCopyTo);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfMemoryCopyToBuffer failed 0x%x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
WdfRequestSetInformation(Request, NumBytesToCopyTo);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
EvtIoDeviceControl(
|
||||
_In_ WDFQUEUE Queue,
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ size_t OutputBufferLength,
|
||||
_In_ size_t InputBufferLength,
|
||||
_In_ ULONG IoControlCode
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PQUEUE_CONTEXT queueContext = GetQueueContext(Queue);
|
||||
PDEVICE_CONTEXT deviceContext = queueContext->DeviceContext;
|
||||
UNREFERENCED_PARAMETER (OutputBufferLength);
|
||||
UNREFERENCED_PARAMETER (InputBufferLength);
|
||||
|
||||
Trace(TRACE_LEVEL_INFO,
|
||||
"EvtIoDeviceControl 0x%x", IoControlCode);
|
||||
|
||||
switch (IoControlCode)
|
||||
{
|
||||
|
||||
case IOCTL_SERIAL_SET_BAUD_RATE:
|
||||
{
|
||||
//
|
||||
// This is a driver for a virtual serial port. Since there is no
|
||||
// actual hardware, we just store the baud rate and don't do
|
||||
// anything with it.
|
||||
//
|
||||
SERIAL_BAUD_RATE baudRateBuffer = {0};
|
||||
|
||||
status = RequestCopyToBuffer(Request,
|
||||
&baudRateBuffer,
|
||||
sizeof(baudRateBuffer));
|
||||
|
||||
if( NT_SUCCESS(status) ) {
|
||||
SetBaudRate(deviceContext, baudRateBuffer.BaudRate);
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_GET_BAUD_RATE:
|
||||
{
|
||||
SERIAL_BAUD_RATE baudRateBuffer = {0};
|
||||
|
||||
baudRateBuffer.BaudRate = GetBaudRate(deviceContext);
|
||||
|
||||
status = RequestCopyFromBuffer(Request,
|
||||
&baudRateBuffer,
|
||||
sizeof(baudRateBuffer));
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_SET_MODEM_CONTROL:
|
||||
{
|
||||
//
|
||||
// This is a driver for a virtual serial port. Since there is no
|
||||
// actual hardware, we just store the modem control register
|
||||
// configuration and don't do anything with it.
|
||||
//
|
||||
ULONG *modemControlRegister = GetModemControlRegisterPtr(deviceContext);
|
||||
|
||||
ASSERT(modemControlRegister);
|
||||
|
||||
status = RequestCopyToBuffer(Request,
|
||||
modemControlRegister,
|
||||
sizeof(ULONG));
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_GET_MODEM_CONTROL:
|
||||
{
|
||||
ULONG *modemControlRegister = GetModemControlRegisterPtr(deviceContext);
|
||||
|
||||
ASSERT(modemControlRegister);
|
||||
|
||||
status = RequestCopyFromBuffer(Request,
|
||||
modemControlRegister,
|
||||
sizeof(ULONG));
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_SET_FIFO_CONTROL:
|
||||
{
|
||||
//
|
||||
// This is a driver for a virtual serial port. Since there is no
|
||||
// actual hardware, we just store the FIFO control register
|
||||
// configuration and don't do anything with it.
|
||||
//
|
||||
ULONG *fifoControlRegister = GetFifoControlRegisterPtr(deviceContext);
|
||||
|
||||
ASSERT(fifoControlRegister);
|
||||
|
||||
status = RequestCopyToBuffer(Request,
|
||||
fifoControlRegister,
|
||||
sizeof(ULONG));
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_GET_LINE_CONTROL:
|
||||
{
|
||||
status = QueueProcessGetLineControl(
|
||||
queueContext,
|
||||
Request);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case IOCTL_SERIAL_SET_LINE_CONTROL:
|
||||
{
|
||||
status = QueueProcessSetLineControl(
|
||||
queueContext,
|
||||
Request);
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_GET_TIMEOUTS:
|
||||
{
|
||||
SERIAL_TIMEOUTS timeoutValues = {0};
|
||||
|
||||
status = RequestCopyFromBuffer(Request,
|
||||
(void*) &timeoutValues,
|
||||
sizeof(timeoutValues));
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_SET_TIMEOUTS:
|
||||
{
|
||||
SERIAL_TIMEOUTS timeoutValues = {0};
|
||||
|
||||
status = RequestCopyToBuffer(Request,
|
||||
(void*) &timeoutValues,
|
||||
sizeof(timeoutValues));
|
||||
|
||||
if( NT_SUCCESS(status) )
|
||||
{
|
||||
if ((timeoutValues.ReadIntervalTimeout == MAXULONG) &&
|
||||
(timeoutValues.ReadTotalTimeoutMultiplier == MAXULONG) &&
|
||||
(timeoutValues.ReadTotalTimeoutConstant == MAXULONG))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
if( NT_SUCCESS(status) ) {
|
||||
SetTimeouts(deviceContext, timeoutValues);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_WAIT_ON_MASK:
|
||||
{
|
||||
//
|
||||
// NOTE: A wait-on-mask request should not be completed until either:
|
||||
// 1) A wait event occurs; or
|
||||
// 2) A set-wait-mask request is received
|
||||
//
|
||||
// This is a driver for a virtual serial port. Since there is no
|
||||
// actual hardware, we complete the request with some failure code.
|
||||
//
|
||||
WDFREQUEST savedRequest;
|
||||
|
||||
status = WdfIoQueueRetrieveNextRequest(
|
||||
queueContext->WaitMaskQueue,
|
||||
&savedRequest);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
WdfRequestComplete(savedRequest,
|
||||
STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
//
|
||||
// Keep the request in a manual queue and the framework will take
|
||||
// care of cancelling them when the app exits
|
||||
//
|
||||
status = WdfRequestForwardToIoQueue(
|
||||
Request,
|
||||
queueContext->WaitMaskQueue);
|
||||
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfRequestForwardToIoQueue failed 0x%x", status);
|
||||
WdfRequestComplete(Request, status);
|
||||
}
|
||||
|
||||
//
|
||||
// Instead of "break", use "return" to prevent the current request
|
||||
// from being completed.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_SET_WAIT_MASK:
|
||||
{
|
||||
//
|
||||
// NOTE: If a wait-on-mask request is already pending when set-wait-mask
|
||||
// request is processed, the pending wait-on-event request is completed
|
||||
// with STATUS_SUCCESS and the output wait event mask is set to zero.
|
||||
//
|
||||
WDFREQUEST savedRequest;
|
||||
|
||||
status = WdfIoQueueRetrieveNextRequest(
|
||||
queueContext->WaitMaskQueue,
|
||||
&savedRequest);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
|
||||
ULONG eventMask = 0;
|
||||
status = RequestCopyFromBuffer(
|
||||
savedRequest,
|
||||
&eventMask,
|
||||
sizeof(eventMask));
|
||||
|
||||
WdfRequestComplete(savedRequest, status);
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE: The application expects STATUS_SUCCESS for these IOCTLs.
|
||||
//
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_SERIAL_SET_QUEUE_SIZE:
|
||||
case IOCTL_SERIAL_SET_DTR:
|
||||
case IOCTL_SERIAL_SET_RTS:
|
||||
case IOCTL_SERIAL_CLR_RTS:
|
||||
case IOCTL_SERIAL_SET_XON:
|
||||
case IOCTL_SERIAL_SET_XOFF:
|
||||
case IOCTL_SERIAL_SET_CHARS:
|
||||
case IOCTL_SERIAL_GET_CHARS:
|
||||
case IOCTL_SERIAL_GET_HANDFLOW:
|
||||
case IOCTL_SERIAL_SET_HANDFLOW:
|
||||
case IOCTL_SERIAL_RESET_DEVICE:
|
||||
//
|
||||
// NOTE: The application expects STATUS_SUCCESS for these IOCTLs.
|
||||
//
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// complete the request
|
||||
//
|
||||
WdfRequestComplete(Request, status);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
EvtIoWrite(
|
||||
_In_ WDFQUEUE Queue,
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ size_t Length
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PQUEUE_CONTEXT queueContext = GetQueueContext(Queue);
|
||||
WDFMEMORY memory;
|
||||
WDFREQUEST savedRequest;
|
||||
size_t availableData = 0;
|
||||
|
||||
Trace(TRACE_LEVEL_INFO,
|
||||
"EvtIoWrite 0x%p", Request);
|
||||
|
||||
status = WdfRequestRetrieveInputMemory(Request, &memory);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfRequestRetrieveInputMemory failed 0x%x", status);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Process input
|
||||
//
|
||||
status = QueueProcessWriteBytes(
|
||||
queueContext,
|
||||
(PUCHAR)WdfMemoryGetBuffer(memory, NULL),
|
||||
Length);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
WdfRequestCompleteWithInformation(Request, status, Length);
|
||||
|
||||
//
|
||||
// Get the amount of data available in the ring buffer
|
||||
//
|
||||
RingBufferGetAvailableData(
|
||||
&queueContext->RingBuffer,
|
||||
&availableData);
|
||||
|
||||
if (availableData == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Continue with the next request, if there is one pending
|
||||
//
|
||||
for ( ; ; ) {
|
||||
|
||||
status = WdfIoQueueRetrieveNextRequest(
|
||||
queueContext->ReadQueue,
|
||||
&savedRequest);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
status = WdfRequestForwardToIoQueue(
|
||||
savedRequest,
|
||||
Queue);
|
||||
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfRequestForwardToIoQueue failed 0x%x", status);
|
||||
WdfRequestComplete(savedRequest, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
EvtIoRead(
|
||||
_In_ WDFQUEUE Queue,
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ size_t Length
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PQUEUE_CONTEXT queueContext = GetQueueContext(Queue);
|
||||
WDFMEMORY memory;
|
||||
size_t bytesCopied = 0;
|
||||
|
||||
Trace(TRACE_LEVEL_INFO,
|
||||
"EvtIoRead 0x%p", Request);
|
||||
|
||||
status = WdfRequestRetrieveOutputMemory(Request, &memory);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfRequestRetrieveOutputMemory failed 0x%x", status);
|
||||
WdfRequestComplete(Request, status);
|
||||
return;
|
||||
}
|
||||
|
||||
status = RingBufferRead(&queueContext->RingBuffer,
|
||||
(BYTE*)WdfMemoryGetBuffer(memory, NULL),
|
||||
Length,
|
||||
&bytesCopied);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
WdfRequestComplete(Request, status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytesCopied > 0) {
|
||||
//
|
||||
// Data was read from buffer succesfully
|
||||
//
|
||||
WdfRequestCompleteWithInformation(Request, status, bytesCopied);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// No data to read. Queue the request for later processing.
|
||||
//
|
||||
status = WdfRequestForwardToIoQueue(Request,
|
||||
queueContext->ReadQueue);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
Trace(TRACE_LEVEL_ERROR,
|
||||
"Error: WdfRequestForwardToIoQueue failed 0x%x", status);
|
||||
WdfRequestComplete(Request, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
QueueProcessWriteBytes(
|
||||
_In_ PQUEUE_CONTEXT QueueContext,
|
||||
_In_reads_bytes_(Length)
|
||||
PUCHAR Characters,
|
||||
_In_ size_t Length
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
This function is called when the framework receives IRP_MJ_WRITE
|
||||
requests from the system. The write event handler(FmEvtIoWrite) calls ProcessWriteBytes.
|
||||
It parses the Characters passed in and looks for the for sequences "AT" -ok ,
|
||||
"ATA" --CONNECT, ATD<number> -- CONNECT and sets the state of the device appropriately.
|
||||
These bytes are placed in the read Buffer to be processed later since this device
|
||||
works in a loopback fashion.
|
||||
|
||||
Arguments:
|
||||
|
||||
Characters - Pointer to the write IRP's system buffer.
|
||||
|
||||
Length - Length of the IO operation
|
||||
The default property of the queue is to not dispatch
|
||||
zero lenght read & write requests to the driver and
|
||||
complete is with status success. So we will never get
|
||||
a zero length request.
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
UCHAR currentCharacter;
|
||||
UCHAR connectString[] = "\r\nCONNECT\r\n";
|
||||
UCHAR connectStringCch = ARRAY_SIZE(connectString) - 1;
|
||||
UCHAR okString[] = "\r\nOK\r\n";
|
||||
UCHAR okStringCch = ARRAY_SIZE(okString) - 1;
|
||||
|
||||
while (Length != 0) {
|
||||
|
||||
currentCharacter = *(Characters++);
|
||||
Length--;
|
||||
|
||||
if(currentCharacter == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
status = RingBufferWrite(&QueueContext->RingBuffer,
|
||||
¤tCharacter,
|
||||
sizeof(currentCharacter));
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
return status;
|
||||
}
|
||||
|
||||
switch (QueueContext->CommandMatchState) {
|
||||
|
||||
case COMMAND_MATCH_STATE_IDLE:
|
||||
|
||||
if ((currentCharacter == 'a') || (currentCharacter == 'A')) {
|
||||
//
|
||||
// got an A
|
||||
//
|
||||
QueueContext->CommandMatchState = COMMAND_MATCH_STATE_GOT_A;
|
||||
QueueContext->ConnectCommand = FALSE;
|
||||
QueueContext->IgnoreNextChar = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_MATCH_STATE_GOT_A:
|
||||
|
||||
if ((currentCharacter == 't') || (currentCharacter == 'T')) {
|
||||
//
|
||||
// got a T
|
||||
//
|
||||
QueueContext->CommandMatchState = COMMAND_MATCH_STATE_GOT_T;
|
||||
}
|
||||
else {
|
||||
QueueContext->CommandMatchState = COMMAND_MATCH_STATE_IDLE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case COMMAND_MATCH_STATE_GOT_T:
|
||||
|
||||
if (! QueueContext->IgnoreNextChar) {
|
||||
//
|
||||
// the last char was not a special char
|
||||
// check for CONNECT command
|
||||
//
|
||||
if ((currentCharacter == 'A') || (currentCharacter == 'a')) {
|
||||
QueueContext->ConnectCommand = TRUE;
|
||||
}
|
||||
|
||||
if ((currentCharacter == 'D') || (currentCharacter == 'd')) {
|
||||
QueueContext->ConnectCommand = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
QueueContext->IgnoreNextChar = TRUE;
|
||||
|
||||
if (currentCharacter == '\r') {
|
||||
//
|
||||
// got a CR, send a response to the command
|
||||
//
|
||||
QueueContext->CommandMatchState = COMMAND_MATCH_STATE_IDLE;
|
||||
|
||||
if (QueueContext->ConnectCommand) {
|
||||
//
|
||||
// place <cr><lf>CONNECT<cr><lf> in the buffer
|
||||
//
|
||||
status = RingBufferWrite(&QueueContext->RingBuffer,
|
||||
connectString,
|
||||
connectStringCch);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
return status;
|
||||
}
|
||||
//
|
||||
// connected now raise CD
|
||||
//
|
||||
QueueContext->CurrentlyConnected = TRUE;
|
||||
QueueContext->ConnectionStateChanged = TRUE;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// place <cr><lf>OK<cr><lf> in the buffer
|
||||
//
|
||||
status = RingBufferWrite(&QueueContext->RingBuffer,
|
||||
okString,
|
||||
okStringCch);
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
QueueProcessGetLineControl(
|
||||
_In_ PQUEUE_CONTEXT QueueContext,
|
||||
_In_ WDFREQUEST Request
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PDEVICE_CONTEXT deviceContext;
|
||||
SERIAL_LINE_CONTROL lineControl = {0};
|
||||
ULONG lineControlSnapshot;
|
||||
ULONG *lineControlRegister;
|
||||
|
||||
deviceContext = QueueContext->DeviceContext;
|
||||
lineControlRegister = GetLineControlRegisterPtr(deviceContext);
|
||||
|
||||
ASSERT(lineControlRegister);
|
||||
|
||||
//
|
||||
// Take a snapshot of the line control register variable
|
||||
//
|
||||
lineControlSnapshot = *lineControlRegister;
|
||||
|
||||
//
|
||||
// Decode the word length
|
||||
//
|
||||
if ((lineControlSnapshot & SERIAL_DATA_MASK) == SERIAL_5_DATA)
|
||||
{
|
||||
lineControl.WordLength = 5;
|
||||
}
|
||||
else if ((lineControlSnapshot & SERIAL_DATA_MASK) == SERIAL_6_DATA)
|
||||
{
|
||||
lineControl.WordLength = 6;
|
||||
}
|
||||
else if ((lineControlSnapshot & SERIAL_DATA_MASK) == SERIAL_7_DATA)
|
||||
{
|
||||
lineControl.WordLength = 7;
|
||||
}
|
||||
else if ((lineControlSnapshot & SERIAL_DATA_MASK) == SERIAL_8_DATA)
|
||||
{
|
||||
lineControl.WordLength = 8;
|
||||
}
|
||||
|
||||
//
|
||||
// Decode the parity
|
||||
//
|
||||
if ((lineControlSnapshot & SERIAL_PARITY_MASK) == SERIAL_NONE_PARITY)
|
||||
{
|
||||
lineControl.Parity = NO_PARITY;
|
||||
}
|
||||
else if ((lineControlSnapshot & SERIAL_PARITY_MASK) == SERIAL_ODD_PARITY)
|
||||
{
|
||||
lineControl.Parity = ODD_PARITY;
|
||||
}
|
||||
else if ((lineControlSnapshot & SERIAL_PARITY_MASK) == SERIAL_EVEN_PARITY)
|
||||
{
|
||||
lineControl.Parity = EVEN_PARITY;
|
||||
}
|
||||
else if ((lineControlSnapshot & SERIAL_PARITY_MASK) == SERIAL_MARK_PARITY)
|
||||
{
|
||||
lineControl.Parity = MARK_PARITY;
|
||||
}
|
||||
else if ((lineControlSnapshot & SERIAL_PARITY_MASK) == SERIAL_SPACE_PARITY)
|
||||
{
|
||||
lineControl.Parity = SPACE_PARITY;
|
||||
}
|
||||
|
||||
//
|
||||
// Decode the length of the stop bit
|
||||
//
|
||||
if (lineControlSnapshot & SERIAL_2_STOP)
|
||||
{
|
||||
if (lineControl.WordLength == 5)
|
||||
{
|
||||
lineControl.StopBits = STOP_BITS_1_5;
|
||||
}
|
||||
else
|
||||
{
|
||||
lineControl.StopBits = STOP_BITS_2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lineControl.StopBits = STOP_BIT_1;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the information that was decoded to the caller's buffer
|
||||
//
|
||||
status = RequestCopyFromBuffer(Request,
|
||||
(void*) &lineControl,
|
||||
sizeof(lineControl));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
QueueProcessSetLineControl(
|
||||
_In_ PQUEUE_CONTEXT QueueContext,
|
||||
_In_ WDFREQUEST Request
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PDEVICE_CONTEXT deviceContext;
|
||||
SERIAL_LINE_CONTROL lineControl = {0};
|
||||
ULONG *lineControlRegister;
|
||||
UCHAR lineControlData = 0;
|
||||
UCHAR lineControlStop = 0;
|
||||
UCHAR lineControlParity = 0;
|
||||
ULONG lineControlSnapshot;
|
||||
ULONG lineControlNew;
|
||||
ULONG lineControlPrevious;
|
||||
ULONG i;
|
||||
|
||||
deviceContext = QueueContext->DeviceContext;
|
||||
lineControlRegister = GetLineControlRegisterPtr(deviceContext);
|
||||
|
||||
ASSERT(lineControlRegister);
|
||||
|
||||
//
|
||||
// This is a driver for a virtual serial port. Since there is no
|
||||
// actual hardware, we just store the line control register
|
||||
// configuration and don't do anything with it.
|
||||
//
|
||||
status = RequestCopyToBuffer(Request,
|
||||
(void*) &lineControl,
|
||||
sizeof(lineControl));
|
||||
|
||||
//
|
||||
// Bits 0 and 1 of the line control register
|
||||
//
|
||||
if( NT_SUCCESS(status) )
|
||||
{
|
||||
switch (lineControl.WordLength)
|
||||
{
|
||||
case 5:
|
||||
lineControlData = SERIAL_5_DATA;
|
||||
SetValidDataMask(deviceContext, 0x1f);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
lineControlData = SERIAL_6_DATA;
|
||||
SetValidDataMask(deviceContext, 0x3f);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
lineControlData = SERIAL_7_DATA;
|
||||
SetValidDataMask(deviceContext, 0x7f);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
lineControlData = SERIAL_8_DATA;
|
||||
SetValidDataMask(deviceContext, 0xff);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Bit 2 of the line control register
|
||||
//
|
||||
if( NT_SUCCESS(status) )
|
||||
{
|
||||
switch (lineControl.StopBits)
|
||||
{
|
||||
case STOP_BIT_1:
|
||||
lineControlStop = SERIAL_1_STOP;
|
||||
break;
|
||||
|
||||
case STOP_BITS_1_5:
|
||||
if (lineControlData != SERIAL_5_DATA)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
lineControlStop = SERIAL_1_5_STOP;
|
||||
break;
|
||||
|
||||
case STOP_BITS_2:
|
||||
if (lineControlData == SERIAL_5_DATA)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
lineControlStop = SERIAL_2_STOP;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Bits 3, 4 and 5 of the line control register
|
||||
//
|
||||
if( NT_SUCCESS(status) )
|
||||
{
|
||||
switch (lineControl.Parity)
|
||||
{
|
||||
case NO_PARITY:
|
||||
lineControlParity = SERIAL_NONE_PARITY;
|
||||
break;
|
||||
|
||||
case EVEN_PARITY:
|
||||
lineControlParity = SERIAL_EVEN_PARITY;
|
||||
break;
|
||||
|
||||
case ODD_PARITY:
|
||||
lineControlParity = SERIAL_ODD_PARITY;
|
||||
break;
|
||||
|
||||
case SPACE_PARITY:
|
||||
lineControlParity = SERIAL_SPACE_PARITY;
|
||||
break;
|
||||
|
||||
case MARK_PARITY:
|
||||
lineControlParity = SERIAL_MARK_PARITY;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update our line control register variable atomically
|
||||
//
|
||||
i=0;
|
||||
do {
|
||||
i++;
|
||||
if ((i & 0xf) == 0) {
|
||||
//
|
||||
// We've been spinning in a loop for a while trying to
|
||||
// update the line control register variable atomically.
|
||||
// Yield the CPU for other threads for a while.
|
||||
//
|
||||
#ifdef _KERNEL_MODE
|
||||
LARGE_INTEGER interval;
|
||||
interval.QuadPart = 0;
|
||||
KeDelayExecutionThread(UserMode, FALSE, &interval);
|
||||
#else
|
||||
SwitchToThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
lineControlSnapshot = *lineControlRegister;
|
||||
|
||||
lineControlNew = (lineControlSnapshot & SERIAL_LCR_BREAK) |
|
||||
(lineControlData | lineControlParity | lineControlStop);
|
||||
|
||||
lineControlPrevious = InterlockedCompareExchange(
|
||||
(LONG *) lineControlRegister,
|
||||
lineControlNew,
|
||||
lineControlSnapshot);
|
||||
|
||||
} while (lineControlPrevious != lineControlSnapshot);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation, All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
queue.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This file defines the queue callback interface.
|
||||
|
||||
Environment:
|
||||
|
||||
Windows Driver Framework
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
// Set ring buffer size
|
||||
#define DATA_BUFFER_SIZE 1024
|
||||
|
||||
//
|
||||
// Device states
|
||||
//
|
||||
#define COMMAND_MATCH_STATE_IDLE 0
|
||||
#define COMMAND_MATCH_STATE_GOT_A 1
|
||||
#define COMMAND_MATCH_STATE_GOT_T 2
|
||||
|
||||
//
|
||||
// Define useful macros
|
||||
//
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
#define MAXULONG 0xffffffff
|
||||
|
||||
typedef struct _QUEUE_CONTEXT
|
||||
{
|
||||
UCHAR CommandMatchState;
|
||||
|
||||
BOOLEAN ConnectCommand;
|
||||
|
||||
BOOLEAN IgnoreNextChar;
|
||||
|
||||
BOOLEAN ConnectionStateChanged;
|
||||
|
||||
BOOLEAN CurrentlyConnected;
|
||||
|
||||
RING_BUFFER RingBuffer; // Ring buffer for pending data
|
||||
|
||||
BYTE Buffer[DATA_BUFFER_SIZE];
|
||||
|
||||
WDFQUEUE Queue; // Default parallel queue
|
||||
|
||||
WDFQUEUE ReadQueue; // Manual queue for pending reads
|
||||
|
||||
WDFQUEUE WaitMaskQueue; // Manual queue for pending ioctl wait-on-mask
|
||||
|
||||
PDEVICE_CONTEXT DeviceContext;
|
||||
|
||||
} QUEUE_CONTEXT, *PQUEUE_CONTEXT;
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, GetQueueContext);
|
||||
|
||||
EVT_WDF_IO_QUEUE_IO_READ EvtIoRead;
|
||||
EVT_WDF_IO_QUEUE_IO_WRITE EvtIoWrite;
|
||||
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl;
|
||||
|
||||
NTSTATUS
|
||||
QueueCreate(
|
||||
_In_ PDEVICE_CONTEXT DeviceContext
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QueueProcessWriteBytes(
|
||||
_In_ PQUEUE_CONTEXT QueueContext,
|
||||
_In_reads_bytes_(Length)
|
||||
PUCHAR Characters,
|
||||
_In_ size_t Length
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QueueProcessGetLineControl(
|
||||
_In_ PQUEUE_CONTEXT QueueContext,
|
||||
_In_ WDFREQUEST Request
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QueueProcessSetLineControl(
|
||||
_In_ PQUEUE_CONTEXT QueueContext,
|
||||
_In_ WDFREQUEST Request
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
RequestCopyFromBuffer(
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ PVOID SourceBuffer,
|
||||
_In_ size_t NumBytesToCopyFrom
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
RequestCopyToBuffer(
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ PVOID DestinationBuffer,
|
||||
_In_ size_t NumBytesToCopyTo
|
||||
);
|
||||
|
||||
|
|
@ -1,338 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation, All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
RingBuffer.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This file implements the Ring Buffer
|
||||
|
||||
Environment:
|
||||
|
||||
--*/
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
VOID
|
||||
RingBufferInitialize(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_In_reads_bytes_(BufferSize)
|
||||
BYTE* Buffer,
|
||||
_In_ size_t BufferSize
|
||||
)
|
||||
{
|
||||
Self->Size = BufferSize;
|
||||
Self->Base = Buffer;
|
||||
Self->End = Buffer + BufferSize;
|
||||
Self->Head = Buffer;
|
||||
Self->Tail = Buffer;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
RingBufferGetAvailableSpace(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_Out_ size_t *AvailableSpace
|
||||
)
|
||||
{
|
||||
BYTE* headSnapshot = NULL;
|
||||
BYTE* tailSnapshot = NULL;
|
||||
BYTE* tailPlusOne = NULL;
|
||||
|
||||
ASSERT(AvailableSpace);
|
||||
|
||||
//
|
||||
// Take a snapshot of the head and tail pointers. We will compute the
|
||||
// available space based on this snapshot. This is safe to do in a
|
||||
// single-producer, single-consumer model, because -
|
||||
// * A producer will call GetAvailableSpace() to determine whether
|
||||
// there is enough space to write the data it is trying to write.
|
||||
// The only other thread that could modify the amount of space
|
||||
// available is the consumer thread, which can only increase the
|
||||
// amount of space available. Hence it is safe for the producer
|
||||
// to write based on this snapshot.
|
||||
// * A consumer thread will call GetAvailableSpace() to determine
|
||||
// whether there is enough data in the buffer for it to read.
|
||||
// (Available data = Buffer size - Available space). The only
|
||||
// other thread that could modify the amount of space available
|
||||
// is the producer thread, which can only decrease the amount of
|
||||
// space available (thereby increasing the amount of data
|
||||
// available. Hence it is safe for the consumer to read based on
|
||||
// this snapshot.
|
||||
//
|
||||
headSnapshot = Self->Head;
|
||||
tailSnapshot = Self->Tail;
|
||||
|
||||
//
|
||||
// In order to distinguish between a full buffer and an empty buffer,
|
||||
// we always leave the last byte of the buffer unused. So, an empty
|
||||
// buffer is denoted by -
|
||||
// tail == head
|
||||
// ... and a full buffer is denoted by -
|
||||
// (tail+1) == head
|
||||
//
|
||||
tailPlusOne = ((tailSnapshot+1) == Self->End) ? Self->Base : (tailSnapshot+1);
|
||||
|
||||
if (tailPlusOne == headSnapshot)
|
||||
{
|
||||
//
|
||||
// Buffer full
|
||||
//
|
||||
*AvailableSpace = 0;
|
||||
}
|
||||
else if (tailSnapshot == headSnapshot)
|
||||
{
|
||||
//
|
||||
// Buffer empty
|
||||
// The -1 in the computation below is to account for the fact that
|
||||
// we always leave the last byte of the ring buffer unused in order
|
||||
// to distinguish between an empty buffer and a full buffer.
|
||||
//
|
||||
*AvailableSpace = Self->Size - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tailSnapshot > headSnapshot)
|
||||
{
|
||||
//
|
||||
// Data has not wrapped around the end of the buffer
|
||||
// The -1 in the computation below is to account for the fact
|
||||
// that we always leave the last byte of the ring buffer unused
|
||||
// in order to distinguish between an empty buffer and a full
|
||||
// buffer.
|
||||
//
|
||||
*AvailableSpace = Self->Size - (tailSnapshot - headSnapshot) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Data has wrapped around the end of the buffer
|
||||
// The -1 in the computation below is to account for the fact
|
||||
// that we always leave the last byte of the ring buffer unused
|
||||
// in order to distinguish between an empty buffer and a full
|
||||
// buffer.
|
||||
//
|
||||
*AvailableSpace = (headSnapshot - tailSnapshot) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
RingBufferGetAvailableData(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_Out_ size_t *AvailableData
|
||||
)
|
||||
{
|
||||
size_t availableSpace;
|
||||
|
||||
ASSERT(AvailableData);
|
||||
|
||||
RingBufferGetAvailableSpace(Self, &availableSpace);
|
||||
|
||||
//
|
||||
// The -1 in the arithmetic below accounts for the fact that we always
|
||||
// keep 1 byte of the ring buffer unused in order to distinguish
|
||||
// between a full buffer and an empty buffer.
|
||||
//
|
||||
*AvailableData = Self->Size - availableSpace - 1;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
RingBufferWrite(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_In_reads_bytes_(DataSize)
|
||||
BYTE* Data,
|
||||
_In_ size_t DataSize
|
||||
)
|
||||
{
|
||||
size_t availableSpace;
|
||||
size_t bytesToCopy;
|
||||
size_t spaceFromCurrToEnd;
|
||||
|
||||
ASSERT(Data && (0 != DataSize));
|
||||
|
||||
if (Self->Tail >= Self->End)
|
||||
{
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the amount of space available in the buffer
|
||||
//
|
||||
RingBufferGetAvailableSpace(Self, &availableSpace);
|
||||
|
||||
//
|
||||
// If there is not enough space to fit in all the data passed in by the
|
||||
// caller then copy as much as possible and throw away the rest
|
||||
//
|
||||
if (availableSpace < DataSize)
|
||||
{
|
||||
bytesToCopy = availableSpace;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesToCopy = DataSize;
|
||||
}
|
||||
|
||||
if (bytesToCopy)
|
||||
{
|
||||
//
|
||||
// The buffer has some space at least
|
||||
//
|
||||
if ((Self->Tail + bytesToCopy) > Self->End)
|
||||
{
|
||||
//
|
||||
// The data being written will wrap around the end of the buffer.
|
||||
// So the copy has to be done in two steps -
|
||||
// * X bytes from current position to end of the buffer
|
||||
// * the remaining (bytesToCopy - X) from the start of the buffer
|
||||
//
|
||||
|
||||
//
|
||||
// The first step of the copy ...
|
||||
//
|
||||
spaceFromCurrToEnd = Self->End - Self->Tail;
|
||||
|
||||
RtlCopyMemory(Self->Tail, Data, spaceFromCurrToEnd);
|
||||
|
||||
Data += spaceFromCurrToEnd;
|
||||
|
||||
bytesToCopy -= spaceFromCurrToEnd;
|
||||
|
||||
//
|
||||
// The second step of the copy ...
|
||||
//
|
||||
RtlCopyMemory(Self->Base, Data, bytesToCopy);
|
||||
|
||||
//
|
||||
// Advance the tail pointer
|
||||
//
|
||||
Self->Tail = Self->Base + bytesToCopy;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Data does NOT wrap around the end of the buffer. Just copy it
|
||||
// over in a single step
|
||||
//
|
||||
RtlCopyMemory(Self->Tail, Data, bytesToCopy);
|
||||
|
||||
//
|
||||
// Advance the tail pointer
|
||||
//
|
||||
Self->Tail += bytesToCopy;
|
||||
if (Self->Tail == Self->End)
|
||||
{
|
||||
//
|
||||
// We have exactly reached the end of the buffer. The next
|
||||
// write should wrap around and start from the beginning.
|
||||
//
|
||||
Self->Tail = Self->Base;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(Self->Tail < Self->End);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
RingBufferRead(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_Out_writes_bytes_to_(DataSize, *BytesCopied)
|
||||
BYTE* Data,
|
||||
_In_ size_t DataSize,
|
||||
_Out_ size_t *BytesCopied
|
||||
)
|
||||
{
|
||||
size_t availableData;
|
||||
size_t dataFromCurrToEnd;
|
||||
|
||||
ASSERT(Data && (DataSize != 0));
|
||||
|
||||
if (Self->Head >= Self->End)
|
||||
{
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the amount of data available in the buffer
|
||||
//
|
||||
RingBufferGetAvailableData(Self, &availableData);
|
||||
|
||||
if (availableData == 0)
|
||||
{
|
||||
*BytesCopied = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (DataSize > availableData)
|
||||
{
|
||||
DataSize = availableData;
|
||||
}
|
||||
|
||||
*BytesCopied = DataSize;
|
||||
|
||||
if ((Self->Head + DataSize) > Self->End)
|
||||
{
|
||||
//
|
||||
// The data requested by the caller is wrapped around the end of the
|
||||
// buffer. So we'll do the copy in two steps -
|
||||
// * Copy X bytes from the current position to the end buffer into
|
||||
// the caller's buffer
|
||||
// * Copy (DataSize - X) bytes from the beginning to the buffer into
|
||||
// the caller's buffer
|
||||
//
|
||||
|
||||
//
|
||||
// The first step of the copy ...
|
||||
//
|
||||
dataFromCurrToEnd = Self->End - Self->Head;
|
||||
RtlCopyMemory(Data, Self->Head, dataFromCurrToEnd);
|
||||
Data += dataFromCurrToEnd;
|
||||
DataSize -= dataFromCurrToEnd;
|
||||
|
||||
//
|
||||
// The second step of the copy ...
|
||||
//
|
||||
RtlCopyMemory(Data, Self->Base, DataSize);
|
||||
|
||||
//
|
||||
// Advance the head pointer
|
||||
//
|
||||
Self->Head = Self->Base + DataSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// The data in the buffer is NOT wrapped around the end of the buffer.
|
||||
// Simply copy the data over to the caller's buffer in a single step.
|
||||
//
|
||||
RtlCopyMemory(Data, Self->Head, DataSize);
|
||||
|
||||
//
|
||||
// Advance the head pointer
|
||||
//
|
||||
Self->Head += DataSize;
|
||||
if (Self->Head == Self->End)
|
||||
{
|
||||
//
|
||||
// We have exactly reached the end of the buffer. The next
|
||||
// read should wrap around and start from the beginning.
|
||||
//
|
||||
Self->Head = Self->Base;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(Self->Head < Self->End);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
Ringbuffer.h
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct _RING_BUFFER
|
||||
{
|
||||
//
|
||||
// The size in bytes of the ring buffer.
|
||||
//
|
||||
size_t Size;
|
||||
|
||||
//
|
||||
// A pointer to the base of the ring buffer.
|
||||
//
|
||||
BYTE* Base;
|
||||
|
||||
//
|
||||
// A pointer to the byte beyond the end of the ring buffer. Used for
|
||||
// quick comparisons when determining if we need to wrap.
|
||||
//
|
||||
BYTE* End;
|
||||
|
||||
//
|
||||
// A pointer to the current read point in the ring buffer.
|
||||
//
|
||||
// Updates to this are not protected by any lock. This is different from
|
||||
// the write pointer, which is protected by the "pending read pointer"
|
||||
// lock. The reason for this difference is that in this driver, we do not
|
||||
// keep write requests pending. If there is not enough space to write all
|
||||
// the data that was requested, we write as much as we can and drop the
|
||||
// rest (lossy data transfer).
|
||||
//
|
||||
// If we had multiple threads modifying this pointer, then that would
|
||||
// provide yet another reason for protecting updates to the pointer using a
|
||||
// lock. However, in this driver, at any given time we have only one thread
|
||||
// that modifies this pointer (the thread that runs the read callback).
|
||||
// This is true because we use a sequential queue for read requests. If we
|
||||
// were to change our read queue to be a parallel queue, this would no
|
||||
// longer be true.
|
||||
//
|
||||
//
|
||||
BYTE* Head;
|
||||
|
||||
//
|
||||
// A pointer to the current write point in the ring buffer.
|
||||
//
|
||||
// Updates to this pointer are protected by the "pending read pointer
|
||||
// lock", because we do not want a consumer thread to mark a read request
|
||||
// as pending while we are in the process of writing data to the buffer.
|
||||
// The reason is that the write that we are currently performing might
|
||||
// actually supply enough data to satisfy the read request, in which case
|
||||
// it should not be marked pending at all.
|
||||
// If the read request were to be marked pending in the situation described
|
||||
// above, then we would need some trigger to later retrieve the request and
|
||||
// complete it. In our driver, arrival of data is the only event that can
|
||||
// trigger this. So if no more data arrives, the request will remain
|
||||
// pending forever, even though there is enough data in the buffer to
|
||||
// complete it. Hence we do not keep a read request pending in situations
|
||||
// where the read buffer contains enough data to satisfy it.
|
||||
//
|
||||
// If we had multiple threads modifying this pointer, then that would
|
||||
// provide yet another reason for protecting updates to the pointer using a
|
||||
// lock. However, in this driver, at any given time we have only one thread
|
||||
// that modifies this pointer (the thread that runs the write callback).
|
||||
// This is true because we use a sequential queue for write requests. If we
|
||||
// were to change our write queue to be a parallel queue, this would no
|
||||
// longer be true.
|
||||
//
|
||||
BYTE* Tail;
|
||||
|
||||
} RING_BUFFER, *PRING_BUFFER;
|
||||
|
||||
|
||||
VOID
|
||||
RingBufferInitialize(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_In_reads_bytes_(BufferSize)
|
||||
BYTE* Buffer,
|
||||
_In_ size_t BufferSize
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
RingBufferWrite(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_In_reads_bytes_(DataSize)
|
||||
BYTE* Data,
|
||||
_In_ size_t DataSize
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
RingBufferRead(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_Out_writes_bytes_to_(DataSize, *BytesCopied)
|
||||
BYTE* Data,
|
||||
_In_ size_t DataSize,
|
||||
_Out_ size_t *BytesCopied
|
||||
);
|
||||
|
||||
VOID
|
||||
RingBufferGetAvailableSpace(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_Out_ size_t *AvailableSpace
|
||||
);
|
||||
|
||||
VOID
|
||||
RingBufferGetAvailableData(
|
||||
_In_ PRING_BUFFER Self,
|
||||
_Out_ size_t *AvailableData
|
||||
);
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
Serial.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Type definitions and data for the serial port driver
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// This defines the bit used to control whether the device is sending
|
||||
// a break. When this bit is set the device is sending a space (logic 0).
|
||||
//
|
||||
// Most protocols will assume that this is a hangup.
|
||||
//
|
||||
#define SERIAL_LCR_BREAK 0x40
|
||||
|
||||
//
|
||||
// These defines are used to set the line control register.
|
||||
//
|
||||
#define SERIAL_5_DATA ((UCHAR)0x00)
|
||||
#define SERIAL_6_DATA ((UCHAR)0x01)
|
||||
#define SERIAL_7_DATA ((UCHAR)0x02)
|
||||
#define SERIAL_8_DATA ((UCHAR)0x03)
|
||||
#define SERIAL_DATA_MASK ((UCHAR)0x03)
|
||||
|
||||
#define SERIAL_1_STOP ((UCHAR)0x00)
|
||||
#define SERIAL_1_5_STOP ((UCHAR)0x04) // Only valid for 5 data bits
|
||||
#define SERIAL_2_STOP ((UCHAR)0x04) // Not valid for 5 data bits
|
||||
#define SERIAL_STOP_MASK ((UCHAR)0x04)
|
||||
|
||||
#define SERIAL_NONE_PARITY ((UCHAR)0x00)
|
||||
#define SERIAL_ODD_PARITY ((UCHAR)0x08)
|
||||
#define SERIAL_EVEN_PARITY ((UCHAR)0x18)
|
||||
#define SERIAL_MARK_PARITY ((UCHAR)0x28)
|
||||
#define SERIAL_SPACE_PARITY ((UCHAR)0x38)
|
||||
#define SERIAL_PARITY_MASK ((UCHAR)0x38)
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
|
||||
#include <ntddser.h>
|
||||
|
||||
#else
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Instead of #include <ntddser.h>, the following are copied from that header,
|
||||
// as ntddser.h is conflicted with winioctl.h which is included from wdf.h
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define IOCTL_SERIAL_SET_BAUD_RATE CTL_CODE(FILE_DEVICE_SERIAL_PORT, 1,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_QUEUE_SIZE CTL_CODE(FILE_DEVICE_SERIAL_PORT, 2,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_LINE_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT, 3,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_BREAK_ON CTL_CODE(FILE_DEVICE_SERIAL_PORT, 4,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_BREAK_OFF CTL_CODE(FILE_DEVICE_SERIAL_PORT, 5,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_IMMEDIATE_CHAR CTL_CODE(FILE_DEVICE_SERIAL_PORT, 6,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_TIMEOUTS CTL_CODE(FILE_DEVICE_SERIAL_PORT, 7,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_TIMEOUTS CTL_CODE(FILE_DEVICE_SERIAL_PORT, 8,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_DTR CTL_CODE(FILE_DEVICE_SERIAL_PORT, 9,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_CLR_DTR CTL_CODE(FILE_DEVICE_SERIAL_PORT,10,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_RESET_DEVICE CTL_CODE(FILE_DEVICE_SERIAL_PORT,11,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_RTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,12,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_CLR_RTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,13,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_XOFF CTL_CODE(FILE_DEVICE_SERIAL_PORT,14,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_XON CTL_CODE(FILE_DEVICE_SERIAL_PORT,15,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_WAIT_MASK CTL_CODE(FILE_DEVICE_SERIAL_PORT,16,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_WAIT_MASK CTL_CODE(FILE_DEVICE_SERIAL_PORT,17,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_WAIT_ON_MASK CTL_CODE(FILE_DEVICE_SERIAL_PORT,18,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_PURGE CTL_CODE(FILE_DEVICE_SERIAL_PORT,19,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_BAUD_RATE CTL_CODE(FILE_DEVICE_SERIAL_PORT,20,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_LINE_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,21,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_CHARS CTL_CODE(FILE_DEVICE_SERIAL_PORT,22,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_CHARS CTL_CODE(FILE_DEVICE_SERIAL_PORT,23,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_HANDFLOW CTL_CODE(FILE_DEVICE_SERIAL_PORT,24,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_HANDFLOW CTL_CODE(FILE_DEVICE_SERIAL_PORT,25,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_MODEMSTATUS CTL_CODE(FILE_DEVICE_SERIAL_PORT,26,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_COMMSTATUS CTL_CODE(FILE_DEVICE_SERIAL_PORT,27,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_XOFF_COUNTER CTL_CODE(FILE_DEVICE_SERIAL_PORT,28,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_PROPERTIES CTL_CODE(FILE_DEVICE_SERIAL_PORT,29,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_GET_DTRRTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,30,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_SERIAL_GET_MODEM_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,37,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_MODEM_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,38,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
#define IOCTL_SERIAL_SET_FIFO_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,39,METHOD_BUFFERED,FILE_ANY_ACCESS)
|
||||
|
||||
|
||||
typedef struct _SERIAL_BAUD_RATE {
|
||||
ULONG BaudRate;
|
||||
} SERIAL_BAUD_RATE,*PSERIAL_BAUD_RATE;
|
||||
|
||||
typedef struct _SERIAL_LINE_CONTROL {
|
||||
UCHAR StopBits;
|
||||
UCHAR Parity;
|
||||
UCHAR WordLength;
|
||||
} SERIAL_LINE_CONTROL,*PSERIAL_LINE_CONTROL;
|
||||
|
||||
typedef struct _SERIAL_TIMEOUTS {
|
||||
ULONG ReadIntervalTimeout;
|
||||
ULONG ReadTotalTimeoutMultiplier;
|
||||
ULONG ReadTotalTimeoutConstant;
|
||||
ULONG WriteTotalTimeoutMultiplier;
|
||||
ULONG WriteTotalTimeoutConstant;
|
||||
} SERIAL_TIMEOUTS,*PSERIAL_TIMEOUTS;
|
||||
|
||||
#define STOP_BIT_1 0
|
||||
#define STOP_BITS_1_5 1
|
||||
#define STOP_BITS_2 2
|
||||
|
||||
#define NO_PARITY 0
|
||||
#define ODD_PARITY 1
|
||||
#define EVEN_PARITY 2
|
||||
#define MARK_PARITY 3
|
||||
#define SPACE_PARITY 4
|
||||
|
||||
#endif // #ifdef _KERNEL_MODE, #include <ntddser.h>
|
||||
|
||||
//
|
||||
// DEFINE_GUID(GUID_DEVINTERFACE_MODEM, 0x2c7089aa, 0x2e0e, 0x11d1, 0xb1, 0x14, 0x00, 0xc0, 0x4f, 0xc2, 0xaa, 0xe4);
|
||||
//
|
||||
#include <ntddmodm.h>
|
||||
Loading…
Reference in a new issue