summaryrefslogtreecommitdiff
path: root/smartcrd/pscr
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-04-29 09:48:49 -0700
committerDave Wilson <[email protected]>2015-04-29 10:47:29 -0700
commitd40232638faaab19de557e70a3ee938da7a35295 (patch)
tree14e61c973745949af186b7940e3a53d25322f5de /smartcrd/pscr
parent02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff)
samples update for //build
Diffstat (limited to 'smartcrd/pscr')
-rw-r--r--smartcrd/pscr/Pscr.vcxproj183
-rw-r--r--smartcrd/pscr/Pscr.vcxproj.Filters51
-rw-r--r--smartcrd/pscr/pscr.htm867
-rw-r--r--smartcrd/pscr/pscr.inxbin0 -> 6292 bytes
-rw-r--r--smartcrd/pscr/pscr.rc48
-rw-r--r--smartcrd/pscr/pscrcb.c1008
-rw-r--r--smartcrd/pscr/pscrcb.h84
-rw-r--r--smartcrd/pscr/pscrcmd.c981
-rw-r--r--smartcrd/pscr/pscrcmd.h107
-rw-r--r--smartcrd/pscr/pscrlog.mc103
-rw-r--r--smartcrd/pscr/pscrnt.c1687
-rw-r--r--smartcrd/pscr/pscrnt.h187
-rw-r--r--smartcrd/pscr/pscrrdwr.c509
-rw-r--r--smartcrd/pscr/pscrrdwr.h366
-rw-r--r--smartcrd/pscr/pscrvers.h43
15 files changed, 6224 insertions, 0 deletions
diff --git a/smartcrd/pscr/Pscr.vcxproj b/smartcrd/pscr/Pscr.vcxproj
new file mode 100644
index 00000000..88bc7891
--- /dev/null
+++ b/smartcrd/pscr/Pscr.vcxproj
@@ -0,0 +1,183 @@
+<?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>{E963C756-D675-4202-A229-6B3ADB94B252}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{1C4F5FFD-0F09-4478-A3F7-DEF422837617}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <Inf Include=".\pscr.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\pscr.inf</CopyOutput>
+ </Inf>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>Pscr</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>Pscr</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>Pscr</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>Pscr</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\smclib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\smclib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\smclib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\smclib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="PscrCB.c" />
+ <ClCompile Include="PscrCmd.c" />
+ <ClCompile Include="PscrNT.c" />
+ <ClCompile Include="PscrRdWr.c" />
+ <MessageCompile Include="PscrLog.mc" />
+ <ResourceCompile Include="pscr.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/smartcrd/pscr/Pscr.vcxproj.Filters b/smartcrd/pscr/Pscr.vcxproj.Filters
new file mode 100644
index 00000000..55f941f4
--- /dev/null
+++ b/smartcrd/pscr/Pscr.vcxproj.Filters
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{7EB6DC3A-11A4-48F2-9730-419C9A104242}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{2AAA41D4-E19E-409F-87C1-EA4C640F0BAA}</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>{9FEF86B3-6289-44F6-B036-2C15E61CDDDE}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{A832F7F9-C73F-4032-83DF-1CA14DE6C0FF}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\pscr.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include=".\pscr.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ <MessageCompile Include="PscrLog.mc">
+ <Filter>Driver Files</Filter>
+ </MessageCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="PscrCB.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="PscrCmd.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="PscrNT.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="PscrRdWr.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="pscr.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/smartcrd/pscr/pscr.htm b/smartcrd/pscr/pscr.htm
new file mode 100644
index 00000000..934a4c0e
--- /dev/null
+++ b/smartcrd/pscr/pscr.htm
@@ -0,0 +1,867 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml"
+xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:w="urn:schemas-microsoft-com:office:word"
+xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
+<meta name=ProgId content=Word.Document>
+<meta name=Generator content="Microsoft Word 12">
+<meta name=Originator content="Microsoft Word 12">
+<link rel=File-List href="pscr2_files/filelist.xml">
+<title>PSCR.SYS�PCMCIA Smart Card Driver</title>
+<!--[if gte mso 9]><xml>
+ <o:DocumentProperties>
+ <o:Author>Michael Tsang</o:Author>
+ <o:LastAuthor>Michael Tsang</o:LastAuthor>
+ <o:Revision>2</o:Revision>
+ <o:TotalTime>75</o:TotalTime>
+ <o:Created>2009-02-13T19:09:00Z</o:Created>
+ <o:LastSaved>2009-02-13T19:09:00Z</o:LastSaved>
+ <o:Pages>1</o:Pages>
+ <o:Words>838</o:Words>
+ <o:Characters>4780</o:Characters>
+ <o:Company>Microsoft</o:Company>
+ <o:Lines>39</o:Lines>
+ <o:Paragraphs>11</o:Paragraphs>
+ <o:CharactersWithSpaces>5607</o:CharactersWithSpaces>
+ <o:Version>12.00</o:Version>
+ </o:DocumentProperties>
+</xml><![endif]-->
+<link rel=themeData href="pscr2_files/themedata.thmx">
+<link rel=colorSchemeMapping href="pscr2_files/colorschememapping.xml">
+<!--[if gte mso 9]><xml>
+ <w:WordDocument>
+ <w:Zoom>125</w:Zoom>
+ <w:SpellingState>Clean</w:SpellingState>
+ <w:GrammarState>Clean</w:GrammarState>
+ <w:TrackMoves>false</w:TrackMoves>
+ <w:TrackFormatting/>
+ <w:ValidateAgainstSchemas/>
+ <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
+ <w:IgnoreMixedContent>false</w:IgnoreMixedContent>
+ <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
+ <w:DoNotPromoteQF/>
+ <w:LidThemeOther>EN-US</w:LidThemeOther>
+ <w:LidThemeAsian>X-NONE</w:LidThemeAsian>
+ <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
+ <w:Compatibility>
+ <w:BreakWrappedTables/>
+ <w:SnapToGridInCell/>
+ <w:WrapTextWithPunct/>
+ <w:UseAsianBreakRules/>
+ <w:DontGrowAutofit/>
+ <w:SplitPgBreakAndParaMark/>
+ <w:DontVertAlignCellWithSp/>
+ <w:DontBreakConstrainedForcedTables/>
+ <w:DontVertAlignInTxbx/>
+ <w:Word11KerningPairs/>
+ <w:CachedColBalance/>
+ </w:Compatibility>
+ <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
+ <m:mathPr>
+ <m:mathFont m:val="Cambria Math"/>
+ <m:brkBin m:val="before"/>
+ <m:brkBinSub m:val="&#45;-"/>
+ <m:smallFrac m:val="off"/>
+ <m:dispDef/>
+ <m:lMargin m:val="0"/>
+ <m:rMargin m:val="0"/>
+ <m:defJc m:val="centerGroup"/>
+ <m:wrapIndent m:val="1440"/>
+ <m:intLim m:val="subSup"/>
+ <m:naryLim m:val="undOvr"/>
+ </m:mathPr></w:WordDocument>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
+ DefSemiHidden="true" DefQFormat="false" DefPriority="99"
+ LatentStyleCount="267">
+ <w:LsdException Locked="false" Priority="0" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
+ <w:LsdException Locked="false" Priority="9" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
+ <w:LsdException Locked="false" Priority="9" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="heading 2"/>
+ <w:LsdException Locked="false" Priority="9" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="heading 3"/>
+ <w:LsdException Locked="false" Priority="9" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="heading 4"/>
+ <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
+ <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
+ <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
+ <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
+ <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 1"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 2"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 3"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 4"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 5"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 6"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 7"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 8"/>
+ <w:LsdException Locked="false" Priority="39" Name="toc 9"/>
+ <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
+ <w:LsdException Locked="false" Priority="10" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Title"/>
+ <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
+ <w:LsdException Locked="false" Priority="11" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
+ <w:LsdException Locked="false" Priority="22" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
+ <w:LsdException Locked="false" Priority="20" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
+ <w:LsdException Locked="false" Priority="59" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Table Grid"/>
+ <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
+ <w:LsdException Locked="false" Priority="1" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
+ <w:LsdException Locked="false" Priority="60" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Shading"/>
+ <w:LsdException Locked="false" Priority="61" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light List"/>
+ <w:LsdException Locked="false" Priority="62" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Grid"/>
+ <w:LsdException Locked="false" Priority="63" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 1"/>
+ <w:LsdException Locked="false" Priority="64" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 2"/>
+ <w:LsdException Locked="false" Priority="65" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 1"/>
+ <w:LsdException Locked="false" Priority="66" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 2"/>
+ <w:LsdException Locked="false" Priority="67" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 1"/>
+ <w:LsdException Locked="false" Priority="68" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 2"/>
+ <w:LsdException Locked="false" Priority="69" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 3"/>
+ <w:LsdException Locked="false" Priority="70" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Dark List"/>
+ <w:LsdException Locked="false" Priority="71" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Shading"/>
+ <w:LsdException Locked="false" Priority="72" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful List"/>
+ <w:LsdException Locked="false" Priority="73" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Grid"/>
+ <w:LsdException Locked="false" Priority="60" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
+ <w:LsdException Locked="false" Priority="61" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light List Accent 1"/>
+ <w:LsdException Locked="false" Priority="62" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
+ <w:LsdException Locked="false" Priority="63" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
+ <w:LsdException Locked="false" Priority="64" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
+ <w:LsdException Locked="false" Priority="65" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
+ <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
+ <w:LsdException Locked="false" Priority="34" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
+ <w:LsdException Locked="false" Priority="29" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
+ <w:LsdException Locked="false" Priority="30" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
+ <w:LsdException Locked="false" Priority="66" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
+ <w:LsdException Locked="false" Priority="67" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
+ <w:LsdException Locked="false" Priority="68" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
+ <w:LsdException Locked="false" Priority="69" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
+ <w:LsdException Locked="false" Priority="70" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Dark List Accent 1"/>
+ <w:LsdException Locked="false" Priority="71" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
+ <w:LsdException Locked="false" Priority="72" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
+ <w:LsdException Locked="false" Priority="73" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
+ <w:LsdException Locked="false" Priority="60" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
+ <w:LsdException Locked="false" Priority="61" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light List Accent 2"/>
+ <w:LsdException Locked="false" Priority="62" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
+ <w:LsdException Locked="false" Priority="63" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
+ <w:LsdException Locked="false" Priority="64" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
+ <w:LsdException Locked="false" Priority="65" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
+ <w:LsdException Locked="false" Priority="66" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
+ <w:LsdException Locked="false" Priority="67" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
+ <w:LsdException Locked="false" Priority="68" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
+ <w:LsdException Locked="false" Priority="69" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
+ <w:LsdException Locked="false" Priority="70" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Dark List Accent 2"/>
+ <w:LsdException Locked="false" Priority="71" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
+ <w:LsdException Locked="false" Priority="72" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
+ <w:LsdException Locked="false" Priority="73" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
+ <w:LsdException Locked="false" Priority="60" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
+ <w:LsdException Locked="false" Priority="61" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light List Accent 3"/>
+ <w:LsdException Locked="false" Priority="62" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
+ <w:LsdException Locked="false" Priority="63" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
+ <w:LsdException Locked="false" Priority="64" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
+ <w:LsdException Locked="false" Priority="65" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
+ <w:LsdException Locked="false" Priority="66" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
+ <w:LsdException Locked="false" Priority="67" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
+ <w:LsdException Locked="false" Priority="68" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
+ <w:LsdException Locked="false" Priority="69" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
+ <w:LsdException Locked="false" Priority="70" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Dark List Accent 3"/>
+ <w:LsdException Locked="false" Priority="71" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
+ <w:LsdException Locked="false" Priority="72" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
+ <w:LsdException Locked="false" Priority="73" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
+ <w:LsdException Locked="false" Priority="60" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
+ <w:LsdException Locked="false" Priority="61" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light List Accent 4"/>
+ <w:LsdException Locked="false" Priority="62" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
+ <w:LsdException Locked="false" Priority="63" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
+ <w:LsdException Locked="false" Priority="64" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
+ <w:LsdException Locked="false" Priority="65" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
+ <w:LsdException Locked="false" Priority="66" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
+ <w:LsdException Locked="false" Priority="67" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
+ <w:LsdException Locked="false" Priority="68" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
+ <w:LsdException Locked="false" Priority="69" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
+ <w:LsdException Locked="false" Priority="70" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Dark List Accent 4"/>
+ <w:LsdException Locked="false" Priority="71" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
+ <w:LsdException Locked="false" Priority="72" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
+ <w:LsdException Locked="false" Priority="73" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
+ <w:LsdException Locked="false" Priority="60" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
+ <w:LsdException Locked="false" Priority="61" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light List Accent 5"/>
+ <w:LsdException Locked="false" Priority="62" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
+ <w:LsdException Locked="false" Priority="63" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
+ <w:LsdException Locked="false" Priority="64" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
+ <w:LsdException Locked="false" Priority="65" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
+ <w:LsdException Locked="false" Priority="66" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
+ <w:LsdException Locked="false" Priority="67" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
+ <w:LsdException Locked="false" Priority="68" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
+ <w:LsdException Locked="false" Priority="69" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
+ <w:LsdException Locked="false" Priority="70" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Dark List Accent 5"/>
+ <w:LsdException Locked="false" Priority="71" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
+ <w:LsdException Locked="false" Priority="72" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
+ <w:LsdException Locked="false" Priority="73" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
+ <w:LsdException Locked="false" Priority="60" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
+ <w:LsdException Locked="false" Priority="61" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light List Accent 6"/>
+ <w:LsdException Locked="false" Priority="62" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
+ <w:LsdException Locked="false" Priority="63" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
+ <w:LsdException Locked="false" Priority="64" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
+ <w:LsdException Locked="false" Priority="65" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
+ <w:LsdException Locked="false" Priority="66" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
+ <w:LsdException Locked="false" Priority="67" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
+ <w:LsdException Locked="false" Priority="68" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
+ <w:LsdException Locked="false" Priority="69" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
+ <w:LsdException Locked="false" Priority="70" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Dark List Accent 6"/>
+ <w:LsdException Locked="false" Priority="71" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
+ <w:LsdException Locked="false" Priority="72" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
+ <w:LsdException Locked="false" Priority="73" SemiHidden="false"
+ UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
+ <w:LsdException Locked="false" Priority="19" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
+ <w:LsdException Locked="false" Priority="21" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
+ <w:LsdException Locked="false" Priority="31" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
+ <w:LsdException Locked="false" Priority="32" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
+ <w:LsdException Locked="false" Priority="33" SemiHidden="false"
+ UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
+ <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
+ <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
+ </w:LatentStyles>
+</xml><![endif]-->
+<style>
+<!--
+ /* Font Definitions */
+ @font-face
+ {font-family:Courier;
+ panose-1:2 7 4 9 2 2 5 2 4 4;
+ mso-font-charset:0;
+ mso-generic-font-family:modern;
+ mso-font-format:other;
+ mso-font-pitch:fixed;
+ mso-font-signature:3 0 0 0 1 0;}
+@font-face
+ {font-family:"Cambria Math";
+ panose-1:2 4 5 3 5 4 6 3 2 4;
+ mso-font-charset:0;
+ mso-generic-font-family:roman;
+ mso-font-pitch:variable;
+ mso-font-signature:-1610611985 1107304683 0 0 415 0;}
+@font-face
+ {font-family:Consolas;
+ panose-1:2 11 6 9 2 2 4 3 2 4;
+ mso-font-charset:0;
+ mso-generic-font-family:modern;
+ mso-font-pitch:fixed;
+ mso-font-signature:-520092929 1073806591 9 0 415 0;}
+@font-face
+ {font-family:Verdana;
+ panose-1:2 11 6 4 3 5 4 4 2 4;
+ mso-font-charset:0;
+ mso-generic-font-family:swiss;
+ mso-font-pitch:variable;
+ mso-font-signature:-1593833729 1073750107 16 0 415 0;}
+@font-face
+ {font-family:"MS Sans Serif";
+ panose-1:0 0 0 0 0 0 0 0 0 0;
+ mso-font-alt:"Times New Roman";
+ mso-font-charset:0;
+ mso-generic-font-family:roman;
+ mso-font-format:other;
+ mso-font-pitch:auto;
+ mso-font-signature:0 0 0 0 0 0;}
+@font-face
+ {font-family:"MS Shell Dlg";
+ panose-1:2 11 6 4 2 2 2 2 2 4;
+ mso-font-charset:0;
+ mso-generic-font-family:swiss;
+ mso-font-pitch:variable;
+ mso-font-signature:-520082689 -1073741822 8 0 66047 0;}
+ /* Style Definitions */
+ p.MsoNormal, li.MsoNormal, div.MsoNormal
+ {mso-style-unhide:no;
+ mso-style-qformat:yes;
+ mso-style-parent:"";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";
+ mso-fareast-font-family:"Times New Roman";}
+h2
+ {mso-style-priority:9;
+ mso-style-unhide:no;
+ mso-style-qformat:yes;
+ mso-style-link:"Heading 2 Char";
+ mso-margin-top-alt:auto;
+ margin-right:0in;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ mso-outline-level:2;
+ font-size:18.0pt;
+ font-family:"Times New Roman","serif";
+ mso-fareast-font-family:"Times New Roman";
+ mso-fareast-theme-font:minor-fareast;
+ font-weight:bold;}
+h3
+ {mso-style-priority:9;
+ mso-style-unhide:no;
+ mso-style-qformat:yes;
+ mso-style-link:"Heading 3 Char";
+ mso-margin-top-alt:auto;
+ margin-right:0in;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ mso-outline-level:3;
+ font-size:13.5pt;
+ font-family:"Times New Roman","serif";
+ mso-fareast-font-family:"Times New Roman";
+ mso-fareast-theme-font:minor-fareast;
+ font-weight:bold;}
+h4
+ {mso-style-priority:9;
+ mso-style-unhide:no;
+ mso-style-qformat:yes;
+ mso-style-link:"Heading 4 Char";
+ mso-margin-top-alt:auto;
+ margin-right:0in;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ mso-outline-level:4;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";
+ mso-fareast-font-family:"Times New Roman";
+ mso-fareast-theme-font:minor-fareast;
+ font-weight:bold;}
+a:link, span.MsoHyperlink
+ {mso-style-noshow:yes;
+ mso-style-priority:99;
+ color:blue;
+ text-decoration:underline;
+ text-underline:single;}
+a:visited, span.MsoHyperlinkFollowed
+ {mso-style-noshow:yes;
+ mso-style-priority:99;
+ color:purple;
+ text-decoration:underline;
+ text-underline:single;}
+p
+ {mso-style-noshow:yes;
+ mso-style-priority:99;
+ mso-margin-top-alt:auto;
+ margin-right:0in;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";
+ mso-fareast-font-family:"Times New Roman";}
+pre
+ {mso-style-noshow:yes;
+ mso-style-priority:99;
+ mso-style-link:"HTML Preformatted Char";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt;
+ font-size:10.0pt;
+ font-family:"Courier New";
+ mso-fareast-font-family:"Times New Roman";}
+span.Heading2Char
+ {mso-style-name:"Heading 2 Char";
+ mso-style-noshow:yes;
+ mso-style-priority:9;
+ mso-style-unhide:no;
+ mso-style-locked:yes;
+ mso-style-link:"Heading 2";
+ mso-ansi-font-size:13.0pt;
+ mso-bidi-font-size:13.0pt;
+ font-family:"Cambria","serif";
+ mso-ascii-font-family:Cambria;
+ mso-ascii-theme-font:major-latin;
+ mso-fareast-font-family:"Times New Roman";
+ mso-fareast-theme-font:major-fareast;
+ mso-hansi-font-family:Cambria;
+ mso-hansi-theme-font:major-latin;
+ mso-bidi-font-family:"Times New Roman";
+ mso-bidi-theme-font:major-bidi;
+ color:#4F81BD;
+ mso-themecolor:accent1;
+ font-weight:bold;}
+span.Heading3Char
+ {mso-style-name:"Heading 3 Char";
+ mso-style-noshow:yes;
+ mso-style-priority:9;
+ mso-style-unhide:no;
+ mso-style-locked:yes;
+ mso-style-link:"Heading 3";
+ mso-ansi-font-size:12.0pt;
+ mso-bidi-font-size:12.0pt;
+ font-family:"Cambria","serif";
+ mso-ascii-font-family:Cambria;
+ mso-ascii-theme-font:major-latin;
+ mso-fareast-font-family:"Times New Roman";
+ mso-fareast-theme-font:major-fareast;
+ mso-hansi-font-family:Cambria;
+ mso-hansi-theme-font:major-latin;
+ mso-bidi-font-family:"Times New Roman";
+ mso-bidi-theme-font:major-bidi;
+ color:#4F81BD;
+ mso-themecolor:accent1;
+ font-weight:bold;}
+span.Heading4Char
+ {mso-style-name:"Heading 4 Char";
+ mso-style-noshow:yes;
+ mso-style-priority:9;
+ mso-style-unhide:no;
+ mso-style-locked:yes;
+ mso-style-link:"Heading 4";
+ mso-ansi-font-size:12.0pt;
+ mso-bidi-font-size:12.0pt;
+ font-family:"Cambria","serif";
+ mso-ascii-font-family:Cambria;
+ mso-ascii-theme-font:major-latin;
+ mso-fareast-font-family:"Times New Roman";
+ mso-fareast-theme-font:major-fareast;
+ mso-hansi-font-family:Cambria;
+ mso-hansi-theme-font:major-latin;
+ mso-bidi-font-family:"Times New Roman";
+ mso-bidi-theme-font:major-bidi;
+ color:#4F81BD;
+ mso-themecolor:accent1;
+ font-weight:bold;
+ font-style:italic;}
+span.HTMLPreformattedChar
+ {mso-style-name:"HTML Preformatted Char";
+ mso-style-noshow:yes;
+ mso-style-priority:99;
+ mso-style-unhide:no;
+ mso-style-locked:yes;
+ mso-style-link:"HTML Preformatted";
+ font-family:Consolas;
+ mso-ascii-font-family:Consolas;
+ mso-hansi-font-family:Consolas;
+ mso-bidi-font-family:Consolas;}
+span.SpellE
+ {mso-style-name:"";
+ mso-spl-e:yes;}
+span.GramE
+ {mso-style-name:"";
+ mso-gram-e:yes;}
+.MsoChpDefault
+ {mso-style-type:export-only;
+ mso-default-props:yes;
+ font-size:10.0pt;
+ mso-ansi-font-size:10.0pt;
+ mso-bidi-font-size:10.0pt;}
+@page Section1
+ {size:8.5in 11.0in;
+ margin:1.0in 1.25in 1.0in 1.25in;
+ mso-header-margin:.5in;
+ mso-footer-margin:.5in;
+ mso-paper-source:0;}
+div.Section1
+ {page:Section1;}
+ /* List Definitions */
+ @list l0
+ {mso-list-id:1673945939;
+ mso-list-type:hybrid;
+ mso-list-template-ids:-2047047524 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
+@list l0:level1
+ {mso-level-tab-stop:none;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+ol
+ {margin-bottom:0in;}
+ul
+ {margin-bottom:0in;}
+-->
+</style>
+<!--[if gte mso 10]>
+<style>
+ /* Style Definitions */
+ table.MsoNormalTable
+ {mso-style-name:"Table Normal";
+ mso-tstyle-rowband-size:0;
+ mso-tstyle-colband-size:0;
+ mso-style-noshow:yes;
+ mso-style-priority:99;
+ mso-style-qformat:yes;
+ mso-style-parent:"";
+ mso-padding-alt:0in 5.4pt 0in 5.4pt;
+ mso-para-margin:0in;
+ mso-para-margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:10.0pt;
+ font-family:"Times New Roman","serif";}
+</style>
+<![endif]--><!--[if gte mso 9]><xml>
+ <u1:shapedefaults u2:ext="edit" spidmax="4098"/>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <u3:shapelayout u4:ext="edit">
+ <u3:idmap u4:ext="edit" data="1"/>
+ </u3:shapelayout>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <u1:shapedefaults u2:ext="edit" spidmax="3074"/>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <u3:shapelayout u4:ext="edit">
+ <u3:idmap u4:ext="edit" data="1"/>
+ </u3:shapelayout>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <u1:shapedefaults u2:ext="edit" spidmax="2050"/>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <u3:shapelayout u4:ext="edit">
+ <u3:idmap u4:ext="edit" data="1"/>
+ </u3:shapelayout>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <o:shapedefaults v:ext="edit" spidmax="3074"/>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <o:shapelayout v:ext="edit">
+ <o:idmap v:ext="edit" data="1"/>
+ </o:shapelayout></xml><![endif]-->
+</head>
+
+<body bgcolor=white lang=EN-US link=blue vlink=purple style='tab-interval:.5in'
+leftmargin=8>
+
+<div class=Section1>
+
+<h2><a name=MYSAMPLE></a><a name="_top"></a><span style='mso-bookmark:MYSAMPLE'><span
+style='font-family:"Verdana","sans-serif";mso-fareast-font-family:"Times New Roman"'>PSCR.SYS�PCMCIA
+Smart Card Driver</span></span><u5:p></u5:p><u6:p></u6:p><span
+style='mso-bookmark:MYSAMPLE'></span><span style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></h2>
+
+<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman"'><u7:p></u7:p>SUMMARY<u7:p></u7:p></span><span
+style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></h3>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>The PCMCIA
+Smart Card Driver is used for the SCM PCMCIA smart card reader. <u7:p></u7:p>This
+driver is written using Kernel-Mode Driver Framework. </span></p>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>This
+driver implements Plug and Play and Power Management and is compliant with
+64-bit versions of Microsoft�&nbsp;Windows�.<u7:p></u7:p></span></p>
+
+<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman"'>BUILDING PSCR.SYS<u7:p></u7:p></span><span style='mso-fareast-font-family:
+"Times New Roman"'><o:p></o:p></span></h3>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>To build
+the Pscr.sys driver, select either the checked or free DDK environment,
+navigate to the Bulltlp3 directory, and type <b>build</b>.&nbsp;This driver
+uses services provided by the smart card driver library (Smclib.sys), which are
+explained in detail in the accompanying documentation.<u7:p></u7:p></span></p>
+
+<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman"'>INSTALLING PSCR.SYS<u7:p></u7:p></span><span
+style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></h3>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>The
+PSCR.SYS driver is included in-box in the Windows Operating Systems. Therefore,
+when the SCM 488 PCMCIA reader is inserted, the system will automatically
+install the in-box driver. However, if you want to customize the source code of
+this driver and would like to replace the in-box driver with your driver, you
+can follow the instructions below.<o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>To install
+your driver, you will need to provide the INF file (on a disk), WDF <span
+class=SpellE>coinstaller</span> from the %BASEDIR%\<span class=SpellE>redist</span>\<span
+class=SpellE>wdf</span>\ directory and the driver file, which will be copied to
+your System32\Drivers directory. The INF file makes a reference to the WDF <span
+class=SpellE>coinstaller</span>. </span></p>
+
+<p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span></span></span><![endif]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Launch �Device
+Manager� by clicking the �Windows� button and type �devmgmt.msc� in the �Search
+programs and files� box.<o:p></o:p></span></p>
+
+<p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span></span></span><![endif]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Locate the SCM 488
+Smartcard reader device from the �Smart cards readers� category.<o:p></o:p></span></p>
+
+<p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>3.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span></span></span><![endif]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Right click on the
+reader device and select �Update Driver Software�<span class=GramE>�.</span><o:p></o:p></span></p>
+
+<p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>4.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span></span></span><![endif]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Select �Browse my
+computer for driver software�.<o:p></o:p></span></p>
+
+<p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>5.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span></span></span><![endif]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Select �Let me pick
+from a list of device drivers on my computer�.<o:p></o:p></span></p>
+
+<p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>6.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span></span></span><![endif]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Click the �Have
+Disk�� button and point it to the folder that contains your driver, INF and
+coinstaller.<o:p></o:p></span></p>
+
+<p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>7.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span></span></span><![endif]><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Follow the
+instructions of the device installation wizard to finish the installation.<o:p></o:p></span></p>
+
+<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman"'>TOOLS</span><span style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></h3>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Microsoft
+offers a test tool (Ifdtest.exe) that allows you to use a smart card reader
+directly from the command line. Normally, the smart card resource manager is
+connected to a reader. To use Ifdtest.exe, you must stop the smart card
+resource manager (Scardsvr.exe) by typing <b>net stop <span class=SpellE>scardsvr</span></b>
+at the command line. Ifdtest.exe is also used for the smart card reader logo
+test.<u7:p></u7:p><o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>The driver
+will not unload as long as you have Ifdtest.exe running and connected to the
+driver. <u7:p></u7:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>You can
+download Ifdtest.exe from </span><span style='font-size:10.0pt;font-family:
+"Verdana","sans-serif";mso-bidi-font-family:"MS Shell Dlg"'><a
+href="http://www.microsoft.com/whdc/whql/default.mspx">http://www.microsoft.com/whdc/whql/default.mspx</a></span><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> by following the
+links for smart cards. You need to order special test smart cards to have your
+smart card reader qualify for the &quot;Designed for Windows&quot; logo. You
+can find ordering information at </span><span style='font-size:10.0pt;
+font-family:"Verdana","sans-serif";mso-bidi-font-family:"MS Shell Dlg"'><a
+href="http://www.microsoft.com/whdc/whql/default.mspx">http://www.microsoft.com/whdc/whql/default.mspx</a></span><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>. <u7:p></u7:p>&nbsp;<u7:p></u7:p></span></p>
+
+<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman"'>RESOURCES<u7:p></u7:p></span><span style='mso-fareast-font-family:
+"Times New Roman"'><o:p></o:p></span></h3>
+
+<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>ISO 7816
+Part 3 describes smart cards and smart card protocols in detail. Refer to the
+PC99 Handbook for smart card reader requirements.<u7:p></u7:p></span></p>
+
+<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman"'>CODE TOUR<u7:p></u7:p></span><span style='mso-fareast-font-family:
+"Times New Roman"'><o:p></o:p></span></h3>
+
+<h4><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman"'>File Manifest<u7:p></u7:p></span><span style='mso-fareast-font-family:
+"Times New Roman"'><o:p></o:p></span></h4>
+
+<pre><u>Files<span style='mso-spacerun:yes'>�������� </span>Description<u7:p></u7:p></u></pre><pre>PSCR.HTM<span style='mso-spacerun:yes'>����� </span>The documentation for this sample (this file).</pre><pre>PSCR.RC<span style='mso-spacerun:yes'>������ </span>Resource <span
+class=GramE>definition file</span> for driver.</pre><pre><span class=GramE><span
+style='font-family:Courier'>SOURCES<span style='mso-spacerun:yes'>������ </span>The generic file for building the code sample.<u7:p></u7:p></span></span></pre><pre><span
+style='font-family:Courier'>MAKEFILE<span style='mso-spacerun:yes'>����� </span><span
+class=SpellE>Makefile</span> required <span class=GramE>to build</span> the driver.<u7:p></u7:p></span></pre><pre><span
+style='font-family:Courier'>PSCR.INF<span style='mso-spacerun:yes'>����� </span>The INF <span
+class=GramE>file</span> for installing the code sample.<u7:p></u7:p></span></pre><pre><span
+style='font-family:Courier'>PSCRCB.C<span style='mso-spacerun:yes'>����� </span>Source file that contains the callback functions for the smart card library.<u7:p></u7:p></span></pre><pre><span
+style='font-family:Courier'>PSCRCB.H<span style='mso-spacerun:yes'>����� </span>Function prototypes for the previous file.<u7:p></u7:p></span></pre><pre><span
+style='font-family:Courier'>PSCRCMD.C<span style='mso-spacerun:yes'>���� </span>Implements the reader commands.<u7:p></u7:p></span></pre><pre><span
+style='font-family:Courier'>PSCRCMD.H<span style='mso-spacerun:yes'>���� </span>Function prototypes for the previous file.<u7:p></u7:p></span></pre><pre><span
+style='font-family:Courier'>PSCRLOG.MC<span style='mso-spacerun:yes'>��� </span>Error messages for this driver.<u7:p></u7:p></span></pre><pre><span
+style='font-family:Courier'>PSCRNT.C<span style='mso-spacerun:yes'>����� </span>The main source file (load, unload, Plug and Play, Power Management).<u7:p></u7:p></span></pre><pre><span
+class=GramE><span style='font-family:Courier'>PSCRNT.H<span style='mso-spacerun:yes'>����� </span>Data definitions and prototypes for the previous file.<u7:p></u7:p></span></span></pre><pre><span
+style='font-family:Courier'>PSCRRDWR.C<span style='mso-spacerun:yes'>��� </span>Implements read/write operations.<u7:p></u7:p></span></pre><pre><span
+class=GramE><span style='font-family:Courier'>PSCRRDWR.H<span style='mso-spacerun:yes'>��� </span>Data definitions and constant definitions for this reader.<u7:p></u7:p></span></span></pre><pre><span
+class=GramE><span style='font-family:Courier'>PSCRVERS.H<span style='mso-spacerun:yes'>��� </span>Driver-specific version information.<u7:p></u7:p></span></span></pre><pre><span
+style='font-family:"Verdana","sans-serif"'> </span><o:p></o:p></pre>
+
+<h4 style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span
+style='font-family:"Verdana","sans-serif";mso-fareast-font-family:"Times New Roman"'><u7:p></u7:p><u5:p></u5:p><u6:p></u6:p>Programming
+Tour<u7:p></u7:p><o:p></o:p></span></h4>
+
+<h4 style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman"'>Driver Design<o:p></o:p></span></h4>
+
+<h4 style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family:
+"Times New Roman";font-weight:normal;mso-bidi-font-weight:bold'>This driver in its
+original form was written in WDM. It was converted to KMDF to avail all the
+benefits provided by KMDF in terms of reducing complexity and making it robust.
+Since this driver still had to work with the existing smartcard library to
+handle smartcard specific processing, I couldn�t restrict the driver to using
+only KMDF interfaces. I have to escape out of KMDF for processing I/O requests
+to get the underlying IRPs and provide that to smartcard library, and use
+advanced IRP handling techniques to work around the limitations imposed by
+smartcard library. Except for this quirk, the driver as a whole is fully
+functional KMDF driver. As a sample, it also makes it easier for somebody to
+adapt this driver for USB devices because KMDF has good support for interfacing
+with USB devices.<o:p></o:p></span></h4>
+
+<p style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><b><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Power Management</span></b><u5:p></u5:p><u6:p></u6:p><o:p></o:p></p>
+
+<u7:p></u7:p>
+
+<p style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Power Management is
+described in detail in the DDK documentation. There is, however, one situation
+that is specific to smart card readers: how to deal with smart card insertions
+and removals while the system is in standby or hibernation mode. <u7:p></u7:p></span></p>
+
+<p style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span
+style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Your reader will
+not see any card insertion or removal events in these modes, because the bus
+might not even have power. You must save the card state before your reader goes
+into standby or hibernation mode. After the system returns from these modes,
+you need to determine what the state of the card is. You must complete card
+tracking calls whenever there was a card in the reader before standby or
+hibernation mode <i>or</i> whenever there is a card in the reader after these
+modes. This step is necessary because the user could have changed the card
+while the system was in a low-power mode. <u7:p></u7:p></span></p>
+
+<p style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'>&nbsp;</p>
+
+<p align=center style='text-align:center;tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><a
+href="#_top"><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Top
+of page</span></a><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>
+</span><o:p></o:p></p>
+
+<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 width=499
+ style='width:5.2in;mso-cellspacing:0in;mso-yfti-tbllook:1184;mso-padding-alt:
+ 0in 5.4pt 0in 5.4pt'>
+ <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes;mso-yfti-lastrow:yes;
+ height:1.2pt'>
+ <td style='background:aqua;padding:.75pt .75pt .75pt .75pt;height:1.2pt'>
+ <p class=MsoNormal><span style='color:black'><u7:p><u7:p></u7:p><u5:p></u5:p><u6:p></u6:p>&nbsp;</u7:p></span></p>
+ </td>
+ </tr>
+</table>
+
+<p style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span
+style='font-size:7.5pt;font-family:"MS Sans Serif","serif"'>� 2004 Microsoft
+Corporation</span><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>
+</span><o:p></o:p></p>
+
+</div>
+
+<u6:p></u6:p><u5:p></u5:p><u7:p></u7:p>
+</body>
+
+</html>
diff --git a/smartcrd/pscr/pscr.inx b/smartcrd/pscr/pscr.inx
new file mode 100644
index 00000000..28e93816
--- /dev/null
+++ b/smartcrd/pscr/pscr.inx
Binary files differ
diff --git a/smartcrd/pscr/pscr.rc b/smartcrd/pscr/pscr.rc
new file mode 100644
index 00000000..4bf91809
--- /dev/null
+++ b/smartcrd/pscr/pscr.rc
@@ -0,0 +1,48 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+//
+// Copyright (C) SCM Microsystems, 1998 - 1999
+//
+// File: pscr.rc
+//
+// Notes:
+//
+// The file pscr.rc was reviewed by LCA in June 2011 and per license is
+// acceptable for Microsoft use under Dealpoint ID 178449.
+//
+//--------------------------------------------------------------------------
+
+#include <windows.h>
+#include <ntverp.h>
+
+/* These need to be defined before including common.ver: */
+/*-----------------------------------------------------------------*/
+/* String Equate Default Value (if not defined) */
+/* ------------------------ -------------------------------- */
+/* VER_LEGALCOPYRIGHT_STR VER_LEGALCOPYRIGHT_YEARS */
+/* VER_FILETYPE */
+/* VER_FILESUBTYPE */
+/* VER_FILEDESCRIPTION_STR */
+/* VER_INTERNALNAME_STR */
+/* VER_FILEVERSION VER_PRODUCTVERSION */
+/* VER_FILEVERSION_STR VER_PRODUCTVERSION_STR */
+/* VER_ORIGINALFILENAME_STR VER_INTERNALNAME_STR */
+/*-----------------------------------------------------------------*/
+
+
+#define VER_LEGALCOPYRIGHT_YEARS "1997-1999"
+#define VER_LEGALCOPYRIGHT_STR "Copyright (C) SCM Microsystems, Inc. " VER_LEGALCOPYRIGHT_YEARS
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "SCM PCMCIA Smart Card Reader"
+#define VER_INTERNALNAME_STR "pscr.sys"
+#define VER_ORIGINALFILENAME_STR "pscr.sys"
+
+#undef VER_COMPANYNAME_STR
+#define VER_COMPANYNAME_STR "SCM Microsystems, Inc."
+
+#include "common.ver"
+#include "pscrlog.rc"
+
diff --git a/smartcrd/pscr/pscrcb.c b/smartcrd/pscr/pscrcb.c
new file mode 100644
index 00000000..4b89680c
--- /dev/null
+++ b/smartcrd/pscr/pscrcb.c
@@ -0,0 +1,1008 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrCB.c
+
+Abstract:
+
+ callback handler for PSCR.xxx driver
+
+Author:
+
+ Andreas Straub
+
+Environment:
+
+ Win 95 Sys... calls are resolved by Pscr95Wrap.asm functions and
+ Pscr95Wrap.h macros, resp.
+
+ NT 4.0 Sys... functions resolved by PscrNTWrap.c functions and
+ PscrNTWrap.h macros, resp.
+
+Notes:
+
+ The file pscrcb.c was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+ Andreas Straub 8/18/1997 1.00 Initial Version
+ Andreas Straub 9/24/1997 1.02 Flush Interface if card tracking
+ requested
+
+--*/
+
+#include <PscrNT.h>
+#include <PscrRdWr.h>
+#include <PscrCmd.h>
+#include <PscrCB.h>
+
+
+NTSTATUS
+CBCardPower(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+/*++
+
+CBCardPower:
+ callback handler for SMCLIB RDF_CARD_POWER
+
+Arguments:
+ SmartcardExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_NO_MEDIA
+ STATUS_TIMEOUT
+ STATUS_BUFFER_TOO_SMALL
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR ATRBuffer[ ATR_SIZE ], TLVList[16];
+ ULONG Command,
+ ATRLength = 0;
+ PREADER_EXTENSION ReaderExtension;
+ BYTE CardState;
+ KIRQL irql;
+#if DBG || DEBUG
+ static PCHAR request[] = { "PowerDown", "ColdReset", "WarmReset"};
+#endif
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBCardPower: Enter, Request = %s\n",
+ request[SmartcardExtension->MinorIoControlCode])
+ );
+
+ ReaderExtension = SmartcardExtension->ReaderExtension;
+
+ //
+ // update actual power state
+ //
+ Command = SmartcardExtension->MinorIoControlCode;
+
+ switch ( Command ) {
+ case SCARD_WARM_RESET:
+
+ // if the card was not powerd, fall thru to cold reset
+ KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
+ &irql);
+
+ if ( SmartcardExtension->ReaderCapabilities.CurrentState >
+ SCARD_SWALLOWED ) {
+ KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
+ irql);
+
+ // reset the card
+ ATRLength = ATR_SIZE;
+ NTStatus = CmdReset(
+ ReaderExtension,
+ ReaderExtension->Device,
+ TRUE, // warm reset
+ ATRBuffer,
+ &ATRLength
+ );
+
+ break;
+ } else {
+ KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
+ irql);
+
+ }
+
+ // warm reset not possible because card was not powerd
+ case SCARD_COLD_RESET:
+
+ // reset the card
+ ATRLength = ATR_SIZE;
+ NTStatus = CmdReset(
+ ReaderExtension,
+ ReaderExtension->Device,
+ FALSE, // cold reset
+ ATRBuffer,
+ &ATRLength
+ );
+ break;
+
+ case SCARD_POWER_DOWN:
+ ATRLength = 0;
+ NTStatus = CmdDeactivate(
+ ReaderExtension,
+ ReaderExtension->Device
+ );
+
+ // discard old card status
+ CardState = CBGetCardState(SmartcardExtension);
+ CBUpdateCardState(SmartcardExtension, CardState, FALSE);
+ break;
+ }
+
+ if (NT_SUCCESS(NTStatus)) {
+
+ //
+ // Set the 'restart of work waiting time' counter for T=0
+ // This will send a WTX request for n NULL bytes received
+ //
+ TLVList[0] = TAG_SET_NULL_BYTES;
+ TLVList[1] = 1;
+ TLVList[2] = 0x05;
+
+ NTStatus = CmdSetInterfaceParameter(
+ ReaderExtension,
+ DEVICE_READER,
+ TLVList,
+ 3
+ );
+ }
+
+ // Removing this assert as this causes unnecessary confusion. The driver
+ // passes ifdtest even with an error here.
+ // NT_ASSERT(NT_SUCCESS(NTStatus));
+
+ // finish the request
+ if ( NT_SUCCESS( NTStatus )) {
+ // update all neccessary data if an ATR was received
+ if ( ATRLength > 2 ) {
+ //
+ // the lib expects only the ATR, so we skip the
+ // 900x from the reader
+ //
+ ATRLength -= 2;
+
+ // copy ATR to user buffer buffer
+ if ( ATRLength <= SmartcardExtension->IoRequest.ReplyBufferLength ) {
+ SysCopyMemory(
+ SmartcardExtension->IoRequest.ReplyBuffer,
+ ATRBuffer,
+ ATRLength
+ );
+ *SmartcardExtension->IoRequest.Information = ATRLength;
+ }
+
+ // copy ATR to card capability buffer
+ if ( ATRLength <= MAXIMUM_ATR_LENGTH ) {
+ SysCopyMemory(
+ SmartcardExtension->CardCapabilities.ATR.Buffer,
+ ATRBuffer,
+ ATRLength
+ );
+
+ SmartcardExtension->CardCapabilities.ATR.Length =
+ ( UCHAR )ATRLength;
+
+ // let the lib update the card capabilities
+ NTStatus = SmartcardUpdateCardCapabilities(
+ SmartcardExtension
+ );
+ } else {
+ NTStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+ }
+
+ if ( !NT_SUCCESS( NTStatus )) {
+ switch ( NTStatus ) {
+ case STATUS_NO_MEDIA:
+ case STATUS_BUFFER_TOO_SMALL:
+ break;
+
+ case STATUS_TIMEOUT:
+ NTStatus = STATUS_IO_TIMEOUT;
+ break;
+
+ default:
+ NTStatus = STATUS_UNRECOGNIZED_MEDIA;
+ break;
+ }
+ if( NTStatus != STATUS_SUCCESS )
+ {
+
+ // notify resman if card was removed
+ CBUpdateCardState(
+ SmartcardExtension,
+ CBGetCardState( SmartcardExtension ),
+ FALSE
+ );
+
+ // resman requires status ok to translate ntstatus to scard... error.
+ if( SmartcardExtension->ReaderCapabilities.CurrentState <= SCARD_ABSENT )
+ {
+ SmartcardUpdateCardCapabilities( SmartcardExtension );
+ NTStatus = STATUS_SUCCESS;
+ }
+ }
+ }
+
+ // start freeze routine, if an interrupt was sent, but no freeze data was read
+ if( SmartcardExtension->ReaderExtension->RequestInterrupt )
+ PscrFreeze( SmartcardExtension );
+
+ // Clearing the buffers
+ RtlZeroMemory (ATRBuffer, ATR_SIZE);
+ RtlZeroMemory (TLVList, 16);
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBCardPower: Exit (%lx)\n", NTStatus )
+ );
+
+ return( NTStatus );
+}
+
+NTSTATUS
+CBSetProtocol(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+
+/*++
+
+CBSetProtocol:
+ callback handler for SMCLIB RDF_SET_PROTOCOL
+
+Arguments:
+ SmartcardExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_NO_MEDIA
+ STATUS_TIMEOUT
+ STATUS_BUFFER_TOO_SMALL
+ STATUS_INVALID_DEVICE_STATE
+ STATUS_INVALID_DEVICE_REQUEST
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_PENDING;
+ USHORT SCLibProtocol;
+ UCHAR TLVList[ TLV_BUFFER_SIZE ];
+ PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
+ KIRQL irql;
+
+ KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
+ &irql);
+
+ if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC) {
+ KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
+ irql);
+
+
+ return STATUS_SUCCESS;
+ } else {
+ KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
+ irql);
+
+ }
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBSetProtocol: Enter\n" )
+ );
+
+ SCLibProtocol = ( USHORT )( SmartcardExtension->MinorIoControlCode );
+
+ if (SCLibProtocol & (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)) {
+ //
+ // setup the TLV list for the Set Interface Parameter List
+ //
+ TLVList[ 0 ] = TAG_ICC_PROTOCOLS;
+ TLVList[ 1 ] = 0x01;
+ TLVList[ 2 ] =
+ (SCLibProtocol & SCARD_PROTOCOL_T1 ? PSCR_PROTOCOL_T1 : PSCR_PROTOCOL_T0);
+
+ // do the PTS
+ NTStatus = CmdSetInterfaceParameter(
+ ReaderExtension,
+ ReaderExtension->Device,
+ TLVList,
+ 3 // size of list
+ );
+
+ } else {
+
+ // we don't support other modi
+ NTStatus = STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // if protocol selection failed, prevent from calling invalid protocols
+ if ( NT_SUCCESS( NTStatus )) {
+
+ KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
+ &irql);
+ SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
+ SCLibProtocol = (SCLibProtocol & SCARD_PROTOCOL_T1 &
+ SmartcardExtension->CardCapabilities.Protocol.Supported) ?
+ SCARD_PROTOCOL_T1 :
+ SCARD_PROTOCOL_T0;
+
+ KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
+ irql);
+ } else {
+ SCLibProtocol = SCARD_PROTOCOL_UNDEFINED;
+ }
+
+ // Return the selected protocol to the caller.
+ SmartcardExtension->CardCapabilities.Protocol.Selected = SCLibProtocol;
+ *( PULONG )( SmartcardExtension->IoRequest.ReplyBuffer ) = SCLibProtocol;
+ *( SmartcardExtension->IoRequest.Information ) = sizeof( ULONG );
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBSetProtocol: Exit (%lx)\n", NTStatus )
+ );
+
+ return( NTStatus );
+}
+
+NTSTATUS
+CBTransmit(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+/*++
+
+CBTransmit:
+ callback handler for SMCLIB RDF_TRANSMIT
+
+Arguments:
+ SmartcardExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_NO_MEDIA
+ STATUS_TIMEOUT
+ STATUS_INVALID_DEVICE_REQUEST
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBTransmit: Enter\n" )
+ );
+
+ // dispatch on the selected protocol
+ switch ( SmartcardExtension->CardCapabilities.Protocol.Selected ) {
+ case SCARD_PROTOCOL_T0:
+ NTStatus = CBT0Transmit( SmartcardExtension );
+ break;
+
+ case SCARD_PROTOCOL_T1:
+ NTStatus = CBT1Transmit( SmartcardExtension );
+ break;
+
+ case SCARD_PROTOCOL_RAW:
+ NTStatus = CBRawTransmit( SmartcardExtension );
+ break;
+
+ default:
+ NTStatus = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBTransmit: Exit (%lx)\n", NTStatus )
+ );
+
+ return( NTStatus );
+}
+
+NTSTATUS
+CBRawTransmit(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+/*++
+
+CBRawTransmit:
+ finishes the callback RDF_TRANSMIT for the RAW protocol
+
+Arguments:
+ SmartcardExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_NO_MEDIA
+ STATUS_TIMEOUT
+ STATUS_INVALID_DEVICE_REQUEST
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR TLVList[ TLV_BUFFER_SIZE ],
+ Val,
+ Len;
+ ULONG TLVListLen;
+ PREADER_EXTENSION ReaderExtension;
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBRawTransmit: Enter\n" )
+ );
+
+ ReaderExtension = SmartcardExtension->ReaderExtension;
+ //
+ // read the status file of ICC1 from the reader
+ //
+ TLVListLen = TLV_BUFFER_SIZE;
+ NTStatus = CmdReadStatusFile(
+ ReaderExtension,
+ ReaderExtension->Device,
+ TLVList,
+ &TLVListLen
+ );
+
+ //
+ // check the active protocol of the reader
+ //
+ if ( NT_SUCCESS( NTStatus )) {
+ Len = sizeof(Val);
+ NTStatus = CmdGetTagValue(
+ TAG_ICC_PROTOCOLS,
+ TLVList,
+ TLVListLen,
+ &Len,
+ ( PVOID ) &Val
+ );
+
+ // execute the active protocol
+ if ( NT_SUCCESS( NTStatus )) {
+
+ // translate the actual protocol to a value the lib can understand
+ switch ( Val ) {
+ case PSCR_PROTOCOL_T0:
+ NTStatus = CBT0Transmit( SmartcardExtension );
+ break;
+ case PSCR_PROTOCOL_T1:
+ NTStatus = CBT1Transmit( SmartcardExtension );
+ break;
+ default:
+ NTStatus = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ }
+ }
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBRawTransmit: Exit (%lx)\n", NTStatus )
+ );
+ return( NTStatus );
+}
+
+NTSTATUS
+CBT1Transmit(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+/*++
+
+CBT1Transmit:
+ finishes the callback RDF_TRANSMIT for the T1 protocol
+
+Arguments:
+ SmartcardExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_NO_MEDIA
+ STATUS_TIMEOUT
+ STATUS_INVALID_DEVICE_REQUEST
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ ULONG IOBytes;
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBT1Transmit: Enter\n" )
+ );
+ //
+ // use the lib support to construct the T=1 packets
+ //
+ do {
+ //
+ // no header for the T=1 protocol
+ //
+ SmartcardExtension->SmartcardRequest.BufferLength = 0;
+ //
+ // SCM-TM: Siemens 4440 accepts only NAD=0!!!
+ //
+ SmartcardExtension->T1.NAD = 0;
+ //
+ // let the lib setup the T=1 APDU & check for errors
+ //
+ NTStatus = SmartcardT1Request( SmartcardExtension );
+ if ( NT_SUCCESS( NTStatus )) {
+
+ // send command (don't calculate LRC because CRC may be used!)
+ IOBytes = 0;
+ NTStatus = PscrWriteDirect(
+ SmartcardExtension->ReaderExtension,
+ SmartcardExtension->SmartcardRequest.Buffer,
+ SmartcardExtension->SmartcardRequest.BufferLength,
+ &IOBytes
+ );
+ if ( !NT_SUCCESS(NTStatus)) {
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBT1Transmit: PscrWriteDirect error (%lx)\n", NTStatus )
+ );
+ }
+ //
+ // extend the timeout if a Wtx request was sent by the card. if the
+ // card responds before the waiting time extension expires, the data are
+ // buffered in the reader. A delay without polling the reader status
+ // slows down the performance of the driver, but wtx is an exeption,
+ // not the rule.
+ //
+ if (SmartcardExtension->T1.Wtx) {
+ SysDelay(
+ (( SmartcardExtension->T1.Wtx *
+ SmartcardExtension->CardCapabilities.T1.BWT + 999L )/
+ 1000L)
+ );
+
+ }
+
+ // get response
+ SmartcardExtension->SmartcardReply.BufferLength = 0;
+ NTStatus = PscrRead(
+ SmartcardExtension->ReaderExtension,
+ SmartcardExtension->SmartcardReply.Buffer,
+ MAX_T1_BLOCK_SIZE,
+ &SmartcardExtension->SmartcardReply.BufferLength
+ );
+
+ // if PscrRead detects an LRC error, ignore it (maybe CRC used)
+ if ( NTStatus == STATUS_CRC_ERROR ) {
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBT1Transmit: PscrRead CRC error (%lx)\n", NTStatus )
+ );
+ }
+
+ //
+ // We even continue if the prev. read failed.
+ // We let the smart card library continue, because it might
+ // send a resynch. request in case of a timeout
+ //
+ NTStatus = SmartcardT1Reply( SmartcardExtension );
+ }
+
+ // continue if the lib wants to send the next packet
+ } while ( NTStatus == STATUS_MORE_PROCESSING_REQUIRED );
+
+ // start freeze routine, if an interrupt was sent, but no freeze data was read
+ if( SmartcardExtension->ReaderExtension->RequestInterrupt )
+ PscrFreeze( SmartcardExtension );
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBT1Transmit: Exit (%lx)\n", NTStatus )
+ );
+
+ return( NTStatus );
+}
+
+NTSTATUS
+CBT0Transmit(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+/*++
+
+CBT0Transmit:
+ finishes the callback RDF_TRANSMIT for the T0 protocol
+
+Arguments:
+ SmartcardExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_NO_MEDIA
+ STATUS_TIMEOUT
+ STATUS_INVALID_DEVICE_REQUEST
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ PUCHAR pRequest,pReply;
+ ULONG IOBytes, APDULength, RequestLength;
+ UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
+ UCHAR WtxReply[16];
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBT0Transmit: Enter\n" )
+ );
+
+ SysFillMemory( SmartcardExtension->SmartcardReply.Buffer, 0xCC, MAX_T1_BLOCK_SIZE );
+
+ pRequest = SmartcardExtension->SmartcardRequest.Buffer;
+ pReply = SmartcardExtension->SmartcardReply.Buffer;
+
+ // setup the command header
+ pRequest[ PSCR_NAD ] =
+ ( SmartcardExtension->ReaderExtension->Device == DEVICE_ICC1 ) ?
+ NAD_TO_ICC1 : NAD_TO_ICC1;
+
+ pRequest[ PSCR_PCB ] = PCB_DEFAULT;
+ //
+ // get the length of the user data packet & set the appropriate LEN
+ // information the complete user packet consists of a SCARD_IO_REQUEST
+ // structure followed by the APDU. the length of SCARD_IO_REQUEST is
+ // transferred in the member cbPciLength of the structure
+ //
+ APDULength = SmartcardExtension->IoRequest.RequestBufferLength;
+ if ((((PSCARD_IO_REQUEST) SmartcardExtension->IoRequest.RequestBuffer)->cbPciLength) >= APDULength) {
+ // Prevent integer underflow
+ return (STATUS_INSUFFICIENT_RESOURCES);
+ }
+ APDULength -= ((PSCARD_IO_REQUEST) SmartcardExtension->
+ IoRequest.RequestBuffer)->cbPciLength;
+ //
+ // a 4 byte APDU will be patched to a 5 byte TPDU by the lib; see
+ // annex of the ISO
+ //
+ if ( APDULength == 4 ) APDULength++;
+ //
+ // if the total length of the T1 (reader) packet is larger than 0xFF
+ // the extended length notation will be used
+ //
+ if ( APDULength >= 0xFF ) {
+ pRequest[ PSCR_LEN ] = 0xFF;
+ pRequest[ PSCR_LEN+1 ] = HIBYTE( APDULength );
+ pRequest[ PSCR_LEN+2 ] = LOBYTE( APDULength );
+ SmartcardExtension->SmartcardRequest.BufferLength =
+ PSCR_EXT_PROLOGUE_LENGTH;
+ } else {
+ pRequest[ PSCR_LEN ] = ( UCHAR ) APDULength;
+ SmartcardExtension->SmartcardRequest.BufferLength =
+ PSCR_PROLOGUE_LENGTH;
+ }
+
+ // let the lib setup the T=1 APDU & check for errors
+ NTStatus = SmartcardT0Request( SmartcardExtension );
+ RequestLength = SmartcardExtension->SmartcardRequest.BufferLength;
+
+ while ( NT_SUCCESS( NTStatus )) {
+
+ // check to see if device is busy.
+ {
+ PPSCR_REGISTERS IOBase;
+ UCHAR Status;
+
+ IOBase = SmartcardExtension->ReaderExtension->IOBase;
+
+ Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
+
+ if( 0x03 == Status )
+ {
+ NTStatus = STATUS_DEVICE_BUSY;
+ break;
+ }
+ }
+
+ // send command
+ IOBytes = 0;
+ NTStatus = PscrWrite(
+ SmartcardExtension->ReaderExtension,
+ pRequest,
+ RequestLength,
+ &IOBytes
+ );
+
+ // get response
+ if ( NT_SUCCESS( NTStatus )) {
+ IOBytes = 0;
+ NTStatus = PscrRead(
+ SmartcardExtension->ReaderExtension,
+ IOData,
+ MAX_T1_BLOCK_SIZE,
+ &IOBytes
+ );
+
+ // extract APDU from T=1 transport packet
+ if ( NT_SUCCESS( NTStatus )) {
+
+ if (IOBytes < 4) {
+
+ NTStatus = STATUS_DEVICE_PROTOCOL_ERROR;
+ break;
+
+ }
+ if (IOData[ PSCR_PCB ] == WTX_REQUEST) {
+
+ WtxReply[PSCR_NAD] = NAD_TO_PSCR;
+ WtxReply[PSCR_PCB] = WTX_REPLY;
+ WtxReply[PSCR_LEN] = 1;
+ WtxReply[PSCR_INF] = IOData[PSCR_INF];
+
+ RequestLength = 4;
+ pRequest = WtxReply;
+ continue;
+ }
+
+ if ( IOData[ PSCR_LEN ] == 0xFF ) {
+ //
+ // extended length byte used
+ //
+ APDULength = IOData[ PSCR_LEN + 1 ] << 8;
+ APDULength += IOData[ PSCR_LEN + 2 ];
+
+ SmartcardExtension->SmartcardReply.BufferLength = APDULength ;
+ if (APDULength >= (sizeof(IOData) - (PSCR_APDU + 2))) {
+ NTStatus = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+ SysCopyMemory( pReply, &IOData[ PSCR_APDU + 2 ], APDULength );
+ } else {
+
+ if ((IOData[PSCR_LEN] > SmartcardExtension->SmartcardReply.BufferSize) ||
+ (IOData[PSCR_LEN] > MAX_T1_BLOCK_SIZE + PSCR_APDU)) {
+ NTStatus = STATUS_DEVICE_PROTOCOL_ERROR;
+ break;
+ }
+ SmartcardExtension->SmartcardReply.BufferLength =
+ IOData[ PSCR_LEN ];
+
+ SysCopyMemory(
+ pReply,
+ &IOData[ PSCR_APDU ],
+ IOData[ PSCR_LEN ]
+ );
+ }
+
+ if( SmartcardExtension->ReaderCapabilities.CurrentState <=
+ SCARD_ABSENT )
+ {
+ NTStatus = STATUS_NO_MEDIA;
+ }
+ else
+ {
+ // let the lib evaluate the result & tansfer the data
+ NTStatus = SmartcardT0Reply( SmartcardExtension );
+ }
+ break;
+ }
+ }
+ }
+
+ // start freeze routine, if an interrupt was sent, but no freeze data was read
+ if( SmartcardExtension->ReaderExtension->RequestInterrupt )
+ PscrFreeze( SmartcardExtension );
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBT0Transmit: Exit (%lx)\n", NTStatus )
+ );
+
+ return( NTStatus );
+}
+
+NTSTATUS
+CBCardTracking(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+/*++
+
+CBCardTracking:
+ callback handler for SMCLIB RDF_CARD_TRACKING. the requested event was
+ validated by the smclib (i.e. a card removal request will only be passed
+ if a card is present).
+ for a win95 build STATUS_PENDING will be returned without any other action.
+ for NT the cancel routine for the irp will be set to the drivers cancel
+ routine.
+
+Arguments:
+ SmartcardExtension context of call
+
+Return Value:
+ STATUS_PENDING
+
+--*/
+{
+ WDFREQUEST request;
+ PDEVICE_EXTENSION DeviceExtension;
+ NTSTATUS status;
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBCardTracking: Enter\n" )
+ );
+
+ request = GET_WDFREQUEST_FROM_IRP(SmartcardExtension->OsData->NotificationIrp);
+
+ DeviceExtension = GetDeviceExtension(WdfIoQueueGetDevice(WdfRequestGetIoQueue(request)));
+
+ IoMarkIrpPending(SmartcardExtension->OsData->NotificationIrp);
+
+ //
+ // Move the stack pointer back to where it was when the IRP
+ // was delivered to the driver. This compensates for the
+ // IoSetNextIrpStackLocation that we did when we presented the IRP
+ // to the smartcard libarary.
+ //
+ IoSkipCurrentIrpStackLocation(SmartcardExtension->OsData->NotificationIrp);
+
+ status = WdfRequestForwardToIoQueue(request,
+ DeviceExtension->NotificationQueue);
+ if (!NT_SUCCESS(status)) {
+ NT_ASSERT(NT_SUCCESS(status));
+ InterlockedExchangePointer(
+ &(SmartcardExtension->OsData->NotificationIrp),
+ NULL
+ );
+ WdfRequestComplete(request, status);
+ }
+
+ status = STATUS_PENDING;
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBCardTracking: Exit \n" )
+ );
+
+ return status;
+}
+
+VOID
+CBUpdateCardState(
+ PSMARTCARD_EXTENSION SmartcardExtension,
+ UCHAR IccState,
+ BOOLEAN SystemWakeUp
+ )
+{
+ ULONG oldState;
+ NTSTATUS status;
+ KIRQL irql;
+ WDFREQUEST request;
+ PDEVICE_EXTENSION DeviceExtension;
+
+
+ KeAcquireSpinLock(
+ &SmartcardExtension->OsData->SpinLock,
+ &irql
+ );
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBUpdateCardState: Enter \n" )
+ );
+
+ oldState =
+ (SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT ?
+ SCARD_PRESENT : SCARD_ABSENT);
+
+ SmartcardExtension->ReaderCapabilities.CurrentState =
+ (IccState == PSCR_ICC_PRESENT ? SCARD_PRESENT : SCARD_ABSENT);
+
+ SmartcardDebug(
+ DEBUG_DRIVER,
+ ( "PSCR!CBUpdateCardState: Smart card %s\n",
+ IccState == PSCR_ICC_PRESENT ? "inserted" : "removed")
+ );
+
+ if ( SmartcardExtension->OsData->NotificationIrp != NULL &&
+ (SystemWakeUp &&
+ (oldState == SCARD_PRESENT ||
+ SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_PRESENT) ||
+ SmartcardExtension->ReaderCapabilities.CurrentState != oldState)) {
+ PIRP notificationIrp ;
+
+ notificationIrp = InterlockedExchangePointer(
+ &(SmartcardExtension->OsData->NotificationIrp),
+ NULL
+ );
+
+ DeviceExtension = GetDeviceExtension(WdfWdmDeviceGetWdfDeviceHandle(SmartcardExtension->OsData->DeviceObject));
+
+ KeReleaseSpinLock(
+ &SmartcardExtension->OsData->SpinLock,
+ irql
+ );
+
+ status = WdfIoQueueRetrieveNextRequest(
+ DeviceExtension->NotificationQueue,
+ &request);
+ if (NT_SUCCESS(status)) {
+
+ SmartcardDebug(
+ DEBUG_DRIVER,
+ ( "PSCR!CBUpdateCardState: Completing Irp %p\n",
+ notificationIrp)
+ );
+
+ WdfRequestCompleteWithInformation(request, status, 0);
+ }
+ else {
+ NT_ASSERTMSG("WdfIoQueueRetrieveNextRequest failed",
+ status == STATUS_NO_MORE_ENTRIES);
+ }
+ } else {
+ KeReleaseSpinLock(
+ &SmartcardExtension->OsData->SpinLock,
+ irql
+ );
+ }
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!CBUpdateCardState: Exit \n" )
+ );
+}
+
+UCHAR
+CBGetCardState(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+/*++
+
+CBUpdateCardState:
+ updates the variable CurrentState in SmartcardExtension
+
+Arguments:
+ SmartcardExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+
+--*/
+{
+ UCHAR TLVList[ TLV_BUFFER_SIZE ], Val, Len;
+ ULONG TLVListLen;
+ PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
+
+ // read the status file of ICC1 from the reader
+ TLVListLen = TLV_BUFFER_SIZE;
+
+ if ( NT_SUCCESS( CmdReadStatusFile(
+ ReaderExtension,
+ ReaderExtension->Device,
+ TLVList,
+ &TLVListLen
+ ))) {
+
+ // get reader status value
+ Len = sizeof(Val);
+ CmdGetTagValue(
+ TAG_READER_STATUS,
+ TLVList,
+ TLVListLen,
+ &Len,
+ ( PVOID ) &Val
+ );
+ } else {
+ // IO-error is interpreted as card absent
+ Val = PSCR_ICC_ABSENT;
+ }
+
+ return Val;
+}
+
+// -------------------------------- END OF FILE ------------------------------
+
+
+
diff --git a/smartcrd/pscr/pscrcb.h b/smartcrd/pscr/pscrcb.h
new file mode 100644
index 00000000..51a161a8
--- /dev/null
+++ b/smartcrd/pscr/pscrcb.h
@@ -0,0 +1,84 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrCB.h
+
+Abstract:
+
+ prototypes of callback handlers for pscr.xxx
+
+Author:
+
+ Andreas Straub
+
+Environment:
+
+ Win 95
+ NT 4.0
+
+Notes:
+
+ The file pscrcb.h was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+ Andreas Straub 7/16/1997 Initial Version
+
+--*/
+
+#if !defined( __PSCR_CALLBACK_H__ )
+#define __PSCR_CALLBACK_H__
+
+NTSTATUS
+CBCardPower(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+NTSTATUS
+CBSetProtocol(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+NTSTATUS
+CBTransmit(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+NTSTATUS
+CBT0Transmit(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+NTSTATUS
+CBT1Transmit(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+NTSTATUS
+CBRawTransmit(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+NTSTATUS
+CBCardTracking(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+VOID
+CBUpdateCardState(
+ PSMARTCARD_EXTENSION SmartcardExtension,
+ UCHAR CardState,
+ BOOLEAN SystemWakeUp
+ );
+
+UCHAR
+CBGetCardState(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+#endif // __PSCR_CALLBACK_H__
+
+// ------------------------------- END OF FILE -------------------------------
diff --git a/smartcrd/pscr/pscrcmd.c b/smartcrd/pscr/pscrcmd.c
new file mode 100644
index 00000000..ff694089
--- /dev/null
+++ b/smartcrd/pscr/pscrcmd.c
@@ -0,0 +1,981 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrCmd.c
+
+Abstract:
+
+ Basic command functions for SCM PSCR smartcard reader
+
+Author:
+
+ Andreas Straub
+
+Environment:
+
+
+ Win 95 Sys... calls are resolved by Pscr95Wrap.asm functions and
+ Pscr95Wrap.h macros, resp.
+
+ NT 4.0 Sys... functions resolved by PscrNTWrap.c functions and
+ PscrNTWrap.h macros, resp.
+
+Notes:
+
+ The file pscrcmd.c was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+ Andreas Straub 8/18/1997 1.00 Initial Version
+ Andreas Straub 9/24/1997 1.02 delay for read/write removed
+
+--*/
+
+#include <PscrNT.h>
+#include <PscrRdWr.h>
+#include <PscrCmd.h>
+
+NTSTATUS
+CmdResetInterface(
+ PREADER_EXTENSION ReaderExtension
+ )
+/*++
+CmdResetInterface:
+
+ Performs a reset of the reader interface (NOT of the PCMCIA controller)
+ - flush available data
+ - set RESET bit
+ - perform a buffer size exchange between reader & host
+ - enables interrupts for freeze events
+ - disables default PTS
+
+Arguments:
+ ReaderExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_IO_DEVICE_ERROR
+
+--*/
+{
+
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR Len,
+ Tag,
+ Cnt,
+ InData[ TLV_BUFFER_SIZE ] = {0};
+ PPSCR_REGISTERS IOBase;
+ UCHAR EnableInterrupts[] = { 0x28, 0x01, 0x01};
+
+
+ IOBase = ReaderExtension->IOBase;
+
+ // discard any data
+ PscrFlushInterface( ReaderExtension );
+
+ // reset reader
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_RESET_BIT );
+ SysDelay( DELAY_WRITE_PSCR_REG );
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
+
+ NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT );
+
+ // read & check vendor string
+ if ( NT_SUCCESS( NTStatus )) {
+
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
+ SysDelay( DELAY_WRITE_PSCR_REG );
+ //
+ // get actual len from TLV list
+ //
+ READ_PORT_UCHAR( &IOBase->SizeMSReg );
+ READ_PORT_UCHAR( &IOBase->SizeLSReg );
+
+ Tag = READ_PORT_UCHAR( &IOBase->DataReg );
+ Len = READ_PORT_UCHAR( &IOBase->DataReg );
+ //
+ // avoid overwrite of buffer
+ //
+ if ( Len > TLV_BUFFER_SIZE ) {
+ Len = TLV_BUFFER_SIZE;
+ }
+ for ( Cnt = 0; Cnt < Len; Cnt++ ) {
+ InData[ Cnt ] = READ_PORT_UCHAR( &IOBase->DataReg );
+ }
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
+ //
+ // check vendor string
+ //
+ if ( SysCompareMemory(
+ InData,
+ PSCR_ID_STRING,
+ sizeof( PSCR_ID_STRING )
+ )) {
+ NTStatus = STATUS_IO_DEVICE_ERROR;
+ } else {
+ //
+ // vendor string was correct, check buffer size
+ //
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_SIZE_READ_BIT );
+ NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT );
+ //
+ // reader ready to transfer interface buffer size
+ //
+ if ( NT_SUCCESS( NTStatus )) {
+ //
+ // set size read & host control
+ //
+ WRITE_PORT_UCHAR(
+ &IOBase->CmdStatusReg,
+ PSCR_SIZE_READ_BIT | PSCR_HOST_CONTROL_BIT
+ );
+
+ SysDelay( DELAY_WRITE_PSCR_REG );
+ //
+ // read buffer length
+ //
+ Len = READ_PORT_UCHAR( &IOBase->SizeMSReg );
+ Len = READ_PORT_UCHAR( &IOBase->SizeLSReg );
+ //
+ // avoid overwrite of buffer
+ //
+ if ( Len > TLV_BUFFER_SIZE ) {
+ Len = TLV_BUFFER_SIZE;
+ }
+ for ( Cnt = 0; Cnt < Len; Cnt++ ) {
+ InData[ Cnt ] = READ_PORT_UCHAR( &IOBase->DataReg );
+ }
+ //
+ // transfer of interface buffer size okay
+ //
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
+ SysDelay( DELAY_WRITE_PSCR_REG );
+ //
+ // notify the reader about the supported buffer size
+ //
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
+ SysDelay( DELAY_WRITE_PSCR_REG );
+
+ WRITE_PORT_UCHAR( &IOBase->SizeMSReg, 0 );
+ WRITE_PORT_UCHAR( &IOBase->SizeLSReg, 2 );
+ //
+ // Write the same data buffer size as the one we just got.
+ //
+ if (Len >= 1) {
+ WRITE_PORT_UCHAR( &IOBase->DataReg, InData[ 0 ] );
+ WRITE_PORT_UCHAR( &IOBase->DataReg, InData[ 1 ] );
+ }
+ //
+ // store the size to report to the lib
+ // The maximum buffer size of the reader is to betrieved with
+ // ((ULONG)InData[ 1 ] << 8) | InData[ 0 ]
+ //
+ ReaderExtension->MaxIFSD = 254;
+
+ //
+ // let the reader process the size write command
+ //
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_SIZE_WRITE_BIT );
+ NTStatus = PscrWait( ReaderExtension, PSCR_FREE_BIT );
+ }
+ }
+ }
+ //
+ // clean up any host control settings
+ //
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
+ //
+ // enable interrupts
+ //
+ CmdSetInterfaceParameter(
+ ReaderExtension,
+ ReaderExtension->Device,
+ EnableInterrupts,
+ sizeof( EnableInterrupts )
+ );
+
+ return( NTStatus );
+}
+
+NTSTATUS
+CmdReset(
+ PREADER_EXTENSION ReaderExtension,
+ UCHAR Device,
+ BOOLEAN WarmReset,
+ PUCHAR pATR,
+ PULONG pATRLength
+ )
+/*++
+CmdReset:
+ performs a reset of the reader / ICC
+
+Arguments:
+ ReaderExtension context of call
+ Device device requested ( ICC_1, ICC_2, PSCR )
+ WarmReset kind of ICC reset
+ pATR ptr to ATR buffer, NULL if no ATR required
+ pATRLength size of ATR buffer / length of ATR
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_NO_MEDIA
+ STATUS_UNRECOGNIZED_MEDIA
+ error values from PscrRead / PscrWrite
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR IOData[ MAX_T1_BLOCK_SIZE ],
+ P2;
+ USHORT ICCStatus;
+ ULONG IOBytes;
+
+ // ATR from the smartcard requestet? P2 = 1
+ P2 = 0;
+ if (( pATR != NULL ) && ( pATRLength != NULL )) {
+ if ( *pATRLength > 0 )
+ P2 = 0x01;
+ }
+
+ // build the RESET command.
+ IOData[ PSCR_NAD ] = NAD_TO_PSCR;
+ IOData[ PSCR_PCB ] = PCB_DEFAULT;
+ IOData[ PSCR_LEN ] = 0x05;
+
+ if ( WarmReset == TRUE ) {
+ IOData[ PSCR_INF+0 ] = CLA_WARM_RESET;
+ IOData[ PSCR_INF+1 ] = INS_WARM_RESET;
+ } else {
+ IOData[ PSCR_INF+0 ] = CLA_RESET;
+ IOData[ PSCR_INF+1 ] = INS_RESET;
+ }
+ IOData[ PSCR_INF+2 ] = Device;
+ IOData[ PSCR_INF+3 ] = P2;
+ IOData[ PSCR_INF+4 ] = 0x00;
+
+ // write command
+ NTStatus = PscrWrite(
+ ReaderExtension,
+ IOData,
+ 8,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+ // read data
+ IOBytes = 0;
+ NTStatus = PscrRead(
+ ReaderExtension,
+ IOData,
+ MAX_T1_BLOCK_SIZE,
+ &IOBytes
+ );
+
+ // error detection
+ if ( NT_SUCCESS( NTStatus )) {
+ //
+ // the location of the error code in the buffer
+ // is: ( data ) - STATUS_MSB - STATUS_LSB - EPILOGUE
+ //
+ ICCStatus = (( USHORT )IOData[ IOBytes-PSCR_EPILOGUE_LENGTH-2 ]) << 8;
+ ICCStatus |= ( USHORT )IOData[ IOBytes-PSCR_EPILOGUE_LENGTH-1 ];
+
+ switch ( ICCStatus ) {
+ case PSCR_SW_SYNC_ATR_SUCCESS:
+ case PSCR_SW_ASYNC_ATR_SUCCESS:
+ break;
+
+ case PSCR_SW_NO_ICC:
+ NTStatus = STATUS_NO_MEDIA;
+ break;
+
+ case PSCR_SW_NO_PROTOCOL:
+ case PSCR_SW_NO_ATR:
+ case PSCR_SW_NO_ATR_OR_PROTOCOL:
+ case PSCR_SW_NO_ATR_OR_PROTOCOL2:
+ case PSCR_SW_ICC_NOT_ACTIVE:
+ case PSCR_SW_NON_SUPPORTED_PROTOCOL:
+ case PSCR_SW_PROTOCOL_ERROR:
+ default:
+ NTStatus = STATUS_UNRECOGNIZED_MEDIA;
+ }
+ //
+ // copy ATR if required
+ //
+ if ( NT_SUCCESS( NTStatus )) {
+ if ( P2 == 0x01 ) {
+ IOBytes -= PSCR_PROLOGUE_LENGTH + PSCR_EPILOGUE_LENGTH;
+ if ( IOBytes > *pATRLength ) {
+ IOBytes = *pATRLength;
+ }
+ SysCopyMemory(
+ pATR,
+ &IOData[ PSCR_PROLOGUE_LENGTH ],
+ IOBytes
+ );
+ *pATRLength = IOBytes;
+ }
+ }
+ }
+ }
+ return( NTStatus );
+}
+
+
+NTSTATUS
+CmdDeactivate(
+ PREADER_EXTENSION ReaderExtension,
+ UCHAR Device
+ )
+/*++
+CmdDeactivate:
+ Deactivates the requested device
+
+Arguments:
+ ReaderExtension context of call
+ Device requested device
+
+Return Value:
+ STATUS_SUCCESS
+ error values from PscrRead / PscrWrite
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
+ ULONG IOBytes;
+
+ //
+ // build the DEACTIVATE command.
+ //
+ IOData[ PSCR_NAD ] = NAD_TO_PSCR;
+ IOData[ PSCR_PCB ] = PCB_DEFAULT;
+ IOData[ PSCR_LEN ] = 0x05;
+
+ IOData[ PSCR_INF+0 ] = CLA_DEACTIVATE;
+ IOData[ PSCR_INF+1 ] = INS_DEACTIVATE;
+ IOData[ PSCR_INF+2 ] = Device;
+ IOData[ PSCR_INF+3 ] = 0x00;
+ IOData[ PSCR_INF+4 ] = 0x00;
+ //
+ // write command
+ //
+ NTStatus = PscrWrite(
+ ReaderExtension,
+ IOData,
+ 8,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+ //
+ // read data to trap communication errors
+ //
+ IOBytes = 0;
+ NTStatus = PscrRead(
+ ReaderExtension,
+ IOData,
+ MAX_T1_BLOCK_SIZE,
+ &IOBytes
+ );
+ }
+ return( NTStatus );
+}
+
+NTSTATUS
+CmdReadBinary(
+ PREADER_EXTENSION ReaderExtension,
+ USHORT Offset,
+ PUCHAR pBuffer,
+ PULONG pBufferLength
+ )
+/*++
+CmdReadBinary:
+ read binary data from an PSCR data file
+
+Arguments:
+ ReaderExtension context of call
+ Offset offset in file
+ pBuffer ptr to data buffer
+ pBufferLength length of buffer / number of bytes read
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_UNSUCCESSFUL
+ error values from PscrRead / PscrWrite
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
+ USHORT ICCStatus;
+ ULONG IOBytes;
+ //
+ // check parameters
+ //
+ if (( pBuffer == NULL ) || ( pBufferLength == NULL)) {
+ NTStatus = STATUS_INVALID_PARAMETER;
+ } else {
+ //
+ // build the READ BINARY command
+ //
+ IOData[ PSCR_NAD] = NAD_TO_PSCR;
+ IOData[ PSCR_PCB] = PCB_DEFAULT;
+ IOData[ PSCR_LEN] = 0x05;
+
+ IOData[ PSCR_INF+0 ] = CLA_READ_BINARY;
+ IOData[ PSCR_INF+1 ] = INS_READ_BINARY;
+ IOData[ PSCR_INF+2 ] = HIBYTE( Offset );
+ IOData[ PSCR_INF+3 ] = LOBYTE( Offset );
+ IOData[ PSCR_INF+4 ] = 0x00;
+ //
+ // write command
+ //
+ NTStatus = PscrWrite(
+ ReaderExtension,
+ IOData,
+ 8,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+ //
+ // read data
+ //
+ IOBytes = 0;
+ NTStatus = PscrRead(
+ ReaderExtension,
+ IOData,
+ MAX_T1_BLOCK_SIZE,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+ //
+ // error check
+ //
+ ICCStatus =
+ ((USHORT)IOData[ IOBytes-2-PSCR_EPILOGUE_LENGTH ]) << 8;
+ ICCStatus |=
+ (USHORT)IOData[ IOBytes-1-PSCR_EPILOGUE_LENGTH ];
+
+ switch ( ICCStatus ) {
+ case PSCR_SW_FILE_NO_ACCEPPTED_AUTH:
+ case PSCR_SW_FILE_NO_ACCESS:
+ case PSCR_SW_FILE_BAD_OFFSET:
+ case PSCR_SW_END_OF_FILE_READ:
+ NTStatus = STATUS_UNSUCCESSFUL;
+ break;
+ default:
+ break;
+ }
+ //
+ // copy data
+ //
+ if ( NT_SUCCESS( NTStatus )) {
+ if ( *pBufferLength <
+ IOBytes-PSCR_PROLOGUE_LENGTH-PSCR_STATUS_LENGTH ) {
+ NTStatus = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ ( *pBufferLength ) =
+ IOBytes-PSCR_PROLOGUE_LENGTH-PSCR_STATUS_LENGTH;
+ SysCopyMemory(
+ pBuffer,
+ &IOData[ PSCR_PROLOGUE_LENGTH ],
+ *pBufferLength
+ );
+ }
+ }
+ }
+ }
+ }
+ return( NTStatus );
+}
+
+NTSTATUS
+CmdSelectFile(
+ PREADER_EXTENSION ReaderExtension,
+ USHORT FileId
+ )
+/*++
+CmdSelectFile:
+ selects a file/directoy of the reader
+
+Arguments:
+ ReaderExtension context of call
+ FileId ID of file
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_UNSUCCESSFUL
+ error values from PscrRead / PscrWrite
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
+ USHORT ICCStatus;
+ ULONG IOBytes;
+
+ //
+ // build the SELECT FILE command
+ //
+ IOData[ PSCR_NAD ] = NAD_TO_PSCR;
+ IOData[ PSCR_PCB ] = PCB_DEFAULT;
+ IOData[ PSCR_LEN ] = 0x07;
+
+ IOData[ PSCR_INF+0 ] = CLA_SELECT_FILE;
+ IOData[ PSCR_INF+1 ] = INS_SELECT_FILE;
+ IOData[ PSCR_INF+2 ] = 0x00;
+ IOData[ PSCR_INF+3 ] = 0x00;
+ IOData[ PSCR_INF+4 ] = 0x02;
+ IOData[ PSCR_INF+5 ] = HIBYTE( FileId );
+ IOData[ PSCR_INF+6 ] = LOBYTE( FileId );
+ //
+ // write command
+ //
+ NTStatus = PscrWrite(
+ ReaderExtension,
+ IOData,
+ 10,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+ //
+ // get the response of the reader
+ //
+ IOBytes = 0;
+ NTStatus = PscrRead(
+ ReaderExtension,
+ IOData,
+ MAX_T1_BLOCK_SIZE,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+ //
+ // check errors
+ //
+ ICCStatus =
+ ((USHORT)IOData[ IOBytes-2-PSCR_EPILOGUE_LENGTH ]) << 8;
+ ICCStatus |=
+ (USHORT)IOData[ IOBytes-1-PSCR_EPILOGUE_LENGTH ];
+
+ if ( ICCStatus == PSCR_SW_FILE_NOT_FOUND ) {
+ NTStatus = STATUS_UNSUCCESSFUL;
+ }
+ }
+ }
+ return( NTStatus );
+}
+
+NTSTATUS
+CmdSetInterfaceParameter(
+ PREADER_EXTENSION ReaderExtension,
+ UCHAR Device,
+ PUCHAR pTLVList,
+ UCHAR TLVListLen
+ )
+/*++
+CmdSetInterfaceParameter:
+ Sets the interface pareameter of the ICC interface to the values specified
+ in the TLV list
+
+Arguments:
+ ReaderExtension context of call
+ Device device
+ pTLVList ptr to list of tag-len-value's specified by caller
+ TLVListLen length of list
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_INVALID_PARAMETER
+ STATUS_INVALID_DEVICE_STATE
+ error values from PscrRead / PscrWrite
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
+ USHORT ICCStatus;
+ ULONG IOBytes;
+
+ //
+ // check parameter
+ //
+ if ( pTLVList == NULL ) {
+ NTStatus = STATUS_INVALID_PARAMETER;
+ } else {
+ //
+ // build the SET INTERFACE PARAMETER command
+ //
+ IOData[ PSCR_NAD ] = NAD_TO_PSCR;
+ IOData[ PSCR_PCB ] = PCB_DEFAULT;
+ IOData[ PSCR_LEN ] = 0x05 + TLVListLen;
+
+ IOData[ PSCR_INF+0 ] = CLA_SET_INTERFACE_PARAM;
+ IOData[ PSCR_INF+1 ] = INS_SET_INTERFACE_PARAM;
+ IOData[ PSCR_INF+2 ] = Device;
+ IOData[ PSCR_INF+3 ] = 0x00;
+ IOData[ PSCR_INF+4 ] = TLVListLen;
+
+ SysCopyMemory( &IOData[ PSCR_INF+5 ], pTLVList, TLVListLen );
+ //
+ // write command
+ //
+ NTStatus = PscrWrite(
+ ReaderExtension,
+ IOData,
+ 8 + TLVListLen,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+
+ // do an dummy read to catch errors.
+ IOBytes = 0;
+ NTStatus = PscrRead(
+ ReaderExtension,
+ IOData,
+ MAX_T1_BLOCK_SIZE,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+
+ // check error
+ ICCStatus =
+ ((USHORT)IOData[ IOBytes - 2 - PSCR_EPILOGUE_LENGTH ]) << 8;
+ ICCStatus |=
+ (USHORT)IOData[ IOBytes - 1 - PSCR_EPILOGUE_LENGTH ];
+
+ if ( ICCStatus != 0x9000 ) {
+ NTStatus = STATUS_INVALID_DEVICE_STATE;
+ }
+ }
+ }
+ }
+ return( NTStatus );
+}
+
+
+NTSTATUS
+CmdReadStatusFile (
+ PREADER_EXTENSION ReaderExtension,
+ UCHAR Device,
+ PUCHAR pTLVList,
+ PULONG pTLVListLen
+ )
+/*++
+CmdReadStatusFile:
+ read the status file of the requested device from the reader filesystem
+
+Arguments:
+ ReaderExtension context of call
+ Device requested device
+ pTLVList ptr to list (i.e. the status file)
+ pTLVListLen length of buffer / returned list
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL
+ error values from PscrRead / PscrWrite
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
+ UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
+ ULONG IOBytes;
+
+ // select ICC status file if it's not the active file
+ if ( ReaderExtension->StatusFileSelected == FALSE ) {
+
+ // select master file on reader
+ NTStatus = CmdSelectFile( ReaderExtension, FILE_MASTER );
+
+ // select ICC directory
+ if ( NT_SUCCESS( NTStatus )) {
+ if ( Device != DEVICE_ICC1 ) {
+ NTStatus = STATUS_UNSUCCESSFUL;
+ } else {
+ NTStatus = CmdSelectFile(
+ ReaderExtension,
+ FILE_ICC1_DIR
+ );
+
+ // select status file
+ if ( NT_SUCCESS( NTStatus )) {
+ NTStatus = CmdSelectFile(
+ ReaderExtension,
+ FILE_ICC1_DIR_STATUS
+ );
+ if ( NT_SUCCESS( NTStatus )) {
+ ReaderExtension->StatusFileSelected = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ // read status file if successful selected
+ if ( ReaderExtension->StatusFileSelected == TRUE ) {
+ IOBytes = MAX_T1_BLOCK_SIZE;
+ NTStatus = CmdReadBinary(
+ ReaderExtension,
+ 0,
+ IOData,
+ &IOBytes
+ );
+
+ // copy data to user buffer
+ if ( NT_SUCCESS( NTStatus )) {
+ if (( pTLVList != NULL ) && ( IOBytes < *pTLVListLen )) {
+ *pTLVListLen = IOBytes;
+ SysCopyMemory( pTLVList, IOData, IOBytes );
+ } else {
+ NTStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+ }
+ return( NTStatus );
+}
+
+
+NTSTATUS
+CmdGetFirmwareRevision (
+ PREADER_EXTENSION ReaderExtension
+ )
+/*++
+CmdGetFirmwareRevision:
+ get the firmware revision of the reader. Ther firmware revision is found
+ in the PSCR configuration file (ID 0x0020) in the master directory.
+ The tag of the revision is 0x0F, and the value is coded as an ASCII string,
+ p.E. "2.20"
+
+Arguments:
+ ReaderExtension context of call
+
+Return Value:
+ STATUS_SUCCESS
+ error values from PscrRead / PscrWrite
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR TLVList[ MAX_T1_BLOCK_SIZE ],
+ Len;
+ char Revision[ 0x10 ],
+ UpdateKey[ 0x10 ];
+ ULONG IOBytes;
+ //
+ // select master file on reader
+ //
+ NTStatus = CmdSelectFile( ReaderExtension, FILE_MASTER );
+ //
+ // select pscr configuration file
+ //
+ if ( NT_SUCCESS( NTStatus )) {
+ NTStatus = CmdSelectFile( ReaderExtension, FILE_PSCR_CONFIG );
+ //
+ // read confiuration file
+ //
+ if ( NT_SUCCESS( NTStatus )) {
+ IOBytes = MAX_T1_BLOCK_SIZE;
+ NTStatus = CmdReadBinary(
+ ReaderExtension,
+ 0,
+ TLVList,
+ &IOBytes
+ );
+ //
+ // get the value of revison
+ //
+ if ( NT_SUCCESS( NTStatus )) {
+ Len = sizeof(Revision);
+ CmdGetTagValue(
+ TAG_SOFTWARE_REV,
+ TLVList,
+ IOBytes,
+ &Len,
+ Revision
+ );
+ //
+ // the coding is always X.YY (in ASCII), so we can get the numeric
+ // values hardcoded by taking the low nibbles of the char's.
+ //
+ ReaderExtension->FirmwareMajor = Revision[0] & 0x0F;
+ ReaderExtension->FirmwareMinor = ( Revision[2] & 0x0F ) << 4;
+ ReaderExtension->FirmwareMinor |= Revision[3] & 0x0F;
+ //
+ // get value of update key
+ //
+ Len = sizeof(UpdateKey);
+ CmdGetTagValue(
+ TAG_UPDATE_KEY,
+ TLVList,
+ IOBytes,
+ &Len,
+ UpdateKey
+ );
+
+ ReaderExtension->UpdateKey = UpdateKey[0];
+ }
+ }
+ }
+ ReaderExtension->StatusFileSelected = FALSE;
+ return( NTStatus );
+}
+
+NTSTATUS
+CmdPscrCommand (
+ PREADER_EXTENSION ReaderExtension,
+ PUCHAR pInData,
+ ULONG InDataLen,
+ PUCHAR pOutData,
+ ULONG OutDataLen,
+ PULONG pNBytes
+ )
+/*++
+CmdPscrCommand:
+ send a command transparent to the reader
+
+Arguments:
+ ReaderExtension context of call
+ pInData, ptr to input buffer
+ InDataLen, len of input buffer
+ pOutData, ptr to output buffer
+ OutDataLen, len of output buffer
+ pNBytes number of bytes transferred
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_INVALID_PARAMETER
+ error values from PscrRead / PscrWrite
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR IOData[ MAX_T1_BLOCK_SIZE ] = { 0};
+ ULONG IOBytes;
+ //
+ // the function is used for generic ioctl's, so carful ALL
+ // parametes will be checked!
+ //
+ if ( ( pInData == NULL ) ||
+ ( pOutData == NULL ) ||
+ ( pNBytes == NULL ) ||
+ (InDataLen == 0 ) ||
+ (OutDataLen == 0 )
+ ) {
+ NTStatus = STATUS_INVALID_PARAMETER;
+ } else {
+ IOBytes = 0;
+ NTStatus = PscrWriteDirect(
+ ReaderExtension,
+ pInData,
+ InDataLen,
+ &IOBytes
+ );
+
+ if ( NT_SUCCESS( NTStatus )) {
+ //
+ // get result. ignore all reader errors
+ //
+ IOBytes = 0;
+ NTStatus = PscrRead(
+ ReaderExtension,
+ IOData,
+ MAX_T1_BLOCK_SIZE,
+ &IOBytes
+ );
+ //
+ // tranfer data
+ //
+ if ( IOBytes > OutDataLen ) {
+ NTStatus = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ *pNBytes = IOBytes;
+ SysCopyMemory( pOutData, IOData, IOBytes );
+ }
+ }
+ }
+ return( NTStatus );
+}
+
+NTSTATUS
+CmdGetTagValue (
+ UCHAR Tag,
+ PUCHAR pTLVList,
+ ULONG TLVListLen,
+ PUCHAR pTagLen,
+ PVOID pTagVal
+ )
+/*++
+CmdGetTagValue:
+ scans a TLV list for the value of a user specified tag
+ it is assumed, the caller knows the kind of the requested
+ field, so only the ptr to the buffer will be checked
+
+Arguments:
+ Tag requested Tag
+ pTLVList ptr to list
+ TLVListLen length of list
+ pTagLen ptr to length
+ pTagVal ptr to value
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_UNSUCCESSFUL
+ STATUS_INVALID_PARAMETER
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ ULONG Idx;
+ UCHAR maxLen;
+ //
+ // step through the given list
+ //
+ if (( pTLVList != NULL ) && ( pTagVal != NULL ) && ( pTagLen != NULL )) {
+ maxLen = *pTagLen;
+ //
+ // look for requested tag
+ //
+ Idx = 0;
+ while ( Idx < TLVListLen ) {
+ if ( pTLVList[ Idx ] == Tag ) {
+ //
+ // ASSUMED THE CALLER KNOWS KIND OF FIELD!!!
+ //
+
+ if (pTLVList[Idx+1] > maxLen) {
+ NTStatus = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ *pTagLen = pTLVList[ Idx + 1 ];
+ SysCopyMemory(
+ pTagVal,
+ &pTLVList[ Idx+2 ],
+ pTLVList[ Idx+1 ]
+ );
+
+ break;
+ }
+ Idx += pTLVList[ Idx+1 ] + 2;
+ }
+ if ( Idx >= TLVListLen ) {
+ NTStatus = STATUS_UNSUCCESSFUL;
+ }
+ } else {
+ NTStatus = STATUS_INVALID_PARAMETER;
+ }
+ return( NTStatus );
+}
+
+// ------------------------------- END OF FILE -------------------------------
+
diff --git a/smartcrd/pscr/pscrcmd.h b/smartcrd/pscr/pscrcmd.h
new file mode 100644
index 00000000..57a4bdea
--- /dev/null
+++ b/smartcrd/pscr/pscrcmd.h
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrCmd.h
+
+Abstract:
+
+ Prototypes of basic command functions for SCM PSCR smartcard reader
+
+Author:
+
+ Andreas Straub
+
+Notes:
+
+ The file pscrcmd.h was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+ Andreas Straub 7/16/1997 Initial Version
+
+--*/
+
+#if !defined( __PSCR_CMD_H__ )
+#define __PSCR_CMD_H__
+
+NTSTATUS
+CmdResetInterface(
+ PREADER_EXTENSION ReaderExtension // context of call
+ );
+
+NTSTATUS
+CmdReset(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ UCHAR Device, // device
+ BOOLEAN WarmReset, // TRUE: Warm, FALSE: cold Reset
+ PUCHAR pATR, // ptr to ATR buffer
+ PULONG ATRLength // len of ATR
+ );
+
+NTSTATUS
+CmdDeactivate(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ UCHAR Device // device
+ );
+
+NTSTATUS
+CmdReadBinary(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ USHORT Offset, // offset in file
+ PUCHAR pData, // data buffer
+ PULONG pNBytes // length of bytes read
+ );
+
+NTSTATUS
+CmdSelectFile(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ USHORT FileId // File Id
+ );
+
+NTSTATUS
+CmdSetInterfaceParameter(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ UCHAR Device, // device
+ PUCHAR pTLVList, // ptr to TLV list
+ UCHAR TLVListLen // len of TLV list
+ );
+
+NTSTATUS
+CmdReadStatusFile (
+ PREADER_EXTENSION ReaderExtension, // context of call
+ UCHAR Device, // device
+ PUCHAR pTLVList, // ptr to TLV list
+ PULONG TLVListLen // len of TLV list
+ );
+
+NTSTATUS
+CmdPscrCommand (
+ PREADER_EXTENSION ReaderExtension, // context of call
+ PUCHAR pInData, // ptr to input buffer
+ ULONG InDataLen, // len of input buffer
+ PUCHAR pOutData, // ptr to ouput buffer
+ ULONG OutDataLen, // len of output buffer
+ PULONG pNBytes // number of bytes transferred
+ );
+
+NTSTATUS
+CmdGetFirmwareRevision (
+ PREADER_EXTENSION ReaderExtension // context of call
+ );
+
+NTSTATUS
+CmdGetTagValue (
+ UCHAR Tag, // tag to be searched
+ PUCHAR pTLVList, // ptr to TLV list
+ ULONG TLVListLen, // len of TLV list
+ PUCHAR pTagLen, // tag length
+ PVOID pTagVal // tag value
+ );
+
+#endif // __PSCR_CMD_H__
+
+//------------------------------- END OF FILE -------------------------------*/
diff --git a/smartcrd/pscr/pscrlog.mc b/smartcrd/pscr/pscrlog.mc
new file mode 100644
index 00000000..6a608ddd
--- /dev/null
+++ b/smartcrd/pscr/pscrlog.mc
@@ -0,0 +1,103 @@
+;// BUILD Version: 0001 // Increment this if a change has global effects
+
+;/*++
+;
+;Copyright (c) 1997 SCM Microsystems, Inc
+;
+;Module Name:
+;
+; PscrLog.mc
+;
+;Abstract:
+;
+; Constant definitions for the I/O error code log values.
+;
+;Notes:
+;
+; The file pscrlog.mc was reviewed by LCA in June 2011 and per license is
+; acceptable for Microsoft use under Dealpoint ID 178449.
+;
+;Revision History:
+;
+;--*/
+;
+;#ifndef __PSCRLOG_H__
+;#define __PSCRLOG_H__
+;
+;//
+;// Status values are 32 bit values layed out as follows:
+;//
+;// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+;// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+;// +---+-+-------------------------+-------------------------------+
+;// |Sev|C| Facility | Code |
+;// +---+-+-------------------------+-------------------------------+
+;//
+;// where
+;//
+;// Sev - is the severity code
+;//
+;// 00 - Success
+;// 01 - Informational
+;// 10 - Warning
+;// 11 - Error
+;//
+;// C - is the Customer code flag
+;//
+;// Facility - is the facility code
+;//
+;// Code - is the facility's status code
+;//
+;
+MessageIdTypedef=NTSTATUS
+
+SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
+ Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
+ Warning=0x2:STATUS_SEVERITY_WARNING
+ Error=0x3:STATUS_SEVERITY_ERROR
+ )
+
+FacilityNames=(System=0x0
+ RpcRuntime=0x2:FACILITY_RPC_RUNTIME
+ RpcStubs=0x3:FACILITY_RPC_STUBS
+ Io=0x4:FACILITY_IO_ERROR_CODE
+ Smartcard=0x10:FACILITY_SCARD
+ )
+
+MessageId=0x0001 Facility=Smartcard Severity=Error SymbolicName=PSCR_NO_DEVICE_FOUND
+Language=English
+No PSCR Smart Card reader found in the system.
+.
+MessageId=0x0002 Facility=Smartcard Severity=Error SymbolicName=PSCR_CANT_INITIALIZE_READER
+Language=English
+The reader inserted is not working properly.
+Please try to change the 'Input/Output Range' and/or 'Interrupt Request'
+settings in Device Manager.
+.
+MessageId=0x0003 Facility=Smartcard Severity=Error SymbolicName=PSCR_INSUFFICIENT_RESOURCES
+Language=English
+Insufficient system resources to start device.
+.
+MessageId=0x0004 Facility=Smartcard Severity=Error SymbolicName=PSCR_ERROR_INTERRUPT
+Language=English
+Can't connect to the interrupt provided by the system.
+Please try to change the 'Interrupt Request' setting in Device Manager.
+.
+MessageId=0x0005 Facility=Smartcard Severity=Error SymbolicName=PSCR_ERROR_IO_PORT
+Language=English
+No I/O port specified or port can not be mapped.
+Please try to change the 'Input/Output Range' setting in the Device Manager.
+.
+MessageId=0x0006 Facility=Smartcard Severity=Error SymbolicName=PSCR_ERROR_CLAIM_RESOURCES
+Language=English
+Resources can not be claimed or an resource conflict exists.
+.
+MessageId=0x0007 Facility=Io Severity=Error SymbolicName=PSCR_NO_MEMORY
+Language=English
+The system does not have enough memory.
+.
+MessageId=0x0007 Facility=Smartcard Severity=Warning SymbolicName=PSCR_WRONG_FIRMWARE
+Language=English
+Your reader needs firmware version 2.30 or higher to work with this driver.
+.
+;#endif // __PSCRLOG_H__
diff --git a/smartcrd/pscr/pscrnt.c b/smartcrd/pscr/pscrnt.c
new file mode 100644
index 00000000..75d37304
--- /dev/null
+++ b/smartcrd/pscr/pscrnt.c
@@ -0,0 +1,1687 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrNT.c
+
+Abstract:
+
+ Main Driver Module - NT Version
+
+Author:
+
+ Andreas Straub
+
+Notes:
+
+ The file pscrnt.c was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+
+ Andreas Straub 1.00 8/18/1997 Initial Version
+ Klaus Schuetz 1.01 9/20/1997 Timing changed
+ Andreas Straub 1.02 9/24/1997 Low Level error handling,
+ minor bugfixes, clanup
+ Andreas Straub 1.03 10/8/1997 Timing changed, generic SCM
+ interface changed
+ Andreas Straub 1.04 10/18/1997 Interrupt handling changed
+ Andreas Straub 1.05 10/19/1997 Generic IOCTL's added
+ Andreas Straub 1.06 10/25/1997 Timeout limit for FW update variable
+ Andreas Straub 1.07 11/7/1997 Version information added
+ Klaus Schuetz 1.08 11/10/1997 PnP capabilities added
+ Klaus Schuetz Cleanup added
+ Calai Bhoopathi 6/12/2006 Changed retry count in Dpc routine
+ Eliyas Yakub 10/6/2006 Ported to KMDF
+
+--*/
+
+#include <PscrNT.h>
+#include <PscrCmd.h>
+#include <PscrCB.h>
+#include <PscrLog.h>
+#include <PscrVers.h>
+
+#pragma alloc_text(INIT, DriverEntry)
+#pragma alloc_text(PAGE, PscrEvtDeviceAdd)
+#pragma alloc_text(PAGE, PscrRegisterWithSmcLib)
+#pragma alloc_text(PAGE, PscrEvtDevicePrepareHardware)
+#pragma alloc_text(PAGE, PscrEvtDeviceD0Exit)
+#pragma alloc_text(PAGE, PscrEvtFileCleanup)
+#pragma alloc_text(PAGE, PscrGetRegistryValue)
+
+NTSTATUS
+DriverEntry(
+ PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath
+ )
+/*++
+
+DriverEntry:
+ entry function of the driver. setup the callbacks for the OS and try to
+ initialize a device object for every device in the system
+
+Arguments:
+ DriverObject context of the driver
+ RegistryPath path to the registry entry for the driver
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_UNSUCCESSFUL
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ WDF_DRIVER_CONFIG config;
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!DriverEntry: Enter - KMDF Version Built %s %s\n",
+ __DATE__, __TIME__ )
+ );
+
+ WDF_DRIVER_CONFIG_INIT(&config, PscrEvtDeviceAdd);
+
+
+ //
+ // Create a framework driver object to represent our driver.
+ //
+ status = WdfDriverCreate(DriverObject,
+ RegistryPath,
+ WDF_NO_OBJECT_ATTRIBUTES, // Driver Attributes
+ &config, // Driver Config Info
+ WDF_NO_HANDLE
+ );
+
+ if (!NT_SUCCESS(status)) {
+ KdPrint( ("WdfDriverCreate failed with status 0x%x\n", status));
+ }
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ("PSCR!DriverEntry: Exit %x\n",
+ status)
+ );
+
+ return status;
+}
+
+NTSTATUS
+PscrEvtDeviceAdd(
+ IN WDFDRIVER Driver,
+ IN PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+
+Routine Description:
+
+ PscrEvtDeviceAdd is called by the framework in response to AddDevice
+ call from the PnP manager. We create and initialize a WDF device object to
+ represent a new instance of toaster device.
+
+Arguments:
+
+ Driver - Handle to a framework driver object created in DriverEntry
+
+ DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
+
+Return Value:
+
+ NTSTATUS
+--*/
+{
+ NTSTATUS status;
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDFDEVICE device;
+ PDEVICE_EXTENSION DeviceExtension;
+ WDF_IO_QUEUE_CONFIG ioQueueConfig;
+ WDF_INTERRUPT_CONFIG interruptConfig;
+ WDF_FILEOBJECT_CONFIG fileobjectConfig;
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ PAGED_CODE();
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!PscrAddDevice: Enter\n" )
+ );
+
+ WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SMARTCARD);
+
+ WdfDeviceInitSetExclusive(DeviceInit, TRUE);
+
+ WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
+
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
+
+ pnpPowerCallbacks.EvtDevicePrepareHardware = PscrEvtDevicePrepareHardware;
+
+ pnpPowerCallbacks.EvtDeviceD0Entry = PscrEvtDeviceD0Entry;
+ pnpPowerCallbacks.EvtDeviceD0Exit = PscrEvtDeviceD0Exit;
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
+
+ //
+ // Register close callback so that we can clear the notification irp.
+ //
+ WDF_FILEOBJECT_CONFIG_INIT(
+ &fileobjectConfig,
+ WDF_NO_EVENT_CALLBACK, // Create
+ WDF_NO_EVENT_CALLBACK, // Close
+ PscrEvtFileCleanup // Cleanup
+ );
+
+ WdfDeviceInitSetFileObjectConfig(
+ DeviceInit,
+ &fileobjectConfig,
+ WDF_NO_OBJECT_ATTRIBUTES
+ );
+ //
+ // Initialize attributes and a context area for the device object.
+ //
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION);
+ attributes.EvtCleanupCallback = PscrEvtDeviceContextCleanup;
+
+ //
+ // Create a framework device object.This call will in turn create
+ // a WDM device object, attach to the lower stack, and set the
+ // appropriate flags and attributes.
+ //
+ status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
+ if (!NT_SUCCESS(status)) {
+ SmartcardLogError(
+ WdfDriverWdmGetDriverObject(WdfGetDriver()),
+ PSCR_INSUFFICIENT_RESOURCES,
+ NULL,
+ 0
+ );
+ return status;
+ }
+
+ //
+ // Get the device context by using the accessor function specified in
+ // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_EXTENSION.
+ //
+ DeviceExtension = GetDeviceExtension(device);
+
+ DeviceExtension->Device = device;
+
+ InterlockedIncrement((PLONG)&DeviceExtension->DeviceInstanceNo);
+
+ //
+ // Add an extra stack location to the IRP disaptched to our device so
+ // that we can use that to workaround the problem of scmlib completing
+ // ioctl IRPs.
+ //
+ WdfDeviceWdmGetDeviceObject(DeviceExtension->Device)->StackSize++;
+
+ //
+ // Tell the Framework that this device will need an interface
+ //
+ status = WdfDeviceCreateDeviceInterface(
+ device,
+ &SmartCardReaderGuid,
+ NULL // ReferenceString
+ );
+
+ if (!NT_SUCCESS (status)) {
+ SmartcardLogError(
+ WdfDriverWdmGetDriverObject(WdfGetDriver()),
+ PSCR_INSUFFICIENT_RESOURCES,
+ NULL,
+ 0
+ );
+
+ return status;
+ }
+
+ //
+ // Create a parallel queue for dispatching ioctl requests.
+ //
+
+ WDF_IO_QUEUE_CONFIG_INIT(
+ &ioQueueConfig,
+ WdfIoQueueDispatchParallel
+ );
+
+ ioQueueConfig.EvtIoDeviceControl = PscrEvtIoDeviceControl;
+
+
+ status = WdfIoQueueCreate (
+ device,
+ &ioQueueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DeviceExtension->IoctlQueue
+ );
+
+ if(!NT_SUCCESS (status)){
+ return status;
+ }
+
+ status = WdfDeviceConfigureRequestDispatching(
+ device,
+ DeviceExtension->IoctlQueue,
+ WdfRequestTypeDeviceControl);
+
+ if(!NT_SUCCESS (status)){
+ return status;
+ }
+
+ //
+ // Manual queue for parking smartcard notification request.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT(
+ &ioQueueConfig,
+ WdfIoQueueDispatchManual
+ );
+
+ //
+ // Since this request dispatch from this queue doesn't touch the
+ // hardware, it doesn't have to be power managed.
+ //
+ ioQueueConfig.PowerManaged = WdfFalse;
+
+ //
+ // Smartcard library keeps track of last outstanding notification
+ // request provided to the client driver. When the client driver
+ // completes the request, it has to clear the field in the data-
+ // structure maintained by the library. Since we keep the request
+ // in a queue, we need a notification from the framework when the
+ // request is cancelled so that we can clear the field.
+ //
+ ioQueueConfig.EvtIoCanceledOnQueue = PscrEvtIoCanceledOnQueue;
+
+ status = WdfIoQueueCreate (
+ device,
+ &ioQueueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DeviceExtension->NotificationQueue
+ );
+
+ if(!NT_SUCCESS (status)){
+ return status;
+ }
+
+ //
+ // Create WDFINTERRUPT object. Framework will take care of parsing
+ // the interrupt resource and connecting and disconnecting the ISR
+ // at the appropriate PNP/POWER state changes.
+ //
+
+ WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,
+ PscrEvtInterruptServiceRoutine,
+ PscrEvtInterruptDpc);
+
+ status = WdfInterruptCreate(device,
+ &interruptConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DeviceExtension->Interrupt);
+ if (!NT_SUCCESS (status)) {
+ return status;
+ }
+
+ //
+ // Register with smartcard libarary.
+ //
+ status = PscrRegisterWithSmcLib(DeviceExtension);
+ if (!NT_SUCCESS (status)) {
+ return status;
+ }
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!PscrAddDevice: Exit %x\n",
+ status)
+ );
+
+ return status;
+}
+
+VOID
+PscrEvtDeviceContextCleanup (
+ WDFOBJECT Object
+ )
+/*++
+
+Routine Description:
+
+ Called when the device object is deleted by the framework in response
+ to REMOVE_DEVICE request. Here, free up all the resources that wouldn't
+ cleaned up by the framework automatically due to parent child relationship.
+
+Arguments:
+
+ Device - Handle to a framework device object.
+
+Return Value:
+
+ VOID
+
+--*/
+{
+ WDFDEVICE Device;
+ PDEVICE_EXTENSION DeviceExtension;
+
+ Device = (WDFDEVICE)Object;
+ DeviceExtension = GetDeviceExtension(Device);
+
+ InterlockedDecrement((PLONG)&DeviceExtension->DeviceInstanceNo);
+
+ if (DeviceExtension->SmartcardExtension.ReaderExtension != NULL) {
+
+ ExFreePoolWithTag(DeviceExtension->SmartcardExtension.ReaderExtension,
+ SMARTCARD_POOL_TAG);
+
+ DeviceExtension->SmartcardExtension.ReaderExtension = NULL;
+ }
+}
+
+NTSTATUS
+PscrRegisterWithSmcLib(
+ PDEVICE_EXTENSION DeviceExtension
+ )
+{
+ PREADER_EXTENSION ReaderExtension;
+ PSMARTCARD_EXTENSION SmartcardExtension;
+ UNICODE_STRING vendorNameU, ifdTypeU;
+ ANSI_STRING vendorNameA, ifdTypeA;
+ WDFSTRING vendorNameStr, ifdTypeStr;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ vendorNameStr = NULL;
+ ifdTypeStr = NULL;
+
+ RtlZeroMemory(&vendorNameA, sizeof(vendorNameA));
+ RtlZeroMemory(&ifdTypeA, sizeof(ifdTypeA));
+
+ // set up the device extension.
+ SmartcardExtension = &DeviceExtension->SmartcardExtension;
+
+ // allocate the reader extension
+ ReaderExtension = ExAllocatePoolWithTag(
+ NonPagedPool,
+ sizeof( READER_EXTENSION ),
+ SMARTCARD_POOL_TAG
+ );
+
+ if ( ReaderExtension == NULL ) {
+ SmartcardLogError(
+ WdfDriverWdmGetDriverObject(WdfGetDriver()),
+ PSCR_INSUFFICIENT_RESOURCES,
+ NULL,
+ 0
+ );
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ return status;
+ }
+
+ RtlZeroMemory( ReaderExtension, sizeof( READER_EXTENSION ));
+
+ SmartcardExtension->ReaderExtension = ReaderExtension;
+
+ ReaderExtension->CompletionRoutine = CBUpdateCardState;
+ ReaderExtension->TrackingContext = SmartcardExtension;
+
+ ReaderExtension->dataRatesSupported[0] = (ULONG) 9600;
+ ReaderExtension->dataRatesSupported[1] = (ULONG) 38400;
+ ReaderExtension->dataRatesSupported[2] = (ULONG) 57600;
+ ReaderExtension->dataRatesSupported[3] = (ULONG) 115200;
+
+ // Initialize the RequestInterrupt flag
+ ReaderExtension->RequestInterrupt = FALSE;
+
+ // setup smartcard extension - callback's
+ SmartcardExtension->ReaderFunction[RDF_CARD_POWER] = CBCardPower;
+ SmartcardExtension->ReaderFunction[RDF_TRANSMIT] = CBTransmit;
+ SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = CBCardTracking;
+ SmartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = CBSetProtocol;
+ SmartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] = PscrGenericIOCTL;
+
+ // setup smartcard extension - vendor attribute
+ RtlCopyMemory(
+ SmartcardExtension->VendorAttr.VendorName.Buffer,
+ PSCR_VENDOR_NAME,
+ sizeof( PSCR_VENDOR_NAME )
+ );
+ SmartcardExtension->VendorAttr.VendorName.Length =
+ sizeof( PSCR_VENDOR_NAME );
+
+ RtlCopyMemory(
+ SmartcardExtension->VendorAttr.IfdType.Buffer,
+ PSCR_IFD_TYPE,
+ sizeof( PSCR_IFD_TYPE )
+ );
+ SmartcardExtension->VendorAttr.IfdType.Length =
+ sizeof( PSCR_IFD_TYPE );
+
+ SmartcardExtension->VendorAttr.UnitNo = DeviceExtension->DeviceInstanceNo;
+
+ SmartcardExtension->VendorAttr.IfdVersion.BuildNumber = 0;
+
+ // store firmware revision in ifd version
+ SmartcardExtension->VendorAttr.IfdVersion.VersionMajor =
+ ReaderExtension->FirmwareMajor;
+ SmartcardExtension->VendorAttr.IfdVersion.VersionMinor =
+ ReaderExtension->FirmwareMinor;
+ SmartcardExtension->VendorAttr.IfdSerialNo.Length = 0;
+
+ // setup smartcard extension - reader capabilities
+ SmartcardExtension->ReaderCapabilities.SupportedProtocols =
+ SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
+
+ SmartcardExtension->ReaderCapabilities.ReaderType =
+ SCARD_READER_TYPE_PCMCIA;
+ SmartcardExtension->ReaderCapabilities.MechProperties = 0;
+ SmartcardExtension->ReaderCapabilities.Channel = 0;
+
+ SmartcardExtension->ReaderCapabilities.CLKFrequency.Default = 4000;
+ SmartcardExtension->ReaderCapabilities.CLKFrequency.Max = 4000;
+
+ // reader could support higher data rates
+ SmartcardExtension->ReaderCapabilities.DataRatesSupported.List =
+ ReaderExtension->dataRatesSupported;
+ SmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries = MAX_DATARATES;
+ SmartcardExtension->ReaderCapabilities.DataRate.Default = ReaderExtension->dataRatesSupported[0];
+ SmartcardExtension->ReaderCapabilities.DataRate.Max =
+ ReaderExtension->dataRatesSupported[ MAX_DATARATES-1 ];
+
+ // enter correct version of the lib
+ SmartcardExtension->Version = SMCLIB_VERSION;
+ SmartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
+ SmartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
+
+ SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
+
+ status = SmartcardInitialize(SmartcardExtension);
+
+ if (status != STATUS_SUCCESS) {
+
+ SmartcardLogError(
+ WdfDriverWdmGetDriverObject(WdfGetDriver()),
+ PSCR_INSUFFICIENT_RESOURCES,
+ NULL,
+ 0
+ );
+ //
+ // No need to worry about freeing the pool we allocated earlier.
+ // It will be freed in the cleanup callback when the device is
+ // deleted by the framework as a result of failing this call.
+ //
+ return status;
+ }
+
+ SmartcardExtension->OsData->DeviceObject =
+ WdfDeviceWdmGetDeviceObject(DeviceExtension->Device);
+
+ vendorNameStr = PscrGetRegistryValue(DeviceExtension->Device, L"VendorName");
+ if (vendorNameStr != NULL) {
+
+ WdfStringGetUnicodeString(vendorNameStr, &vendorNameU);
+
+ status = RtlUnicodeStringToAnsiString(
+ &vendorNameA,
+ &vendorNameU,
+ TRUE
+ );
+ if (NT_SUCCESS(status)) {
+ if (vendorNameA.Length > 0 && vendorNameA.Length < MAXIMUM_ATTR_STRING_LENGTH) {
+ RtlCopyMemory(
+ SmartcardExtension->VendorAttr.VendorName.Buffer,
+ vendorNameA.Buffer,
+ vendorNameA.Length
+ );
+ SmartcardExtension->VendorAttr.VendorName.Length = vendorNameA.Length;
+ }
+ RtlFreeAnsiString(&vendorNameA);
+ }
+
+ //
+ // We have copied the string to the extension. No need to keep the object
+ // around and waste memory.
+ //
+ WdfObjectDelete(vendorNameStr);
+ vendorNameStr = NULL;
+ } else {
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ ifdTypeStr = PscrGetRegistryValue(DeviceExtension->Device, L"IfdType");
+ if (ifdTypeStr != NULL) {
+
+ WdfStringGetUnicodeString(ifdTypeStr, &ifdTypeU);
+
+ status = RtlUnicodeStringToAnsiString(
+ &ifdTypeA,
+ &ifdTypeU,
+ TRUE
+ );
+ if (NT_SUCCESS(status)) {
+ if (ifdTypeA.Length > 0 && ifdTypeA.Length < MAXIMUM_ATTR_STRING_LENGTH) {
+ RtlCopyMemory(
+ SmartcardExtension->VendorAttr.IfdType.Buffer,
+ ifdTypeA.Buffer,
+ ifdTypeA.Length
+ );
+ SmartcardExtension->VendorAttr.IfdType.Length = ifdTypeA.Length;
+ }
+ RtlFreeAnsiString(&ifdTypeA);
+ }
+
+ WdfObjectDelete(ifdTypeStr);
+ ifdTypeStr = NULL;
+ } else {
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+PscrEvtDevicePrepareHardware (
+ WDFDEVICE Device,
+ WDFCMRESLIST Resources,
+ WDFCMRESLIST ResourcesTranslated
+ )
+/*++
+
+Routine Description:
+
+ EvtDevicePrepareHardware event callback performs operations that are necessary
+ to make the driver's device operational. The framework calls the driver's
+ EvtDeviceStart callback when the PnP manager sends an IRP_MN_START_DEVICE
+ request to the driver stack.
+
+Arguments:
+
+ Device - Handle to a framework device object.
+
+ Resources - Handle to a collection of framework resource objects.
+ This collection identifies the raw (bus-relative) hardware
+ resources that have been assigned to the device.
+
+ ResourcesTranslated - Handle to a collection of framework resource objects.
+ This collection identifies the translated (system-physical)
+ hardware resources that have been assigned to the device.
+ The resources appear from the CPU's point of view.
+ Use this list of resources to map I/O space and
+ device-accessible memory into virtual address space
+
+Return Value:
+
+ WDF status code
+
+--*/
+{
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
+ PDEVICE_EXTENSION DeviceExtension = GetDeviceExtension(Device);
+ PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
+ PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
+ NTSTATUS status;
+ ULONG i;
+
+ UNREFERENCED_PARAMETER(Resources);
+ UNREFERENCED_PARAMETER(ResourcesTranslated);
+
+ PAGED_CODE();
+
+ for (i=0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {
+
+ descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);
+
+ switch(descriptor->Type) {
+
+ case CmResourceTypePort:
+
+ KdPrint(("I/O Port: (%x) Length: (%d)\n",
+ descriptor->u.Port.Start.LowPart,
+ descriptor->u.Port.Length));
+
+ ReaderExtension->IOBase =
+ (PPSCR_REGISTERS) UlongToPtr(descriptor->u.Port.Start.LowPart);
+
+ NT_ASSERT(descriptor->u.Port.Length >= 4);
+
+ break;
+
+ case CmResourceTypeMemory:
+
+ KdPrint(("Memory: (%x) Length: (%d)\n",
+ descriptor->u.Memory.Start.LowPart,
+ descriptor->u.Memory.Length));
+ break;
+ case CmResourceTypeInterrupt:
+ //
+ // Framework will parse the interrupt resource and connect and
+ // disconnect interrupt. We don't have to do anything here.
+ //
+ KdPrint(("Interrupt level: 0x%0x, Vector: 0x%0x, Affinity: 0x%0x\n",
+ descriptor->u.Interrupt.Level,
+ descriptor->u.Interrupt.Vector,
+ descriptor->u.Interrupt.Affinity));
+
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+
+ if ( ReaderExtension->IOBase == NULL ) {
+ SmartcardLogError(
+ WdfDriverWdmGetDriverObject(WdfGetDriver()),
+ PSCR_ERROR_IO_PORT,
+ NULL,
+ 0
+ );
+
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ return status;
+ }
+
+
+ ReaderExtension->Device = DEVICE_ICC1;
+ ReaderExtension->MaxRetries = PSCR_MAX_RETRIES;
+ status = CmdResetInterface( ReaderExtension );
+
+ SmartcardExtension->ReaderCapabilities.MaxIFSD =
+ ReaderExtension->MaxIFSD;
+
+ if (status != STATUS_SUCCESS) {
+
+ SmartcardLogError(
+ WdfDriverWdmGetDriverObject(WdfGetDriver()),
+ PSCR_CANT_INITIALIZE_READER,
+ NULL,
+ 0
+ );
+
+ return status;
+ }
+
+ status = CmdReset(
+ ReaderExtension,
+ 0x00, // reader
+ FALSE, // cold reset
+ NULL, // no atr
+ NULL
+ );
+
+ if (status != STATUS_SUCCESS) {
+
+ SmartcardLogError(
+ WdfDriverWdmGetDriverObject(WdfGetDriver()),
+ PSCR_CANT_INITIALIZE_READER,
+ NULL,
+ 0
+ );
+
+ return status;
+ }
+
+ PscrFlushInterface(DeviceExtension->SmartcardExtension.ReaderExtension);
+
+ CmdGetFirmwareRevision(
+ DeviceExtension->SmartcardExtension.ReaderExtension
+ );
+
+ // If you change the min. firmware version here, please update
+ // the .mc file for the correct error message, too
+ if (SmartcardExtension->ReaderExtension->FirmwareMajor < 2 ||
+ SmartcardExtension->ReaderExtension->FirmwareMajor == 2 &&
+ SmartcardExtension->ReaderExtension->FirmwareMinor < 0x34) {
+
+ SmartcardLogError(
+ WdfDriverWdmGetDriverObject(WdfGetDriver()),
+ PSCR_WRONG_FIRMWARE,
+ NULL,
+ 0
+ );
+ }
+
+ // store firmware revision in ifd version
+ SmartcardExtension->VendorAttr.IfdVersion.VersionMajor =
+ ReaderExtension->FirmwareMajor;
+ SmartcardExtension->VendorAttr.IfdVersion.VersionMinor =
+ ReaderExtension->FirmwareMinor;
+
+ // reader could support higher data rates
+ SmartcardExtension->ReaderCapabilities.DataRatesSupported.List =
+ ReaderExtension->dataRatesSupported;
+ SmartcardExtension->ReaderCapabilities.DataRate.Default = ReaderExtension->dataRatesSupported[0];
+
+ SmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries = 2;
+ SmartcardExtension->ReaderCapabilities.DataRate.Max =
+ ReaderExtension->dataRatesSupported[ 1 ];
+
+ NT_ASSERT(status == STATUS_SUCCESS);
+
+ return status;
+}
+
+NTSTATUS
+PscrEvtDeviceD0Entry(
+ IN WDFDEVICE Device,
+ IN WDF_POWER_DEVICE_STATE PreviousState
+ )
+/*++
+
+Routine Description:
+
+ EvtDeviceD0Entry event callback must perform any operations that are
+ necessary before the specified device is used. It will be called every
+ time the hardware needs to be (re-)initialized. This includes after
+ IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,
+ IRP_MN_SET_POWER-D0.
+
+ This function runs at PASSIVE_LEVEL, though it is generally not paged. A
+ driver can optionally make this function pageable if DO_POWER_PAGABLE is set.
+
+ Even if DO_POWER_PAGABLE isn't set, this function still runs at
+ PASSIVE_LEVEL. In this case, though, the function absolutely must not do
+ anything that will cause a page fault.
+
+Arguments:
+
+ Device - Handle to a framework device object.
+
+ PreviousState - Device power state which the device was in most recently.
+ If the device is being newly started, this will be
+ PowerDeviceUnspecified.
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ NTSTATUS status;
+ PDEVICE_EXTENSION DeviceExtension;
+ PSMARTCARD_EXTENSION SmartcardExtension;
+ UCHAR state;
+ WDF_INTERRUPT_INFO interruptInfo;
+
+ //
+ //MikeTs(10/15/2008): http://msdn.microsoft.com/en-us/library/bb725862.aspx
+ // explains although the callback function is called at PASSIVE_LEVEL,
+ // callback functions that leave a lower device state returning to
+ // working state should not be pageable.
+ //
+ DeviceExtension = GetDeviceExtension(Device);
+
+ //
+ // Find out if the interrupt is shared.
+ //
+ WDF_INTERRUPT_INFO_INIT(&interruptInfo);
+ WdfInterruptGetInfo(DeviceExtension->Interrupt, &interruptInfo);
+ DeviceExtension->bSharedIRQ =
+ (interruptInfo.ShareDisposition == CmResourceShareShared);
+
+ SmartcardExtension = (PSMARTCARD_EXTENSION) &DeviceExtension->SmartcardExtension;
+
+ status = CmdResetInterface(SmartcardExtension->ReaderExtension);
+ NT_ASSERT(status == STATUS_SUCCESS);
+
+ SmartcardExtension->ReaderExtension->StatusFileSelected = FALSE;
+ state = CBGetCardState(SmartcardExtension);
+
+
+ // save the current power state of the reader
+ SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
+
+ //
+ // We will use PreviousState to differetiate whether EvtDeviceD0Entry is
+ // called due to implicit power when the device is first started or when
+ // the device is resume power a low power state (due to explicit power up).
+ //
+ if (PreviousState != WdfPowerDeviceD3Final) {
+ //
+ // The device is resuming from a suspended state.
+ //
+ CBUpdateCardState(SmartcardExtension, state, TRUE);
+ } else {
+ //
+ // The device is starting up for the first time.
+ //
+ CBUpdateCardState(SmartcardExtension, state, FALSE);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+PscrEvtDeviceD0Exit(
+ IN WDFDEVICE Device,
+ IN WDF_POWER_DEVICE_STATE TargetState
+ )
+/*++
+
+Routine Description:
+
+ This routine undoes anything done in EvtDeviceD0Entry. It is called
+ whenever the device leaves the D0 state, which happens when the device is
+ stopped, when it is removed, and when it is powered off.
+
+ The device is still in D0 when this callback is invoked, which means that
+ the driver can still touch hardware in this routine.
+
+ Note that interrupts have already been disabled by the time that this
+ callback is invoked.
+
+ EvtDeviceD0Exit event callback must perform any operations that are
+ necessary before the specified device is moved out of the D0 state. If the
+ driver needs to save hardware state before the device is powered down, then
+ that should be done here.
+
+ This function runs at PASSIVE_LEVEL, though it is generally not paged. A
+ driver can optionally make this function pageable if DO_POWER_PAGABLE is set.
+
+ Even if DO_POWER_PAGABLE isn't set, this function still runs at
+ PASSIVE_LEVEL. In this case, though, the function absolutely must not do
+ anything that will cause a page fault.
+
+Arguments:
+
+ Device - Handle to a framework device object.
+
+ TargetState - Device power state which the device will be put in once this
+ callback is complete.
+
+Return Value:
+
+ Success implies that the device can be used. Failure will result in the
+ device stack being torn down.
+
+--*/
+{
+ NTSTATUS status;
+ PDEVICE_EXTENSION DeviceExtension;
+ PSMARTCARD_EXTENSION smartcardExtension;
+
+ PAGED_CODE();
+
+ DeviceExtension = GetDeviceExtension(Device);
+ smartcardExtension = (PSMARTCARD_EXTENSION) &DeviceExtension->SmartcardExtension;
+
+ switch (TargetState) {
+ case WdfPowerDeviceD1:
+ case WdfPowerDeviceD2:
+ case WdfPowerDeviceD3:
+
+ smartcardExtension->ReaderExtension->CardPresent =
+ smartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT ? TRUE: FALSE;
+
+ if (smartcardExtension->ReaderExtension->CardPresent) {
+ smartcardExtension->MinorIoControlCode = SCARD_POWER_DOWN;
+ status = CBCardPower(smartcardExtension);
+ NT_ASSERT(NT_SUCCESS(status));
+ }
+ // save the current power state of the reader
+ smartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderOff;
+ break;
+
+ case WdfPowerDevicePrepareForHibernation:
+
+ //
+ // Fill in any code to save hardware state here. Do not put in any
+ // code to shut the device off. If this device cannot support being
+ // in the paging path (or being a parent or grandparent of a paging
+ // path device) then this whole case can be deleted.
+ //
+ NT_ASSERT(FALSE); // This driver shouldn't get this.
+ break;
+
+ case WdfPowerDeviceD3Final:
+ //
+ // Reset and put the device into a known initial state we're shutting
+ // down for the last time.
+ //
+ break;
+
+ default:
+ break;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+VOID
+PscrEvtFileCleanup(
+ IN WDFFILEOBJECT FileObject
+ )
+/*++
+
+ EvtFileClose is called when all the handles represented by the FileObject
+ is closed and all the references to FileObject is removed. This callback
+ may get called in an arbitrary thread context instead of the thread that
+ called CloseHandle. If you want to delete any per FileObject context that
+ must be done in the context of the user thread that made the Create call,
+ you should do that in the EvtDeviceCleanp callback.
+
+Arguments:
+
+ FileObject - Pointer to fileobject that represents the open handle.
+
+Return Value:
+
+ VOID
+
+--*/
+
+{
+ PDEVICE_EXTENSION DeviceExtension;
+ PSMARTCARD_EXTENSION smartcardExtension;
+ NTSTATUS status;
+ WDFREQUEST request;
+
+ PAGED_CODE();
+
+ //KdPrint(("PscrEvtFileCleanup called\n"));
+
+ //
+ // After cleanup callback is invoked, framework flushes all the queues
+ // by fileobject to cancel irps belonging to the file handle being closed.
+ // Since framework version 1.5 and less have a bug in that on cleanup-
+ // flush the EvtIoCanceledOnQueue callback is not invoked, we will
+ // retrive the request by fileobject ourselves and complete the request
+ // and clear the NotificaitonIrp field.
+ //
+ DeviceExtension = GetDeviceExtension(WdfFileObjectGetDevice(FileObject));
+ smartcardExtension = (PSMARTCARD_EXTENSION) &DeviceExtension->SmartcardExtension;
+
+ do {
+ status = WdfIoQueueRetrieveRequestByFileObject(
+ DeviceExtension->NotificationQueue,
+ FileObject,
+ &request);
+
+ if (NT_SUCCESS(status)) {
+
+ NT_ASSERT(smartcardExtension->OsData->NotificationIrp ==
+ WdfRequestWdmGetIrp(request));
+
+ InterlockedExchangePointer(
+ &(smartcardExtension->OsData->NotificationIrp),
+ NULL
+ );
+
+ WdfRequestComplete(request, STATUS_CANCELLED);
+ }
+ }while (NT_SUCCESS(status));
+
+ NT_ASSERT(status == STATUS_NO_MORE_ENTRIES);
+
+ return;
+}
+
+_Function_class_(IO_COMPLETION_ROUTINE)
+NTSTATUS
+PscrSmcLibComplete (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context
+ )
+/*++
+
+Routine Description:
+
+ Completion routine is called when the IRP is completed by the smclib.
+ We will interrupt the completion of the IRP, and inturn complete the
+ WDFREQUEST given to us by the framework.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ //KdPrint(("<-- PscrSmcLibComplete called %x Request %x\n",
+ // Irp->IoStatus.Status, Context));
+
+ WdfRequestComplete((WDFREQUEST)Context, Irp->IoStatus.Status);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+
+VOID
+PscrEvtIoDeviceControl(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t OutputBufferLength,
+ IN size_t InputBufferLength,
+ IN ULONG IoControlCode
+ )
+/*++
+
+Routine Description:
+
+ This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
+ requests from the system.
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated
+ with the I/O request.
+ Request - Handle to a framework request object.
+
+ OutputBufferLength - length of the request's output buffer,
+ if an output buffer is available.
+ InputBufferLength - length of the request's input buffer,
+ if an input buffer is available.
+
+ IoControlCode - the driver-defined or system-defined I/O control code
+ (IOCTL) that is associated with the request.
+Return Value:
+
+ VOID
+
+--*/
+{
+ PDEVICE_EXTENSION deviceExtension;
+ PIRP irp;
+
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(IoControlCode);
+
+ //KdPrint(("--> PscrEvtIoDeviceControl called %s Request 0x%x\n",
+ // GetIoctlName(IoControlCode), Request));
+
+ deviceExtension = GetDeviceExtension(WdfIoQueueGetDevice(Queue));
+
+ //
+ // Since smartcard library expects an IRP, we will get the underlying
+ // irp.
+ //
+ irp = WdfRequestWdmGetIrp(Request);
+
+ //
+ // We will store the Request handle in the IRP DriverContext field so
+ // that we can get the handle back in vendor-ioctl callback routine.
+ //
+ SET_REQUEST_IN_IRP(irp, Request);
+
+ //
+ // To workaround the problem of smartcard completing the IRP we provided.
+ // we will use the extra stack location to set a completion routine so that
+ // when it completes the IRP, our completion routine will be called, where
+ // we can interrupt the completion and complete the actual WDFREQUEST.
+ //
+ IoCopyCurrentIrpStackLocationToNext(irp);
+
+ IoSetCompletionRoutine (irp,
+ PscrSmcLibComplete,
+ Request,
+ TRUE,
+ TRUE,
+ TRUE
+ );
+
+ IoSetNextIrpStackLocation(irp);
+
+ //
+ // Ignore the return value because framework has marked the irp pending
+ // and will return status-pending when we return from this routine.
+ //
+ (VOID) SmartcardDeviceControl(&(deviceExtension->SmartcardExtension), irp);
+
+ return;
+}
+
+NTSTATUS
+PscrGenericIOCTL(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+/*++
+
+PscrGenericIOCTL:
+ Performs generic callbacks to the reader
+
+Arguments:
+ SmartcardExtension context of the call
+
+Return Value:
+ STATUS_SUCCESS
+
+--*/
+{
+ NTSTATUS status;
+ PIRP Irp;
+ WDFREQUEST request;
+ ULONG bytesTransfered;
+ size_t inBufLen, outBufLen;
+ PVOID inBuf, outBuf;
+ PIO_STACK_LOCATION IrpStack;
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!PscrGenericIOCTL: Enter\n" )
+ );
+
+ //
+ // get pointer to current IRP stack location
+ //
+ Irp = SmartcardExtension->OsData->CurrentIrp;
+ IrpStack = IoGetCurrentIrpStackLocation( Irp );
+
+ //
+ // Get the request from the IRP so that we can call framework functions
+ // to retreive the buffers.
+ //
+ request = GET_WDFREQUEST_FROM_IRP(SmartcardExtension->OsData->CurrentIrp);
+
+ status = WdfRequestRetrieveInputBuffer(request, 0, &inBuf, &inBufLen);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = WdfRequestRetrieveOutputBuffer(request, 0, &outBuf, &outBufLen);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ //
+ // assume error
+ //
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ bytesTransfered = 0;
+
+ //
+ // dispatch IOCTL
+ //
+ switch ( IrpStack->Parameters.DeviceIoControl.IoControlCode ) {
+ case IOCTL_PSCR_COMMAND:
+
+ status = CmdPscrCommand(
+ SmartcardExtension->ReaderExtension,
+ (PUCHAR) inBuf,
+ (ULONG) inBufLen,
+ (PUCHAR) outBuf,
+ (ULONG) outBufLen,
+ (PULONG) &bytesTransfered
+ );
+ //
+ // the command could change the active file in the reader file
+ // system, so make sure that the status file will be selected
+ // before the next read
+ //
+ SmartcardExtension->ReaderExtension->StatusFileSelected = FALSE;
+ break;
+
+ case IOCTL_GET_VERSIONS:
+
+ if ( outBufLen < SIZEOF_VERSION_CONTROL ) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ PVERSION_CONTROL VersionControl;
+
+ VersionControl = (PVERSION_CONTROL)outBufLen;
+
+ VersionControl->SmclibVersion = SmartcardExtension->Version;
+ VersionControl->DriverMajor = PSCR_MAJOR_VERSION;
+ VersionControl->DriverMinor = PSCR_MINOR_VERSION;
+
+ // update firmware version (changed after update)
+ CmdGetFirmwareRevision(
+ SmartcardExtension->ReaderExtension
+ );
+ VersionControl->FirmwareMajor =
+ SmartcardExtension->ReaderExtension->FirmwareMajor;
+
+ VersionControl->FirmwareMinor =
+ SmartcardExtension->ReaderExtension->FirmwareMinor;
+
+ VersionControl->UpdateKey =
+ SmartcardExtension->ReaderExtension->UpdateKey;
+
+ bytesTransfered = SIZEOF_VERSION_CONTROL;
+ status = STATUS_SUCCESS;
+ }
+ break;
+
+ case IOCTL_SET_TIMEOUT:
+ {
+ ULONG NewLimit;
+ //
+ // get new timeout limit
+ //
+ if ( inBufLen == sizeof( ULONG )) {
+ NewLimit = *(PULONG)inBuf;
+ } else {
+ NewLimit = 0;
+ }
+
+ //
+ // report actual timeout limit
+ //
+ if (outBufLen == sizeof( ULONG )) {
+
+ *(PULONG)outBuf = SmartcardExtension->ReaderExtension->MaxRetries
+ * DELAY_PSCR_WAIT;
+ bytesTransfered = sizeof( ULONG );
+ }
+
+ //
+ // set new timeout limit
+ //
+ if ( (NewLimit != 0) ||
+ (NewLimit == MAXULONG-DELAY_PSCR_WAIT+2 )) {
+ SmartcardExtension->ReaderExtension->MaxRetries =
+ (NewLimit + DELAY_PSCR_WAIT - 1) / DELAY_PSCR_WAIT;
+ }
+ }
+ status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_GET_CONFIGURATION:
+ //
+ // return IOBase and IRQ
+ //
+ if (outBufLen < SIZEOF_PSCR_CONFIGURATION ) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ PPSCR_CONFIGURATION PSCRConfiguration;
+
+ PSCRConfiguration = (PPSCR_CONFIGURATION) outBuf;
+ PSCRConfiguration->IOBase =
+ SmartcardExtension->ReaderExtension->IOBase;
+ PSCRConfiguration->IRQ =
+ SmartcardExtension->ReaderExtension->CurrentIRQ;
+
+ bytesTransfered = SIZEOF_PSCR_CONFIGURATION;
+ status = STATUS_SUCCESS;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // set status of the packet
+ //
+ Irp->IoStatus.Status = status;
+ Irp->IoStatus.Information = bytesTransfered;
+
+ //
+ // The request will be completed the smartcard library.
+ //
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!PscrGenericIOCTL: Exit\n" )
+ );
+
+ return( status );
+}
+
+
+VOID
+PscrEvtIoCanceledOnQueue(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request
+ )
+/*++
+
+PscrEvtIoCanceledOnQueue:
+
+ This routine is called when the request is cancelled on the queue.
+
+ We will use the notificatio to clear the NotificationIrp field set by
+ the smartcard library.
+
+Arguments:
+
+Return Value:
+ VOID
+
+--*/
+{
+ PDEVICE_EXTENSION DeviceExtension;
+ PSMARTCARD_EXTENSION smartcardExtension;
+
+ DeviceExtension = GetDeviceExtension(WdfIoQueueGetDevice(Queue));
+ smartcardExtension = (PSMARTCARD_EXTENSION) &DeviceExtension->SmartcardExtension;
+
+ //KdPrint(("Cancelled on queue 0x%x\n", WdfRequestWdmGetIrp(Request)));
+
+ InterlockedExchangePointer(
+ &(smartcardExtension->OsData->NotificationIrp),
+ NULL
+ );
+
+ WdfRequestComplete(Request, STATUS_CANCELLED);
+}
+
+BOOLEAN
+PscrEvtInterruptServiceRoutine(
+ IN WDFINTERRUPT Interrupt,
+ IN ULONG MessageID
+ )
+/*++
+
+PscrIrqServiceRoutine:
+
+ Because the device not supports shared interrupts, the call is passed
+ to the DPC routine immediately and the IRQ is reported as served.
+
+Arguments:
+
+Return Value:
+ STATUS_SUCCESS
+
+--*/
+{
+ LARGE_INTEGER Time;
+ TIME_FIELDS TimeFields;
+ TIME_FIELDS SaveTimeFields;
+ BOOLEAN Status = TRUE;
+ PDEVICE_EXTENSION DeviceExtension;
+
+ UNREFERENCED_PARAMETER(MessageID);
+
+ DeviceExtension= GetDeviceExtension(WdfInterruptGetDevice(Interrupt));
+
+ KeQuerySystemTime( &Time );
+ RtlTimeToTimeFields( &Time, &TimeFields );
+ RtlTimeToTimeFields( &DeviceExtension->SaveTime, &SaveTimeFields );
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ("PSCR!PscrIrqServiceRoutine: Enter\n")
+ );
+
+ // if the interrupt is shared the PscrIrqServiceRoutine shall return always FALSE
+ // since te driver can't detect if the interrupt was sending from the reader when
+ // the firmware <2.50 is using
+ // if the interrupt is used exclusiv and the PscrIrqServiceRoutine returns FALSE,
+ // no more interrupts will be sended
+ if(( DeviceExtension->bSharedIRQ ) &&
+ ( TimeFields.Minute == SaveTimeFields.Minute ) &&
+ ( TimeFields.Second == SaveTimeFields.Second ) &&
+ ( TimeFields.Milliseconds < SaveTimeFields.Milliseconds+50 ))
+ {
+ KdPrint(( "****** Status FALSE ******\n" ));
+ SysDelay( 5 );
+ Status = FALSE;
+ }
+ else
+ {
+ //
+ // When someone yanks out the card the interrupt handler gets called,
+ // but since there is no card anymore when don't need to schedule a DPC
+ //
+
+ //
+ // the interrupt is caused by a freeze event. the interface will be
+ // cleared either by PscrRead() or the DPC routine (depending on
+ // which is called first)
+ //
+ // DeviceExtension->SmartcardExtension.ReaderExtension->FreezePending = TRUE;
+
+ InterlockedIncrement((PLONG)&DeviceExtension->PendingInterrupts);
+
+ WdfInterruptQueueDpcForIsr( Interrupt );
+
+ if( DeviceExtension->bSharedIRQ ) {
+ Status = FALSE;
+ }
+ }
+
+ DeviceExtension->SaveTime.QuadPart = Time.QuadPart;
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!PscrIrqServiceRoutine: Exit\n" )
+ );
+
+ return Status ;
+}
+
+VOID
+PscrEvtInterruptDpc(
+ IN WDFINTERRUPT Interrupt,
+ IN WDFOBJECT Device
+ )
+/*++
+
+PscrDpcRoutine:
+ finishes interrupt requests. the freeze event data of the reader will be read
+ & the card state will be updated if data valid
+
+Arguments:
+
+Return Value:
+ void
+
+--*/
+{
+ PDEVICE_EXTENSION DeviceExtension;
+ PSMARTCARD_EXTENSION SmartcardExtension;
+
+ UNREFERENCED_PARAMETER(Interrupt);
+
+ DeviceExtension= GetDeviceExtension(Device);
+ SmartcardExtension = (PSMARTCARD_EXTENSION) &DeviceExtension->SmartcardExtension;
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!PscrInterruptEvent: IoBase %p\n",
+ SmartcardExtension->ReaderExtension->IOBase)
+ );
+
+ //
+ // In case of a card change the reader provides a TLV packet describing
+ // the event ('freeze event'). If PscrRead was called before the DPC
+ // routine is called, this event was cleared; in this case the card state
+ // will be updated by reading the card status file
+ //
+ do {
+
+
+ NT_ASSERT(DeviceExtension->PendingInterrupts < 10);
+
+ SmartcardDebug(
+ DEBUG_TRACE,
+ ( "PSCR!PscrInterruptEvent: PendingInterrupts = %ld\n",
+ DeviceExtension->PendingInterrupts)
+ );
+
+ if( !SmartcardExtension->ReaderExtension->RequestPending )
+ {
+ PscrFreeze( SmartcardExtension );
+ }
+ else
+ {
+ // sometimes the fw doesn't send the freeze data
+ SmartcardExtension->ReaderExtension->RequestInterrupt = TRUE;
+ }
+
+ } while (InterlockedDecrement((PLONG)&DeviceExtension->PendingInterrupts) > 0);
+}
+
+void
+PscrFreeze(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ )
+
+/*++
+PscrFreeze:
+ Read & evaluate freeze data
+
+Arguments:
+ ReaderExtension context of call
+ pDevice device which causes the freeze event
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_UNSUCCESSFUL
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
+ UCHAR TLVList[9];
+ ULONG NBytes;
+ ULONG Retries;
+ UCHAR ReadFreeze[] = { 0x12, 0x00, 0x05, 0x00, 0xB0, 0x00, 0x00, 0x01, 0xA6};
+
+ for (Retries = 0; Retries < 2; Retries++) // CB - code sync - 7/13/2006
+ {
+
+ PscrWriteDirect(
+ SmartcardExtension->ReaderExtension,
+ (PUCHAR)ReadFreeze,
+ sizeof( ReadFreeze ),
+ &NBytes
+ );
+
+ SysDelay( 20 );
+
+ NTStatus = PscrRead(
+ SmartcardExtension->ReaderExtension,
+ (PUCHAR) TLVList,
+ sizeof( TLVList ),
+ &NBytes
+ );
+
+ if( NT_SUCCESS( NTStatus ))
+ {
+ //
+ // get result
+ //
+ if( ( TLVList[ PSCR_NAD ] == 0x21 ) &&
+ ( TLVList[ PSCR_INF ] == TAG_FREEZE_EVENTS ))
+ {
+ break;
+ }
+ }
+ }
+}
+
+WDFSTRING
+PscrGetRegistryValue(
+ _In_ WDFDEVICE Device,
+ _In_ LPCWSTR Name
+ )
+/*++
+
+Routine Description:
+
+ Get the registry values from the device parameters key.
+
+Arguments:
+
+
+Return Value:
+
+--*/
+{
+ WDFKEY hKey = NULL;
+ NTSTATUS status;
+ UNICODE_STRING valueName;
+ WDFSTRING string = NULL;
+
+ PAGED_CODE();
+
+ status = WdfDeviceOpenRegistryKey(Device,
+ PLUGPLAY_REGKEY_DEVICE,
+ STANDARD_RIGHTS_ALL,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &hKey);
+ if (NT_SUCCESS (status)) {
+
+ status = WdfStringCreate(
+ NULL,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &string
+ );
+ if (NT_SUCCESS (status)) {
+ RtlInitUnicodeString(&valueName, Name);
+
+ status = WdfRegistryQueryString(hKey, &valueName, string);
+ if (!NT_SUCCESS (status)) {
+ WdfObjectDelete(string);
+ string = NULL;
+ }
+ }
+
+ WdfRegistryClose(hKey);
+ }
+
+ return string;
+}
+
+void
+SysDelay(
+ ULONG Timeout
+ )
+/*++
+
+SysDelay:
+ performs a required delay. The usage of KeStallExecutionProcessor is
+ very nasty, but it happends only if SysDelay is called in the context of
+ our DPC routine (which is only called if a card change was detected).
+
+ For 'normal' IO we have Irql < DISPATCH_LEVEL, so if the reader is polled
+ while waiting for response we will not block the entire system
+
+Arguments:
+ Timeout delay in milli seconds
+
+Return Value:
+ void
+
+--*/
+{
+ LARGE_INTEGER SysTimeout;
+
+ if ( KeGetCurrentIrql() >= DISPATCH_LEVEL ) {
+ ULONG Cnt = 20 * Timeout;
+
+ while ( Cnt-- ) {
+ // KeStallExecutionProcessor: counted in us
+ KeStallExecutionProcessor( 50 );
+ }
+ } else {
+ SysTimeout.QuadPart = (LONGLONG)-10 * 1000 * Timeout;
+
+ // KeDelayExecutionThread: counted in 100 ns
+ KeDelayExecutionThread( KernelMode, FALSE, &SysTimeout );
+ }
+ return;
+}
+
+PCHAR
+GetIoctlName(
+ ULONG IoControlCode
+ )
+{
+ switch (IoControlCode) {
+ case IOCTL_SMARTCARD_POWER: return "IOCTL_SMARTCARD_POWER";
+ case IOCTL_SMARTCARD_GET_ATTRIBUTE: return "IOCTL_SMARTCARD_GET_ATTRIBUTE";
+ case IOCTL_SMARTCARD_SET_ATTRIBUTE: return "IOCTL_SMARTCARD_SET_ATTRIBUTE";
+ case IOCTL_SMARTCARD_CONFISCATE: return "IOCTL_SMARTCARD_CONFISCATE";
+ case IOCTL_SMARTCARD_TRANSMIT: return "IOCTL_SMARTCARD_TRANSMIT";
+ case IOCTL_SMARTCARD_EJECT: return "IOCTL_SMARTCARD_EJECT";
+ case IOCTL_SMARTCARD_SWALLOW: return "IOCTL_SMARTCARD_SWALLOW";
+ case IOCTL_SMARTCARD_IS_PRESENT: return "IOCTL_SMARTCARD_IS_PRESENT";
+ case IOCTL_SMARTCARD_IS_ABSENT: return "IOCTL_SMARTCARD_IS_ABSENT";
+ case IOCTL_SMARTCARD_SET_PROTOCOL: return "IOCTL_SMARTCARD_SET_PROTOCOL";
+ case IOCTL_SMARTCARD_GET_STATE: return "IOCTL_SMARTCARD_GET_STATE";
+ case IOCTL_SMARTCARD_GET_LAST_ERROR: return "IOCTL_SMARTCARD_GET_LAST_ERROR";
+ default: return "Unknow_ioctl";
+ }
+}
diff --git a/smartcrd/pscr/pscrnt.h b/smartcrd/pscr/pscrnt.h
new file mode 100644
index 00000000..959b9b22
--- /dev/null
+++ b/smartcrd/pscr/pscrnt.h
@@ -0,0 +1,187 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrNT.h
+
+Abstract:
+
+ Driver header - NT Version
+
+Author:
+
+ Andreas Straub (SCM Microsystems, Inc.)
+ Klaus Schuetz (Microsoft Corp.)
+
+Notes:
+
+ The file pscrnt.h was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+ Andreas Straub 1.00 8/18/1997 Initial Version
+ Klaus Schuetz 1.01 9/20/1997 Timing changed
+ Andreas Straub 1.02 9/24/1997 Low Level error handling,
+ minor bugfixes, clanup
+ Andreas Straub 1.03 10/8/1997 Timing changed, generic SCM
+ interface changed
+ Andreas Straub 1.04 10/18/1997 Interrupt handling changed
+ Andreas Straub 1.05 10/19/1997 Generic IOCTL's added
+ Andreas Straub 1.06 10/25/1997 Timeout limit for FW update variable
+ Andreas Straub 1.07 11/7/1997 Version information added
+ Andreas Straub 1.08 11/10/1997 Generic IOCTL GET_CONFIGURATION
+ Klaus Schuetz 1998 PnP and Power Management added
+
+--*/
+
+#if !defined ( __PSCR_NT_DRV_H__ )
+#define __PSCR_NT_DRV_H__
+#define SMARTCARD_POOL_TAG '4SCS'
+
+#include <ntddk.h>
+#include <wdf.h>
+#include <DEVIOCTL.H>
+
+#pragma warning(push)
+#pragma warning(disable:4201)
+#include "SMCLIB.h"
+#pragma warning(pop)
+
+#include "PscrRdWr.h"
+
+_Analysis_mode_(_Analysis_code_type_kernel_driver_)
+
+#if !defined( STATUS_DEVICE_REMOVED )
+#define STATUS_DEVICE_REMOVED STATUS_UNSUCCESSFUL
+#endif
+
+#define SysCompareMemory( p1, p2, Len ) ( RtlCompareMemory( p1,p2, Len ) != Len )
+#define SysCopyMemory( pDest, pSrc, Len ) RtlCopyMemory( pDest, pSrc, Len )
+#define SysFillMemory( pDest, Value, Len ) RtlFillMemory( pDest, Len, Value )
+
+#define DELAY_WRITE_PSCR_REG 1
+#define DELAY_PSCR_WAIT 5
+
+#define LOBYTE( any ) ((UCHAR)( any & 0xFF ) )
+#define HIBYTE( any ) ((UCHAR)( ( any >> 8) & 0xFF ))
+
+//
+// These macros will store and retrieve the request handle from the IRP.
+// We will use the first slot of DriverContext because framework reserves
+// the use of 3rd & 4rd slot of DriverContext for its own purpose.
+//
+#define GET_WDFREQUEST_FROM_IRP(Irp) (WDFREQUEST)Irp->Tail.Overlay.DriverContext[0]
+#define SET_REQUEST_IN_IRP(Irp, Request) {Irp->Tail.Overlay.DriverContext[0] = (PVOID)Request;}
+
+typedef struct _DEVICE_EXTENSION
+{
+ SMARTCARD_EXTENSION SmartcardExtension;
+
+ WDFDEVICE Device;
+
+ // Out interrupt resource
+ WDFINTERRUPT Interrupt;
+
+ WDFQUEUE IoctlQueue;
+
+ WDFQUEUE NotificationQueue;
+
+ // Flag that indicates if we need to unmap the port upon stop
+ BOOLEAN UnMapPort;
+
+ // Number of pending card tracking interrupts
+ ULONG PendingInterrupts;
+
+ // If the PCMCIA works in PCI mode, check the time between two interrupts
+ BOOLEAN bSharedIRQ;
+ LARGE_INTEGER SaveTime;
+
+ ULONG DeviceInstanceNo;
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+//
+// This macro defines an accessor function which will be used to get the context
+// pointer from the device handle.
+//
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, GetDeviceExtension)
+
+#define IOCTL_PSCR_COMMAND SCARD_CTL_CODE( 0x8000 )
+#define IOCTL_GET_VERSIONS SCARD_CTL_CODE( 0x8001 )
+#define IOCTL_SET_TIMEOUT SCARD_CTL_CODE( 0x8002 )
+#define IOCTL_GET_CONFIGURATION SCARD_CTL_CODE( 0x8003 )
+
+typedef struct _VERSION_CONTROL
+{
+ ULONG SmclibVersion;
+ UCHAR DriverMajor,
+ DriverMinor,
+ FirmwareMajor,
+ FirmwareMinor,
+ UpdateKey;
+} VERSION_CONTROL, *PVERSION_CONTROL;
+
+#define SIZEOF_VERSION_CONTROL sizeof( VERSION_CONTROL )
+
+typedef struct _PSCR_CONFIGURATION
+{
+ PPSCR_REGISTERS IOBase;
+ ULONG IRQ;
+
+} PSCR_CONFIGURATION, *PPSCR_CONFIGURATION;
+
+#define SIZEOF_PSCR_CONFIGURATION sizeof( PSCR_CONFIGURATION )
+
+
+DRIVER_INITIALIZE DriverEntry;
+
+EVT_WDF_DRIVER_DEVICE_ADD PscrEvtDeviceAdd;
+
+EVT_WDF_OBJECT_CONTEXT_CLEANUP PscrEvtDeviceContextCleanup;
+
+EVT_WDF_DEVICE_D0_ENTRY PscrEvtDeviceD0Entry;
+EVT_WDF_DEVICE_D0_EXIT PscrEvtDeviceD0Exit;
+EVT_WDF_DEVICE_PREPARE_HARDWARE PscrEvtDevicePrepareHardware;
+
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL PscrEvtIoDeviceControl;
+EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE PscrEvtIoCanceledOnQueue;
+
+EVT_WDF_FILE_CLEANUP PscrEvtFileCleanup;
+
+EVT_WDF_INTERRUPT_ISR PscrEvtInterruptServiceRoutine;
+EVT_WDF_INTERRUPT_DPC PscrEvtInterruptDpc;
+
+NTSTATUS
+PscrGenericIOCTL(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+VOID
+PscrFreeze(
+ PSMARTCARD_EXTENSION SmartcardExtension
+ );
+
+VOID
+SysDelay(
+ ULONG Timeout
+ );
+
+NTSTATUS
+PscrRegisterWithSmcLib(
+ PDEVICE_EXTENSION DeviceExtension
+ );
+
+WDFSTRING
+PscrGetRegistryValue(
+ _In_ WDFDEVICE Device,
+ _In_ LPCWSTR Name
+ );
+
+PCHAR
+GetIoctlName(
+ ULONG IoControlCode
+ );
+
+#endif // __PSCR_NT_DRV_H__
diff --git a/smartcrd/pscr/pscrrdwr.c b/smartcrd/pscr/pscrrdwr.c
new file mode 100644
index 00000000..82ebb03d
--- /dev/null
+++ b/smartcrd/pscr/pscrrdwr.c
@@ -0,0 +1,509 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrRdWr.c
+
+Abstract:
+
+ Hardware access functions for SCM PSCR smartcard reader
+
+Author:
+
+ Andreas Straub
+
+Environment:
+
+ Win 95 Sys... calls are resolved by Pscr95Wrap.asm functions and
+ Pscr95Wrap.h macros, resp.
+
+ NT 4.0 Sys... functions resolved by PscrNTWrap.c functions and
+ PscrNTWrap.h macros, resp.
+
+Notes:
+
+ The file pscrrdwr.c was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+ Andreas Straub 7/16/1997 1.00 Initial Version
+ Klaus Schuetz 9/20/1997 1.01 Timing changed
+ Andreas Straub 9/24/1997 1.02 Low Level error handling,
+ minor bugfixes, clanup
+
+--*/
+
+#include <PscrNT.h>
+#include <PscrCmd.h>
+#include <PscrRdWr.h>
+
+#pragma optimize( "", off )
+VOID
+PscrFlushInterface( PREADER_EXTENSION ReaderExtension )
+/*++
+
+PscrFlushInterface:
+ Read & discard data from the pcmcia interface
+
+Arguments:
+ ReaderExtension context of call
+
+Return Value:
+ void
+
+--*/
+{
+ UCHAR Status;
+ ULONG Length;
+ PPSCR_REGISTERS IOBase;
+
+ IOBase = ReaderExtension->IOBase;
+
+ Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
+ if (( Status & PSCR_DATA_AVAIL_BIT ) && ( Status & PSCR_FREE_BIT )) {
+
+ // take control over
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
+
+ // get number of available bytes
+ Length = ((ULONG)READ_PORT_UCHAR( &IOBase->SizeMSReg )) << 8;
+ Length |= READ_PORT_UCHAR( &IOBase->SizeLSReg );
+
+ // perform a dummy read
+ while ( Length-- ) {
+ READ_PORT_UCHAR( &IOBase->DataReg );
+ }
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
+ }
+ return;
+}
+
+
+NTSTATUS
+PscrRead(
+ _In_ PREADER_EXTENSION ReaderExtension, // context of call
+ _Out_writes_bytes_(DataLen) PUCHAR pData, // ptr to data buffer
+ _In_ ULONG DataLen, // length of data
+ _Out_ PULONG pNBytes // number of bytes read
+ )
+/*++
+PscrRead:
+ wait until data available & transfer data from reader to host
+
+Arguments:
+ ReaderExtension context of call
+ pData ptr to data buffer
+ DataLen length of data buffer
+ pNBytes number of bytes returned
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL
+ STATUS_UNSUCCESSFUL
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
+ ULONG NBytes = 0;
+
+ NTStatus = PscrReadDirect(
+ ReaderExtension,
+ pData,
+ DataLen,
+ &NBytes
+ );
+
+ if( NTStatus == STATUS_SUCCESS )
+ {
+ // error check
+ if( pData[ NBytes - 1 ] !=
+ PscrCalculateLRC( pData, (USHORT)( NBytes-1 )))
+ {
+ NTStatus = STATUS_CRC_ERROR;
+ }
+ else
+ {
+ USHORT ReaderStatus;
+ //
+ // Evaluation of reader errors. A reader error is indicated
+ // if the T1 length is 2 and the Nad indicates that this
+ // packet came from the reader
+ //
+ if( ( ( pData[ PSCR_NAD ] & 0x0F ) == 0x01 ) &&
+ ( pData[ PSCR_LEN ] == 0x02 )
+ )
+ {
+ ReaderStatus = (( USHORT ) pData[3] ) << 8;
+ ReaderStatus |= (( USHORT ) pData[4] );
+
+ if( ( ReaderStatus != 0x9000 ) &&
+ ( ReaderStatus != 0x9001 )
+ )
+ {
+ NBytes = 0;
+
+ if( ReaderStatus == PSCR_SW_PROTOCOL_ERROR )
+ {
+ NTStatus = STATUS_IO_TIMEOUT;
+ }
+ else if( ReaderStatus == PSCR_SW_NO_ICC )
+ {
+ NTStatus = STATUS_NO_MEDIA;
+ }
+ else
+ {
+ NTStatus = STATUS_UNSUCCESSFUL;
+ }
+ }
+ }
+
+ // check freeze data
+ if( ( NBytes == 9 ) &&
+ ( pData[ PSCR_NAD ] == 0x21 ) &&
+ ( pData[ PSCR_INF ] == TAG_FREEZE_EVENTS ))
+ {
+ UCHAR CardState;
+
+ CardState = pData[PSCR_INF + 2] == DEVICE_ICC1 ?
+ PSCR_ICC_PRESENT : PSCR_ICC_ABSENT;
+
+ if( ( ReaderExtension->CompletionRoutine != NULL ) &&
+ ( ReaderExtension->TrackingContext != NULL ))
+ {
+
+ // Freeze Data read
+ ReaderExtension->RequestInterrupt = FALSE; // set in DPC/reset here
+
+ (ReaderExtension->CompletionRoutine)(
+ ReaderExtension->TrackingContext,
+ CardState,
+ FALSE
+ );
+ }
+ NBytes = 0;
+
+ if( CardState == PSCR_ICC_ABSENT )
+ {
+ NTStatus = STATUS_NO_MEDIA;
+ }
+ }
+ }
+ }
+
+ // write number of bytes received
+ *pNBytes = NBytes;
+
+ if( NBytes )
+ {
+ NTStatus = STATUS_SUCCESS;
+ }
+
+ return ( NTStatus );
+}
+
+
+NTSTATUS
+PscrReadDirect(
+ PREADER_EXTENSION ReaderExtension,
+ _Out_writes_bytes_(DataLen) PUCHAR pData,
+ ULONG DataLen,
+ PULONG pNBytes
+ )
+/*++
+PscrReadDirect:
+ wait until data available & transfer data from reader to host
+
+Arguments:
+ ReaderExtension context of call
+ pData ptr to data buffer
+ DataLen length of data buffer
+ pNBytes number of bytes returned
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL
+ STATUS_UNSUCCESSFUL
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
+ PPSCR_REGISTERS IOBase;
+ USHORT InDataLen;
+ ULONG Idx;
+
+ IOBase = ReaderExtension->IOBase;
+
+ // wait until interface is ready to transfer
+ InDataLen = 0;
+
+ if( NT_SUCCESS( NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT | PSCR_FREE_BIT )))
+ {
+
+ // take control over
+
+ SysDelay( DELAY_PSCR_WAIT );
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
+ SysDelay( DELAY_PSCR_WAIT );
+
+ // get number of available bytes
+ InDataLen = ( READ_PORT_UCHAR( &IOBase->SizeMSReg ) << 8 );
+ InDataLen |= READ_PORT_UCHAR( &IOBase->SizeLSReg );
+
+ // check buffer size. if buffer to small, the data will be discarded
+ if( ( ULONG )InDataLen <= DataLen )
+ {
+ // read data
+ for (Idx = 0; Idx < InDataLen; Idx++) {
+
+ pData[ Idx ] = READ_PORT_UCHAR( &IOBase->DataReg );
+ if(( READ_PORT_UCHAR( &IOBase->CmdStatusReg )) == 0x02 )
+ {
+ Idx++;
+ break;
+ }
+
+ }
+
+ if( Idx < ( ULONG )InDataLen )
+ {
+ if(( InDataLen - Idx ) == 1 )
+ {
+ pData[ Idx ] = PscrCalculateLRC( pData, ( USHORT ) Idx );
+ }
+ else
+ {
+ InDataLen = 0;
+ NTStatus = STATUS_UNSUCCESSFUL;
+ }
+ }
+ }
+ else
+ {
+ // flush interface in case of wrong buffer size
+ do
+ {
+ READ_PORT_UCHAR( &IOBase->DataReg );
+ } while( --InDataLen );
+ NTStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ // clean up
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
+
+ }
+
+ ReaderExtension->RequestPending = FALSE;
+
+ // write number of bytes received
+ if( InDataLen )
+ {
+ if( pNBytes != NULL )
+ {
+ ( *pNBytes ) = ( ULONG ) InDataLen;
+ }
+ NTStatus = STATUS_SUCCESS;
+ }
+ return ( NTStatus );
+}
+
+NTSTATUS
+PscrWrite(
+ PREADER_EXTENSION ReaderExtension,
+ PUCHAR pData,
+ ULONG DataLen,
+ PULONG pNBytes
+ )
+/*++
+PscrWrite:
+ calculates the LRC of the buffer & sends command to the reader
+
+Arguments:
+ ReaderExtension context of call
+ pData ptr to data buffer
+ DataLen length of data buffer (exclusive LRC!)
+ pNBytes number of bytes written
+
+Return Value:
+ return value of PscrWriteDirect
+
+--*/
+{
+ NTSTATUS NTStatus;
+
+ // Add the EDC field to the end of the data
+ pData[ DataLen ] = PscrCalculateLRC( pData, ( USHORT ) DataLen );
+
+ // Send buffer
+ NTStatus = PscrWriteDirect(
+ ReaderExtension,
+ pData,
+ DataLen + PSCR_EPILOGUE_LENGTH,
+ pNBytes
+ );
+
+ return( NTStatus );
+}
+
+NTSTATUS
+PscrWriteDirect(
+ PREADER_EXTENSION ReaderExtension,
+ PUCHAR pData,
+ ULONG DataLen,
+ PULONG pNBytes
+ )
+
+/*++
+PscrWriteDirect:
+ sends command to the reader. The LRC / CRC must be calculated by caller!
+
+Arguments:
+ ReaderExtension context of call
+ pData ptr to data buffer
+ DataLen length of data buffer (exclusive LRC!)
+ pNBytes number of bytes written
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_DEVICE_BUSY
+
+--*/
+{
+ NTSTATUS NTStatus = STATUS_SUCCESS;
+ UCHAR Status;
+ PPSCR_REGISTERS IOBase;
+
+ IOBase = ReaderExtension->IOBase;
+
+ // in case of card change, there may be data available
+ Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
+ if ( Status & PSCR_DATA_AVAIL_BIT ) {
+ NTStatus = STATUS_DEVICE_BUSY;
+
+ } else {
+ //
+ // wait until reader is ready
+ //
+ ReaderExtension->RequestPending = TRUE;
+
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
+ NTStatus = PscrWait( ReaderExtension, PSCR_FREE_BIT );
+
+ if ( NT_SUCCESS( NTStatus )) {
+ ULONG Idx;
+
+ // take control over
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
+
+ // write the buffer size
+ WRITE_PORT_UCHAR( &IOBase->SizeMSReg, ( UCHAR )( DataLen >> 8 ));
+ SysDelay( DELAY_WRITE_PSCR_REG );
+ WRITE_PORT_UCHAR( &IOBase->SizeLSReg, ( UCHAR )( DataLen & 0x00FF ));
+ SysDelay( DELAY_WRITE_PSCR_REG );
+
+ // write data
+ for (Idx = 0; Idx < DataLen; Idx++) {
+
+ WRITE_PORT_UCHAR( &IOBase->DataReg, pData[ Idx ] );
+ }
+
+ if ( pNBytes != NULL ) {
+ *pNBytes = DataLen;
+ }
+ }
+
+ // clean up
+ WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
+ }
+
+ return( NTStatus );
+}
+
+UCHAR
+PscrCalculateLRC(
+ PUCHAR pData,
+ USHORT DataLen
+ )
+/*++
+
+PscrCalculateLRC:
+ calculates the XOR LRC of a buffer.
+
+Arguments:
+ pData ptr to data buffer
+ DataLen length of range
+
+Return Value:
+ LRC
+
+--*/
+{
+ UCHAR Lrc;
+ USHORT Idx;
+
+ //
+ // Calculate LRC by XORing all the bytes.
+ //
+ Lrc = pData[ 0 ];
+ for ( Idx = 1 ; Idx < DataLen; Idx++ ) {
+ Lrc ^= pData[ Idx ];
+ }
+ return( Lrc );
+}
+
+NTSTATUS
+PscrWait(
+ PREADER_EXTENSION ReaderExtension,
+ UCHAR Mask
+ )
+/*++
+PscrWait:
+ Test the status port of the reader until ALL bits in the mask are set.
+ The maximum of time until DEVICE_BUSY is returned is approx.
+ MaxRetries * DELAY_PSCR_WAIT if MaxRetries != 0.
+ If MaxRetries = 0 the driver waits until the requested status is reported or the
+ user defines a timeout.
+
+Arguments:
+ ReaderExtension context of call
+ Mask mask of bits to test the status register
+
+Return Value:
+ STATUS_SUCCESS
+ STATUS_DEVICE_BUSY
+
+--*/
+{
+ NTSTATUS NTStatus;
+ PPSCR_REGISTERS IOBase;
+ ULONG Retries;
+
+ IOBase = ReaderExtension->IOBase;
+ NTStatus = STATUS_DEVICE_BUSY;
+
+ // wait until condition fulfilled or specified timeout expired
+ for ( Retries = 0; Retries < ReaderExtension->MaxRetries; Retries++) {
+
+ if (( (READ_PORT_UCHAR( &IOBase->CmdStatusReg )) == 0x01) &&
+ ReaderExtension->InvalidStatus) {
+ NTStatus = STATUS_CANCELLED;
+ break;
+ }
+
+ // test requested bits
+ if (( (READ_PORT_UCHAR( &IOBase->CmdStatusReg )) & Mask ) == Mask ) {
+ NTStatus = STATUS_SUCCESS;
+ break;
+ }
+ SysDelay( DELAY_PSCR_WAIT );
+ }
+
+ (void) READ_PORT_UCHAR( &IOBase->CmdStatusReg );
+
+ return NTStatus;
+}
+
+#pragma optimize( "", on )
+
+
diff --git a/smartcrd/pscr/pscrrdwr.h b/smartcrd/pscr/pscrrdwr.h
new file mode 100644
index 00000000..4a1a2bff
--- /dev/null
+++ b/smartcrd/pscr/pscrrdwr.h
@@ -0,0 +1,366 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrRdWr.h
+
+Abstract:
+
+ Constants & access function prototypes for SCM PSCR smartcard reader
+
+Author:
+
+ Andreas Straub
+
+Notes:
+
+ The file pscrrdwr.h was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+ Andreas Straub 7/16/1997 Initial Version
+
+--*/
+
+#if !defined( __PSCR_RDWR_H__ )
+#define __PSCR_RDWR_H__
+
+#pragma pack( 1 )
+//
+// The usage of the PSCR_REGISTERS struct is a little bit tricky:
+// We set the address of that stucture to the IO Base Port, then
+// the other reg's can accessed by their address.
+// p.E. &PscrRegs = 0x320 --> &PscrRegs->CmdStatusReg = 0x321...
+//
+typedef struct _PSCR_REGISTERS {
+
+ UCHAR DataReg;
+ UCHAR CmdStatusReg;
+ UCHAR SizeLSReg;
+ UCHAR SizeMSReg;
+
+ } PSCR_REGISTERS, *PPSCR_REGISTERS;
+
+#define SIZEOF_PSCR_REGISTERS ( sizeof( PSCR_REGISTERS )
+
+#pragma pack()
+
+
+typedef enum _READER_POWER_STATE {
+ PowerReaderUnspecified = 0,
+ PowerReaderWorking,
+ PowerReaderOff
+} READER_POWER_STATE, *PREADER_POWER_STATE;
+
+typedef void ( *PTRACKING_COMPLETION )( PVOID TrackingContext, UCHAR Status, BOOLEAN Wakeup );
+
+#define MAX_DATARATES 4
+
+typedef struct _READER_EXTENSION {
+
+ // I/O address where the reader is configured.
+ PPSCR_REGISTERS IOBase;
+ ULONG IOWindow;
+ ULONG MaxIFSD;
+
+ // IRQ assigned by the system
+ ULONG CurrentIRQ;
+
+ //
+ // limit for read timeout. the absolute timeout limit is
+ // MaxRetries * DELAY_PSCR_WAIT
+ //
+
+ ULONG MaxRetries;
+
+ // Source/Destination byte always used by the PCMCIA (PC Card) reader.
+ UCHAR Device;
+
+ // Software revision ID of the SwapSmart firmware.
+ UCHAR FirmwareMajor, FirmwareMinor, UpdateKey;
+
+ //
+ // Interrupt status; the flag is raised if an freeze event was detected
+ // and cleared if the interface was cleared (int service routine or
+ // PscrRead)
+ //
+ BOOLEAN FreezePending;
+
+ //
+ // Selected file in the reader file system; the flag is raised if the
+ // ICC1 status file was selected & is cleared if any generic ioctl was
+ // issued (in this case another file may be selected)
+ //
+ BOOLEAN StatusFileSelected;
+
+ // used to cancel a read request
+ BOOLEAN RequestPending;
+ // set TRUE if an interrupt is sending, but the reader is busy
+ BOOLEAN RequestInterrupt;
+
+ BOOLEAN InvalidStatus;
+
+ BOOLEAN CardPresent;
+
+ // Current reader power state.
+ READER_POWER_STATE ReaderPowerState;
+
+ PTRACKING_COMPLETION CompletionRoutine;
+
+ PVOID TrackingContext;
+
+ ULONG dataRatesSupported[MAX_DATARATES];
+
+} READER_EXTENSION, *PREADER_EXTENSION;
+
+#define SIZEOF_READER_EXTENSION ( sizeof( READER_EXTENSION ))
+
+//
+// Constants -----------------------------------------------------------------
+//
+#define PSCR_ID_STRING "SCM SwapSmart 2."
+
+#define TLV_BUFFER_SIZE 0x20
+#define ATR_SIZE 0x40 // TS + 32 + SW + PROLOGUE + EPILOGUE...
+
+#define PSCR_MAX_RETRIES 1000
+
+#define CLEAR_BIT 0x00
+
+#define DEFAULT_WAIT_TIME 0x01
+
+#define PSCR_PROLOGUE_LENGTH 0x03
+#define PSCR_EXT_PROLOGUE_LENGTH 0x05
+#define PSCR_STATUS_LENGTH 0x02
+
+#define PSCR_LRC_LENGTH 0x01
+#define PSCR_CRC_LENGTH 0x02
+
+#define PSCR_EPILOGUE_LENGTH PSCR_LRC_LENGTH
+
+#define PCB_DEFAULT 0x00
+
+#define MAX_T1_BLOCK_SIZE 270
+//
+// data buffer idx
+//
+#define PSCR_NAD 0x00
+#define PSCR_PCB 0x01
+#define PSCR_LEN 0x02
+#define PSCR_INF 0x03
+#define PSCR_APDU PSCR_INF
+//
+// device identifier for reset, deactivate
+//
+#define DEVICE_READER 0x00
+#define DEVICE_ICC1 0x01
+#define DEVICE_ICC2 0x02
+//
+// NAD's
+//
+#define NAD_TO_ICC1 0x02
+#define NAD_TO_ICC2 0x42
+#define NAD_TO_PSCR 0x12
+#define REMOTE_NAD_TO_ICC1 0x03
+#define REMOTE_NAD_TO_ICC2 0x43
+#define REMOTE_NAD_TO_PSCR 0x13
+//
+// PSCR Commands
+//
+#define CLA_SET_INTERFACE_PARAM 0x80
+#define CLA_FREEZE 0x80
+#define CLA_RESET 0x20
+#define CLA_DEACTIVATE 0x20
+#define CLA_SELECT_FILE 0x00
+#define CLA_READ_BINARY 0x00
+#define CLA_WRITE_BINARY 0x00
+#define CLA_VERIFY 0x00
+#define CLA_WARM_RESET 0x20
+#define CLA_SOFTWARE_UPDATE 0x80
+#define CLA_SET_MODE 0x80
+
+#define INS_SET_INTERFACE_PARAM 0x60
+#define INS_FREEZE 0x70
+#define INS_RESET 0x10
+#define INS_DEACTIVATE 0x14
+#define INS_SELECT_FILE 0xA4
+#define INS_READ_BINARY 0xB0
+#define INS_WRITE_BINARY 0xD0
+#define INS_VERIFY 0x20
+#define INS_WARM_RESET 0x1F
+#define INS_SOFTWARE_UPDATE 0xFF
+#define INS_SET_MODE 0x61
+
+//
+// Status Read Only Register
+//
+#define PSCR_DATA_AVAIL_BIT 0x80
+#define PSCR_FREE_BIT 0x40
+#define PSCR_WRITE_ERROR_BIT 0x02
+#define PSCR_READ_ERROR_BIT 0x01
+//
+// Command Write Only Register...
+//
+#define PSCR_RESET_BIT 0x08
+#define PSCR_SIZE_READ_BIT 0x04
+#define PSCR_SIZE_WRITE_BIT 0x02
+#define PSCR_HOST_CONTROL_BIT 0x01
+//
+// Tags...
+//
+#define TAG_MODULE 0x02
+#define TAG_MEMORY_SIZE 0x03
+#define TAG_UPDATE_KEY 0x08
+#define TAG_SOFTWARE_REV 0x0F
+#define TAG_BLOCK_COMP_OPTION 0x13
+#define TAG_READER_MECH_OPTIONS 0x20
+#define TAG_READER_STATUS 0x21
+#define TAG_ICC_PROTOCOLS 0x22
+#define TAG_BI 0x23
+#define TAG_FI 0x24
+#define TAG_PTS_PARAM 0x25
+#define TAG_PROTOCOL_STATUS 0x26
+#define TAG_SET_NULL_BYTES 0x2d
+#define TAG_FREEZE_EVENTS 0x30
+#define TAG_BIT_LENGTH 0x40
+#define TAG_CGT 0x41
+#define TAG_BWT 0x42
+#define TAG_CWT 0x43
+#define TAG_PROTOCOL_PARAM 0x44
+//
+// card power definitions ( Tag 0x21 )
+//
+#define PSCR_ICC_ABSENT 0x00
+#define PSCR_ICC_PRESENT 0x01
+#define PSCR_ICC_POWERED 0x02
+#define PSCR_ICC_IN_TRANSP_MODE 0xA0
+#define PSCR_ICC_UNKNOWN 0xFF
+//
+// protocol definitions ( Tag 0x22 )
+//
+#define PSCR_PROTOCOL_UNDEFINED 0x00
+#define PSCR_PROTOCOL_T0 0x01
+#define PSCR_PROTOCOL_T1 0x02
+#define PSCR_PROTOCOL_T14 0x03
+#define PSCR_PROTOCOL_I2C 0x80
+#define PSCR_PROTOCOL_3WIRE 0x81
+#define PSCR_PROTOCOL_2WIRE 0x81
+
+#define WTX_REQUEST 0xC3
+#define WTX_REPLY 0xE3
+//
+// File ID's
+//
+#define FILE_MASTER 0x3F00
+#define FILE_PSCR_CONFIG 0x0020
+#define FILE_PSCR_DIR 0x7F60
+#define FILE_PSCR_DIR_CONFIG 0x6020
+#define FILE_PSCR_DIR_STATUS 0x6021
+#define FILE_PSCR_DIR_FREEZE_CONFIG 0x6030
+#define FILE_PSCR_DIR_FREEZE_STATUS 0x6031
+#define FILE_ICC1_DIR 0x7F70
+#define FILE_ICC1_DIR_CONFIG 0x7020
+#define FILE_ICC1_DIR_STATUS 0x7021
+#define FILE_ICC2_DIR_CONFIG 0x7120
+#define FILE_ICC2_DIR_STATUS 0x7121
+//
+// Status Word Definitions
+//
+#define PSCR_SW_COMMAND_FAIL 0x6985
+#define PSCR_SW_INVALID_PARAM 0x6A80
+#define PSCR_SW_INCONSISTENT_DATA 0x6A85
+#define PSCR_SW_NO_PROTOCOL_SUPPORT 0x62A3
+#define PSCR_SW_SYNC_ATR_SUCCESS 0x9000
+#define PSCR_SW_ASYNC_ATR_SUCCESS 0x9001
+#define PSCR_SW_NO_PROTOCOL 0x62A5
+#define PSCR_SW_NO_ATR 0x62A6
+#define PSCR_SW_NO_ATR_OR_PROTOCOL 0x62A7
+#define PSCR_SW_NO_ICC 0x64A1
+#define PSCR_SW_ICC_NOT_ACTIVE 0x64A2
+#define PSCR_SW_NON_SUPPORTED_PROTOCOL 0x64A3
+#define PSCR_SW_PROTOCOL_ERROR 0x64A8
+#define PSCR_SW_NO_ATR_OR_PROTOCOL2 0x64A7
+#define PSCR_SW_FILE_NOT_FOUND 0x6A82
+#define PSCR_SW_FILE_NO_ACCEPPTED_AUTH 0x6982
+#define PSCR_SW_FILE_NO_ACCESS 0x6985
+#define PSCR_SW_FILE_BAD_OFFSET 0x6B00
+#define PSCR_SW_END_OF_FILE_READ 0x6282
+#define PSCR_SW_END_OF_FILE_WRITE 0x6301
+#define PSCR_SW_WRITE_FILE_FAIL 0x6500
+#define PSCR_SW_NO_PASSWORD 0x6200
+#define PSCR_SW_WRONG_PASSWORD 0x6300
+#define PSCR_SW_VERIFY_COUNTER_FAIL 0x6983
+#define PSCR_SW_NO_REF_DATA 0x6A88
+#define PSCR_SW_FLASH_MEM_ERROR 0x6481
+#define PSCR_SW_FLASH_MEM_ERR2 0x6581
+#define PSCR_SW_WRONG_LENGTH 0x6700
+#define PSCR_SW_UNKNOWN_ICC_ERROR 0x64A0
+#define PSCR_SW_UNKNOWN_PROTOCOL_ERROR 0x64A9
+#define PSCR_SW_NO_PROTOCOL_SELECTED 0x64A5
+#define PSCR_SW_PTS_PROTOCOL_ERROR 0x64AA
+#define PSCR_SW_WTX_ERROR 0x64AB
+#define PSCR_SW_WTX_ERR2 0x65AB
+#define PSCR_SW_INVALID_SOURCE_ADDR 0x6F82
+
+//
+// Prototypes for access functions -------------------------------------------
+//
+
+
+VOID
+PscrFlushInterface(
+ PREADER_EXTENSION ReaderExtension // context of call
+ );
+
+NTSTATUS
+PscrRead(
+ _In_ PREADER_EXTENSION ReaderExtension, // context of call
+ _Out_writes_bytes_(DataLen) PUCHAR pData, // ptr to data buffer
+ _In_ ULONG DataLen, // length of data
+ _Out_ PULONG pNBytes // number of bytes read
+ );
+
+NTSTATUS
+PscrReadDirect(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ _Out_writes_bytes_(DataLen) PUCHAR pData, // ptr to data buffer
+ ULONG DataLen, // length of data
+ PULONG pNBytes // number of bytes read
+ );
+
+NTSTATUS
+PscrWrite(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ PUCHAR pData, // ptr to data buffer
+ ULONG DataLength, // length of data
+ PULONG pNBytes // number of bytes written
+ );
+
+NTSTATUS
+PscrWriteDirect(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ PUCHAR pData, // ptr to data buffer
+ ULONG DataLength, // length of data
+ PULONG pNBytes // number of bytes written
+ );
+
+UCHAR
+PscrCalculateLRC(
+ PUCHAR pData, // ptr to data buffer
+ USHORT DataLength // length of data
+ );
+
+NTSTATUS
+PscrWait(
+ PREADER_EXTENSION ReaderExtension, // context of call
+ UCHAR Mask // mask of requested bits
+ );
+
+#endif // __PSCR_RDWR_H__
+
+// ------------------------------- END OF FILE -------------------------------
+
+
diff --git a/smartcrd/pscr/pscrvers.h b/smartcrd/pscr/pscrvers.h
new file mode 100644
index 00000000..0ee8b0a8
--- /dev/null
+++ b/smartcrd/pscr/pscrvers.h
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
+
+Module Name:
+
+ PscrVers.h
+
+Abstract:
+
+ header file for version information
+
+Author:
+
+ Andreas Straub
+
+Environment:
+
+ Win 95, Win NT
+
+Notes:
+
+ The file pscrvers.h was reviewed by LCA in June 2011 and per license is
+ acceptable for Microsoft use under Dealpoint ID 178449.
+
+Revision History:
+
+--*/
+#if !defined( __PSCRVERS_H__ )
+#define __PSCRVERS_H__
+
+#define PSCR_VERSION_STR "1.26"
+#define PSCR_MAJOR_VERSION 1
+#define PSCR_MINOR_VERSION 26
+
+#define PSCR_NAME "PSCR"
+#define PSCR_PRODUCT_NAME "PSCR SmartCard Reader"
+#define PSCR_VENDOR_NAME "PSCR"
+#define PSCR_IFD_TYPE "PCMCIA Reader"
+#define PSCR_VXD_NAME "PSCR.VXD"
+#define PSCR_DEVICE_NAME "PSCR_0"
+
+#endif // __PSCRVERS_H__