diff --git a/.gitignore b/.gitignore
index 314e6954e1e..732ceba80ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,7 +59,6 @@ artifacts/
StyleCopReport.xml
# Files built by Visual Studio
-*_i.c
*_p.c
*_i.h
*.ilk
diff --git a/Microsoft.Dotnet.Wpf.sln b/Microsoft.Dotnet.Wpf.sln
index ce33ffb5fc1..b37679fab27 100644
--- a/Microsoft.Dotnet.Wpf.sln
+++ b/Microsoft.Dotnet.Wpf.sln
@@ -159,6 +159,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsFormsIntegration-ref
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PresentationUI-ref", "src\Microsoft.DotNet.Wpf\src\PresentationUI\ref\PresentationUI-ref.csproj", "{C79A5A35-2470-46C0-A2B6-BA0633A80420}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "redist", "redist", "{DDED00A7-24FD-4AEF-B264-2150F0E59B4D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3DCompiler", "src\Microsoft.DotNet.Wpf\redist\D3DCompiler\D3DCompiler.vcxproj", "{60E8E057-79E1-4860-A015-23C9587434F7}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCRuntime", "src\Microsoft.DotNet.Wpf\redist\VCRuntime\VCRuntime.vcxproj", "{B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unmanaged", "Unmanaged", "{4557C5C6-10B1-475C-8279-5511955D1C29}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Managed", "Managed", "{2EE4A2DA-70B3-4767-9D18-618DA0FE3105}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabLib", "src\Microsoft.DotNet.Wpf\src\PenImc\tablib\TabLib.vcxproj", "{8F91EB3A-C530-4CEA-90BF-AFC8165B6456}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PenImc", "PenImc", "{956D1AA8-9E02-49CA-A496-689D7024D444}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PenImc", "src\Microsoft.DotNet.Wpf\src\PenImc\dll\PenImc.vcxproj", "{8383C663-E8D0-4D2D-B65A-FE4A253E3319}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -925,24 +941,97 @@ Global
{C79A5A35-2470-46C0-A2B6-BA0633A80420}.Release|x64.Build.0 = Release|x64
{C79A5A35-2470-46C0-A2B6-BA0633A80420}.Release|x86.ActiveCfg = Release|Any CPU
{C79A5A35-2470-46C0-A2B6-BA0633A80420}.Release|x86.Build.0 = Release|Any CPU
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|Any CPU.Build.0 = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x64.ActiveCfg = Debug|x64
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x64.Build.0 = Debug|x64
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x86.ActiveCfg = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x86.Build.0 = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x86.Deploy.0 = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|Any CPU.ActiveCfg = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|Any CPU.Build.0 = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|Any CPU.Deploy.0 = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x64.ActiveCfg = Release|x64
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x64.Build.0 = Release|x64
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x86.ActiveCfg = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x86.Build.0 = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x86.Deploy.0 = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|Any CPU.Build.0 = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x64.ActiveCfg = Debug|x64
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x64.Build.0 = Debug|x64
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x86.ActiveCfg = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x86.Build.0 = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x86.Deploy.0 = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|Any CPU.ActiveCfg = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|Any CPU.Build.0 = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|Any CPU.Deploy.0 = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x64.ActiveCfg = Release|x64
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x64.Build.0 = Release|x64
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x86.ActiveCfg = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x86.Build.0 = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x86.Deploy.0 = Release|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|Any CPU.Build.0 = Debug|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x64.ActiveCfg = Debug|x64
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x64.Build.0 = Debug|x64
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x86.ActiveCfg = Debug|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x86.Build.0 = Debug|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x86.Deploy.0 = Debug|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|Any CPU.ActiveCfg = Release|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|Any CPU.Build.0 = Release|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|Any CPU.Deploy.0 = Release|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x64.ActiveCfg = Release|x64
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x64.Build.0 = Release|x64
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x86.ActiveCfg = Release|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x86.Build.0 = Release|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x86.Deploy.0 = Release|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|Any CPU.Build.0 = Debug|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x64.ActiveCfg = Debug|x64
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x64.Build.0 = Debug|x64
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x86.ActiveCfg = Debug|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x86.Build.0 = Debug|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x86.Deploy.0 = Debug|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|Any CPU.ActiveCfg = Release|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|Any CPU.Build.0 = Release|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|Any CPU.Deploy.0 = Release|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x64.ActiveCfg = Release|x64
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x64.Build.0 = Release|x64
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x86.ActiveCfg = Release|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x86.Build.0 = Release|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x86.Deploy.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
+ {9AC36357-34B7-40A1-95CA-FE9F46D089A7} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
{BF20132A-191F-4D34-9A1B-831772A6DFCF} = {0159B0F1-0626-4BED-8D1B-CBFF4F12C369}
{C847934A-828C-4EBB-A004-B0E97C8313F4} = {BF20132A-191F-4D34-9A1B-831772A6DFCF}
{9A7E395B-E859-40E2-809D-EFB72CF3A2EE} = {BF20132A-191F-4D34-9A1B-831772A6DFCF}
{8A2ABE39-2D50-48CA-AC32-078BBA32757A} = {0159B0F1-0626-4BED-8D1B-CBFF4F12C369}
{B73BB4AB-68DE-4B91-BBB0-AB4F2D504AC3} = {8A2ABE39-2D50-48CA-AC32-078BBA32757A}
{BFF6C118-3369-43B5-ACA6-D65ED00EEBE0} = {22D643D8-87D6-4FE8-9632-58A3CD3DC7CB}
+ {4216C2EA-E2B9-4FB2-9803-F73FDC64CAC4} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
{1D4C8AD7-12E7-4987-98AF-AEE79F53E494} = {0159B0F1-0626-4BED-8D1B-CBFF4F12C369}
{440D06B8-E3DE-4C0D-AD25-CD4F43D836E1} = {1D4C8AD7-12E7-4987-98AF-AEE79F53E494}
{22D643D8-87D6-4FE8-9632-58A3CD3DC7CB} = {0159B0F1-0626-4BED-8D1B-CBFF4F12C369}
+ {FA69991B-9696-42D0-A5C7-F5E73F0DEE9E} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {50A5318F-3B9A-48B9-9615-D5FA9D6D9C3E} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {74C63A45-EAE5-407A-9F89-E0C6BC604841} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {B0C1157E-8664-44C4-AD8E-35CD6A78C769} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {4572CF94-B209-4479-85AB-59CA87BF5AFA} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
{2DD6F2F8-DFF4-4EE1-9D48-0FD692DB084D} = {4572CF94-B209-4479-85AB-59CA87BF5AFA}
{D242FDF9-F132-4154-BB9F-3F85C39F6F4C} = {4572CF94-B209-4479-85AB-59CA87BF5AFA}
{4C99DEEE-ED7A-4225-8127-3B1E6EDB39D0} = {4572CF94-B209-4479-85AB-59CA87BF5AFA}
{152C4B33-3B53-4180-B8BC-7BB0BC91A2ED} = {4572CF94-B209-4479-85AB-59CA87BF5AFA}
+ {B6F41F07-2117-49E0-A2B7-4BC6F586057B} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {17AA6CC2-CAE3-429C-B065-B76B8E14C632} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
{47BC9F30-4DFF-4DEB-BFFE-1EC9735E6965} = {271ED3B3-976D-4253-85F5-E98CC86993D6}
{FC06FD19-DE12-42BF-908E-8391AF63DB7E} = {271ED3B3-976D-4253-85F5-E98CC86993D6}
{3F4CA1F0-0FA6-4191-B29D-1A283D13C55B} = {271ED3B3-976D-4253-85F5-E98CC86993D6}
@@ -971,6 +1060,8 @@ Global
{2B18C965-BE75-4814-876D-8659D4A8A943} = {88264221-65BC-4E7E-8891-D26467BC250C}
{25EDAA5F-CA1E-4792-9CC3-0B4373E9C77F} = {88264221-65BC-4E7E-8891-D26467BC250C}
{A78C427C-F7FE-486A-8777-1701E6E81BE0} = {88264221-65BC-4E7E-8891-D26467BC250C}
+ {88264221-65BC-4E7E-8891-D26467BC250C} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {5ACFB055-649D-4A01-98C2-B0BFE7E543D6} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
{17C69C55-A365-4040-974D-06BB8BB5AF1F} = {5ACFB055-649D-4A01-98C2-B0BFE7E543D6}
{0D089FF4-33B1-4009-B367-A9E5F558A6BE} = {5ACFB055-649D-4A01-98C2-B0BFE7E543D6}
{C966E164-061D-411F-B358-764A80B2F39C} = {5ACFB055-649D-4A01-98C2-B0BFE7E543D6}
@@ -981,13 +1072,23 @@ Global
{419232AF-647C-4B99-A9E6-5F24AA65295A} = {60F4058B-D35B-42D2-B276-D44B3AC579BD}
{97CFC19A-54E3-4F09-AAFD-487ED55359F6} = {60F4058B-D35B-42D2-B276-D44B3AC579BD}
{CD1664AE-A70E-4DE6-A523-FFD6916E337D} = {60F4058B-D35B-42D2-B276-D44B3AC579BD}
+ {3B0404D6-0317-4DF3-95A4-A45B0C421910} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {A65AB368-1C20-4D4B-9A5B-CB3656CA05BC} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
{E0043FA2-FB86-4EFB-87DF-70B4FE10A895} = {D0AED517-9972-41CB-8751-983E4EB8F511}
{DC69B536-1F6E-4A7C-B126-2057E7B03591} = {D0AED517-9972-41CB-8751-983E4EB8F511}
{D224BACC-340B-4986-81D6-C695EB2B5A62} = {60F4058B-D35B-42D2-B276-D44B3AC579BD}
{EA7825C4-0E99-477A-985D-0B5F0421A30A} = {60F4058B-D35B-42D2-B276-D44B3AC579BD}
{598B6188-937C-448B-8E6B-925F000BC076} = {60F4058B-D35B-42D2-B276-D44B3AC579BD}
+ {765E6BBC-772B-4808-BB72-E85615E8F237} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {B8E5B99C-D162-4DCA-9C4F-90CF2CDE942E} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
+ {9F3166CE-7406-4A8F-8B00-705AE57E6D35} = {2EE4A2DA-70B3-4767-9D18-618DA0FE3105}
{61334087-4A73-4F17-984B-56B84D2148DA} = {D0AED517-9972-41CB-8751-983E4EB8F511}
{C79A5A35-2470-46C0-A2B6-BA0633A80420} = {D0AED517-9972-41CB-8751-983E4EB8F511}
+ {60E8E057-79E1-4860-A015-23C9587434F7} = {DDED00A7-24FD-4AEF-B264-2150F0E59B4D}
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA} = {DDED00A7-24FD-4AEF-B264-2150F0E59B4D}
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456} = {956D1AA8-9E02-49CA-A496-689D7024D444}
+ {956D1AA8-9E02-49CA-A496-689D7024D444} = {4557C5C6-10B1-475C-8279-5511955D1C29}
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319} = {956D1AA8-9E02-49CA-A496-689D7024D444}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B4340004-DAC0-497D-B69D-CFA7CD93F567}
diff --git a/src/Microsoft.DotNet.Wpf/redist/D3DCompiler/D3DCompiler.vcxproj b/src/Microsoft.DotNet.Wpf/redist/D3DCompiler/D3DCompiler.vcxproj
new file mode 100644
index 00000000000..ac5e5d2caa6
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/redist/D3DCompiler/D3DCompiler.vcxproj
@@ -0,0 +1,44 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ DynamicLibrary
+ false
+
+
+
+
+
+ $(D3DCompilerDllBaseName)$(D3DCompilerVersion)$(WpfVersionSuffix)
+
+
+
+ $(Windows10SdkPath)Redist\D3D\$(Architecture)\$(D3DCompilerDllBaseName)$(D3DCompilerVersion).dll
+
+
+ 16.0
+ {60E8E057-79E1-4860-A015-23C9587434F7}
+ Win32Proj
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.Wpf/redist/Directory.Build.Props b/src/Microsoft.DotNet.Wpf/redist/Directory.Build.Props
new file mode 100644
index 00000000000..1122b2e3100
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/redist/Directory.Build.Props
@@ -0,0 +1,10 @@
+
+
+
+ true
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/redist/Redist.sln b/src/Microsoft.DotNet.Wpf/redist/Redist.sln
new file mode 100644
index 00000000000..89a601a9210
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/redist/Redist.sln
@@ -0,0 +1,59 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28606.126
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCRuntime", "VCRuntime\VCRuntime.vcxproj", "{B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3DCompiler", "D3DCompiler\D3DCompiler.vcxproj", "{60E8E057-79E1-4860-A015-23C9587434F7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|AnyCPU = Debug|AnyCPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|AnyCPU = Release|AnyCPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|AnyCPU.ActiveCfg = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|AnyCPU.Build.0 = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|AnyCPU.Deploy.0 = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x64.ActiveCfg = Debug|x64
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x64.Build.0 = Debug|x64
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x86.ActiveCfg = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x86.Build.0 = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Debug|x86.Deploy.0 = Debug|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|AnyCPU.ActiveCfg = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|AnyCPU.Build.0 = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|AnyCPU.Deploy.0 = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x64.ActiveCfg = Release|x64
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x64.Build.0 = Release|x64
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x86.ActiveCfg = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x86.Build.0 = Release|Win32
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}.Release|x86.Deploy.0 = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|AnyCPU.ActiveCfg = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|AnyCPU.Build.0 = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|AnyCPU.Deploy.0 = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x64.ActiveCfg = Debug|x64
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x64.Build.0 = Debug|x64
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x86.ActiveCfg = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x86.Build.0 = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Debug|x86.Deploy.0 = Debug|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|AnyCPU.ActiveCfg = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|AnyCPU.Build.0 = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|AnyCPU.Deploy.0 = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x64.ActiveCfg = Release|x64
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x64.Build.0 = Release|x64
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x86.ActiveCfg = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x86.Build.0 = Release|Win32
+ {60E8E057-79E1-4860-A015-23C9587434F7}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {CF85847B-E97C-4020-A8DC-AA3B46E42331}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Microsoft.DotNet.Wpf/redist/VCRuntime/VCRuntime.vcxproj b/src/Microsoft.DotNet.Wpf/redist/VCRuntime/VCRuntime.vcxproj
new file mode 100644
index 00000000000..34229aa58ca
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/redist/VCRuntime/VCRuntime.vcxproj
@@ -0,0 +1,80 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+ DynamicLibrary
+ false
+
+
+
+
+
+
+
+ Microsoft.VC142.CRT
+ Microsoft.VC142.DebugCRT
+
+
+ Microsoft.VC141.CRT
+ Microsoft.VC141.DebugCRT
+
+
+ $(VCRuntimeDllBaseName)$(VCRuntimeVersion)$(LibSuffix)$(WpfVersionSuffix)
+ $(VCRuntimeDllBaseName)$(VCRuntimeVersion)$(LibSuffix)
+
+
+
+
+
+ $(VCInstallDir)Redist\MSVC\$(VCToolsRedistVersion)\
+ $(VCInstallDir)Redist\MSVC\$(VCToolsRedistVersion)\debug_nonredist\
+
+ $(VCRedistRoot)$(Architecture)\$(VCRedistCrtFolderName)\$(VCRuntimeDllBaseName)$(VCRuntimeVersion)$(LibSuffix).dll
+ $(VCRedistRoot)$(Architecture)\$(VCRedistFallbackCrtFolderName)\$(VCRuntimeDllBaseName)$(VCRuntimeVersion)$(LibSuffix).dll
+
+
+
+
+
+ $(OutDir)$(MSVCPDllBaseName)$(MSVCPVersion)$(LibSuffix).dll
+
+
+
+ $(OutDir)$(MSVCPDllBaseName)$(MSVCPVersion)$(LibSuffix).dll
+
+
+
+
+ 16.0
+ {B7399B2E-CE92-42D5-B36A-EBD4C9C4FBDA}
+ Win32Proj
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dir.targets b/src/Microsoft.DotNet.Wpf/src/PenImc/dir.targets
new file mode 100644
index 00000000000..5236e7c6faf
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dir.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComApartmentVerifier.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComApartmentVerifier.cpp
new file mode 100644
index 00000000000..5a754446d3d
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComApartmentVerifier.cpp
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+
+#include "stdafx.h"
+
+#include "ComApartmentVerifier.hpp"
+
+using namespace ComUtils;
+
+ComApartmentVerifier::ComApartmentVerifier()
+ : m_valid(false)
+{
+}
+
+ComApartmentVerifier ComApartmentVerifier::Mta()
+{
+ // MTA is free threaded.
+ return ComApartmentVerifier(APTTYPE::APTTYPE_MTA);
+}
+
+ComApartmentVerifier ComApartmentVerifier::CurrentSta()
+{
+ APTTYPE aptType;
+ APTTYPEQUALIFIER aptQualifier;
+
+ HRESULT hr = CoGetApartmentType(&aptType, &aptQualifier);
+
+ if (hr != S_OK || (aptType != APTTYPE::APTTYPE_STA && aptType != APTTYPE::APTTYPE_MAINSTA))
+ {
+ return ComApartmentVerifier();
+ }
+
+ // For STA, ensure we use the current thread and that the current apartment type matches.
+ // This is so we capture the COM thread/apartment state at creation to use later.
+ return ComApartmentVerifier(aptType, ::GetCurrentThreadId());
+}
+
+HRESULT ComApartmentVerifier::VerifyCurrentApartmentType()
+{
+ HRESULT hr = RPC_E_WRONG_THREAD;
+
+ if (m_valid)
+ {
+ APTTYPE aptType;
+ APTTYPEQUALIFIER aptQualifier;
+
+ HRESULT aptHr = CoGetApartmentType(&aptType, &aptQualifier);
+
+ if (aptHr == S_OK
+ && aptType == m_expectedApartment
+ && (!m_expectedApartmentIsSta || m_expectedStaThreadId == ::GetCurrentThreadId()))
+ {
+ hr = S_OK;
+ }
+ }
+
+ return hr;
+}
+
+
+ComApartmentVerifier::ComApartmentVerifier(APTTYPE aptType) :
+ m_expectedApartment(aptType),
+ m_expectedApartmentIsSta(false),
+ m_expectedStaThreadId(0),
+ m_valid(m_expectedApartment != APTTYPE::APTTYPE_STA && m_expectedApartment != APTTYPE::APTTYPE_MAINSTA)
+{
+ // We only verify STA/MAINSTA via a thread id constructor.
+}
+
+ComApartmentVerifier::ComApartmentVerifier(APTTYPE aptType, DWORD threadId) :
+ m_expectedApartment(aptType),
+ m_expectedApartmentIsSta(true),
+ m_expectedStaThreadId(threadId),
+ m_valid(m_expectedApartment == APTTYPE::APTTYPE_STA || m_expectedApartment == APTTYPE::APTTYPE_MAINSTA)
+{
+ // Don't use a thread id constructor for any other apartment types but STA/MAINSTA.
+}
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComApartmentVerifier.hpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComApartmentVerifier.hpp
new file mode 100644
index 00000000000..4b89a22b374
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComApartmentVerifier.hpp
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+
+#pragma once
+
+#include
+
+namespace ComUtils
+{
+ // DDVSO:514949
+ // This class provides functionality for checking and verifying apartment state.
+ class ComApartmentVerifier
+ {
+ public:
+
+ // Default constructor, sets an invalid state.
+ ComApartmentVerifier();
+
+ // Returns a verifier for MTA
+ static ComApartmentVerifier Mta();
+
+ // Returns a verifier for the current STA.
+ // NOTE: This verifier includes the current thread id in verification.
+ static ComApartmentVerifier CurrentSta();
+
+ // Verifies the current apartment and, if applicable, thread id.
+ HRESULT VerifyCurrentApartmentType();
+
+ private:
+
+ // Constructor for apartment type, free threaded.
+ ComApartmentVerifier(APTTYPE);
+
+ // Constructor for apartment type, specific thread.
+ ComApartmentVerifier(APTTYPE, DWORD);
+
+ // The COM apartment type to expect.
+ APTTYPE m_expectedApartment;
+
+ // If the apartment type is STA.
+ bool m_expectedApartmentIsSta;
+
+ // The id of the thread to expect.
+ DWORD m_expectedStaThreadId;
+
+ // Determines if this is in a valid (non-default constructed, appropriate arguments) state.
+ bool m_valid;
+ };
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComLockableWrapper.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComLockableWrapper.cpp
new file mode 100644
index 00000000000..7e76166c0bd
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComLockableWrapper.cpp
@@ -0,0 +1,87 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+
+#include "stdafx.h"
+
+#include "ComApartmentVerifier.hpp"
+#include "ComLockableWrapper.hpp"
+
+using namespace ComUtils;
+
+ComLockableWrapper::ComLockableWrapper()
+ : m_serverObject(nullptr),
+ m_expectedApartment(ComApartmentVerifier())
+
+{
+}
+
+ComLockableWrapper::ComLockableWrapper(IUnknown *obj, ComApartmentVerifier expectedApartment)
+ : m_serverObject(obj),
+ m_expectedApartment(expectedApartment)
+{
+}
+
+HRESULT ComLockableWrapper::Lock()
+{
+ HRESULT hr = m_expectedApartment.VerifyCurrentApartmentType();
+
+ if (SUCCEEDED(hr))
+ {
+ hr = E_ILLEGAL_METHOD_CALL;
+
+ if (m_serverObject != nullptr)
+ {
+ IUnknown *unk = nullptr;
+ hr = m_serverObject->QueryInterface(IID_IUnknown, reinterpret_cast(&unk));
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CoLockObjectExternal(unk,
+ true, // fLock
+ false); // fLastUnlockReleases - unused
+
+ unk->Release();
+ }
+ }
+ }
+
+ return hr;
+}
+
+HRESULT ComLockableWrapper::Unlock()
+{
+ HRESULT hr = m_expectedApartment.VerifyCurrentApartmentType();
+
+ if (SUCCEEDED(hr))
+ {
+ hr = E_ILLEGAL_METHOD_CALL;
+
+ if (m_serverObject != nullptr)
+ {
+ IUnknown *unk = nullptr;
+ hr = m_serverObject->QueryInterface(IID_IUnknown, reinterpret_cast(&unk));
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CoLockObjectExternal(unk,
+ false, // fLock
+ true); // fLastUnlockReleases
+
+ // The QI AddRefs, so balance it
+ unk->Release();
+
+ // This lock is one shot, do not allow further operations.
+ m_serverObject = nullptr;
+ }
+ }
+ }
+
+ return hr;
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComLockableWrapper.hpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComLockableWrapper.hpp
new file mode 100644
index 00000000000..b16aae55806
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComLockableWrapper.hpp
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+
+#pragma once
+
+#include "ComApartmentVerifier.hpp"
+
+namespace ComUtils
+{
+ // DDVSO:514949
+ // This class provides functionality used for various methods of
+ // working around the COM rundown issues present in the OS (see OSGVSO:10779198).
+ // The purpose is to call CoLockObjectExternal on a server object to ensure that
+ // none of the COM hierarchy of the object is released during rundown.
+ // NOTE:
+ // Unlocking makes this object invalid. The server object is set to nullptr.
+ // Using this after unlocking will not succeed.
+ class ComLockableWrapper
+ {
+ public:
+
+ // Default constructor, wraps a nullptr
+ ComLockableWrapper();
+
+ // Wraps a pointer with specific apartment type
+ // Requires manual locking/unlocking.
+ ComLockableWrapper(IUnknown *obj, ComApartmentVerifier expectedApartment);
+
+ // Attempts to lock the server object via CoLockObjectExternal.
+ // The apartment is verified during this call.
+ HRESULT Lock();
+
+ // Attempts to unlock the server object via CoLockObjectExternal.
+ // The apartment is verified during this call.
+ HRESULT Unlock();
+
+ private:
+
+ IUnknown *m_serverObject;
+ ComApartmentVerifier m_expectedApartment;
+ };
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/GitComLockableWrapper.hpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/GitComLockableWrapper.hpp
new file mode 100644
index 00000000000..18481694fee
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/GitComLockableWrapper.hpp
@@ -0,0 +1,158 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+
+#pragma once
+
+#include "ComLockableWrapper.hpp"
+#include "ComApartmentVerifier.hpp"
+
+namespace ComUtils
+{
+ // DDVSO:514949
+ // This class provides functionality used for various methods of
+ // working around the COM rundown issues present in the OS (see OSGVSO:10779198).
+ // The purpose is to obtain an object from the GIT and then use ComLockableWrapper
+ // to ensure the object obtained survives rundown.
+ // NOTE:
+ // Unlocking makes this object invalid.The GIT pointer is set to nullptr.
+ // Using this after unlocking will not succeed.
+ template
+ class GitComLockableWrapper
+ {
+ public:
+
+ // Default constructor, wraps a nullptr
+ GitComLockableWrapper();
+
+ // COM object constructor.
+ // Inserts the COM object into the GIT and stores the key.
+ GitComLockableWrapper(CComPtr obj, ComApartmentVerifier expectedApartment);
+
+ // GIT key constructor.
+ // Stores the key for later use in other operations.
+ GitComLockableWrapper(DWORD gitKey, ComApartmentVerifier expectedApartment);
+
+ // Attempts to Lock the object by querying it from the GIT
+ // and then using ComLockableWrapper.
+ // Apartment is verified during this call.
+ HRESULT Lock();
+
+ // Attempts to Unlock the object by querying it from the GIT
+ // and then using ComLockableWrapper.
+ // Apartment is verified during this call.
+ HRESULT Unlock();
+
+ // Returns the GIT cookie that refers to this wrapped object in the GIT.
+ DWORD GetCookie() const { return m_gitKey; }
+
+ // Retrieves the wrapped object from the GIT.
+ CComPtr GetComObject();
+
+ // Revokes the wrapped object from the GIT if the cookie is valid.
+ // Otherwise this is a no_op.
+ void RevokeIfValid();
+
+ // Checks the validity of the GIT Cookie.
+ HRESULT CheckCookie() { return (m_gitKey != 0) ? S_OK : E_FAIL; };
+
+ private:
+
+ DWORD m_gitKey;
+ ComApartmentVerifier m_expectedApartment;
+ };
+
+ template
+ GitComLockableWrapper::GitComLockableWrapper()
+ : m_gitKey(0),
+ m_expectedApartment(ComApartmentVerifier())
+ {
+ }
+
+ template
+ GitComLockableWrapper::GitComLockableWrapper(CComPtr obj, ComApartmentVerifier expectedApartment)
+ : m_expectedApartment(expectedApartment)
+ {
+ CComGITPtr git(obj);
+ m_gitKey = git.Detach();
+ }
+
+ template
+ GitComLockableWrapper::GitComLockableWrapper(DWORD gitKey, ComApartmentVerifier expectedApartment)
+ : m_gitKey(gitKey),
+ m_expectedApartment(expectedApartment)
+ {
+ }
+
+ template
+ CComPtr GitComLockableWrapper::GetComObject()
+ {
+ CComPtr result = nullptr;
+
+ if (m_gitKey != 0)
+ {
+ T *instance = nullptr;
+
+ CComGITPtr git(m_gitKey);
+ HRESULT hr = git.CopyTo(&instance);
+ git.Detach();
+
+ if (SUCCEEDED(hr))
+ {
+ result = instance;
+ instance->Release();
+ }
+ }
+
+ return result;
+ }
+
+ template
+ HRESULT GitComLockableWrapper::Lock()
+ {
+ HRESULT hr = E_FAIL;
+
+ CComPtr obj = GetComObject();
+
+ if (obj != nullptr)
+ {
+ ComLockableWrapper wrapper(obj, m_expectedApartment);
+ hr = wrapper.Lock();
+ }
+
+ return hr;
+ }
+
+ template
+ HRESULT GitComLockableWrapper::Unlock()
+ {
+ HRESULT hr = E_FAIL;
+
+ CComPtr obj = GetComObject();
+
+ if (obj != nullptr)
+ {
+ ComLockableWrapper wrapper(obj, m_expectedApartment);
+ hr = wrapper.Unlock();
+ }
+
+ return hr;
+ }
+
+ template
+ void GitComLockableWrapper::RevokeIfValid()
+ {
+ if (SUCCEEDED(CheckCookie()))
+ {
+ CComGITPtr git(m_gitKey);
+ git.Revoke();
+ }
+ }
+}
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbList.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbList.cpp
new file mode 100644
index 00000000000..a83c5e759a9
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbList.cpp
@@ -0,0 +1,250 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#include "StdAfx.h"
+#include "PbList.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef DBG
+void AssertSizeOfList(CPbList * pList, INT cExpected)
+{
+ ASSERT(0 <= cExpected);
+ ASSERT(0 == cExpected && pList->IsEmpty() ||
+ 0 < cExpected && !pList->IsEmpty());
+
+ // a sample enumeration forward
+
+ PBLKEY key = pList->GetHead();
+ INT cActualF = 0;
+ while (!pList->IsAtEnd(key))
+ {
+ cActualF++;
+ key = pList->GetNext(key);
+ }
+
+ // a sample enumeration backwards
+
+ key = pList->GetTail();
+ INT cActualB = 0;
+ while (!pList->IsAtEnd(key))
+ {
+ cActualB++;
+ key = pList->GetPrev(key);
+ }
+
+ // assert
+
+ ASSERT (cActualF == cExpected);
+ ASSERT (cActualB == cExpected);
+}
+
+void TestPbList()
+{
+ DHR;
+ PBLKEY key = PBLKEY_NULL;
+ CPbList list;
+
+ // still empty
+ ASSERT (list.IsEmpty());
+
+ // add item 1
+ CHR_VERIFY(list.AddToTail(&key));
+ list[key] = 1;
+ AssertSizeOfList(&list, 1);
+ key = list.GetHead();
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // add item 2
+ CHR_VERIFY(list.AddToTail(&key));
+ list[key] = 2;
+ AssertSizeOfList(&list, 2);
+ key = list.GetHead();
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // add item 3
+ CHR_VERIFY(list.AddToTail(&key));
+ list[key] = 3;
+ AssertSizeOfList(&list, 3);
+ key = list.GetHead();
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 3);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // add item 4, to head
+ CHR_VERIFY(list.AddToHead(&key));
+ list[key] = 4;
+ AssertSizeOfList(&list, 4);
+ key = list.GetHead();
+ ASSERT (list[key] == 4);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 3);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // delete the head item
+ key = list.GetHead();
+ CHR_VERIFY(list.Remove(key));
+ AssertSizeOfList(&list, 3);
+ key = list.GetHead();
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 3);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // delete the tail item
+ key = list.GetTail();
+ CHR_VERIFY(list.Remove(key));
+ AssertSizeOfList(&list, 2);
+ key = list.GetHead();
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // delete the tail item again
+ key = list.GetTail();
+ CHR_VERIFY(list.Remove(key));
+ AssertSizeOfList(&list, 1);
+ key = list.GetHead();
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // delete the last remaining item
+ key = list.GetHead();
+ CHR_VERIFY(list.Remove(key));
+ AssertSizeOfList(&list, 0);
+ ASSERT (list.IsEmpty());
+
+ // populate a bigger list (reversed in order)
+ AssertSizeOfList(&list, 0);
+ CHR_VERIFY(list.AddToHead(&key));
+ list[key] = 1;
+ AssertSizeOfList(&list, 1);
+ CHR_VERIFY(list.AddToHead(&key));
+ list[key] = 2;
+ AssertSizeOfList(&list, 2);
+ CHR_VERIFY(list.AddToHead(&key));
+ list[key] = 3;
+ AssertSizeOfList(&list, 3);
+ CHR_VERIFY(list.AddToHead(&key));
+ list[key] = 4;
+ AssertSizeOfList(&list, 4);
+ CHR_VERIFY(list.AddToHead(&key));
+ list[key] = 5;
+ AssertSizeOfList(&list, 5);
+
+ // delete from the middle
+ key = list.GetHead();
+ key = list.GetNext(key);
+ key = list.GetNext(key);
+ CHR_VERIFY(list.Remove(key));
+ AssertSizeOfList(&list, 4);
+ key = list.GetHead();
+ ASSERT (list[key] == 5);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 4);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // move last item to front
+ key = list.GetTail();
+ CHR_VERIFY(list.MoveToHead(key));
+ AssertSizeOfList(&list, 4);
+ key = list.GetHead();
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 5);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 4);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // move second item to back
+ key = list.GetHead();
+ key = list.GetNext(key);
+ CHR_VERIFY(list.MoveToTail(key));
+ AssertSizeOfList(&list, 4);
+ key = list.GetHead();
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 4);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 5);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // insert an item to head
+ CHR_VERIFY(list.InsertBefore(list.GetHead(), &key));
+ list[key] = 3;
+ AssertSizeOfList(&list, 5);
+ key = list.GetHead();
+ ASSERT (list[key] == 3);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 4);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 5);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+ // insert an item in the middle
+ key = list.GetHead();
+ key = list.GetNext(key);
+ key = list.GetNext(key);
+ CHR_VERIFY(list.InsertBefore(key, &key));
+ list[key] = 6;
+ AssertSizeOfList(&list, 6);
+ key = list.GetHead();
+ ASSERT (list[key] == 3);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 1);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 6);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 4);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 2);
+ key = list.GetNext(key);
+ ASSERT (list[key] == 5);
+ key = list.GetNext(key);
+ ASSERT (list.IsAtEnd(key));
+
+CLEANUP:
+ return;
+}
+#endif
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbList.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbList.h
new file mode 100644
index 00000000000..7503fb7a5fc
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbList.h
@@ -0,0 +1,392 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef DWORD_PTR PBLKEY; // PBList KEY
+
+#define PBLKEY_NULL NULL
+
+/////////////////////////////////////////////////////////////////////////////
+
+template
+class CPbList
+{
+public:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ CPbList()
+ {
+ m_pHead = NULL;
+ m_pTail = NULL;
+#ifdef DBG
+ m_pfSyncCheckDbg = NULL;
+#endif
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ ~CPbList()
+ {
+ ClearList();
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+#ifdef DBG
+ void SetSyncCheckDbg(BOOL * pfSyncCheckDbg)
+ {
+ m_pfSyncCheckDbg = pfSyncCheckDbg;
+ }
+#endif
+
+ /////////////////////////////////////////////////////////////////////////
+
+#ifdef DBG
+ BOOL SyncCheckDbg()
+ {
+ if (!m_pfSyncCheckDbg)
+ return TRUE;
+ return SyncCheckCoreDbg(*m_pfSyncCheckDbg);
+ }
+#endif
+
+ /////////////////////////////////////////////////////////////////////////
+
+#ifdef DBG
+ static BOOL SyncCheckCoreDbg(BOOL fSyncCheckDbg)
+ {
+ return fSyncCheckDbg;
+ }
+#endif
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT AddToHead(ENTRY_TYPE entry)
+ {
+ DHR;
+ PBLKEY key;
+ CHR(AddToHead(&key));
+ (*this)[key] = entry;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT AddToTail(ENTRY_TYPE entry)
+ {
+ DHR;
+ PBLKEY key;
+ CHR(AddToTail(&key));
+ (*this)[key] = entry;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT AddToHead(__typefix(CListEntry *) __out PBLKEY * pkeyNew)
+ {
+ DHR;
+ ASSERT (SyncCheckDbg());
+ ASSERT (pkeyNew);
+ CListEntry * pNew = new CListEntry;
+ CHR_MEMALLOC(pNew);
+ CHR(AddToHeadCore(pNew))
+ *pkeyNew = (PBLKEY)pNew;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT AddToTail(__typefix(CListEntry *) __out PBLKEY * pkeyNew)
+ {
+ DHR;
+ ASSERT (SyncCheckDbg());
+ ASSERT (pkeyNew);
+ CListEntry * pNew = new CListEntry;
+ CHR_MEMALLOC(pNew);
+ CHR(AddToTailCore(pNew))
+ *pkeyNew = (PBLKEY)pNew;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT InsertBefore(__typefix(CListEntry *) __inout PBLKEY keyBefore, __typefix(CListEntry *) __out PBLKEY * pkeyNew)
+ {
+ DHR;
+ ASSERT (SyncCheckDbg());
+ ASSERT (pkeyNew);
+ CListEntry * pNew = new CListEntry;
+ CHR_MEMALLOC(pNew);
+ CHR(InsertBeforeCore(keyBefore, pNew))
+ *pkeyNew = (PBLKEY)pNew;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT Remove(__typefix(CListEntry *) __in PBLKEY key, bool deleteEntry)
+ {
+ DHR;
+ ASSERT (SyncCheckDbg());
+ ASSERT (!IsAtEnd(key));
+ CListEntry * p = (CListEntry*)key;
+ CHR(RemoveCore(p));
+
+ if (deleteEntry)
+ {
+ delete p;
+ }
+
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT MoveToHead(__typefix(CListEntry *) __inout PBLKEY key)
+ {
+ DHR;
+ ASSERT (SyncCheckDbg());
+ ASSERT (!IsAtEnd(key));
+ CListEntry * p = (CListEntry*)key;
+ CHR(RemoveCore(p));
+ CHR(AddToHeadCore(p));
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT MoveToTail(__typefix(CListEntry *) __inout PBLKEY key)
+ {
+ DHR;
+ ASSERT (SyncCheckDbg());
+ ASSERT (!IsAtEnd(key));
+ CListEntry * p = (CListEntry*)key;
+ CHR(RemoveCore(p));
+ CHR(AddToTailCore(p));
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline __typefix(CListEntry *) __out PBLKEY GetHead()
+ {
+ ASSERT (SyncCheckDbg());
+ return (PBLKEY)m_pHead;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline __typefix(CListEntry *) __out PBLKEY GetTail()
+ {
+ ASSERT (SyncCheckDbg());
+ return (PBLKEY)m_pTail;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline __typefix(CListEntry *) __out PBLKEY GetNext(__typefix(CListEntry *) __in PBLKEY key)
+ {
+ ASSERT (SyncCheckDbg());
+ ASSERT (!IsAtEnd(key));
+ CListEntry * p = (CListEntry*)key;
+ return (PBLKEY)p->m_pNext;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline __typefix(CListEntry *) __out PBLKEY GetPrev(__typefix(CListEntry *) __in PBLKEY key)
+ {
+ ASSERT (SyncCheckDbg());
+ ASSERT (!IsAtEnd(key));
+ CListEntry * p = (CListEntry*)key;
+ return (PBLKEY)p->m_pPrev;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline __out ENTRY_TYPE & operator[](__typefix(CListEntry *) __in PBLKEY key)
+ {
+ ASSERT (SyncCheckDbg());
+ return Entry(key);
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline static __out ENTRY_TYPE & Entry(
+ __typefix(CListEntry *) __in PBLKEY key
+#ifdef DBG
+ , BOOL fSyncCheckDbg = TRUE
+#endif
+ )
+ {
+ ASSERT (SyncCheckCoreDbg(fSyncCheckDbg));
+ CListEntry * p = (CListEntry*)key;
+ return p->m_data;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline BOOL IsAtEnd(__typefix(CListEntry *) __in PBLKEY key)
+ {
+ ASSERT (SyncCheckDbg());
+ return key == NULL;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline BOOL IsEmpty()
+ {
+ ASSERT (SyncCheckDbg());
+ return m_pHead == NULL;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+protected:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ class CListEntry
+ {
+ public:
+ ENTRY_TYPE m_data;
+ CListEntry * m_pPrev;
+ CListEntry * m_pNext;
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+
+ void ClearList()
+ {
+ CListEntry * pCur = m_pHead;
+ while (pCur)
+ {
+ CListEntry * pToDel = pCur;
+ pCur = pCur->m_pNext;
+ delete pToDel;
+ }
+ m_pHead = m_pTail = NULL;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT AddToHeadCore(__inout CListEntry * pNew)
+ {
+ DHR;
+
+ if (!m_pTail)
+ m_pTail = pNew;
+
+ pNew->m_pPrev = NULL;
+ pNew->m_pNext = m_pHead;
+
+ if (m_pHead)
+ m_pHead->m_pPrev = pNew;
+
+ m_pHead = pNew;
+
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT AddToTailCore(__inout CListEntry * pNew)
+ {
+ DHR;
+
+ if (!m_pHead)
+ m_pHead = pNew;
+
+ pNew->m_pPrev = m_pTail;
+ pNew->m_pNext = NULL;
+
+ if (m_pTail)
+ m_pTail->m_pNext = pNew;
+
+ m_pTail = pNew;
+
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT InsertBeforeCore(__typefix(CListEntry *) __inout PBLKEY keyBefore, __inout CListEntry * pNew)
+ {
+ DHR;
+
+ ASSERT(pNew);
+
+ CListEntry * pPoint = (CListEntry*)keyBefore;
+ CListEntry * pPrev = pPoint->m_pPrev;
+
+ if (pPrev)
+ pPrev->m_pNext = pNew;
+ else
+ m_pHead = pNew;
+
+ pPoint->m_pPrev = pNew;
+
+ pNew->m_pPrev = pPrev;
+ pNew->m_pNext = pPoint;
+
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT RemoveCore (__in CListEntry * p)
+ {
+ DHR;
+
+ ASSERT (p);
+
+ CListEntry * pPrev = p->m_pPrev;
+ CListEntry * pNext = p->m_pNext;
+ if (pPrev)
+ pPrev->m_pNext = pNext;
+ if (pNext)
+ pNext->m_pPrev = pPrev;
+
+ if (m_pHead == p)
+ m_pHead = pNext;
+ if (m_pTail == p)
+ m_pTail = pPrev;
+
+ ASSERT (m_pHead != p);
+ ASSERT (m_pTail != p);
+
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ CListEntry * m_pHead;
+ CListEntry * m_pTail;
+
+#ifdef DBG
+ BOOL * m_pfSyncCheckDbg;
+#endif
+}; // class CPbList
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef DBG
+void TestPbList();
+#endif
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbPreallocArray.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbPreallocArray.cpp
new file mode 100644
index 00000000000..5654eda0daa
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbPreallocArray.cpp
@@ -0,0 +1,162 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+
+template
+class CPbPreallocArray
+{
+public:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ CPbPreallocArray()
+ {
+ m_cCurrent = 0;
+ m_cAllocated = INITIAL_COUNT;
+ m_pa = m_aInitial;
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+
+ ~CPbPreallocArray()
+ {
+ if (m_pa != NULL &&
+ m_pa != m_aInitial)
+ {
+ delete m_pa;
+ }
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline INT GetSize()
+ {
+ return m_cCurrent;
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT SetSize(INT cNew, BOOL fGrowFast = TRUE)
+ {
+ DHR;
+
+ CHR(EnsureSize(cNew, fGrowFast));
+
+ m_cCurrent = cNew;
+
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT Add(INT * pidxNew, BOOL fGrowFast = TRUE)
+ {
+ DHR;
+ ASSERT (pidxNew);
+ CHR(SetSize(GetSize() + 1, fGrowFast));
+ *pidxNew = GetSize() - 1;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT Add(ENTRY_TYPE entry, BOOL fGrowFast = TRUE)
+ {
+ DHR;
+ INT idxNew;
+ CHR(Add(&idxNew));
+ (*this)[idxNew] = entry;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ ENTRY_TYPE & operator[](UINT idx)
+ {
+ ASSERT (idx < m_cCurrent);
+ return m_pa[idx];
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ ENTRY_TYPE * GetData()
+ {
+ ASSERT (m_pa);
+ return m_pa;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT Remove(UINT idx)
+ {
+ DHR;
+ ASSERT (0 <= idx && idx < m_cCurrent);
+ if (idx < m_cCurrent - 1)
+ {
+ UINT cbToCopy = sizeof(m_pa[0]) * (m_cCurrent - idx - 1);
+ ASSERT (sizeof(m_pa[0]) * 1 <= cbToCopy && cbToCopy <= sizeof(m_pa[0]) * (m_cCurrent - 1));
+ CopyMemory(&(m_pa[idx]), &(m_pa[idx + 1]), cbToCopy);
+ }
+ m_cCurrent--;
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+protected:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT EnsureSize(UINT cRequested, BOOL fGrowFast)
+ {
+ DHR;
+
+ if (m_cAllocated < cRequested)
+ {
+ if (fGrowFast)
+ cRequested = max(m_cAllocated * 2, cRequested);
+
+ ASSERT (m_pa != NULL);
+ if (m_pa == m_aInitial)
+ {
+ CHR_MEMALLOC(m_pa = new ENTRY_TYPE[cRequested]);
+ CopyMemory(m_pa, m_aInitial, sizeof(m_pa[0]) * m_cAllocated);
+ }
+ else
+ {
+ ENTRY_TYPE * paNew = (ENTRY_TYPE*)realloc(m_pa, sizeof(m_pa[0]) * cRequested);
+ CHR_MEMALLOC(paNew);
+ m_pa = paNew;
+ }
+ m_cAllocated = cRequested;
+ }
+
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+protected:
+
+ ENTRY_TYPE m_aInitial[INITIAL_COUNT];
+ ENTRY_TYPE* m_pa;
+ UINT m_cAllocated;
+ UINT m_cCurrent;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef DBG
+void TestPbPreallocArray();
+#endif
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbPreallocArray.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbPreallocArray.h
new file mode 100644
index 00000000000..0718fdde35e
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PbPreallocArray.h
@@ -0,0 +1,166 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+
+template
+class CPbPreallocArray
+{
+public:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ CPbPreallocArray()
+ {
+ m_cCurrent = 0;
+ m_cAllocated = INITIAL_COUNT;
+ m_pa = m_aInitial;
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+
+ ~CPbPreallocArray()
+ {
+ if (m_pa != NULL &&
+ m_pa != m_aInitial)
+ {
+ delete m_pa;
+ }
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+
+ inline INT GetSize()
+ {
+ return m_cCurrent;
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT SetSize(INT cNew, BOOL fGrowFast = TRUE)
+ {
+ DHR;
+
+ CHR(EnsureSize(cNew, fGrowFast));
+
+ m_cCurrent = cNew;
+
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT Add(__out INT * pidxNew, BOOL fGrowFast = TRUE)
+ {
+ DHR;
+ ASSERT (pidxNew);
+ // Make sure we don't overflow UINT (GetSize() + 1 < MAXINT). If we do handle as out of memory error.
+ CHR_MEMALLOC(GetSize() < (~(UINT)0) ? 1 /*not NULL*/ : NULL);
+ CHR(SetSize(GetSize() + 1, fGrowFast));
+ *pidxNew = GetSize() - 1;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT Add(ENTRY_TYPE entry, BOOL fGrowFast = TRUE)
+ {
+ DHR;
+ INT idxNew;
+ CHR(Add(&idxNew));
+ (*this)[idxNew] = entry;
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ __out ENTRY_TYPE & operator[](UINT idx)
+ {
+ ASSERT (idx < m_cCurrent);
+ return m_pa[idx];
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ __out ENTRY_TYPE * GetData()
+ {
+ ASSERT (m_pa);
+ return m_pa;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT Remove(UINT idx)
+ {
+ DHR;
+ ASSERT (0 <= idx && idx < m_cCurrent);
+ if (idx < m_cCurrent - 1)
+ {
+ UINT cbToCopy = sizeof(m_pa[0]) * (m_cCurrent - idx - 1);
+ ASSERT (sizeof(m_pa[0]) * 1 <= cbToCopy && cbToCopy <= sizeof(m_pa[0]) * (m_cCurrent - 1));
+ CopyMemory(&(m_pa[idx]), &(m_pa[idx + 1]), cbToCopy);
+ }
+ m_cCurrent--;
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+protected:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ HRESULT EnsureSize(UINT cRequested, BOOL fGrowFast)
+ {
+ DHR;
+
+ if (m_cAllocated < cRequested)
+ {
+ if (fGrowFast)
+ cRequested = max(m_cAllocated * 2, cRequested);
+
+ ASSERT (m_pa != NULL);
+ // Make sure we don't overflow byte count (cRequested * sizeof(ENTRY_TYPE)). If we do handle as out of memory error.
+ CHR_MEMALLOC(cRequested <= ((~(UINT)0) / (sizeof(ENTRY_TYPE))) ? 1 /*not NULL*/ : NULL);
+ if (m_pa == m_aInitial)
+ {
+ CHR_MEMALLOC(m_pa = new ENTRY_TYPE[cRequested]);
+ CopyMemory(m_pa, m_aInitial, sizeof(m_pa[0]) * m_cAllocated);
+ }
+ else
+ {
+ ENTRY_TYPE * paNew = (ENTRY_TYPE*)realloc(m_pa, sizeof(m_pa[0]) * cRequested);
+ CHR_MEMALLOC(paNew);
+ m_pa = paNew;
+ }
+ m_cAllocated = cRequested;
+ }
+
+ CLEANUP:
+ RHR;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+protected:
+
+ ENTRY_TYPE m_aInitial[INITIAL_COUNT];
+ ENTRY_TYPE* m_pa;
+ UINT m_cAllocated;
+ UINT m_cCurrent;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef DBG
+void TestPbPreallocArray();
+#endif
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenIMC.manifest b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenIMC.manifest
new file mode 100644
index 00000000000..076c130ad46
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenIMC.manifest
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.cpp
new file mode 100644
index 00000000000..37ef3140bbd
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.cpp
@@ -0,0 +1,218 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PenImc.cpp : Implementation of DLL Exports.
+
+#include "stdafx.h"
+#include "resource.h"
+#include "PenImc.h"
+#include "PimcManager.h"
+
+#include
+#include "dlldatax.h"
+#include "penimc_i.c"
+#include
+#include
+#include
+//#include
+
+
+#if 1 // from tablib.lib WIP (toddt) this is to be fixed after the new build changes settle down.
+void SafeCloseHandle(__inout HANDLE * pHandle)
+{
+ ASSERT (pHandle);
+
+ if (*pHandle)
+ {
+ CloseHandle(*pHandle);
+ *pHandle = NULL;
+ }
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+class CPenImcModule : public CAtlDllModuleT< CPenImcModule >
+{
+public :
+ DECLARE_LIBID(LIBID_PenImcLib4v3)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_PENIMC, "{E31B1A40-9FE5-46D8-98F0-9B0F75F0320C}")
+};
+
+CPenImcModule _AtlModule;
+
+/////////////////////////////////////////////////////////////////////////////
+
+#if WANT_SINGLETON
+class CPimcManagerFactory : public IClassFactory
+{
+public:
+ STDMETHOD_(ULONG, AddRef) () { return 1; }
+ STDMETHOD_(ULONG, Release)() { return 1; };
+ STDMETHOD(QueryInterface)(REFIID riid, void** ppv);
+ STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID * ppvObject);
+ STDMETHOD(LockServer)(BOOL fLock);
+};
+
+CPimcManagerFactory _PimcManagerFactory;
+#endif // WANT_SINGLETON
+
+/////////////////////////////////////////////////////////////////////////////
+
+extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ g_hMutexHook = CreateMutex(NULL, /* initial ownership */FALSE, NULL);
+ //Assert g_hMutexHook != null?
+ }
+ else if (dwReason == DLL_PROCESS_DETACH)
+ {
+ //ASSERT(g_cHookLock == 0);
+ SafeCloseHandle(&g_hMutexHook);
+ }
+
+#ifdef _MERGE_PROXYSTUB
+ if (!PrxDllMain(hInstance, dwReason, lpReserved))
+ return FALSE;
+#endif
+ hInstance;
+ return _AtlModule.DllMain(dwReason, lpReserved);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+__control_entrypoint(DllExport)
+STDAPI DllCanUnloadNow(void)
+{
+#ifdef _MERGE_PROXYSTUB
+ HRESULT hr = PrxDllCanUnloadNow();
+ if (hr != S_OK)
+ return hr;
+#endif
+ return _AtlModule.DllCanUnloadNow();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+_Check_return_
+STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv)
+{
+#ifdef _MERGE_PROXYSTUB
+ HRESULT hr = PrxDllGetClassObject(rclsid, riid, ppv);
+ if (hr != CLASS_E_CLASSNOTAVAILABLE)
+ return hr;
+#endif
+
+ // NOTE:
+ // In order to support multiple app domains we don't want to return just one
+ // object for both those app domains or we cause problems with the RPC interface
+ // we have to wisptis. We need to actually create two different CPimcManager
+ // objects in order to run properly. This required the removal of the singleton
+ // support below. Since the avalon stylus code uses a static class to manage
+ // the CPimcManager object we will only get one instance per app domain which is
+ // what we want.
+
+#if WANT_SINGLETON
+ // This is how we implement PimcManager as a singleton. We could've used
+ // DECLARE_CLASSFACTORY_SINGLETON, but in that case PimcManager gets released
+ // way too late because _AtlModule is holding refs on it until destructor.
+ // In that case PimcManager thread gets killed rather than experiencing a normal
+ // shutdown.
+ if (IsEqualGUID(rclsid, CLSID_PimcManager))
+ {
+ return _PimcManagerFactory.QueryInterface(riid, ppv);
+ }
+#endif
+
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+__control_entrypoint(DllExport)
+STDAPI DllRegisterServer(void)
+{
+ // registers object, typelib and all interfaces in typelib
+ HRESULT hr = _AtlModule.DllRegisterServer();
+#ifdef _MERGE_PROXYSTUB
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllRegisterServer();
+#endif
+ return hr;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+__control_entrypoint(DllExport)
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+#ifdef _MERGE_PROXYSTUB
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllRegisterServer();
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllUnregisterServer();
+#endif
+ return hr;
+}
+
+
+#if WANT_SINGLETON
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcManagerFactory::QueryInterface(REFIID riid, __typefix(IClassFactory **) __deref_out void** ppv)
+{
+ DHR;
+ if (IsEqualGUID(riid, IID_IUnknown) ||
+ IsEqualGUID(riid, IID_IClassFactory))
+ {
+ *ppv = (IClassFactory*)this;
+ AddRef();
+ CHR(S_OK);
+ }
+ else
+ {
+ CHR(E_NOINTERFACE);
+ }
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcManagerFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, __deref_out LPVOID * ppvObject)
+{
+ DHR;
+ if (Mgr() == NULL)
+ {
+ CComObject * pMgr;
+ CHR(CComObject::CreateInstance(&pMgr));
+ }
+ ASSERT(Mgr() != NULL);
+ CHR(Mgr()->QueryInterface(riid, (void**)ppvObject));
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcManagerFactory::LockServer(BOOL fLock)
+{
+ if (fLock)
+ _AtlModule.Lock();
+ else
+ _AtlModule.Unlock();
+ return S_OK;
+}
+#endif // WANT_SINGLETON
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.def b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.def
new file mode 100644
index 00000000000..193a703c902
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.def
@@ -0,0 +1,25 @@
+; Licensed to the .NET Foundation under one or more agreements.
+; The .NET Foundation licenses this file to you under the MIT license.
+; See the LICENSE file in the project root for more information.
+
+
+; PenImc.def : Declares the module parameters.
+
+LIBRARY DLL_NAME
+
+EXPORTS
+ GetProxyDllInfo PRIVATE
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
+ GetPenEvent PRIVATE
+ GetPenEventMultiple PRIVATE
+ CreateResetEvent PRIVATE
+ DestroyResetEvent PRIVATE
+ RaiseResetEvent PRIVATE
+ GetLastSystemEventData PRIVATE
+ LockWispObjectFromGit PRIVATE
+ UnlockWispObjectFromGit PRIVATE
+ RegisterDllForSxSCOM PRIVATE
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.idl b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.idl
new file mode 100644
index 00000000000..9c31e52c420
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.idl
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PenImc.idl : IDL source for PenImc
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (PenImc.tlb) and marshalling code.
+
+import "oaidl.idl";
+import "ocidl.idl";
+
+[
+ object,
+ uuid(75C6AAEE-2BA4-4008-B523-4F1E033FF049),
+ nonextensible,
+ helpstring("IPimcContext3 Interface"),
+ pointer_default(unique)
+]
+interface IPimcContext3 : IUnknown{
+ [helpstring("method ShutdownComm") ] HRESULT ShutdownComm();
+ [helpstring("method GetPacketDescriptionInfo") ] HRESULT GetPacketDescriptionInfo([out] INT * pcProps, [out] INT * pcButtons);
+ [helpstring("method GetPacketPropertyInfo") ] HRESULT GetPacketPropertyInfo([in] INT iProp, [out] GUID * pGuid, [out] INT * piMin, [out] INT * piMax, [out] INT * piUnits, [out] FLOAT *pflResolution);
+ [helpstring("method GetPacketButtonInfo") ] HRESULT GetPacketButtonInfo([in] INT iButton, [out] GUID * pGuid);
+ [helpstring("method GetLastSystemEventData") ] HRESULT GetLastSystemEventData([out] INT * piEvent, [out] INT * piModifier, [out] INT * piKey, [out] INT * piX, [out] INT * piY, [out] INT * piCursorMode, [out] INT * piButtonState);
+};
+
+[
+ object,
+ uuid(CEB1EF24-BB4E-498B-9DF7-12887ED0EB24),
+ nonextensible,
+ helpstring("IPimcTablet3 Interface"),
+ pointer_default(unique)
+]
+interface IPimcTablet3 : IUnknown{
+ [helpstring("method GetKey") ] HRESULT GetKey ([out] INT * pKey);
+ [helpstring("method GetName") ] HRESULT GetName ([out] LPWSTR * ppszName);
+ [helpstring("method GetPlugAndPlayId") ] HRESULT GetPlugAndPlayId ([out] LPWSTR * ppszPlugAndPlayId);
+ [helpstring("method GetTabletAndDisplaySize")] HRESULT GetTabletAndDisplaySize ([out] INT * piTabletWidth, [out] INT * piTabletHeight, [out] INT * piDisplayWidth, [out] INT * piDisplayHeight);
+ [helpstring("method GetHardwareCaps") ] HRESULT GetHardwareCaps ([out] INT * piCaps);
+ [helpstring("method GetDeviceType") ] HRESULT GetDeviceType ([out] INT * piDevType);
+ [helpstring("method RefreshCursorInfo") ] HRESULT RefreshCursorInfo ();
+ [helpstring("method GetCursorCount") ] HRESULT GetCursorCount ([out] INT * pcCursors);
+ [helpstring("method GetCursorInfo") ] HRESULT GetCursorInfo ([in] INT iCursor, [out] LPWSTR * ppszName, [out] INT * pId, [out] BOOL * pfInverted);
+ [helpstring("method GetCursorButtonCount") ] HRESULT GetCursorButtonCount ([in] INT iCursor, [out] INT * pcButtons);
+ [helpstring("method GetCursorButtonInfo") ] HRESULT GetCursorButtonInfo ([in] INT iCursor, [in] INT iButton, [out] LPWSTR * ppszName, [out] GUID * pGuid);
+ [helpstring("method IsPropertySupported") ] HRESULT IsPropertySupported ([in] GUID guid, [out] BOOL * pfSupported);
+ [helpstring("method GetPropertyInfo") ] HRESULT GetPropertyInfo ([in] GUID guid, [out] INT * piMin, [out] INT * piMax, [out] INT * piUnit, [out] FLOAT *pflResolution);
+ [helpstring("method CreateContext")] HRESULT CreateContext([in] INT_PTR hwnd, [in]BOOL fEnable, [in]UINT timeout, [out]IPimcContext3** ppCtx, [out] INT * pKey, [out] hyper * pHandle);
+ [helpstring("method GetPacketDescriptionInfo") ] HRESULT GetPacketDescriptionInfo([out] INT * pcProps, [out] INT * pcButtons);
+ [helpstring("method GetPacketPropertyInfo") ] HRESULT GetPacketPropertyInfo([in] INT iProp, [out] GUID * pGuid, [out] INT * piMin, [out] INT * piMax, [out] INT * piUnits, [out] FLOAT *pflResolution);
+ [helpstring("method GetPacketButtonInfo") ] HRESULT GetPacketButtonInfo([in] INT iButton, [out] GUID * pGuid);
+};
+
+[
+ object,
+ uuid(BD2C38C2-E064-41D0-A999-940F526219C2),
+ nonextensible,
+ helpstring("IPimcManager3 Interface"),
+ pointer_default(unique)
+]
+interface IPimcManager3 : IUnknown {
+ [helpstring("method GetTabletCount")] HRESULT GetTabletCount([out] ULONG* pcTablets);
+ [helpstring("method GetTablet") ] HRESULT GetTablet([in] ULONG iTablet, [out] IPimcTablet3** ppTablet);
+};
+
+[
+ object,
+ uuid(74D2B283-EDB3-4A8D-8088-445E8766C872),
+ nonextensible,
+ helpstring("IPimcSurrogate3 Interface"),
+ pointer_default(unique)
+]
+interface IPimcSurrogate3 : IUnknown {
+ [helpstring("method GetWisptisITabletManager")] HRESULT GetWisptisITabletManager([out] IUnknown** ppTabletManagerUnknown);
+};
+
+[
+ uuid(33363EEE-828A-4DFC-BB3C-AB9628E6DD62),
+ version(2.0),
+ helpstring("PenIMC v4 2.0 Type Library")
+]
+library PenImcLib4v3
+{
+ importlib("stdole2.tlb");
+
+ [
+ uuid(F269D7C4-EF22-48A1-A503-4E0A620FC746),
+ helpstring("PimcSurrogate3 Class")
+ ]
+ coclass PimcSurrogate3
+ {
+ [default] interface IPimcSurrogate3;
+ };
+
+ [
+ uuid(DB88ADFD-BEC7-47B8-A6B5-58CA3DA2B8D6),
+ helpstring("PimcManager3 Class")
+ ]
+ coclass PimcManager3
+ {
+ [default] interface IPimcManager3;
+ };
+ [
+ uuid(A50E4FEE-6A0C-4AD6-8FDE-8E3EC75956BF),
+ helpstring("PimcContext3 Class")
+ ]
+ coclass PimcContext3
+ {
+ [default] interface IPimcContext3;
+ };
+ [
+ uuid(8E44D1B9-D701-4E65-9917-0FF7488A7F96),
+ helpstring("PimcTablet3 Class")
+ ]
+ coclass PimcTablet3
+ {
+ [default] interface IPimcTablet3;
+ };
+};
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.rc b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.rc
new file mode 100644
index 00000000000..8a769cd3e86
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.rc
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#define FX_VER_FILEDESCRIPTION_STR "Microsoft Tablet PC Component"
+
+#include
+#include "resource.h"
+#include
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// SxS Manifest
+//
+
+ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST "PenIMC.manifest"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PROJNAME "PenImc"
+END
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "PenImc.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.sln b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.sln
new file mode 100644
index 00000000000..8c479c18359
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.sln
@@ -0,0 +1,51 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28407.52
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OSVersionHelper", "..\..\Shared\OSVersionHelper\OSVersionHelper.vcxproj", "{3801B5AE-6871-4A72-B400-1F6ABCBF9045}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabLib", "..\tablib\TabLib.vcxproj", "{8F91EB3A-C530-4CEA-90BF-AFC8165B6456}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PenImc", "PenImc.vcxproj", "{8383C663-E8D0-4D2D-B65A-FE4A253E3319}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Debug|x64.ActiveCfg = Debug|x64
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Debug|x64.Build.0 = Debug|x64
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Debug|x86.ActiveCfg = Debug|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Debug|x86.Build.0 = Debug|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x64.ActiveCfg = Release|x64
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x64.Build.0 = Release|x64
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x86.ActiveCfg = Release|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x86.Build.0 = Release|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x64.ActiveCfg = Debug|x64
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x64.Build.0 = Debug|x64
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x86.ActiveCfg = Debug|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Debug|x86.Build.0 = Debug|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x64.ActiveCfg = Release|x64
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x64.Build.0 = Release|x64
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x86.ActiveCfg = Release|Win32
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}.Release|x86.Build.0 = Release|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x64.ActiveCfg = Debug|x64
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x64.Build.0 = Debug|x64
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x86.ActiveCfg = Debug|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Debug|x86.Build.0 = Debug|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x64.ActiveCfg = Release|x64
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x64.Build.0 = Release|x64
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x86.ActiveCfg = Release|Win32
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {7D57B352-EBB6-4244-9548-0346D749EE47}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.vcxproj b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.vcxproj
new file mode 100644
index 00000000000..8fb2f95f1ad
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PenImc.vcxproj
@@ -0,0 +1,99 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+ false
+ DynamicLibrary
+
+
+
+
+
+
+
+
+ CompileAsC
+ NotUsing
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+ PenImc.h
+ true
+ $(IntermediateOutputPath)
+
+
+
+
+
+
+
+
+ 15.0
+ {8383C663-E8D0-4D2D-B65A-FE4A253E3319}
+ Win32Proj
+ PenImc$(WpfVersionSuffix)
+ PenImc$(WpfVersionSuffix)
+ $(PreProcessorDefinitions);_MERGE_PROXYSTUB;_USRDLL
+ false
+
+
+
+
+ Use
+ true
+ _MERGE_PROXYSTUB;_USRDLL;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories);$(WpfSourceDir)PenImc\inc\;$(IntermediateOutputPath)
+
+
+ $(IntermediateOutputPath)PenImc.i
+ %(AdditionalDependencies);kernel32.lib;advapi32.lib;uuid.lib;ole32.lib;oleaut32.lib;user32.lib;shlwapi.lib;rpcrt4.lib;rpcns4.lib;shell32.lib
+
+
+
+
+
+ {8f91eb3a-c530-4cea-90bf-afc8165b6456}
+
+
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}
+
+
+
+
+
+ $(MSBuildThisFileDirectory)PenImc.def
+ PenImc.i
+
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcContext.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcContext.cpp
new file mode 100644
index 00000000000..9578b17934e
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcContext.cpp
@@ -0,0 +1,1107 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PimcContext.cpp : Implementation of CPimcContext
+
+#include "stdafx.h"
+
+#include "ComApartmentVerifier.hpp"
+#include "pblist.h"
+#include "PimcContext.h"
+#include "..\tablib\sidutils.h"
+#include "..\tablib\scopes.h"
+
+using namespace ComUtils;
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// NOTE (alexz) There are several key assumptions used here to simplify this code.
+// Should the assumptions change, the code may break in a subtle
+// way. This includes data corruption due to missing synchronization, etc.
+// Look for ASSUMPTION markers for more details.
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CPimcContext
+
+/////////////////////////////////////////////////////////////////////////////
+
+CPimcContext::CPimcContext() :
+ m_sink(new CEventSink()), m_hEventMoreData(NULL), m_hEventClientReady(NULL),
+ m_hMutexSharedMemory(NULL), m_hFileMappingSharedMemory(NULL),
+ m_pSharedMemoryHeader(NULL), m_pbSharedMemoryRawData(NULL),
+ m_cHandles(0), m_pHandles(NULL), m_cbPackets(0),
+ m_pbPackets(NULL), m_fCommHandleOutstanding(FALSE),
+ m_pMgr(NULL), m_pPacketDescription(NULL), m_hEventUpdate(NULL), m_fIsTopmostHook(FALSE)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::Init(
+ __inout CComPtr pMgr,
+ __in_opt CComPtr pCtxS,
+ __in HWND hwnd,
+ TABLET_CONTEXT_ID tcid,
+ PACKET_DESCRIPTION * pPacketDescription)
+{
+ DHR;
+ // Make sure we clean up properly on failures.
+ bool fCleanupCritSection = false;
+ bool fCleanupHook = false;
+ bool fCleanupCtx = false;
+
+ m_pMgr = pMgr;
+
+ if (pCtxS)
+ {
+ // DDVSO:289954
+ // We need to store the ITabletContextP inside the COM Global Interface Table
+ // (GIT) because the proxy we get here from the QueryInterface will not be
+ // valid when used within the ExecuteUpdates function. Using the GIT ensures
+ // that we get an appropriate proxy when the time comes.
+ CHR(pCtxS->QueryInterface(IID_ITabletContextP, reinterpret_cast(&m_pCtxS)));
+ m_wispContextLock = GitComLockableWrapper(m_pCtxS, ComApartmentVerifier::Mta());
+ CHR(m_wispContextLock.CheckCookie());
+
+ fCleanupCtx = true;
+
+ m_fIsTopmostHook = (m_pCtxS->IsTopMostHook() == S_OK);
+ }
+
+ m_tcid = tcid;
+ m_pPacketDescription = pPacketDescription;
+
+ m_dwUpdatesPending = 0;
+ InitializeCriticalSection(&m_csUpdates);
+ fCleanupCritSection = true;
+ m_hEventUpdate = CreateEvent(NULL, FALSE, FALSE, NULL);
+ CHR(m_hEventUpdate ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_CREATEEVENT_CALL));
+
+ CHR(m_pMgr->InstallWindowHook(hwnd, this));
+ fCleanupHook = true;
+
+ if (pCtxS)
+ {
+ CComPtr pCtxP;
+ CHR(m_pCtxS->QueryInterface(IID_ITabletContextP, (void**)&pCtxP));
+
+ hr = InitUnnamedCommunications(pCtxP);
+
+ // NOTICE-2006/05/25-WAYNEZEN,
+ // The named communications is supported by wisptis on Vista ONLY.
+ if ( hr == E_ACCESSDENIED && m_pMgr->IsVistaOrGreater() )
+ {
+ hr = InitNamedCommunications(pCtxP);
+ }
+
+ CHR(hr);
+ }
+
+ m_fSingleFireTimeout = FALSE;
+ m_dwSingleFireTimeout = INFINITE;
+
+ RHR;
+
+CLEANUP:
+ // On failure, make sure we clean up things.
+ if (fCleanupHook)
+ m_pMgr->UninstallWindowHook(this);
+ if (fCleanupCritSection)
+ DeleteCriticalSection(&m_csUpdates);
+ SafeCloseHandle(&m_hEventUpdate);
+
+ if (fCleanupCtx)
+ m_wispContextLock.RevokeIfValid();
+
+ m_pMgr = NULL;
+
+ m_pPacketDescription = NULL;
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcContext::FinalRelease()
+{
+ if (m_pMgr != NULL)
+ {
+ m_pMgr->UninstallWindowHook(this);
+
+ ShutdownSharedMemoryCommunications();
+
+ if (m_pPacketDescription)
+ {
+ DestroyPacketDescription(m_pPacketDescription);
+ m_pPacketDescription = NULL;
+ }
+
+ DeleteCriticalSection(&m_csUpdates);
+ SafeCloseHandle(&m_hEventUpdate);
+
+ m_wispContextLock.RevokeIfValid();
+
+ m_pMgr = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::InitUnnamedCommunications(__in CComPtr pCtxP)
+{
+ DHR;
+
+ CHR(pCtxP->UseSharedMemoryCommunications(
+ GetCurrentProcessId(),
+ (DWORD*)&m_hEventMoreData,
+ (DWORD*)&m_hEventClientReady,
+ (DWORD*)&m_hMutexSharedMemory,
+ (DWORD*)&m_hFileMappingSharedMemory));
+ CHR(InitCommunicationsCore());
+
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::InitNamedCommunications(__in CComPtr pCtxP)
+{
+ DHR;
+
+ DWORD dwPid = GetCurrentProcessId();
+ DWORD dwMoreDataEventId;
+ DWORD dwClientReadyEventId;
+ DWORD dwSharedMemoryMutexId;
+ DWORD dwFileMappingId;
+
+ ScopedLocalString pszSid;
+ ScopedLocalString pszSidIntegrity;
+
+ ASSERTSZ(m_pMgr->IsVistaOrGreater(), _T("Only Vista supports the named communications."));
+
+ CHR(GetUserSid(&pszSid.get()));
+ CHR(GetMandatoryLabel(&pszSidIntegrity.get()));
+
+ CHR(pCtxP->UseNamedSharedMemoryCommunications(
+ dwPid,
+ pszSid,
+ pszSidIntegrity,
+ &dwMoreDataEventId,
+ &dwClientReadyEventId,
+ &dwSharedMemoryMutexId,
+ &dwFileMappingId));
+
+ TCHAR szMoreDataName[MAX_PATH + 1];
+ TCHAR szMutexName[MAX_PATH + 1];
+ TCHAR szSectionName[MAX_PATH + 1];
+ TCHAR szClientReadyName[MAX_PATH + 1];
+
+ StringCchPrintf(
+ szMoreDataName,
+ LENGTHOFARRAY(szMoreDataName),
+ WISPTIS_SM_MORE_DATA_EVENT_NAME,
+ dwPid,
+ dwMoreDataEventId);
+
+ StringCchPrintf(
+ szMutexName,
+ LENGTHOFARRAY(szMutexName),
+ WISPTIS_SM_MUTEX_NAME,
+ dwPid,
+ dwSharedMemoryMutexId);
+
+ StringCchPrintf(
+ szSectionName,
+ LENGTHOFARRAY(szSectionName),
+ WISPTIS_SM_SECTION_NAME,
+ dwPid,
+ dwFileMappingId);
+
+ StringCchPrintf(
+ szClientReadyName,
+ LENGTHOFARRAY(szClientReadyName),
+ WISPTIS_SM_THREAD_EVENT_NAME,
+ dwClientReadyEventId);
+
+ m_hEventClientReady = OpenEvent(EVENT_ALL_ACCESS, FALSE, szClientReadyName);
+ CHR_WIN32(m_hEventClientReady);
+
+ m_hEventMoreData = OpenEvent(SYNCHRONIZE, FALSE, szMoreDataName);
+ CHR_WIN32(m_hEventMoreData);
+
+ m_hMutexSharedMemory = OpenMutex(MUTEX_ALL_ACCESS, FALSE, szMutexName);
+ CHR_WIN32(m_hMutexSharedMemory);
+
+ m_hFileMappingSharedMemory = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, szSectionName);
+ CHR_WIN32(m_hFileMappingSharedMemory);
+
+ CHR(InitCommunicationsCore());
+
+ CLEANUP:
+ if(FAILED(hr))
+ {
+ SafeCloseHandle(&m_hFileMappingSharedMemory);
+ SafeCloseHandle(&m_hMutexSharedMemory);
+ SafeCloseHandle(&m_hEventMoreData);
+ SafeCloseHandle(&m_hEventClientReady);
+ }
+
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::InitCommunicationsCore()
+{
+ DHR;
+
+ CHR(m_hEventMoreData && m_hEventClientReady && m_hMutexSharedMemory && m_hFileMappingSharedMemory ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_USESHAREDMEMORYCOM_CALL));
+
+ m_pSharedMemoryHeader = (SHAREDMEMORY_HEADER*)MapViewOfFile(
+ m_hFileMappingSharedMemory, // handle
+ FILE_MAP_READ | FILE_MAP_WRITE, // desired access
+ 0, // offset in file, High
+ 0, // offset in file, Low
+ sizeof(SHAREDMEMORY_HEADER)); // number of bytes to map
+ CHR(m_pSharedMemoryHeader ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_SHAREDMEMORYHEADER_NULL));
+
+#pragma prefast( suppress: 11, "Dereferencing NULL pointer 'm_pSharedMemoryHeader'." )
+ m_pbSharedMemoryRawData = (BYTE*)MapViewOfFile(
+ m_hFileMappingSharedMemory, // handle
+ FILE_MAP_READ, // desired access
+ 0, // offset in file, High
+ 0, // offset in file, Low
+ m_pSharedMemoryHeader->cbTotal);// number of bytes to map
+ CHR(m_pbSharedMemoryRawData ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_SHAREDMEMORYRAWDATA_NULL));
+
+ m_pbSharedMemoryPackets = m_pbSharedMemoryRawData + sizeof(SHAREDMEMORY_HEADER);
+
+ m_cHandles = 0;
+ m_pHandles = NULL;
+ m_cbPackets = 0;
+ m_pbPackets = NULL;
+ m_fCommHandleOutstanding = FALSE;
+
+CLEANUP:
+ if (FAILED(hr))
+ ShutdownSharedMemoryCommunications();
+
+ RHR;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void CPimcContext::ShutdownSharedMemoryCommunications()
+{
+ if (m_pSharedMemoryHeader)
+ {
+ UnmapViewOfFile(m_pSharedMemoryHeader);
+ m_pSharedMemoryHeader = NULL;
+ }
+ if (m_pbSharedMemoryRawData)
+ {
+ UnmapViewOfFile(m_pbSharedMemoryRawData);
+ m_pbSharedMemoryRawData = NULL;
+ }
+
+ SafeCloseHandle(&m_hEventMoreData);
+ SafeCloseHandle(&m_hEventClientReady);
+ SafeCloseHandle(&m_hMutexSharedMemory);
+ SafeCloseHandle(&m_hFileMappingSharedMemory);
+ if (m_pHandles)
+ {
+ delete [] m_pHandles;
+ m_pHandles = NULL;
+ }
+ if (m_pbPackets)
+ {
+ delete [] m_pbPackets;
+ m_pbPackets = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::GetCommHandle(__out INT64* pHandle)
+{
+ // ASSUMPTION (alexz) this call is always balanced by ShutdownComm
+ // (responsibility of the caller)
+ DHR;
+ CHR(pHandle ? S_OK : E_INVALIDARG);
+
+ if (m_wispContextLock.GetCookie() != 0)
+ {
+ ASSERT (!m_fCommHandleOutstanding);
+ CHR(!m_fCommHandleOutstanding ? S_OK : E_UNEXPECTED);
+ m_fCommHandleOutstanding = TRUE;
+ *pHandle = (INT_PTR)this;
+
+ // DDVSO:514949
+ // Create the CPimcContext and CEventSink lock here since we know this object is fully instantiated (including IUnknown).
+ m_contextLock = ComLockableWrapper(this, ComApartmentVerifier::CurrentSta());
+ m_sinkLock = ComLockableWrapper(m_sink.p, ComApartmentVerifier::CurrentSta());
+
+ // DDVSO:514949
+ // Make sure that we increase the ref count here since we
+ // need to ensure that the apartment where this object lives
+ // stays alive.
+ AddRef();
+
+ // DDVSO:514949
+ // Calling this ensures that the CStdIdentity for this object is
+ // not released if we hit a COM rundown due to OSGVSO:10779198.
+ CHR(m_contextLock.Lock());
+
+ // DDVSO:514949
+ // Lock the CEventSink so WISP can rely on its proxy to it.
+ CHR(m_sinkLock.Lock());
+ }
+
+CLEANUP:
+ RHR;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcContext::ShutdownComm()
+{
+ DHR;
+
+ if (m_wispContextLock.GetCookie() != 0)
+ {
+ ASSERT(m_fCommHandleOutstanding);
+ CHR (m_fCommHandleOutstanding ? S_OK : E_UNEXPECTED);
+ m_fCommHandleOutstanding = FALSE;
+
+ // DDVSO:514949
+ // Balance the call in Init.
+ CHR(m_sinkLock.Unlock());
+
+ // DDVSO:514949
+ // Balance the call in GetCommHandle.
+ CHR(m_contextLock.Unlock());
+
+ // DDVSO:514949
+ // Balance out any GetCommHandle call here. This will be done
+ // when the PenThread no longer is using this context.
+ Release();
+ }
+
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::GetKey(__out INT * pKey)
+{
+ DHR;
+ CHR(pKey ? S_OK : E_INVALIDARG);
+ *pKey = m_tcid;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcContext::GetPacketDescriptionInfo(__out INT * pcProps, __out INT * pcButtons)
+{
+ DHR;
+ CHR(pcProps ? S_OK : E_INVALIDARG);
+ CHR(pcButtons ? S_OK : E_INVALIDARG);
+ *pcProps = m_pPacketDescription->cPacketProperties;
+ *pcButtons = m_pPacketDescription->cButtons;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcContext::GetPacketPropertyInfo(INT iProp, __out GUID * pGuid, __out INT * piMin, __out INT * piMax, __out INT * piUnits, __out FLOAT *pflResolution)
+{
+ HRESULT hr = S_OK;
+
+ switch (iProp)
+ {
+ case QUERY_WISP_CONTEXT_KEY:
+ {
+ if (nullptr == piMin)
+ {
+ hr = E_INVALIDARG;
+ }
+ else
+ {
+ *piMin = (INT)m_wispContextLock.GetCookie();
+ }
+ }
+ break;
+ default:
+ {
+ hr = GetPacketPropertyInfoImpl(iProp, pGuid, piMin, piMax, piUnits, pflResolution);
+ }
+ }
+
+ return hr;
+}
+
+STDMETHODIMP CPimcContext::GetPacketPropertyInfoImpl(INT iProp, __out GUID * pGuid, __out INT * piMin, __out INT * piMax, __out INT * piUnits, __out FLOAT *pflResolution)
+{
+ PACKET_PROPERTY * pProp = nullptr;
+ DHR;
+ CHR(0 <= iProp && (DWORD)iProp < m_pPacketDescription->cPacketProperties ? S_OK : E_INVALIDARG);
+ CHR(pGuid ? S_OK : E_INVALIDARG);
+ CHR(piMin ? S_OK : E_INVALIDARG);
+ CHR(piMax ? S_OK : E_INVALIDARG);
+ CHR(piUnits ? S_OK : E_INVALIDARG);
+ CHR(pflResolution ? S_OK : E_INVALIDARG);
+ // iProp value is checked above, disable prefast signedness warnings
+#pragma prefast(suppress: 37001 37002 37003)
+ pProp = &(m_pPacketDescription->pPacketProperties[iProp]);
+ *pGuid = pProp->guid;
+ *piMin = pProp->PropertyMetrics.nLogicalMin;
+ *piMax = pProp->PropertyMetrics.nLogicalMax;
+ *piUnits = pProp->PropertyMetrics.Units;
+ *pflResolution = pProp->PropertyMetrics.fResolution;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcContext::GetPacketButtonInfo(INT iButton, __out GUID * pGuid)
+{
+ DHR;
+ CHR(0 <= iButton && (DWORD)iButton < m_pPacketDescription->cButtons ? S_OK : E_INVALIDARG);
+ CHR(pGuid ? S_OK : E_INVALIDARG);
+ // iButton value is checked above, disable prefast signedness warnings
+#pragma prefast(suppress: 37001 37002 37003)
+ *pGuid = m_pPacketDescription->pguidButtons[iButton];
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcContext::DestroyPacketDescription(__in_opt PACKET_DESCRIPTION * pPacketDescription)
+{
+ if (pPacketDescription)
+ {
+ if (pPacketDescription->pPacketProperties)
+ CoTaskMemFree(pPacketDescription->pPacketProperties);
+
+ if (pPacketDescription->pguidButtons)
+ CoTaskMemFree(pPacketDescription->pguidButtons);
+
+ CoTaskMemFree(pPacketDescription);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::EnsureHandlesArray(INT cHandles)
+{
+ DHR;
+ if (m_cHandles < cHandles)
+ {
+ if (m_pHandles)
+ delete [] m_pHandles;
+ m_cHandles = cHandles * 2;
+ CHR_MEMALLOC(m_pHandles = new HANDLE[m_cHandles]);
+ }
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::EnsurePackets(DWORD cb)
+{
+ DHR;
+ if (m_cbPackets < cb)
+ {
+ if (m_pbPackets)
+ delete [] m_pbPackets;
+ m_cbPackets = max(256, cb * 2);
+ CHR_MEMALLOC(m_pbPackets = new BYTE[m_cbPackets]);
+ }
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::PostUpdate(DWORD update)
+{
+ DHR;
+ EnterCriticalSection(&m_csUpdates);
+ m_dwUpdatesPending |= update;
+ LeaveCriticalSection(&m_csUpdates);
+ SetEvent(m_hEventUpdate);
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::ExecuteUpdates()
+{
+ DWORD dwUpdatesPending;
+
+ EnterCriticalSection(&m_csUpdates);
+ dwUpdatesPending = m_dwUpdatesPending;
+ m_dwUpdatesPending = 0;
+ LeaveCriticalSection(&m_csUpdates);
+
+ CComPtr pCtxS = nullptr;
+
+ if (dwUpdatesPending)
+ {
+ // DDVSO:289954
+ // Access the underlying WISP tablet context in order to properly respond to updates
+ pCtxS = m_wispContextLock.GetComObject();
+
+ if (pCtxS != nullptr)
+ {
+ // (order of these is important)
+
+ if (dwUpdatesPending & UPDATE_SizeMove) // size, move
+ {
+ RECT rc;
+ pCtxS->TrackInputRect(&rc);
+ }
+ if (dwUpdatesPending & UPDATE_SendToBack) // send to back
+ {
+ // If we are in wisptis PREHOOK (IsTopMost==true) queue then we can't call the Overlap API.
+ if (!m_fIsTopmostHook)
+ {
+ TABLET_CONTEXT_ID tcidT;
+ pCtxS->Overlap(/*fTop*/FALSE, &tcidT);
+ }
+ }
+ if (dwUpdatesPending & UPDATE_SendToTop) // send to top
+ {
+ // If we are in wisptis PREHOOK (IsTopMost==true) queue then we can't call the Overlap API.
+ if (!m_fIsTopmostHook)
+ {
+ TABLET_CONTEXT_ID tcidT;
+ pCtxS->Overlap(/*fTop*/TRUE, &tcidT);
+ }
+ }
+ }
+ else
+ {
+ return E_INVALIDARG;
+ }
+ }
+
+ return S_OK;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcContext::GetLastSystemEventData(
+ __out INT * piEvent, __out INT * piModifier, __out INT * piKey,
+ __out INT * piX, __out INT * piY, __out INT * piCursorMode, __out INT * piButtonState)
+{
+ DHR;
+ CHR(piEvent ? S_OK : E_INVALIDARG);
+ CHR(piModifier ? S_OK : E_INVALIDARG);
+ CHR(piKey ? S_OK : E_INVALIDARG);
+ CHR(piX ? S_OK : E_INVALIDARG);
+ CHR(piY ? S_OK : E_INVALIDARG);
+ CHR(piCursorMode ? S_OK : E_INVALIDARG);
+ CHR(piButtonState ? S_OK : E_INVALIDARG);
+ *piEvent = (INT)m_sysEvt;
+ *piModifier = (INT)m_sysEvtData.bModifier;
+ *piKey = (INT)m_sysEvtData.wKey;
+ *piX = (INT)m_sysEvtData.xPos;
+ *piY = (INT)m_sysEvtData.yPos;
+ *piCursorMode = (INT)m_sysEvtData.bCursorMode;
+ *piButtonState = (INT)m_sysEvtData.dwButtonState;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::SetSingleFireTimeout(UINT uiTimeout)
+{
+ DHR;
+ CHR(1 <= uiTimeout ? S_OK : E_INVALIDARG);
+ m_dwSingleFireTimeout = uiTimeout;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef DELIVERY_PROFILING
+void CPimcContext::ProfilePackets(BOOL fDown, BOOL fUp, int x, int y)
+{
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+ unsigned t = counter.LowPart & LONG_MAX;
+
+ const int cMax = 5000;
+ static int cCur = 0;
+ static int xs[cMax];
+ static int ys[cMax];
+ static unsigned ts[cMax];
+
+ switch (fDown * 0x10 + fUp)
+ {
+ case 0x10: // down
+ cCur = 0;
+ // fall thru
+
+ case 0x00: // packets
+ if (cCur < cMax)
+ {
+ xs [cCur] = x;
+ ys [cCur] = y;
+ ts [cCur] = t;
+ cCur++;
+ }
+ break;
+
+ case 0x01: // up
+ {
+ FILE * pf = fopen("c:\\perf_penimc_strokeProfile_wait.xml", "a+");
+ if (pf)
+ {
+ fwprintf(pf, L" \n", cCur);
+
+ for (int i = 0; i < cCur; i++)
+ {
+ fwprintf(pf,
+ L" \n",
+ i, ts[i], xs[i], ys[i]);
+ }
+
+ fwprintf(pf, L" \n");
+
+ fclose(pf);
+ }
+ }
+ break;
+ }
+}
+#endif // DELIVERY_PROFILING
+
+///////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::GetPenEventCore(
+ DWORD dwWait,
+ __out BOOL * pfWaitAgain,
+ __out BOOL * pfShutdown,
+ __out INT * pEvt, __out INT * pCursorId,
+ __out INT * pcPackets, __out INT * pcbPacket, __out INT_PTR * pPackets)
+{
+ DHR;
+
+ ASSERT (pfShutdown);
+ *pfShutdown = FALSE;
+ *pfWaitAgain = FALSE;
+
+ switch (dwWait)
+ {
+ case WAIT_TIMEOUT:
+ m_fSingleFireTimeout = FALSE; // (only fire the timeout once before more data shows up)
+ *pEvt = 1; // timeout event
+ *pCursorId = 0;
+ *pcPackets = 0;
+ *pcbPacket = 0;
+ *pPackets = NULL;
+ break;
+
+ case WAIT_OBJECT_0 + 0: // update
+ *pfWaitAgain = TRUE;
+ ExecuteUpdates();
+ break;
+
+ case WAIT_OBJECT_0 + 1: // more data
+ {
+ m_fSingleFireTimeout = TRUE; // (got more data, set up for the time out again)
+
+ // obtain mutex on the data
+ DWORD dwWaitAccess = WaitForSingleObject(m_hMutexSharedMemory, INFINITE);
+ CHR(dwWaitAccess == WAIT_OBJECT_0 ? S_OK : E_FAIL);
+
+ // get the data
+ switch (m_pSharedMemoryHeader->dwEvent)
+ {
+ case WM_TABLET_PACKET:
+ case WM_TABLET_CURSORDOWN:
+ case WM_TABLET_CURSORUP:
+ *pEvt = m_pSharedMemoryHeader->dwEvent;
+ *pCursorId = m_pSharedMemoryHeader->cid;
+ *pcPackets = m_pSharedMemoryHeader->cPackets;
+ *pcbPacket = m_pSharedMemoryHeader->cbPackets / m_pSharedMemoryHeader->cPackets;
+ CHR(EnsurePackets(m_pSharedMemoryHeader->cbPackets));
+ CopyMemory(m_pbPackets, m_pbSharedMemoryPackets, m_pSharedMemoryHeader->cbPackets);
+ *pPackets = (INT_PTR)m_pbPackets;
+
+#ifdef DELIVERY_PROFILING
+ for (INT iPacket = 0; iPacket < *pcPackets; iPacket++)
+ {
+ INT iOffset = iPacket * (*pcbPacket) / sizeof(LONG);
+ switch (m_pSharedMemoryHeader->dwEvent)
+ {
+ case WM_TABLET_PACKET: ProfilePackets(/*fDown*/FALSE, /*fUp*/FALSE, ((LONG*)m_pbSharedMemoryPackets)[iOffset + 0], ((LONG*)m_pbSharedMemoryPackets)[iOffset + 1]); break;
+ case WM_TABLET_CURSORDOWN: ProfilePackets(/*fDown*/TRUE, /*fUp*/FALSE, ((LONG*)m_pbSharedMemoryPackets)[iOffset + 0], ((LONG*)m_pbSharedMemoryPackets)[iOffset + 1]); break;
+ case WM_TABLET_CURSORUP: ProfilePackets(/*fDown*/FALSE, /*fUp*/TRUE, ((LONG*)m_pbSharedMemoryPackets)[iOffset + 0], ((LONG*)m_pbSharedMemoryPackets)[iOffset + 1]); break;
+ }
+ }
+#endif
+ break;
+
+ case WM_TABLET_CURSORINRANGE:
+ case WM_TABLET_CURSOROUTOFRANGE:
+ *pEvt = m_pSharedMemoryHeader->dwEvent;
+ *pCursorId = m_pSharedMemoryHeader->cid;
+ *pcPackets = 0;
+ *pcbPacket = 0;
+ *pPackets = NULL;
+ break;
+
+ case WM_TABLET_SYSTEMEVENT:
+ *pEvt = m_pSharedMemoryHeader->dwEvent;
+ *pCursorId = m_pSharedMemoryHeader->cid;
+ *pcPackets = 0;
+ *pcbPacket = 0;
+ *pPackets = NULL;
+ m_sysEvt = m_pSharedMemoryHeader->sysEvt;
+ m_sysEvtData = m_pSharedMemoryHeader->sysEvtData;
+ break;
+
+ default:
+ *pEvt = 0;
+ *pCursorId = 0;
+ *pcPackets = 0;
+ *pcbPacket = 0;
+ *pPackets = NULL;
+ break;
+ }
+
+ // release the mutex we holding and signal wisptis to put more data here
+ m_pSharedMemoryHeader->dwEvent = WISPTIS_SHAREDMEMORY_AVAILABLE;
+ ReleaseMutex(m_hMutexSharedMemory);
+ SetEvent(m_hEventClientReady);
+ }
+ break;
+
+ case WAIT_OBJECT_0 + 2: // reset
+ *pfShutdown = TRUE;
+ break;
+
+ default: // an error condition; just keep rolling
+ break;
+ }
+
+CLEANUP:
+ RHR;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::GetPenEvent(
+ __in_opt HANDLE hEventReset, __out BOOL * pfShutdown,
+ __out INT * pEvt, __out INT * pCursorId,
+ __out INT * pcPackets, __out INT * pcbPacket, __out INT_PTR * pPackets)
+{
+ DHR;
+ DWORD cObjects = 2;
+ HANDLE ahObjects[3];
+ ahObjects[0] = m_hEventUpdate;
+ ahObjects[1] = m_hEventMoreData;
+ if (hEventReset)
+ {
+ ahObjects[cObjects] = hEventReset;
+ cObjects++;
+ }
+
+ for (;;)
+ {
+ DWORD dwTimeout = m_fSingleFireTimeout ? m_dwSingleFireTimeout : INFINITE;
+ DWORD dwWait = MsgWaitForMultipleObjectsEx(cObjects, ahObjects, dwTimeout, 0, MWMO_ALERTABLE);
+
+ BOOL fWaitAgain = FALSE;
+ CHR(GetPenEventCore(dwWait, &fWaitAgain, pfShutdown, pEvt, pCursorId, pcPackets, pcbPacket, pPackets));
+ if (!fWaitAgain)
+ break;
+ }
+
+CLEANUP:
+ RHR;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcContext::GetPenEventMultiple(
+ INT cCtxs, __in_ecount(cCtxs) CPimcContext ** ppCtxs,
+ __in_opt HANDLE hEventReset,
+ __out BOOL * pfShutdown,
+ __out INT * piCtxEvt,
+ __out INT * pEvt, __out INT * pCursorId,
+ __out INT * pcPackets, __out INT * pcbPacket, __out INT_PTR * pPackets)
+{
+ DHR;
+
+ ASSERT (pfShutdown);
+ *pfShutdown = FALSE;
+
+ HANDLE * pHandles = NULL;
+ INT cHandles = 0;
+ BOOL fSingleFireTimeout = FALSE;
+ DWORD dwSingleFireTimeout = INFINITE;
+ INT cCtxEvents = 0;
+ CPimcContext ** ppCtxCur = NULL;
+
+ // See if we have a special case where we don't have any real pen contexts
+ // and just created the pen thread to get the UIContext on the pen thread set
+ // up. In this case we only need to wait for the reset event.
+ if (cCtxs == 0)
+ {
+ cHandles = 1;
+ pHandles = &hEventReset;
+ //fSingleFireTimeout = true;
+ //dwSingleFireTimeout = 500; // check every 500ms to see if we should shut down.
+ }
+ else
+ {
+ ASSERT (cCtxs);
+ ASSERT (piCtxEvt);
+
+ // build up the wait array
+ for (INT i = 0; i < cCtxs; i++)
+ {
+ CPimcContext * pCtxHandleArray = ppCtxs[i];
+
+ // Create handles array on the context only if it participates in the wait.
+ if (pCtxHandleArray != NULL &&
+ pCtxHandleArray->m_hEventMoreData)
+ {
+ CHR(pCtxHandleArray->EnsureHandlesArray(2 * cCtxs + 1)); // ASSUMPTION (alexz) no context is invoked on 2 separate threads
+ // via GetPenEvent/GetPenEventMultiple, at the same time
+ pHandles = pCtxHandleArray->m_pHandles;
+ break;
+ }
+ }
+
+ if (NULL == pHandles)
+ {
+ cHandles = 1;
+ pHandles = &hEventReset;
+ }
+ else
+ {
+ HANDLE * phCur = pHandles;
+
+ ppCtxCur = ppCtxs;
+ for (INT i = 0; i < cCtxs; i++)
+ {
+ if ((*ppCtxCur) && (*ppCtxCur)->m_hEventMoreData)
+ {
+ *phCur = (*ppCtxCur)->m_hEventUpdate;
+ phCur++;
+ cHandles++;
+
+ *phCur = (*ppCtxCur)->m_hEventMoreData;
+ phCur++;
+ cHandles++;
+
+ fSingleFireTimeout |= (*ppCtxCur)->m_fSingleFireTimeout;
+ dwSingleFireTimeout = min (dwSingleFireTimeout, (*ppCtxCur)->m_dwSingleFireTimeout);
+ }
+ ppCtxCur++;
+ }
+
+ cCtxEvents = cHandles;
+ if (hEventReset)
+ {
+ *phCur = hEventReset;
+ phCur++;
+ cHandles++;
+ }
+ }
+ }
+
+ // do the wait
+ for (;;)
+ {
+ DWORD dwTimeout = fSingleFireTimeout ? dwSingleFireTimeout : INFINITE;
+ DWORD dwWait = MsgWaitForMultipleObjectsEx(cHandles, pHandles, dwTimeout, 0, MWMO_ALERTABLE);
+ BOOL fWaitAgain = FALSE;
+ // dispatch the result of wait
+ if (dwWait == WAIT_TIMEOUT)
+ {
+ // If we hit a timeout when we don't have any real contexts then just deal with it as a
+ // shutdown so we'll check to see if we should shut this thread down.
+ if (cCtxs == 0)
+ {
+ *pfShutdown = TRUE;
+ }
+ else
+ {
+ *piCtxEvt = 0;
+ *pEvt = 1; // timeout event
+ *pCursorId = 0;
+ *pcPackets = 0;
+ *pcbPacket = 0;
+ *pPackets = NULL;
+ ppCtxCur = ppCtxs;
+ for (INT i = 0; i < cCtxs; i++)
+ {
+ if ( (*ppCtxCur) != NULL )
+ (*ppCtxCur)->m_fSingleFireTimeout = FALSE; // (only fire the timeout once before more data shows up)
+
+ ppCtxCur++;
+ }
+ }
+ }
+ else if (dwWait < WAIT_OBJECT_0 + cCtxEvents)
+ {
+ // Either more data or update event for a context was
+ // signaled. Find it and call GetPenEventCore on it.
+ HANDLE signaledHandle = pHandles[dwWait];
+ *piCtxEvt = -1;
+ for (INT i = 0; i < cCtxs; i++)
+ {
+ // Check if the signaled handle belongs to this context
+ CPimcContext * pCtxHandle = ppCtxs[i];
+ if (pCtxHandle != NULL &&
+ (pCtxHandle->m_hEventMoreData == signaledHandle ||
+ pCtxHandle->m_hEventUpdate == signaledHandle))
+ {
+ *piCtxEvt = i;
+ break;
+ }
+ }
+ ASSERT(*piCtxEvt != -1);
+ CPimcContext * pCtxEvt = ppCtxs[*piCtxEvt];
+ dwWait = dwWait % 2;
+ CHR(pCtxEvt->GetPenEventCore(dwWait, &fWaitAgain, pfShutdown, pEvt, pCursorId, pcPackets, pcbPacket, pPackets));
+ }
+ else if (WAIT_OBJECT_0 + cCtxEvents == dwWait)
+ {
+ // wait was reset
+ *pfShutdown = TRUE;
+ }
+ else
+ {
+ // an unexpected condition; ignore it
+ }
+ if (!fWaitAgain)
+ break;
+ }
+
+CLEANUP:
+ RHR;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" BOOL WINAPI GetPenEvent(
+ __typefix(CPimcContext *) __in INT_PTR commHandle,
+ __typefix(HANDLE) __in_opt INT_PTR commHandleReset,
+ __out INT * pEvt, __out INT * pCursorId,
+ __out INT * pcPackets, __out INT * pcbPacket, __out INT_PTR * pPackets)
+{
+ CPimcContext * pCtx = nullptr;
+ DHR;
+ BOOL fShutdown = TRUE;
+ CHR(commHandle && pEvt && pCursorId && pcPackets && pcbPacket && pPackets ? S_OK : E_INVALIDARG);
+ pCtx = (CPimcContext *)commHandle;
+ CHR(pCtx->GetPenEvent((HANDLE)commHandleReset, &fShutdown, pEvt, pCursorId, pcPackets, pcbPacket, pPackets));
+
+CLEANUP:
+ return SUCCEEDED(hr) && !fShutdown;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" BOOL WINAPI GetPenEventMultiple(
+ INT cCommHandles, __typefix(CPimcContext **) __in_ecount(cCommHandles) INT_PTR * pCommHandles,
+ __typefix(HANDLE) __in_opt INT_PTR commHandleReset,
+ __out INT * piEvt,
+ __out INT * pEvt, __out INT * pCursorId,
+ __out INT * pcPackets, __out INT * pcbPacket, __out INT_PTR * pPackets)
+{
+ DHR;
+ BOOL fShutdown = TRUE;
+
+ CHR (((cCommHandles == 0 && commHandleReset) ||
+ (cCommHandles && pCommHandles && commHandleReset &&
+ piEvt && pEvt && pCursorId && pcPackets && pcbPacket && pPackets)) ?
+ S_OK : E_INVALIDARG);
+
+ CHR(CPimcContext::GetPenEventMultiple(
+ cCommHandles, (CPimcContext **)pCommHandles,
+ (HANDLE) commHandleReset,
+ &fShutdown,
+ piEvt,
+ pEvt, pCursorId,
+ pcPackets, pcbPacket, pPackets));
+
+CLEANUP:
+ return SUCCEEDED(hr) && !fShutdown;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" BOOL WINAPI GetLastSystemEventData(
+ __typefix(CPimcContext *) __in INT_PTR commHandle,
+ __out INT * piEvent, __out INT * piModifier, __out INT * piKey,
+ __out INT * piX, __out INT * piY, __out INT * piCursorMode, __out INT * piButtonState)
+{
+ CPimcContext * pCtx = nullptr;
+ DHR;
+ CHR(piEvent && piModifier && piKey && piX && piY && piCursorMode && piButtonState ? S_OK : E_INVALIDARG);
+ pCtx = (CPimcContext *)commHandle;
+ CHR(pCtx->GetLastSystemEventData(piEvent, piModifier, piKey, piX, piY, piCursorMode, piButtonState));
+CLEANUP:
+ return SUCCEEDED(hr);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" BOOL WINAPI CreateResetEvent(__out INT_PTR * pCommHandleReset)
+{
+ HANDLE hEventReset = nullptr;
+ DHR;
+ CHR (pCommHandleReset ? S_OK : E_INVALIDARG);
+ hEventReset = CreateEvent(NULL, FALSE, FALSE, NULL);
+ CHR(hEventReset ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_CANNOTCREATERESETEVENT));
+ *pCommHandleReset = (INT_PTR)hEventReset;
+CLEANUP:
+ return SUCCEEDED(hr);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" BOOL WINAPI DestroyResetEvent(__typefix(HANDLE) __in INT_PTR commHandleReset)
+{
+ HANDLE hEventReset = nullptr;
+ DHR;
+ CHR (commHandleReset ? S_OK : E_INVALIDARG);
+ hEventReset = (HANDLE)commHandleReset;
+ CloseHandle(hEventReset);
+CLEANUP:
+ return SUCCEEDED(hr);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" BOOL WINAPI RaiseResetEvent(__typefix(HANDLE) __in INT_PTR commHandleReset)
+{
+ HANDLE hEventReset = nullptr;
+ DHR;
+ CHR (commHandleReset ? S_OK : E_INVALIDARG);
+ hEventReset = (HANDLE)commHandleReset;
+ SetEvent(hEventReset);
+CLEANUP:
+ return SUCCEEDED(hr);
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcContext.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcContext.h
new file mode 100644
index 00000000000..baadedd8b42
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcContext.h
@@ -0,0 +1,208 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PimcContext.h : Declaration of the CPimcContext
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "PenImc.h"
+#include "PimcManager.h"
+#include "ComLockableWrapper.hpp"
+#include "GitComLockableWrapper.hpp"
+
+/////////////////////////////////////////////////////////////////////////////
+// CPimcContext
+
+class ATL_NO_VTABLE CPimcContext :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IPimcContext3
+{
+public:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ CPimcContext();
+ HRESULT FinalConstruct() { return S_OK; } ;
+ void FinalRelease();
+ HRESULT Init(__inout CComPtr pMgr,
+ __in_opt CComPtr pCtxS,
+ __in HWND hwnd,
+ TABLET_CONTEXT_ID tcid,
+ PACKET_DESCRIPTION * pPacketDescription);
+
+ HRESULT InitUnnamedCommunications(__in CComPtr pCtxP);
+ HRESULT InitNamedCommunications(__in CComPtr pCtxP);
+ HRESULT InitCommunicationsCore();
+
+ void ShutdownSharedMemoryCommunications();
+
+ HRESULT GetPenEvent (__in_opt HANDLE hEventReset, __out BOOL * pfShutdown, __out INT * pEvt, __out INT * pCursorId, __out INT * pcPackets, __out INT * pcbPacket, __out INT_PTR * pPackets);
+ HRESULT GetPenEventCore (DWORD dwWait, __out BOOL * pfWaitAgain, __out BOOL * pfShutdown, __out INT * pEvt, __out INT * pCursorId, __out INT * pcPackets, __out INT * pcbPacket, __out INT_PTR * pPackets);
+
+ static HRESULT GetPenEventMultiple(
+ INT cCtxs, __in_ecount(cCtxs) CPimcContext ** ppCtxs,
+ __in_opt HANDLE hEventAbort,
+ __out BOOL * pfShutdown,
+ __out INT * piCtxEvt,
+ __out INT * pEvt, __out INT * pCursorId,
+ __out INT * pcPackets, __out INT * pcbPacket, __out INT_PTR * pPackets);
+
+ STDMETHOD(ShutdownComm)();
+ STDMETHOD(GetPacketDescriptionInfo)(__out INT * pcProps, __out INT * pcButtons);
+ STDMETHOD(GetPacketPropertyInfo)(INT iProp, __out GUID * pGuid, __out INT * piMin, __out INT * piMax, __out INT * piUnits, __out FLOAT *pflResolution);
+ STDMETHOD(GetPacketPropertyInfoImpl)(INT iProp, __out GUID * pGuid, __out INT * piMin, __out INT * piMax, __out INT * piUnits, __out FLOAT *pflResolution);
+ STDMETHOD(GetPacketButtonInfo)(INT iButton, __out GUID * pGuid);
+ STDMETHOD(GetLastSystemEventData)(__out INT * piEvent, __out INT * piModifier, __out INT * piKey, __out INT * piX, __out INT * piY, __out INT * piCursorMode, __out INT * piButtonState);
+
+ HRESULT GetCommHandle(__out INT64* pHandle);
+ HRESULT GetKey(__out INT * pKey);
+ HRESULT SetSingleFireTimeout(UINT uiTimeout);
+ HRESULT EnsureHandlesArray(INT cHandles);
+ HRESULT EnsurePackets(DWORD cb);
+ static void DestroyPacketDescription(__in_opt PACKET_DESCRIPTION * pPacketDescription);
+
+#ifdef DELIVERY_PROFILING
+ void ProfilePackets(BOOL fDown, BOOL fUp, int x, int y);
+#endif
+
+ const static DWORD UPDATE_SizeMove = 0x01;
+ const static DWORD UPDATE_SendToTop = 0x02;
+ const static DWORD UPDATE_SendToBack = 0x04;
+ const static DWORD UPDATE_Enable = 0x08;
+ const static DWORD UPDATE_Disable = 0x10;
+
+ HRESULT PostUpdate(DWORD update);
+ HRESULT ExecuteUpdates();
+
+ /////////////////////////////////////////////////////////////////////////
+
+BEGIN_COM_MAP(CPimcContext)
+ COM_INTERFACE_ENTRY(IPimcContext3)
+END_COM_MAP()
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ /////////////////////////////////////////////////////////////////////////
+
+ class CEventSink : public ITabletEventSink
+ {
+ public:
+
+ // DDVSO:514949
+ // The lifetime of this object needs to be correctly tracked via
+ // its IUnknown implementation as this will be passed onto WISP
+ // when a WISP context is created. WISP stores this in a CComPtr
+ // member variable and this object must be alive when the WISP
+ // context accesses it, even if the enclosing CPimcContext is
+ // already destroyed.
+ CEventSink() : m_cRef(0)
+ {
+ }
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID riid, __typefix(ITabletEventSink **) __deref_out_opt void** ppv)
+ {
+ DHR;
+ if (IsEqualGUID(riid, IID_IUnknown) ||
+ IsEqualGUID(riid, IID_ITabletEventSink))
+ {
+ *ppv = (ITabletEventSink*)this;
+ AddRef();
+ hr = S_OK;
+ }
+ else
+ {
+ *ppv = NULL;
+ hr = E_NOINTERFACE;
+ }
+ RHR;
+ }
+
+ STDMETHOD_(ULONG, AddRef) ()
+ {
+ LONG newRefCount = InterlockedIncrement(&m_cRef);
+ return static_cast(newRefCount);
+ }
+
+ STDMETHOD_(ULONG, Release)()
+ {
+ LONG newRefCount = InterlockedDecrement(&m_cRef);
+
+ // We should fail immediately if the ref count is ever below 0.
+ // We want to know, even in production, if we have any unbalanced releases.
+ ATLASSERT(newRefCount >= 0);
+
+ if (newRefCount == 0)
+ {
+ delete this;
+ }
+
+ return static_cast(newRefCount);
+ }
+
+ LONG m_cRef;
+
+ // ITabletEventSink
+ STDMETHOD(ContextCreate) (TABLET_CONTEXT_ID tcid) { return S_OK; }
+ STDMETHOD(ContextDestroy) (TABLET_CONTEXT_ID tcid) { return S_OK; }
+ STDMETHOD(CursorNew) (TABLET_CONTEXT_ID tcid, CURSOR_ID cid) { return S_OK; }
+ STDMETHOD(CursorInRange) (TABLET_CONTEXT_ID tcid, CURSOR_ID cid) { return S_OK; }
+ STDMETHOD(CursorOutOfRange) (TABLET_CONTEXT_ID tcid, CURSOR_ID cid) { return S_OK; }
+ STDMETHOD(CursorMove) (TABLET_CONTEXT_ID tcid, CURSOR_ID cid, HWND hWnd, LONG xPos, LONG yPos) { return S_OK; }
+ STDMETHOD(CursorDown) (TABLET_CONTEXT_ID tcid, CURSOR_ID cid, ULONG nSerialNumber, ULONG cbPkt, BYTE * pbPkt) { return S_OK; }
+ STDMETHOD(CursorUp) (TABLET_CONTEXT_ID tcid, CURSOR_ID cid, ULONG nSerialNumber, ULONG cbPkt, BYTE * pbPkt) { return S_OK; }
+ STDMETHOD(Packets) (TABLET_CONTEXT_ID tcid, ULONG cPkts, ULONG cbPkts, BYTE * pbPkts, ULONG * pnSerialNumbers, CURSOR_ID cid) { return S_OK; }
+ STDMETHOD(SystemEvent) (TABLET_CONTEXT_ID tcid, CURSOR_ID cid, SYSTEM_EVENT, SYSTEM_EVENT_DATA) { return S_OK; }
+ };
+
+ CComPtr m_sink;
+
+
+ /////////////////////////////////////////////////////////////////////////
+
+ // data
+
+ CComPtr m_pMgr;
+ CComPtr m_pCtxS;
+ TABLET_CONTEXT_ID m_tcid;
+ PACKET_DESCRIPTION * m_pPacketDescription;
+
+ HANDLE m_hEventMoreData;
+ HANDLE m_hEventClientReady;
+ HANDLE m_hMutexSharedMemory;
+ HANDLE m_hFileMappingSharedMemory;
+ SHAREDMEMORY_HEADER * m_pSharedMemoryHeader;
+ BYTE * m_pbSharedMemoryRawData;
+ BYTE * m_pbSharedMemoryPackets;
+ BOOL m_fCommHandleOutstanding;
+ INT m_cHandles;
+ HANDLE * m_pHandles;
+ DWORD m_cbPackets;
+ BYTE* m_pbPackets;
+ SYSTEM_EVENT m_sysEvt;
+ SYSTEM_EVENT_DATA m_sysEvtData;
+
+ HookThreadItemKey m_keyHookThreadItem;
+ CPimcManager::HookWindowItemKey m_keyHookWindowItem;
+
+ HANDLE m_hEventUpdate;
+ DWORD m_dwUpdatesPending;
+ CRITICAL_SECTION m_csUpdates;
+
+ BOOL m_fSingleFireTimeout : 1;
+ BOOL m_fIsTopmostHook : 1;
+ DWORD m_dwSingleFireTimeout;
+
+ ComUtils::ComLockableWrapper m_contextLock;
+ ComUtils::ComLockableWrapper m_sinkLock;
+ ComUtils::GitComLockableWrapper m_wispContextLock;
+
+ // DDVSO:514949
+ // Special param flag for COM operations in GetPacketPropertyInfo.
+ static const int QUERY_WISP_CONTEXT_KEY = -1;
+};
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcManager.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcManager.cpp
new file mode 100644
index 00000000000..0c8b10a8af4
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcManager.cpp
@@ -0,0 +1,1188 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PimcManager.cpp : Implementation of CPimcManager
+
+#include "stdafx.h"
+#include "OSVersionHelper.h"
+#include "PimcContext.h"
+#include "PimcTablet.h"
+#include "PimcManager.h"
+#include "Penimc.h"
+#include "shellapi.h"
+#include
+#include "osversionhelper.h"
+
+using namespace ComUtils;
+
+// from drivers/tablet/include/tabinc.h:
+#define PENPROCESS_WISPTIS_REQUEST_EVENT _T("{773F1B9A-35B9-4E95-83A0-A210F2DE3B37}-request")
+#define PENPROCESS_WISPTIS_RUNNING_EVENT _T("{773F1B9A-35B9-4E95-83A0-A210F2DE3B37}-running")
+// Our local define for how long we'll wait for Tablet Input Service to load wisptis.
+#define PENPROCESS_WISPTIS_LOADING_TIMEOUT 30000 // 30 seconds
+#define WISPTIS_DIR _T("%SystemRoot%\\SYSTEM32\\")
+#define WISPTIS_NAME _T("WISPTIS.EXE")
+#define WISPTIS_MANUAL_LAUNCH _T("/ManualLaunch;")
+
+#define KERNEL32_NAME _T("KERNEL32")
+#define WOW64DISABLEWOW64FSREDIRECTION_NAME "Wow64DisableWow64FsRedirection"
+#define WOW64REVERTWOW64FSREDIRECTION_NAME "Wow64RevertWow64FsRedirection"
+typedef BOOL (WINAPI *LPFNWOW64DISABLEWOW64FSREDIRECTION) (PVOID*);
+typedef BOOL (WINAPI *LPFNWOW64REVERTWOW64FSREDIRECTION) (PVOID);
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+class CAsyncData
+{
+public:
+ CAsyncData(DWORD dwArg, BOOL fArg = FALSE, BOOL fEventAck = FALSE)
+ : m_dwArg(dwArg), m_fArg(fArg)
+ {
+ m_hEventAck = fEventAck ? CreateEvent(NULL, FALSE, FALSE, NULL) : NULL;
+ }
+ ~CAsyncData()
+ {
+ if (m_hEventAck)
+ {
+ CloseHandle(m_hEventAck);
+ }
+ }
+ void SignalAck()
+ {
+ if (m_hEventAck)
+ SetEvent(m_hEventAck);
+ }
+ void WaitAck()
+ {
+ if (m_hEventAck)
+ {
+ WaitForSingleObject(m_hEventAck, INFINITE);
+ }
+ }
+
+ HANDLE m_hEventAck;
+ DWORD_PTR m_dwArg;
+ BOOL m_fArg;
+ DWORD_PTR m_dwRes;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CPimcManager
+
+/////////////////////////////////////////////////////////////////////////////
+
+// Store the thread map globally so we can look up the manager given
+// a window in the HookProc since we don't have access to an instance of the
+// CPimcManager at that time.
+CPbList g_HookThreadMap;
+
+HANDLE g_hMutexHook = NULL;
+
+#ifdef DBG_LATER
+DWORD g_dwMutexHookOwnerThreadId = 0;
+BOOL g_cHookLock = 0;
+#endif
+
+CPimcManager::CPimcManager() :
+#if WANT_PROFILE
+ m_fIsProfilingCached(FALSE),
+#endif
+ m_fLoadedWisptis(FALSE)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcManager::FinalConstruct()
+{
+ DHR;
+
+ // DDVSO:514949
+ // Calling this ensures that the CStdIdentity for this IPimcManager3 is
+ // not released if we hit a COM rundown due to OSGVSO:10779198.
+ m_managerLock = ComLockableWrapper(this, ComApartmentVerifier::CurrentSta());
+ CHR(m_managerLock.Lock());
+
+ // Verify the mutex we created in DllLoad went OK.
+ CHR(g_hMutexHook ? S_OK : E_FAIL);
+
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcManager::LoadWisptis()
+{
+ DHR;
+
+ if (!m_fLoadedWisptis)
+ {
+ // **********
+ // NOTE: PenIMC has duplicated the code for loading wisptis from InkObj.
+ // Whenever WIC team makes any changes, we should coordinate with them to work on fixes.
+ // **********
+ if (IsVistaOrGreater())
+ {
+ // DDVSO 144719. There are some scenarios were we must skip loading wisptis since
+ // they are not supported and can cause delays or crashes.
+ if (ShouldLoadWisptis())
+ {
+ // we do this to signal TabSvc that it needs to spin up wisptis
+ // so that it is at the right IL.
+ HANDLE hEventRequest = OpenEvent(EVENT_MODIFY_STATE, FALSE, PENPROCESS_WISPTIS_REQUEST_EVENT);
+ HANDLE hEventRunning = OpenEvent(SYNCHRONIZE, FALSE, PENPROCESS_WISPTIS_RUNNING_EVENT);
+
+ //if we don't have the event (TabSvc isn't running), or we timed out,
+ // that means Wisptis isn't running, so we'll start it; we do this via
+ // ShellExecute so that it gets started at high-IL (as indicated by
+ // Wisptis's manifest) to avoid IL-mismatch issues
+ //we allow wisptis to be started without TabSvc for backcompat
+
+ if(hEventRunning == NULL)
+ {
+ // create the event since TabSvc isn't running
+ hEventRunning = CreateEvent(NULL, TRUE, FALSE, PENPROCESS_WISPTIS_RUNNING_EVENT);
+ }
+
+ if(hEventRequest != NULL && hEventRunning != NULL)
+ {
+ //when this wait returns, wisptis will have registered its classes with COM
+ //if this fails or times out, we'll risk starting wisptis at a mismatched IL
+ DWORD dwResult = SignalObjectAndWait(hEventRequest, hEventRunning, 30000 /* thirty seconds */, FALSE);
+
+ hr = dwResult == WAIT_OBJECT_0 ? S_OK : E_FAIL;
+ }
+
+ // DDVSO:398137
+ // Since hEventRequest is no longer of use at this point, close the handle.
+ SafeCloseHandle(&hEventRequest);
+
+ if(/* wait timed out */ FAILED(hr) ||
+ /* couldn't open the event for some reason */ hEventRunning == NULL ||
+ /* wisptis isn't already running */ WaitForSingleObject(hEventRunning, 0) == WAIT_TIMEOUT)
+ {
+ PVOID pvOldValue = NULL;
+ BOOL bIsWow64 = FALSE;
+ LPFNWOW64DISABLEWOW64FSREDIRECTION fnWow64DisableWow64FsRedirection = NULL;
+ LPFNWOW64REVERTWOW64FSREDIRECTION fnWow64RevertWow64FsRedirection = NULL;
+ HMODULE hKernel32 = NULL;
+
+ // Check whether this is running under Wow64 and, if so, disable file system redirection
+ // on the current thread - otherwise it will look for wisptis in the syswow64 directory
+ // instead of system32.
+ TPDBG_VERIFY(IsWow64Process(GetCurrentProcess(),&bIsWow64));
+ if (bIsWow64)
+ {
+ // NOTICE-2006/06/13-WAYNEZEN,
+ // Since penimc may also run on the top of XPSP2, We cannot call Wow64DisableWow64FsRedirection/Wow64RevertWow64FsRedirection
+ // directly. Otherwise it will cause Entry Point Not Found error even though we don't really on those functions on 32-bit XP.
+ // So we have to use GetProcAddress to resovle the function address dynamically.
+ hKernel32 = GetModuleHandle(KERNEL32_NAME);
+ fnWow64DisableWow64FsRedirection = (LPFNWOW64DISABLEWOW64FSREDIRECTION)GetProcAddress(
+ hKernel32, WOW64DISABLEWOW64FSREDIRECTION_NAME);
+ fnWow64RevertWow64FsRedirection = (LPFNWOW64REVERTWOW64FSREDIRECTION)GetProcAddress(
+ hKernel32, WOW64REVERTWOW64FSREDIRECTION_NAME);
+
+ TPDBG_VERIFY(fnWow64DisableWow64FsRedirection(&pvOldValue));
+ }
+
+ SHELLEXECUTEINFO sei = {0};
+
+ sei.cbSize = sizeof(sei);
+ sei.lpFile = WISPTIS_DIR WISPTIS_NAME;
+ sei.lpParameters = WISPTIS_MANUAL_LAUNCH;
+ sei.lpVerb = NULL;
+ sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI;
+ sei.lpDirectory = WISPTIS_DIR;
+ sei.hInstApp = (HINSTANCE)0;
+
+ BOOL bResult = ShellExecuteEx(&sei);
+
+ // Restore the file system redirection settings.
+ if (bIsWow64)
+ {
+ TPDBG_VERIFY(fnWow64RevertWow64FsRedirection(pvOldValue));
+ }
+
+ hr = bResult ? S_OK : E_FAIL;
+ if(FAILED(hr))
+ {
+ OutputDebugString(L"PimcManager::LoadWisptis failed to ShellExecuteEx.\r\n");
+ }
+ }
+
+ if(SUCCEEDED(hr) && hEventRunning != NULL)
+ {
+ (void)WaitForSingleObject(hEventRunning, PENPROCESS_WISPTIS_LOADING_TIMEOUT /* 30 seconds */);
+ //regardless of the return from this, we'll still try to spin wisptis up via COM
+ }
+
+ SafeCloseHandle(&hEventRunning);
+
+ if(SUCCEEDED(hr))
+ {
+ CHR(m_pMgrS.CoCreateInstance(CLSID_TabletManagerS)); //, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER));
+
+ // Ensure the WISP tablet manager is added to the GIT.
+ m_wispManagerLock = GitComLockableWrapper(m_pMgrS, ComApartmentVerifier::Mta());
+ CHR(m_wispManagerLock.CheckCookie());
+
+ m_fLoadedWisptis = TRUE;
+ }
+ }
+ }
+ else
+ {
+ // To get around the issue with spinning up two wisptis.exe instances per user session we create an
+ // object that is a local server (using DllHost.exe to host one of our objects out of proc) that is
+ // marked as RunAs="Interactive User" to make sure it gets launched with the user's full priveledges.
+ // We then CoCreateInstance the wisptis.exe object from there to ensure we don't spin up an extra instance
+ // of wisptis.exe. The PimcSurrogate object is implemented in penimc.dll.
+ CComPtr pSurrogate;
+ CComPtr pTabletManager;
+ CHR(pSurrogate.CoCreateInstance(CLSID_PimcSurrogate3, NULL, CLSCTX_LOCAL_SERVER));
+ CHR(pSurrogate != NULL ? S_OK : E_UNEXPECTED);
+ CHR(pSurrogate->GetWisptisITabletManager(&pTabletManager));
+ CHR(pTabletManager->QueryInterface(IID_ITabletManager, (void**)&m_pMgrS));
+ m_fLoadedWisptis = TRUE;
+ }
+ }
+
+CLEANUP:
+ // No return code needed.
+ return;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+BOOL CPimcManager::IsVistaOrGreater()
+{
+ static bool bIsVistaOrGreater = WPFUtils::OSVersionHelper::IsWindowsVistaOrGreater();
+ return bIsVistaOrGreater;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+BOOL CPimcManager::ShouldLoadWisptis()
+{
+ // DDVSO 144719. Wisptis(Vista & 7) doesn't support inking while running under the system account
+ // Wisp (Win8 and above) supports this scenario, so we check for OS version and then for system account
+ static bool bShouldLoadWisptis = WPFUtils::OSVersionHelper::IsWindows8OrGreater() ||
+ !UserIsLocalSystem();
+ return bShouldLoadWisptis;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+BOOL CPimcManager::UserIsLocalSystem()
+{
+ BOOL fLocalSystem = FALSE;
+
+ HANDLE hProcess = GetCurrentProcess();
+ HANDLE hToken;
+ if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
+ {
+ DWORD retLength = 0;
+ GetTokenInformation(hToken, TokenUser, nullptr, 0, &retLength);
+ if (retLength)
+ {
+ BYTE* tUser = new (std::nothrow) BYTE[retLength];
+ if (tUser)
+ {
+ DWORD dwRealLength = retLength;
+ if(GetTokenInformation(hToken, TokenUser, tUser, dwRealLength, &retLength))
+ {
+ PSID SIDSystem;
+ SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
+ if(AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID,
+ 0, 0, 0, 0, 0, 0, 0, &SIDSystem))
+ {
+ fLocalSystem = EqualSid(((TOKEN_USER*)tUser)->User.Sid, SIDSystem);
+ FreeSid(SIDSystem);
+ }
+ }
+ delete [] tUser;
+ }
+ }
+ CloseHandle(hToken);
+ }
+
+ return fLocalSystem;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcManager::InitializeHookThread(__inout CHookThreadItem * pThread)
+{
+ DHR;
+
+ BOOL fCleanupThread = FALSE;
+ CAsyncData * pAsyncData = NULL;
+
+ DWORD dwHookThread = 0;
+ DWORD dwWaitHookThread = WAIT_FAILED;
+
+ // Only need to do this once.
+ ASSERT(!pThread->m_hHook);
+
+ // hook handling
+ pThread->m_hEventHookThreadReady = CreateEvent(NULL, FALSE, FALSE, NULL);
+ pThread->m_hEventHookThreadExit = CreateEvent(NULL, FALSE, FALSE, NULL);
+ pThread->m_hEventHookThreadExitAck = CreateEvent(NULL, FALSE, FALSE, NULL);
+ // timer to deal with hosting in other processes (don't get move event)
+ pThread->m_hTimer = CreateWaitableTimer(NULL, TRUE, NULL); // last param make this Waitable Timer
+
+ CHR((pThread->m_hEventHookThreadReady != NULL && pThread->m_hEventHookThreadExit != NULL &&
+ pThread->m_hEventHookThreadExitAck != NULL && pThread->m_hTimer != NULL) ? S_OK : E_FAIL);
+
+ pThread->m_hHookThread = CreateThread(NULL, 0, HookThreadProc, (LPVOID)pThread, 0, &dwHookThread);
+ CHR(pThread->m_hHookThread ? S_OK : E_FAIL);
+
+ dwWaitHookThread = WaitForSingleObject(pThread->m_hEventHookThreadReady, INFINITE);
+ CHR(dwWaitHookThread == WAIT_OBJECT_0 ? S_OK : E_FAIL);
+ fCleanupThread = true;
+
+ // post the APC call
+ CHR_MEMALLOC(pAsyncData = new CAsyncData(/*dwArg*/pThread->m_dwThreadId, /*fArg*/FALSE, /*fEventDone*/TRUE));
+ CHR(QueueUserAPC(InstallWindowHookApcCore, pThread->m_hHookThread, (ULONG_PTR)pAsyncData) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_QUEUEUSERAPC_CALL));
+ pAsyncData->WaitAck();
+ pThread->m_hHook = (HHOOK)pAsyncData->m_dwRes;
+ delete pAsyncData;
+ pAsyncData = NULL;
+
+ RHR;
+
+CLEANUP:
+ if (fCleanupThread)
+ {
+ SignalObjectAndWait(pThread->m_hEventHookThreadExit, pThread->m_hEventHookThreadExitAck, INFINITE, FALSE);
+ }
+ if (pAsyncData)
+ {
+ delete pAsyncData;
+ }
+ SafeCloseHandle(&pThread->m_hHookThread);
+ SafeCloseHandle(&pThread->m_hEventHookThreadReady);
+ SafeCloseHandle(&pThread->m_hEventHookThreadExit);
+ SafeCloseHandle(&pThread->m_hEventHookThreadExitAck);
+ SafeCloseHandle(&pThread->m_hTimer);
+
+ RHR;
+}
+
+void CPimcManager::TerminateHookThread(__inout CHookThreadItem * pThread)
+{
+ // Only do this once.
+ if (pThread->m_hHook != NULL)
+ {
+ UnhookWindowsHookEx(pThread->m_hHook);
+ SignalObjectAndWait(pThread->m_hEventHookThreadExit, pThread->m_hEventHookThreadExitAck, INFINITE, FALSE);
+ pThread->m_hHook = NULL;
+ SafeCloseHandle(&pThread->m_hHookThread);
+ SafeCloseHandle(&pThread->m_hEventHookThreadReady);
+ SafeCloseHandle(&pThread->m_hEventHookThreadExit);
+ SafeCloseHandle(&pThread->m_hEventHookThreadExitAck);
+ SafeCloseHandle(&pThread->m_hTimer);
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcManager::FinalRelease()
+{
+ m_wispManagerLock.RevokeIfValid();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// CPimcManager::HookThreadProc
+//
+// This thread is used to install hooks for contexts. The thread is alertable for APCs and
+// the actual installation of the hook happens in InstallWindowHookApcCore.
+//
+// IMPORTANT NOTE (alexz): there was a significant amount of investigation done about
+// what is the correct logic to maintain hook on a window when done in COM in-proc servers.
+// See Tablet V1 Raid bugs # 17589, 23860 for details.
+// In particular, note that we can not install the hooks from the thread that invokes
+// CPimcContext. This is because the thread used is from the thread pool (either CLR or COM RPC),
+// and can be switched at any moment. When the switch happens, Windows disconnects the hook.
+//
+
+DWORD CPimcManager::HookThreadProc(__typefix(CHookThreadItem *) __in LPVOID pvParam)
+{
+ DHR;
+ CHookThreadItem * pThread = (CHookThreadItem*)pvParam;
+ ASSERT (pThread);
+
+ CHR(SetEvent(pThread->m_hEventHookThreadReady) ? S_OK : E_FAIL);
+
+ // MAIN LOOP
+ {
+ BOOL fLoop = TRUE;
+ HANDLE waitHandles[2] = { pThread->m_hEventHookThreadExit, pThread->m_hTimer };
+ while (fLoop)
+ {
+ DWORD dwWait = MsgWaitForMultipleObjectsEx(
+ 2, &(waitHandles[0]), INFINITE,
+ QS_ALLEVENTS, MWMO_ALERTABLE);
+
+ switch (dwWait)
+ {
+ case WAIT_OBJECT_0 + 0: // m_hEventHookThreadExit
+ fLoop = FALSE;
+ break;
+
+ case WAIT_OBJECT_0 + 1: // waitable timer triggered
+ // See if any of our contexts have changed location
+ HandleTimer(pThread->m_dwThreadId);
+ fLoop = TRUE;
+ break;
+
+ case WAIT_OBJECT_0 + 2: // a message in the queue of this thread
+ {
+ MSG msg;
+ PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); // this will cause hook proc to get invoked
+ }
+ fLoop = TRUE;
+ break;
+
+ case WAIT_IO_COMPLETION: // (an APC call will trigger this)
+ fLoop = TRUE;
+ break;
+
+ default:
+ ASSERT(FALSE && "CPimcManager::HookThreadProc: an unexpected error in the wait");
+ fLoop = FALSE;
+ break;
+ }
+ }
+ }
+
+CLEANUP:
+ SetEvent(pThread->m_hEventHookThreadExitAck);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// A new PimcContext is created, make sure we have a hook set up.
+HRESULT CPimcManager::InstallWindowHook(__in HWND hwnd, __inout CPimcContext * pCtx)
+{
+ DHR;
+ DWORD dwProcessId;
+ CAsyncData * pAsyncData = NULL;
+ BOOL fCleanupThreadItem = false;
+ BOOL fCleanupHook = false;
+ BOOL fCleanupWindowItem = false;
+ BOOL fAddedMgr = FALSE;
+
+ HookThreadItemKey keyHookThreadItem = NULL;
+ CHookThreadItem * pHookThreadItem = NULL;
+ HookWindowItemKey keyHookWindowItem = NULL;
+ CHookWindowItem * pHookWindowItem = NULL;
+
+ ASSERT (hwnd && IsWindow(hwnd));
+
+ // DDVSO:220285
+ // Scope the CHookLock so we don't attempt to call TerminateWindowHook
+ // under the lock (see UninstallWindowHook).
+ {
+ CHookLock lock;
+
+ // we don't allow handling of hwnd-s not owned by this process
+ DWORD dwThreadId = GetWindowThreadProcessId(hwnd, &dwProcessId);
+ DWORD dwProcessIdCur = GetCurrentProcessId();
+ CHR(dwProcessIdCur == dwProcessId ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_GETCURRENTPROCESSID_CALL)); //..WIP (alexz) use TPC_E_INVALID_WINDOW_HANDLE
+
+ // register in m_HookThreadMap
+
+ CHR(EnsureHookThreadItem(dwThreadId, this, &keyHookThreadItem, &fAddedMgr));
+ pHookThreadItem = &(g_HookThreadMap[keyHookThreadItem]);
+ pHookThreadItem->m_cUsages++;
+ fCleanupThreadItem = true;
+
+ // Set up the window hook if it has not been done yet for this thread.
+ if (!pHookThreadItem->m_hHook)
+ {
+ CHR(InitializeHookThread(pHookThreadItem));
+ fCleanupHook = true;
+ }
+
+ pCtx->m_keyHookThreadItem = keyHookThreadItem;
+
+ // register in m_HookWindowMap
+
+ CHR(EnsureHookWindowItem(hwnd, &keyHookWindowItem));
+ fCleanupWindowItem = true;
+ pHookWindowItem = &(m_HookWindowMap[keyHookWindowItem]);
+ CHR(pHookWindowItem->m_ctxs.Add(pCtx));
+
+ pCtx->m_keyHookWindowItem = keyHookWindowItem;
+
+ // Now see if we need to start the waittimer
+ if (pHookWindowItem->m_bNeedsTimer && !pHookThreadItem->m_bTimerStarted)
+ {
+ StartWaitTimer(pHookThreadItem);
+ }
+
+ RHR;
+
+ CLEANUP:
+
+ if (pAsyncData)
+ delete pAsyncData;
+
+ if (fCleanupThreadItem)
+ {
+ if (fAddedMgr)
+ {
+ for (INT i = 0; pHookThreadItem->m_mgrs.GetSize(); i++)
+ {
+ if (pHookThreadItem->m_mgrs[i] == this)
+ {
+ pHookThreadItem->m_mgrs.Remove(i);
+ break;
+ }
+ }
+ }
+
+ pHookThreadItem->m_cUsages--;
+ if (!pHookThreadItem->m_cUsages)
+ {
+ // DDVSO:424827
+ // Keep pHookThreadItem alive until we terminate the hook thread
+ g_HookThreadMap.Remove(keyHookThreadItem, false /*deleteEntry*/);
+ }
+ }
+
+ if (fCleanupWindowItem)
+ {
+ // Add of context failed so see if we need to unregister hwnd key in HookWindowMap
+ if (!pHookWindowItem->m_ctxs.GetSize())
+ {
+ m_HookWindowMap.Remove(keyHookWindowItem, true /*deleteEntry*/);
+ }
+ }
+ } // End of CHookLock block
+
+ if (fCleanupHook)
+ {
+ TerminateHookThread(pHookThreadItem);
+ delete pHookThreadItem;
+ }
+
+ RHR;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+HookThreadItemKey CPimcManager::FindHookThreadItem(DWORD dwThreadId)
+{
+ HookThreadItemKey keyFound = NULL;
+ HookThreadItemKey keyCur = g_HookThreadMap.GetHead();
+ while (!g_HookThreadMap.IsAtEnd(keyCur))
+ {
+ if (g_HookThreadMap[keyCur].m_dwThreadId == dwThreadId)
+ {
+ keyFound = keyCur;
+ break;
+ }
+ keyCur = g_HookThreadMap.GetNext(keyCur);
+ }
+ return keyFound;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcManager::EnsureHookThreadItem(DWORD dwThreadId, __in CPimcManager * pMgr,
+ __out HookThreadItemKey * pKey, __out BOOL *pfAddedManager)
+{
+ DHR;
+ *pfAddedManager = FALSE;
+ *pKey = FindHookThreadItem(dwThreadId);
+ if (!(*pKey))
+ {
+ CHR(g_HookThreadMap.AddToTail(pKey));
+ g_HookThreadMap[*pKey].m_dwThreadId = dwThreadId;
+ g_HookThreadMap[*pKey].m_cUsages = 0;
+ g_HookThreadMap[*pKey].m_hHook = NULL;
+ g_HookThreadMap[*pKey].m_hHookThread = NULL;
+ g_HookThreadMap[*pKey].m_hEventHookThreadReady = NULL;
+ g_HookThreadMap[*pKey].m_hEventHookThreadExit = NULL;
+ g_HookThreadMap[*pKey].m_hEventHookThreadExitAck = NULL;
+ g_HookThreadMap[*pKey].m_hTimer = NULL;
+ g_HookThreadMap[*pKey].m_bTimerStarted = false;
+ g_HookThreadMap[*pKey].m_mgrs.Add(pMgr);
+ }
+ else
+ {
+ // Make sure this manager has been added to the HookThreadItem mgr list
+ CHookThreadItem * pItem = &g_HookThreadMap[*pKey];
+
+ BOOL fFound = FALSE;
+ INT cMgrs = pItem->m_mgrs.GetSize();
+ for (INT iMgr = 0; iMgr < cMgrs; iMgr++)
+ {
+ CPimcManager* pcurMgr = pItem->m_mgrs[iMgr];
+ if (pcurMgr == pMgr)
+ {
+ fFound = TRUE;
+ break;
+ }
+ }
+ if (!fFound)
+ {
+ pItem->m_mgrs.Add(pMgr);
+ *pfAddedManager = TRUE;
+ }
+ }
+
+CLEANUP:
+ RHR;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+CPimcManager::HookWindowItemKey CPimcManager::FindHookWindowItem(__in HWND hwnd)
+{
+ HookWindowItemKey keyFound = NULL;
+ HookWindowItemKey keyCur = m_HookWindowMap.GetHead();
+ while (!m_HookWindowMap.IsAtEnd(keyCur))
+ {
+ if (m_HookWindowMap[keyCur].m_hwnd == hwnd)
+ {
+ keyFound = keyCur;
+ break;
+ }
+ keyCur = m_HookWindowMap.GetNext(keyCur);
+ }
+ return keyFound;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcManager::EnsureHookWindowItem(__in HWND hwnd, __out HookWindowItemKey * pKey)
+{
+ DHR;
+ *pKey = FindHookWindowItem(hwnd);
+ if (!(*pKey))
+ {
+ CHR(m_HookWindowMap.AddToTail(pKey));
+ m_HookWindowMap[*pKey].m_hwnd = hwnd;
+ m_HookWindowMap[*pKey].m_bNeedsTimer = false;
+
+ // See if this hwnd needs tracking by the waitable timer
+ DWORD dwProcessId = 0;
+ DWORD dwThreadId = GetWindowThreadProcessId(hwnd, &dwProcessId);
+ HWND hwndParent = GetParent(hwnd);
+ while (hwndParent != NULL)
+ {
+ DWORD dwProcessIdParent = 0;
+ DWORD dwThreadIdParent = GetWindowThreadProcessId(hwndParent, &dwProcessIdParent);
+ if (dwProcessIdParent != dwProcessId || dwThreadIdParent != dwThreadId)
+ {
+ RECT rc = {0}; // Init to empty rect to make sure it triggers first time.
+ m_HookWindowMap[*pKey].m_rc = rc;
+ m_HookWindowMap[*pKey].m_bNeedsTimer = true;
+ break;
+ }
+ hwndParent = GetParent(hwndParent);
+ }
+ }
+
+CLEANUP:
+ RHR;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void CPimcManager::InstallWindowHookApcCore(__typefix(CAsyncData *) __inout ULONG_PTR pvAsyncData)
+{
+ CAsyncData * pAsyncData = (CAsyncData*)pvAsyncData;
+ DWORD dwThreadId = (DWORD)pAsyncData->m_dwArg;
+
+ HHOOK hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc, NULL, dwThreadId);
+
+ pAsyncData->m_dwRes = (DWORD_PTR)hHook;
+
+ pAsyncData->SignalAck();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcManager::UninstallWindowHook(__in CPimcContext * pCtx)
+{
+ DHR;
+
+ CHookThreadItem * pThreadItem = NULL;
+ HookThreadItemKey keyHookThreadItem = NULL;
+ bool shouldTerminateHookThread = false;
+
+ // DDVSO:220285
+ // Keeping the CHookLock while the hook thread is being terminated in TerminateHookThread
+ // can lead to a deadlock situation. If any message comes through the hook thread
+ // or if the timer ticks while we have this lock, the hook thread itself may attempt
+ // to acquire the lock in several of its handlers. If this occurs, TerminateHookThread
+ // will eventually wait forever on m_hEventHookThreadExitAck which can never be signaled
+ // since the hook thread is waiting on CHookLock.
+ //
+ // To stop this occurring, scope the hook lock to only what needs a lock, the
+ // processing of contexts using the hook thread. Once contexts are manipulated
+ // we can signal the hook thread to exit with confidence that m_hEventHookThreadExitAck
+ // will be signaled as the hook thread is free to process.
+ {
+ CHookLock lock;
+
+ // unregister in HookThreadMap
+
+ keyHookThreadItem = pCtx->m_keyHookThreadItem;
+ pThreadItem = &g_HookThreadMap[keyHookThreadItem];
+
+ // unregister in HookWindowMap
+
+ HookWindowItemKey keyHookWindowItem = pCtx->m_keyHookWindowItem;
+ CHookWindowItem * pWindowItem = &m_HookWindowMap[keyHookWindowItem];
+ for (INT idx = 0; pWindowItem->m_ctxs.GetSize(); idx++)
+ {
+ if (pWindowItem->m_ctxs[idx] == pCtx)
+ {
+ pWindowItem->m_ctxs.Remove(idx);
+ break;
+ }
+ }
+
+ BOOL bNeedsTimer = pWindowItem->m_bNeedsTimer;
+ if (pWindowItem->m_ctxs.GetSize() == 0)
+ {
+ m_HookWindowMap.Remove(keyHookWindowItem, true /*deleteEntry*/);
+
+ // If no more windows on this manager, then remove this pMgr from the list
+ if (m_HookWindowMap.IsEmpty())
+ {
+ for (INT i = 0; pThreadItem->m_mgrs.GetSize(); i++)
+ {
+ if (pThreadItem->m_mgrs[i] == this)
+ {
+ pThreadItem->m_mgrs.Remove(i);
+ break;
+ }
+ }
+ }
+ }
+
+ // see if we can turn off waitabletimer
+ // Now see if we need to start the waittimer
+ if (bNeedsTimer && pThreadItem->m_bTimerStarted)
+ {
+ StopWaitTimerIfNotNeeded(pThreadItem);
+ }
+
+ pThreadItem->m_cUsages--;
+
+ if (pThreadItem->m_cUsages == 0)
+ {
+ // DDVSO:424827
+ // Keep pThreadItem alive until we terminate the hook thread
+ g_HookThreadMap.Remove(keyHookThreadItem, false /*deleteEntry*/);
+ shouldTerminateHookThread = true;
+ }
+ } // End of CHookLock block
+
+ if (shouldTerminateHookThread)
+ {
+ TerminateHookThread(pThreadItem);
+ delete pThreadItem;
+ }
+
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+LRESULT CALLBACK CPimcManager::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ PCWPSTRUCT pcwp = (PCWPSTRUCT)lParam;
+ HWND hwnd = pcwp->hwnd;
+ DWORD dwTid;
+ DWORD dwPid;
+
+ if (!IsWindow(hwnd))
+ goto CLEANUP;
+
+ dwTid = GetWindowThreadProcessId(hwnd, &dwPid);
+ if (dwTid == 0 || GetCurrentProcessId() != dwPid)
+ goto CLEANUP;
+
+ try
+ {
+ //static BOOL fInSizeMove = FALSE;
+
+ if (0 <= nCode)
+ {
+ switch (pcwp->message)
+ {
+ case WM_MDIACTIVATE:
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_SendToTop, (HWND)pcwp->lParam);
+ break;
+
+ case WM_ACTIVATE:
+ {
+ if (WA_INACTIVE != pcwp->wParam)
+ {
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_SendToTop, hwnd);
+ }
+ }
+ break;
+
+ case WM_CHILDACTIVATE:
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_SendToTop, hwnd);
+ break;
+
+ //case WM_INITMENUPOPUP:
+ // MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_SendToBack, hwnd);
+ // break;
+
+ case WM_UNINITMENUPOPUP:
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_SendToTop, hwnd);
+ break;
+
+ case WM_COMMAND:
+ if ((HIWORD(pcwp->wParam) == CBN_CLOSEUP))
+ {
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_SendToTop, hwnd);
+ }
+ break;
+
+ case WM_SIZE:
+ case WM_MOVE:
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_SizeMove, hwnd);
+ break;
+
+#if 0 //..WIP (alexz)
+ case WM_ENTERSIZEMOVE:
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_Disable, hwnd);
+ fInSizeMove = TRUE;
+ break;
+
+ case WM_SETCURSOR:
+ if (!fInSizeMove)
+ break;
+ // else
+ // fall thru
+
+ case WM_EXITSIZEMOVE:
+ //..WIP (alexz) this is not correct if the context was disabled
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_Enable, hwnd);
+ fInSizeMove = FALSE;
+ break;
+
+ case WM_DESTROY:
+ MgrHandleCtxUpdate(dwTid, CPimcContext::UPDATE_Unhook, hwnd);
+ break;
+#endif
+ }
+ }
+ }
+ catch (...)
+ {
+ ASSERT(FALSE && "not reached");
+ }
+
+CLEANUP:
+
+ return CallNextHookEx(NULL, nCode, wParam, lParam);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcManager::HandleTimer(DWORD dwThreadId)
+{
+ CHookLock lock;
+
+ // Look up CHookThreadItem instance for this thread.
+ HookThreadItemKey hookThreadKey = FindHookThreadItem(dwThreadId);
+ CHookThreadItem * pThreadItem = &g_HookThreadMap[hookThreadKey];
+
+ // DDVSO:220285
+ // If the CHookThreadItem is either awaiting cleanup due to a failed install
+ // or we are uninstalling the hook thread, do not initiate processing. Both
+ // cleanup and uninstall will remove the last entry for a CHookThreadItem, so
+ // if the result of the lookup is NULL we know we are in a cleanup/shutdown
+ // scenario.
+ if (NULL != pThreadItem)
+ {
+ // Loop through the CPimcManager list looking for contexts that need the timer.
+ INT cMgrs = pThreadItem->m_mgrs.GetSize();
+ for (INT i = 0; i < cMgrs; i++)
+ {
+ CPimcManager* pMgr = pThreadItem->m_mgrs[i];
+
+ HookWindowItemKey keyCur = pMgr->m_HookWindowMap.GetHead();
+ while (!pMgr->m_HookWindowMap.IsAtEnd(keyCur))
+ {
+ CHookWindowItem * pItem = &pMgr->m_HookWindowMap[keyCur];
+ if (pItem->m_bNeedsTimer)
+ {
+ HWND hwnd = pItem->m_hwnd;
+ // Only do this work if the window is still valid.
+ if (::IsWindow(hwnd))
+ {
+ RECT rc = { 0 };
+ ::GetWindowRect(hwnd, &rc);
+ if (!EqualRect(&rc, &(pItem->m_rc)))
+ {
+ pItem->m_rc = rc;
+ // We only need to update contexts for this window (any children will also use timer).
+ INT c = pItem->m_ctxs.GetSize();
+ for (INT i = 0; i < c; i++)
+ {
+ CPimcContext * pCtx = pItem->m_ctxs[i];
+ pCtx->PostUpdate(CPimcContext::UPDATE_SizeMove);
+ }
+ }
+ }
+ }
+ keyCur = pMgr->m_HookWindowMap.GetNext(keyCur);
+ }
+ }
+
+ StartWaitTimer(pThreadItem);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcManager::StartWaitTimer(__inout CHookThreadItem * pThread)
+{
+ LARGE_INTEGER liDueTime;
+ liDueTime.QuadPart=-WAITTIMER_DELAY;
+
+ pThread->m_bTimerStarted = SetWaitableTimer(pThread->m_hTimer, &liDueTime, 0, NULL, NULL, 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcManager::StopWaitTimerIfNotNeeded(__inout CHookThreadItem * pThread)
+{
+ // If no other contexts require timer then stop it.
+ if (!DoContextsNeedWaitableTimer(pThread))
+ {
+ CancelWaitableTimer(pThread->m_hTimer);
+ pThread->m_bTimerStarted = FALSE;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+BOOL CPimcManager::DoContextsNeedWaitableTimer(__in CHookThreadItem * pThread)
+{
+ // Loop through the CPimcManager list looking for contexts that need the timer.
+ INT cMgrs = pThread->m_mgrs.GetSize();
+ for (INT i = 0; i < cMgrs; i++)
+ {
+ CPimcManager* pMgr = pThread->m_mgrs[i];
+
+ HookWindowItemKey keyCur = pMgr->m_HookWindowMap.GetHead();
+ while (!pMgr->m_HookWindowMap.IsAtEnd(keyCur))
+ {
+ if (pMgr->m_HookWindowMap[keyCur].m_bNeedsTimer)
+ {
+ return TRUE;
+ }
+ keyCur = pMgr->m_HookWindowMap.GetNext(keyCur);
+ }
+ }
+ return FALSE;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+void CPimcManager::MgrHandleCtxUpdate(DWORD dwThreadId, DWORD dwUpdate, __in HWND hwnd)
+{
+ CHookLock lock;
+
+ // Look up CPimcManager instance for this thread and process update on that instance.
+ HookThreadItemKey hookThreadKey = FindHookThreadItem(dwThreadId);
+ CHookThreadItem * pThreadItem = &g_HookThreadMap[hookThreadKey];
+
+ if (pThreadItem != NULL)
+ {
+ PostCtxUpdateForSubtree(dwUpdate, hwnd, pThreadItem);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcManager::PostCtxUpdateForWnd(DWORD dwUpdate, __in HWND hwnd, __in CHookThreadItem * pThreadItem)
+{
+ // Since we can have multiple CPimcManager objects per thread we need to enum
+ // them and notify all of them of this context update for this hwnd.
+ INT cMgrs = pThreadItem->m_mgrs.GetSize();
+ for (INT iMgr = 0; iMgr < cMgrs; iMgr++)
+ {
+ CPimcManager* pMgr = pThreadItem->m_mgrs[iMgr];
+
+ HookWindowItemKey key = pMgr->FindHookWindowItem(hwnd);
+ if (key)
+ {
+ CHookWindowItem * pItem = &(pMgr->m_HookWindowMap[key]);
+
+ // Update our rect if the hookproc window messages triggers an update to our size.
+ if (pItem->m_bNeedsTimer && ((dwUpdate & CPimcContext::UPDATE_SizeMove) != 0))
+ {
+ RECT rc = {0};
+ ::GetWindowRect(pItem->m_hwnd, &rc);
+ pItem->m_rc = rc;
+ }
+
+ INT c = pItem->m_ctxs.GetSize();
+ for (INT i = 0; i < c; i++)
+ {
+ CPimcContext * pCtx = pItem->m_ctxs[i];
+ pCtx->PostUpdate(dwUpdate);
+ }
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcManager::PostCtxUpdateForSubtree(DWORD dwUpdate, __in HWND hwndRoot, __in CHookThreadItem * pThreadItem)
+{
+ try
+ {
+ DHR;
+ CPbList queue;
+ CHR(queue.AddToTail(hwndRoot));
+ for (;;)
+ {
+ PBLKEY keyHead = queue.GetHead();
+ if (queue.IsAtEnd(keyHead))
+ break;
+
+ HWND hwndCur = queue[keyHead];
+ queue.Remove(keyHead, true /*deleteEntry*/);
+
+ // handle the event for this hwnd
+ PostCtxUpdateForWnd(dwUpdate, hwndCur, pThreadItem);
+
+ // enumerate children
+ hwndCur = ::GetWindow(hwndCur, GW_CHILD);
+ if (hwndCur)
+ {
+ hwndCur = ::GetWindow(hwndCur, GW_HWNDLAST);
+ while (hwndCur)
+ {
+ CHR(queue.AddToTail(hwndCur));
+ hwndCur= ::GetWindow(hwndCur, GW_HWNDPREV);
+ }
+ }
+ }
+CLEANUP:
+ return;
+ }
+ catch (...)
+ {
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#if WANT_PROFILE
+BOOL CPimcManager::IsProfiling()
+{
+ if (!m_fIsProfilingCached)
+ {
+ m_fIsProfilingCached = TRUE;
+ m_fIsProfiling = FALSE;
+
+ HKEY hKey;
+ if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CURRENT_USER, SZ_REGKEY_PROFILE, 0, KEY_QUERY_VALUE, &hKey))
+ {
+ DWORD cbSize = sizeof(DWORD);
+ DWORD dwProfiling = 0;
+ RegQueryValueExW(hKey, L"V2Profiling", NULL, NULL, (BYTE*) &dwProfiling, &cbSize);
+ RegCloseKey(hKey);
+
+ m_fIsProfiling = dwProfiling != 0;
+ }
+ }
+ return m_fIsProfiling;
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcManager::GetTabletCount(__out ULONG* pcTablets)
+{
+ DHR;
+
+ ULONG cTablets = 0;
+
+ LoadWisptis(); // Try to load wisptis via the surrogate object.
+
+ // we will return 0 in the case that there is no stylus since mouse is not considered a stylus anymore
+ if (m_fLoadedWisptis)
+ {
+ CHR(m_pMgrS->GetTabletCount(&cTablets));
+ }
+
+ *pcTablets = cTablets;
+
+CLEANUP:
+ RHR;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcManager::GetTablet(ULONG iTablet, __deref_out IPimcTablet3** ppTablet)
+{
+ DHR;
+
+ switch (iTablet)
+ {
+ case RELEASE_MANAGER_EXT:
+ {
+ CHR(m_managerLock.Unlock());
+ }
+ break;
+ default:
+ {
+ CHR(GetTabletImpl(iTablet, ppTablet));
+ }
+ }
+
+CLEANUP:
+ RHR;
+}
+
+STDMETHODIMP CPimcManager::GetTabletImpl(ULONG iTablet, __deref_out IPimcTablet3** ppTablet)
+{
+ DHR;
+ LoadWisptis(); // Make sure wisptis has been loaded! (Can happen when handling OnTabletAdded message)
+
+ CComPtr pTabS;
+ CComObject * pTabC;
+
+ // Can only call if we have real tablet hardware which means wisptis must be loaded!
+ CHR(m_fLoadedWisptis ? S_OK : E_UNEXPECTED);
+ CHR(CComObject::CreateInstance(&pTabC));
+ CHR(pTabC->QueryInterface(IID_IPimcTablet3, (void**)ppTablet));
+ CHR(m_pMgrS->GetTablet(iTablet, &pTabS));
+ CHR(pTabC->Init(m_fLoadedWisptis?pTabS:NULL, this));
+
+CLEANUP:
+ RHR;
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcManager.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcManager.h
new file mode 100644
index 00000000000..18d48f63819
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcManager.h
@@ -0,0 +1,197 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PimcManager.h : Declaration of the CPimcManager
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "PenImc.h"
+#include "PbList.h"
+#include "PbPreallocArray.h"
+#include "ComLockableWrapper.hpp"
+#include "GitComLockableWrapper.hpp"
+
+class CPimcContext;
+class CPimcManager;
+
+
+// thread map
+struct CHookThreadItem
+{
+ DWORD m_dwThreadId;
+ HHOOK m_hHook;
+ DWORD m_cUsages;
+ CPbPreallocArray m_mgrs;
+
+ // Used to manage the hook thread
+ HANDLE m_hHookThread;
+ HANDLE m_hEventHookThreadReady;
+ HANDLE m_hEventHookThreadExit;
+ HANDLE m_hEventHookThreadExitAck;
+ HANDLE m_hTimer;
+ BOOL m_bTimerStarted : 1;
+};
+typedef PBLKEY HookThreadItemKey;
+
+extern HANDLE g_hMutexHook;
+
+#ifdef DBG_LATER
+extern DWORD g_dwMutexHookOwnerThreadId;
+extern BOOL g_cHookLock;
+#endif
+
+#define WAITTIMER_DELAY 2500000 // 250 milliseconds (1/4 sec)
+
+/////////////////////////////////////////////////////////////////////////////
+// CPimcManager
+
+class ATL_NO_VTABLE CPimcManager :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IPimcManager3
+{
+public:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ CPimcManager();
+
+ HRESULT FinalConstruct();
+ void FinalRelease();
+ void LoadWisptis();
+ BOOL IsVistaOrGreater();
+
+protected:
+
+ BOOL ShouldLoadWisptis();
+ BOOL UserIsLocalSystem();
+
+public:
+
+#if WANT_PROFILE
+ BOOL IsProfiling();
+#endif
+
+ HRESULT RegisterCtxS(__in ITabletContextP * pCtxS, __out DWORD * pdwCookie);
+ HRESULT RevokeCtxS (DWORD dwCookie);
+ HRESULT GetCtxS (DWORD dwCookie, __deref_out ITabletContextP ** ppCtxS);
+
+ //
+ // hook handling
+ //
+
+ // methods
+
+ HRESULT InstallWindowHook(__in HWND hwnd, __inout CPimcContext * pCtx);
+ HRESULT UninstallWindowHook(__in CPimcContext * pCtx);
+ static DWORD WINAPI HookThreadProc(__typefix(CHookThreadItem *) __in LPVOID pvParam);
+ static void CALLBACK InstallWindowHookApcCore(__typefix(CAsyncData *) __inout ULONG_PTR pvAsyncData);
+ static HRESULT InitializeHookThread(__inout CHookThreadItem * pThread);
+ static void TerminateHookThread(__inout CHookThreadItem * pThread);
+
+ typedef PBLKEY HookWindowItemKey;
+
+ struct CHookWindowItem
+ {
+ HWND m_hwnd;
+ BOOL m_bNeedsTimer;
+ RECT m_rc;
+ CPbPreallocArray m_ctxs;
+ };
+
+ // tracks windows for this manager thread
+ CPbList m_HookWindowMap;
+
+ static HookThreadItemKey FindHookThreadItem(DWORD dwThreadId);
+ HRESULT EnsureHookThreadItem(DWORD dwThreadId, __in CPimcManager * pMgr, __out HookThreadItemKey * pKey, __out BOOL *pfAddedManager);
+ HookWindowItemKey FindHookWindowItem(__in HWND hwnd);
+ HRESULT EnsureHookWindowItem(__in HWND hwnd, __out HookWindowItemKey * pKey);
+
+ static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
+
+ static void HandleTimer(DWORD dwThreadId);
+ static void StartWaitTimer(__inout CHookThreadItem * pThread);
+ static void StopWaitTimerIfNotNeeded(__inout CHookThreadItem * pThread);
+ static BOOL DoContextsNeedWaitableTimer(__in CHookThreadItem * pThread);
+ static void MgrHandleCtxUpdate(DWORD dwThreadId, DWORD dwUpdate, __in HWND hwnd);
+ static void PostCtxUpdateForSubtree(DWORD dwUpdate, __in HWND hwndRoot, __in CHookThreadItem * pThreadItem);
+ static void PostCtxUpdateForWnd(DWORD dwUpdate, __in HWND hwnd, __in CHookThreadItem * pThreadItem);
+
+ // locking
+
+ class CHookLock
+ {
+ public:
+ CHookLock()
+ {
+ m_dwWait = 0;
+ ASSERT(g_hMutexHook);
+ if (g_hMutexHook)
+ {
+ m_dwWait = WaitForSingleObject(g_hMutexHook, INFINITE);
+ ASSERT (m_dwWait == WAIT_OBJECT_0);
+ }
+#ifdef DBG_LATER
+ g_cHookLock++;
+ g_dwMutexHookOwnerThreadId = GetCurrentThreadId();
+#endif
+ }
+ ~CHookLock()
+ {
+#ifdef DBG_LATER
+ g_dwMutexHookOwnerThreadId = 0;
+ g_cHookLock--;
+#endif
+ if (m_dwWait == WAIT_OBJECT_0)
+ ReleaseMutex(g_hMutexHook);
+ }
+
+ protected:
+ DWORD m_dwWait;
+ };
+
+ //
+ // IPimcManager3
+ //
+
+ STDMETHOD(GetTabletCount)(__out ULONG* pcTablets);
+ STDMETHOD(GetTablet)(ULONG iTablet, __deref_out IPimcTablet3** ppTablet);
+ STDMETHOD(GetTabletImpl)(ULONG iTablet, __deref_out IPimcTablet3** ppTablet);
+
+ // wiring
+
+DECLARE_REGISTRY_RESOURCEID(IDR_PIMCMANAGER)
+
+BEGIN_COM_MAP(CPimcManager)
+ COM_INTERFACE_ENTRY(IPimcManager3)
+END_COM_MAP()
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ /////////////////////////////////////////////////////////////////////////
+
+ // data
+ CComPtr m_pMgrS;
+ ComUtils::GitComLockableWrapper m_wispManagerLock;
+
+ BOOL m_fLoadedWisptis : 1;
+
+ ComUtils::ComLockableWrapper m_managerLock;
+
+ // DDVSO:514949
+ // Special param flag for COM operations in GetTablet
+ const static ULONG RELEASE_MANAGER_EXT = 0xFFFFDEAD;
+
+#if WANT_PROFILE
+ BOOL m_fIsProfilingCached : 1;
+ BOOL m_fIsProfiling : 1;
+#endif // WANT_PROFILE
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+OBJECT_ENTRY_AUTO(__uuidof(PimcManager3), CPimcManager)
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcSurrogate.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcSurrogate.cpp
new file mode 100644
index 00000000000..113a4243827
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcSurrogate.cpp
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PimcSurrogate.cpp : Implementation of CPimcSurrogate
+
+#include "stdafx.h"
+#include "Penimc.h"
+#include "PimcSurrogate.h"
+#include
+#include
+
+/////////////////////////////////////////////////////////////////////////////
+// CPimcSurrogate
+
+/////////////////////////////////////////////////////////////////////////////
+
+CPimcSurrogate::CPimcSurrogate()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcSurrogate::FinalConstruct()
+{
+ DHR;
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcSurrogate::FinalRelease()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcSurrogate::GetWisptisITabletManager(__deref_out IUnknown** ppTabletManagerUnknown)
+{
+ return ::CoCreateInstance(CLSID_TabletManagerS, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IUnknown, (LPVOID*)ppTabletManagerUnknown);
+}
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcSurrogate.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcSurrogate.h
new file mode 100644
index 00000000000..6b88b436ce7
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcSurrogate.h
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PimcSurrogate.h : Declaration of the CPimcSurrogate
+
+#pragma once
+#include "resource.h" // main symbols
+#include "PenImc.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CPimcSurrogate
+class ATL_NO_VTABLE CPimcSurrogate :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IPimcSurrogate3
+{
+public:
+
+ /////////////////////////////////////////////////////////////////////////
+
+ CPimcSurrogate();
+
+ HRESULT FinalConstruct();
+ void FinalRelease();
+
+ //
+ // IPimcSurrogate3
+ //
+ STDMETHOD(GetWisptisITabletManager)(__deref_out IUnknown** ppTabletManagerUnknown);
+
+ // wiring
+ DECLARE_REGISTRY_RESOURCEID(IDR_PIMCSURROGATE)
+
+ BEGIN_COM_MAP(CPimcSurrogate)
+ COM_INTERFACE_ENTRY(IPimcSurrogate3)
+ END_COM_MAP()
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+OBJECT_ENTRY_AUTO(__uuidof(PimcSurrogate3), CPimcSurrogate)
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcTablet.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcTablet.cpp
new file mode 100644
index 00000000000..1cb2d9f4901
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcTablet.cpp
@@ -0,0 +1,961 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PimcTablet.cpp : Implementation of CPimcTablet
+
+#include "stdafx.h"
+#include "PimcContext.h"
+#include "PimcTablet.h"
+#include
+#include
+
+using namespace ComUtils;
+
+#if WANT_PROFILING
+const INT s_cGuidsProfiling = 2;
+#endif // WANT_PROFILING
+const INT s_cGuids = 5;
+GUID s_guids[s_cGuids] = {
+ {0x598A6A8F, 0x52C0, 0x4BA0, 0x93, 0xAF, 0xAF, 0x35, 0x74, 0x11, 0xA5, 0x61}, // GUID_X
+ {0xB53F9F75, 0x04E0, 0x4498, 0xA7, 0xEE, 0xC3, 0x0D, 0xBB, 0x5A, 0x90, 0x11}, // GUID_Y
+ {0x6E0E07BF, 0xAFE7, 0x4CF7, 0x87, 0xD1, 0xAF, 0x64, 0x46, 0x20, 0x84, 0x18}, // GUID_PACKETSTATUS
+ {0x39143d3, 0x78cb, 0x449c, 0xa8, 0xe7, 0x67, 0xd1, 0x88, 0x64, 0xc3, 0x32}, // GUID_TIPBUTTON
+ {0xf0720328, 0x663b, 0x418f, 0x85, 0xa6, 0x95, 0x31, 0xae, 0x3e, 0xcd, 0xfa} // GUID_BARRELBUTTON
+};
+
+// s_guids is used as is in some places as TABLET_CONTEXT_SETTINGS->pguidPktProps.
+// NormalPressure is an optional property and should not be included in s_guids array
+// as a generic entry. Hence a separate constant.
+static const GUID GUID_NORMALPRESSURE = {0x7307502D, 0xF9F4, 0x4E18, {0xB3, 0xF2, 0x2C, 0xE1, 0xB1, 0xA3, 0x61, 0x0C}};
+
+typedef enum GUID_INDEXES
+{
+ GUID_X = 0,
+ GUID_Y,
+ GUID_PACKETSTATUS,
+ GUID_TIPBUTTON,
+ GUID_BARRELBUTTON
+} GUID_INDEXES;
+
+
+// Fake Mouse Device constants
+static const WCHAR* MOUSEDEVICE_CURSOR_NAME = L"Mouse";
+static const WCHAR* MOUSEDEVICE_BUTTON_ONE_NAME = L"Tip Switch";
+static const WCHAR* MOUSEDEVICE_BUTTON_TWO_NAME = L"Barrel Switch";
+static const WCHAR* MOUSEDEVICE_PLUGANDPLAYID = L"SCREEN";
+
+static void EnsureNoDuplicateGUIDs(__in GUID *pGUID, __inout ULONG &cGUID)
+{
+ ULONG iIndex = 0;
+
+ // Move all the unique guids to the beginning of the buffer.
+ for (ULONG i = 0; i < cGUID; i++)
+ {
+ ULONG j = 0;
+ for (; j < iIndex; j++)
+ {
+ if (pGUID[i] == pGUID[j])
+ {
+ break;
+ }
+ }
+ if (j == iIndex)
+ {
+ pGUID[iIndex++] = pGUID[i];
+ }
+ }
+
+ // Set empty guid at left over spots
+ for (ULONG i = iIndex; i < cGUID; i++)
+ {
+ pGUID[i] = GUID_NULL;
+ }
+
+ // Fix the count
+ cGUID = iIndex;
+}
+
+// Helper routine to remove duplicate entries from TABLET_CONTEXT_SETTINGS'
+// pguidPktProps and pguidPktBtns
+static void EnsureNoDuplicates(__in TABLET_CONTEXT_SETTINGS * pTCS)
+{
+ EnsureNoDuplicateGUIDs(pTCS->pguidPktProps, pTCS->cPktProps);
+ EnsureNoDuplicateGUIDs(pTCS->pguidPktBtns, pTCS->cPktBtns);
+}
+
+// Helper routine to sort TABLET_CONTEXT_SETTINGS->pguidPktProps such that
+// X, Y and NormalPressure are always at the beginning in that order.
+static void EnsureXYPressureOrder(__in TABLET_CONTEXT_SETTINGS * pTCS)
+{
+ bool bFoundX = FALSE;
+ bool bFoundY = FALSE;
+ bool bFoundPressure = FALSE;
+
+ ULONG iIncreament = 0;
+ // Guard against integer underflow
+ if (pTCS->cPktProps > 0)
+ {
+ ULONG i = pTCS->cPktProps-1;
+ do {
+ if (pTCS->pguidPktProps[i] == s_guids[GUID_X])
+ {
+ bFoundX = TRUE;
+ iIncreament++;
+ }
+ else if (pTCS->pguidPktProps[i] == s_guids[GUID_Y])
+ {
+ bFoundY = TRUE;
+ iIncreament++;
+ }
+ else if (pTCS->pguidPktProps[i] == GUID_NORMALPRESSURE)
+ {
+ bFoundPressure = TRUE;
+ iIncreament++;
+ }
+ else
+ {
+ // Move other guids to right by an index equal to number of
+ // guids among X,Y and NormalPressure encountered so far.
+ pTCS->pguidPktProps[i + iIncreament] = pTCS->pguidPktProps[i];
+ }
+ } while (i-- > 0);
+ }
+
+ // Set X, Y and NormalPressure at their appropriate indices.
+ if (bFoundPressure)
+ {
+ pTCS->pguidPktProps[--iIncreament] = GUID_NORMALPRESSURE;
+ }
+ if (bFoundY)
+ {
+ pTCS->pguidPktProps[--iIncreament] = s_guids[GUID_Y];
+ }
+ if (bFoundX)
+ {
+ pTCS->pguidPktProps[--iIncreament] = s_guids[GUID_X];
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CPimcTablet
+
+/////////////////////////////////////////////////////////////////////////////
+
+CPimcTablet::CPimcTablet()
+{
+ m_cCursors = 0;
+ m_apCursorInfo = NULL;
+ m_pTCS = NULL;
+ m_pMgr = NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CPimcTablet::Init(__in CComPtr pTabS, __in CComPtr pMgr)
+{
+ DHR;
+ m_pMgr = pMgr;
+ m_pTabS = pTabS;
+
+ // Ensure the WISP tablet is stored in the GIT.
+ m_wispTabletLock = GitComLockableWrapper(m_pTabS, ComApartmentVerifier::Mta());
+ CHR(m_wispTabletLock.CheckCookie());
+
+ // Prefetch packet description info so we don't have to call wisp later for it.
+ // This avoids reentrancy issues with doing an Out Of Proc COM call.
+ INT cProps, cButtons;
+ CHR(GetPacketDescriptionInfo(&cProps, &cButtons));
+ CHR(RefreshCursorInfo());
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcTablet::FinalRelease()
+{
+ m_pMgr = nullptr;
+ m_pTabS = nullptr;
+
+ ReleaseCursorInfo();
+ ReleasePacketDescription();
+
+ m_wispTabletLock.RevokeIfValid();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::CreateContext(__typefix(HWND) __in INT_PTR pwnd, BOOL fEnable, UINT uiTimeout, __deref_out IPimcContext3** ppCtx, __out INT * pId, __out INT64 *pCommHandle)
+{
+ // pCommHandle cannot be a INT_PTR. The reason being that INT_PTR (__int3264) always gets
+ // marshalled as a 32 bit value, which means in a 64 bit process we would lose the first half of the pointer
+ // by the time it reaches the client. Instead this way we always pass a 64 bit value to the client
+ // (irrespective of process bitness) so that nothing gets lost during marshalling.
+
+ DHR;
+ HWND hwnd = (HWND)pwnd;
+ CComPtr pCtxS;
+ CComObject * pCtxC;
+ TABLET_CONTEXT_ID tcid;
+ DWORD dwOptions = TCXO_CURSOR_STATE | TCXO_ALLOW_FLICKS | TCXO_ALLOW_FEEDBACK_TAPS | TCXO_ALLOW_FEEDBACK_BARREL | TCXO_REPORT_RECT_MAPPING_CHANGE;
+ PACKET_DESCRIPTION * pPacketDescription = NULL;
+ TABLET_CONTEXT_SETTINGS * pTCS = nullptr;
+
+ // Make sure we use the default context settings if not already created.
+ if (m_pTabS && !m_pTCS)
+ {
+ CHR(m_pTabS->GetDefaultContextSettings(&m_pTCS));
+ EnsureNoDuplicates(m_pTCS);
+ EnsureXYPressureOrder(m_pTCS);
+ CHR(m_pTCS ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_GETDEFAULTCONTEXT_CALL));
+ }
+
+ pTCS = m_pTCS; // NULL;
+
+ CHR(IsWindow(hwnd) ? S_OK : E_INVALIDARG);
+
+#if WANT_PROFILE
+ if (m_pMgr->IsProfiling())
+ {
+ CHR(m_pTabS->GetDefaultContextSettings(&pTCS));
+
+ CoTaskMemFree(pTCS->pguidPktProps);
+ CoTaskMemFree(pTCS->pguidPktBtns);
+ CoTaskMemFree(pTCS->pdwBtnDnMask);
+ CoTaskMemFree(pTCS->pdwBtnUpMask);
+
+ pTCS->cPktProps = s_cGuidsProfiling;
+ pTCS->pguidPktProps = s_guids;
+ pTCS->cPktBtns = 0;
+ pTCS->pguidPktBtns = NULL;
+ pTCS->pdwBtnDnMask = NULL;
+ pTCS->pdwBtnUpMask = NULL;
+
+ dwOptions = TCXO_DONT_VALIDATE_TCS | TCXO_DONT_SHOW_CURSOR;
+ }
+#endif // WANT_PROFILING
+
+ CHR(CComObject::CreateInstance(&pCtxC));
+ CHR(pCtxC->QueryInterface(IID_IPimcContext3, (void**)ppCtx));
+
+ if (m_pTabS)
+ {
+ CHR(m_pTabS->CreateContext(
+ hwnd, // hwnd
+ NULL, // rc
+ dwOptions, // options
+ pTCS, // tablet context settings
+ fEnable ? CONTEXT_ENABLE :
+ CONTEXT_DISABLE, // enable type
+ &pCtxS, // the ctx
+ &tcid, // context id
+ &pPacketDescription, // packet description
+ (ITabletEventSink*)pCtxC->m_sink // sink
+ ));
+
+ CHR(pCtxC->Init(m_pMgr, pCtxS, hwnd, tcid, pPacketDescription));
+ pPacketDescription = NULL; // transfered ownership to the context
+ CHR(pCtxC->GetKey(pId)); // really just grabs tcid so could avoid call but would have to add param validation.
+ CHR(pCtxC->SetSingleFireTimeout(uiTimeout));
+ CHR(pCtxC->GetCommHandle(pCommHandle)); // This adds a ref to keep pCtxC alive.
+ }
+ else
+ {
+ //need to fill in the context ///
+ pPacketDescription = (PACKET_DESCRIPTION *)CoTaskMemAlloc (sizeof(PACKET_DESCRIPTION));
+ CHR_MEMALLOC(pPacketDescription);
+
+ // Fill in the packet properties.
+ pPacketDescription->cbPacketSize = 3;
+ pPacketDescription->cPacketProperties = 3;
+ pPacketDescription->pPacketProperties = (PACKET_PROPERTY *)CoTaskMemAlloc (sizeof(PACKET_PROPERTY) * pPacketDescription->cbPacketSize);
+ CHR_MEMALLOC(pPacketDescription->pPacketProperties);
+
+ // X
+ pPacketDescription->pPacketProperties[0].guid = s_guids[GUID_X];
+ pPacketDescription->pPacketProperties[0].PropertyMetrics.nLogicalMin = LONG_MIN;
+ pPacketDescription->pPacketProperties[0].PropertyMetrics.nLogicalMax = LONG_MAX;
+ pPacketDescription->pPacketProperties[0].PropertyMetrics.Units = PROPERTY_UNITS_DEFAULT;
+ pPacketDescription->pPacketProperties[0].PropertyMetrics.fResolution = 1.0f;
+
+ // Y
+ pPacketDescription->pPacketProperties[1].guid = s_guids[GUID_Y];
+ pPacketDescription->pPacketProperties[1].PropertyMetrics.nLogicalMin = LONG_MIN;
+ pPacketDescription->pPacketProperties[1].PropertyMetrics.nLogicalMax = LONG_MAX;
+ pPacketDescription->pPacketProperties[1].PropertyMetrics.Units = PROPERTY_UNITS_DEFAULT;
+ pPacketDescription->pPacketProperties[1].PropertyMetrics.fResolution = 1.0f;
+
+ // PacketStatus
+ pPacketDescription->pPacketProperties[2].guid = s_guids[GUID_PACKETSTATUS];
+ pPacketDescription->pPacketProperties[2].PropertyMetrics.nLogicalMin = LONG_MIN;
+ pPacketDescription->pPacketProperties[2].PropertyMetrics.nLogicalMax = LONG_MAX;
+ pPacketDescription->pPacketProperties[2].PropertyMetrics.Units = PROPERTY_UNITS_DEFAULT;
+ pPacketDescription->pPacketProperties[2].PropertyMetrics.fResolution = 1.0f;
+
+ // Fill in button data....
+ pPacketDescription->cButtons = 2;
+ pPacketDescription->pguidButtons = (GUID *)CoTaskMemAlloc (sizeof(GUID)*2);
+ CHR_MEMALLOC(pPacketDescription->pguidButtons);
+ pPacketDescription->pguidButtons[0] = s_guids[GUID_TIPBUTTON];
+ pPacketDescription->pguidButtons[1] = s_guids[GUID_BARRELBUTTON];
+
+ CHR(UIntPtrToULong(pwnd, &tcid));
+ CHR(pCtxC->Init(m_pMgr, pCtxS, hwnd, tcid, pPacketDescription));
+ pPacketDescription = NULL; // transfered ownership to the context
+ CHR(pCtxC->GetKey(pId));
+ // These calls are really not neccessary for mouse context.
+ CHR(pCtxC->SetSingleFireTimeout(uiTimeout));
+ CHR(pCtxC->GetCommHandle(pCommHandle)); // This adds a ref to keep pCtxC alive.
+ }
+
+CLEANUP:
+ if (pPacketDescription)
+ {
+ CPimcContext::DestroyPacketDescription(pPacketDescription);
+ }
+
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetKey(__out INT * pKey)
+{
+ DHR;
+ CHR(pKey ? S_OK : E_INVALIDARG);
+ *pKey = (INT)PtrToInt(m_pTabS.p);
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetName(__out LPWSTR * ppszName)
+{
+ DHR;
+ LPWSTR pszNameCpy = NULL;
+ HMONITOR hMonitor = nullptr;
+ CHR(ppszName ? S_OK : E_INVALIDARG);
+ *ppszName = NULL;
+
+ if (m_pTabS)
+ {
+ // We ignore the result code because otherwise we will throw a COM exception
+ // Invalid name does not mean invalid device.
+ if (!SUCCEEDED(m_pTabS->GetName(ppszName)))
+ {
+ // Do not rely on failure = null behavior of underlying COM component.
+ // We define failure = NULL here explicitly.
+ ppszName = NULL;
+ }
+ goto CLEANUP;
+ }
+
+ // This is the same code that wisptis uses to determine the name of the Mouse device.
+ // Since this is a not very common called API we don't cache the name.
+ MONITORINFOEX MonitorInfoEx;
+ MonitorInfoEx.cbSize = SIZEOFSTRUCT(MonitorInfoEx);
+ hMonitor = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY);
+ CHR(hMonitor != NULL ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_MONITORFROMWINDOW_CALL));
+ CHR(GetMonitorInfo(hMonitor, &MonitorInfoEx) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_GETMONITORINFO_CALL));
+
+ size_t cbName;
+ CHR(StringCchLengthW(MonitorInfoEx.szDevice, STRSAFE_MAX_CCH, &cbName));
+ CHR(SizeTAdd(cbName, 1, &cbName));
+ CHR(SizeTMult(cbName, sizeof(WCHAR), &cbName));
+ pszNameCpy = (LPWSTR)CoTaskMemAlloc (cbName);
+ CHR_MEMALLOC(pszNameCpy);
+ CHR(StringCbCopy(pszNameCpy, cbName, MonitorInfoEx.szDevice));
+
+ *ppszName = pszNameCpy;
+ pszNameCpy = NULL;
+
+CLEANUP:
+ if (pszNameCpy != NULL)
+ {
+ ::CoTaskMemFree(pszNameCpy);
+ }
+ RHR
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetPlugAndPlayId(__out LPWSTR * ppszPlugAndPlayId)
+{
+ DHR;
+ if (m_pTabS)
+ return m_pTabS->GetPlugAndPlayId(ppszPlugAndPlayId);
+ else
+ {
+ // mousetab.cpp in wisptis is hard coded to return "SCREEN" for the mouse device.
+ size_t cbName;
+ CHR(StringCchLength(MOUSEDEVICE_PLUGANDPLAYID, STRSAFE_MAX_CCH, &cbName));
+ CHR(SizeTAdd(cbName, 1, &cbName));
+ CHR(SizeTMult(cbName, sizeof(WCHAR), &cbName));
+
+ *ppszPlugAndPlayId = (LPWSTR)CoTaskMemAlloc (cbName);
+ CHR_MEMALLOC(*ppszPlugAndPlayId);
+ return StringCbCopy(*ppszPlugAndPlayId, cbName, MOUSEDEVICE_PLUGANDPLAYID);
+ }
+ CLEANUP:
+ RHR
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetTabletAndDisplaySize(__out INT * piTabletWidth, __out INT * piTabletHeight, __out INT * piDisplayWidth, __out INT * piDisplayHeight)
+{
+ DHR;
+ RECT rcTablet = {0,0,0,0};
+ CHR(piTabletWidth ? S_OK : E_INVALIDARG);
+ CHR(piTabletHeight ? S_OK : E_INVALIDARG);
+ CHR(piDisplayWidth ? S_OK : E_INVALIDARG);
+ CHR(piDisplayHeight ? S_OK : E_INVALIDARG);
+
+ if (m_pTabS)
+ {
+ // First get tablet info...
+ CHR(m_pTabS->GetMaxInputRect(&rcTablet));
+ *piTabletWidth = rcTablet.right - rcTablet.left;
+ *piTabletHeight = rcTablet.bottom - rcTablet.top;
+
+ // Now get the display info...
+
+ // First see if we have Vista wisptis that supports the new method
+ // that supports mapping integrated digitizers to displays.
+ CComQIPtr spTablet2(m_pTabS);
+ if (nullptr != spTablet2)
+ {
+ RECT rcScreen;
+ CHR(spTablet2->GetMatchingScreenRect(&rcScreen));
+ *piDisplayWidth = rcScreen.right - rcScreen.left;
+ *piDisplayHeight = rcScreen.bottom - rcScreen.top;
+ goto CLEANUP; // we're done.
+ }
+
+ // otherwise figure things out using the XP logic which maps to primary monitor
+ // always for integrated digitizers.
+ int iHwCaps = 0;
+ CHR(GetHardwareCaps(&iHwCaps));
+
+ // See if we are integrated.
+ if ((iHwCaps & THWC_INTEGRATED) != 0)
+ {
+ // integrated, so use primary monitor rect.
+ HMONITOR hMonitor = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY);
+ if (hMonitor != NULL)
+ {
+ MONITORINFOEX monitorInfo;
+ monitorInfo.cbSize = sizeof(MONITORINFOEX);
+ GetMonitorInfo(hMonitor, &monitorInfo);
+ *piDisplayWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
+ *piDisplayHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
+ goto CLEANUP;
+ }
+ }
+
+ // If we fail above then just do non integrated code.
+ // non integrated so use desktop rect.
+ *piDisplayWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ *piDisplayHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ }
+ else
+ {
+ // By default just return same for tablet and display (no scaling).
+ *piTabletWidth = *piDisplayWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ *piTabletHeight = *piDisplayHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ }
+
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetHardwareCaps(__out INT * pCaps)
+{
+ DHR;
+ DWORD dwCaps;
+ CHR(pCaps ? S_OK : E_INVALIDARG);
+ if (m_pTabS)
+ {
+ CHR(m_pTabS->GetHardwareCaps(&dwCaps));
+ *pCaps = (INT)dwCaps;
+ }
+ else
+ {
+ // return the data for our 'fake mouse'
+ *pCaps = (INT)0x2; //StylusMustTouch
+ }
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////
+STDMETHODIMP CPimcTablet::GetDeviceType(__out INT * pKind)
+{
+ HRESULT hr = S_OK;
+ LPWSTR pszName = NULL;
+ CHR(pKind ? S_OK : E_INVALIDARG);
+ *pKind = 0;
+
+ if (m_pTabS)
+ {
+ CComQIPtr spTablet2(m_pTabS);
+ if (nullptr != spTablet2)
+ {
+ TABLET_DEVICE_KIND kind;
+ hr = spTablet2->GetDeviceKind(&kind);
+ if (SUCCEEDED(hr))
+ {
+ *pKind = (INT)kind;
+ goto CLEANUP;
+ }
+ }
+ }
+
+ hr = GetName(&pszName);
+ if (SUCCEEDED(hr))
+ {
+ *pKind = (NULL == wcsstr(pszName, L"\\\\.\\DISPLAY") ? 1 /*Pen*/: 0 /*Mouse*/);
+ }
+
+CLEANUP:
+ ::CoTaskMemFree(pszName);
+ RHR;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::RefreshCursorInfo()
+{
+ DHR;
+ CComPtr pCursorS;
+ CComPtr pButtonS;
+
+ ReleaseCursorInfo();
+
+ if (m_pTabS)
+ {
+ CHR(m_pTabS->GetCursorCount(&m_cCursors));
+ m_apCursorInfo = new PCURSORINFO[m_cCursors]();
+
+ CHR(m_apCursorInfo ? S_OK : E_OUTOFMEMORY);
+
+ for (DWORD iCursor = 0; iCursor < m_cCursors; iCursor++)
+ {
+ CHR(m_pTabS->GetCursor(iCursor, &pCursorS));
+
+ PCURSORINFO pCursorInfo = new CURSORINFO();
+ CHR(pCursorInfo ? S_OK : E_OUTOFMEMORY);
+ #pragma prefast( suppress: 11, "Dereferencing NULL pointer 'm_apCursorInfo'." )
+ m_apCursorInfo[iCursor] = pCursorInfo;
+
+ CHR(pCursorS->GetName(&pCursorInfo->pszName));
+ CHR(pCursorS->GetId (&pCursorInfo->id));
+ HRESULT hrInverted = pCursorS->IsInverted();
+ CHR(hrInverted);
+ pCursorInfo->fInverted = hrInverted == S_OK;
+
+ DWORD cButtons;
+ CHR(pCursorS->GetButtonCount(&cButtons));
+ pCursorInfo->cButtons = cButtons;
+ pCursorInfo->apButtonInfo = new PCURSORBUTTONINFO[cButtons]();
+
+ for (DWORD iButton = 0; iButton < cButtons; iButton++)
+ {
+ CHR(pCursorS->GetButton(iButton, &pButtonS));
+
+ PCURSORBUTTONINFO pButtonInfo = new CURSORBUTTONINFO();
+ CHR(pButtonInfo ? S_OK : E_OUTOFMEMORY);
+ #pragma prefast( suppress: 11, "Dereferencing NULL pointer 'pCursorInfo'." )
+ pCursorInfo->apButtonInfo[iButton] = pButtonInfo;
+
+ CHR(pButtonS->GetName(&pButtonInfo->pszName));
+ CHR(pButtonS->GetGuid(&pButtonInfo->guid));
+
+ // The smart pointer should be smart enough.
+ #pragma prefast( suppress: 416, "Dereferencing NULL smart pointer 'pButtonS'." )
+ pButtonS = nullptr;
+ }
+
+ pCursorS = nullptr;
+ }
+ }
+ else
+ {
+ // fake it up for a mouse...
+ m_cCursors = 1;
+ m_apCursorInfo = new PCURSORINFO[m_cCursors]();
+ CHR(m_apCursorInfo ? S_OK : E_OUTOFMEMORY);
+
+ PCURSORINFO pCursorInfo = new CURSORINFO();
+ CHR(pCursorInfo ? S_OK : E_OUTOFMEMORY);
+ #pragma prefast( suppress: 11, "Dereferencing NULL pointer 'm_apCursorInfo'." )
+ m_apCursorInfo[0] = pCursorInfo;
+
+
+ size_t cbName;
+ CHR(StringCchLength(MOUSEDEVICE_CURSOR_NAME, STRSAFE_MAX_CCH, &cbName));
+ CHR(SizeTAdd(cbName, 1, &cbName));
+ CHR(SizeTMult(cbName, sizeof(WCHAR), &cbName));
+
+ pCursorInfo->pszName = (LPWSTR)CoTaskMemAlloc (cbName);
+ CHR_MEMALLOC(pCursorInfo->pszName);
+ StringCbCopy(pCursorInfo->pszName, cbName, MOUSEDEVICE_CURSOR_NAME);
+
+ pCursorInfo->id = 1; // default for mouse device
+ pCursorInfo->fInverted = false;
+
+ int cButtons = 2; // there are two buttons for a mouse...
+ pCursorInfo->cButtons = cButtons;
+ pCursorInfo->apButtonInfo = new PCURSORBUTTONINFO[cButtons]();
+
+ //Get some memory for the button info...
+ for(int i=0; ipszName = (LPWSTR)CoTaskMemAlloc (cbName);
+ CHR_MEMALLOC(pButtonInfo->pszName);
+ StringCbCopy(pButtonInfo->pszName, cbName, MOUSEDEVICE_BUTTON_ONE_NAME);
+ pButtonInfo->guid = s_guids[GUID_TIPBUTTON];
+ }
+ else
+ {
+ CHR(StringCchLength(MOUSEDEVICE_BUTTON_TWO_NAME, STRSAFE_MAX_CCH, &cbName));
+ CHR(SizeTAdd(cbName, 1, &cbName));
+ CHR(SizeTMult(cbName, sizeof(WCHAR), &cbName));
+
+ pButtonInfo->pszName = (LPWSTR)CoTaskMemAlloc (cbName);
+ CHR_MEMALLOC(pButtonInfo->pszName);
+ StringCbCopy(pButtonInfo->pszName, cbName, MOUSEDEVICE_BUTTON_TWO_NAME);
+ pButtonInfo->guid = s_guids[GUID_BARRELBUTTON];
+ }
+ pCursorInfo->apButtonInfo[i] = pButtonInfo;
+ }
+ }
+
+CLEANUP:
+
+ if ( FAILED(hr) )
+ {
+ ReleaseCursorInfo();
+ }
+
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcTablet::ReleaseCursorInfo()
+{
+ if (m_cCursors > 0)
+ {
+ if (nullptr != m_apCursorInfo)
+ {
+ for (DWORD iCursor = 0; iCursor < m_cCursors; iCursor++)
+ {
+ if (nullptr != m_apCursorInfo[iCursor])
+ {
+ m_apCursorInfo[iCursor]->Clear();
+ delete m_apCursorInfo[iCursor];
+ m_apCursorInfo[iCursor] = nullptr;
+ }
+ }
+ delete [] m_apCursorInfo;
+ m_apCursorInfo = nullptr;
+ }
+ m_cCursors = 0;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetCursorCount(__out INT * pcCursors)
+{
+ DHR;
+ CHR(pcCursors ? S_OK : E_INVALIDARG);
+ *pcCursors = m_cCursors;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetCursorInfo(INT iCursor, __out LPWSTR * ppszName, __out INT * pId, __out BOOL * pfInverted)
+{
+ size_t cbName;
+ PCURSORINFO pCursorInfo = nullptr;
+ DHR;
+
+ CHR(iCursor >= 0 ? S_OK : E_INVALIDARG);
+ CHR((DWORD)iCursor < m_cCursors ? S_OK : E_INVALIDARG);
+ CHR(ppszName ? S_OK : E_INVALIDARG);
+ CHR(pId ? S_OK : E_INVALIDARG);
+ CHR(pfInverted ? S_OK : E_INVALIDARG);
+
+ // iCursor value is checked above, disable prefast signedness warning
+#pragma prefast(suppress: 37001 37002 37003)
+ pCursorInfo = m_apCursorInfo[iCursor];
+ CHR(StringCchLength(pCursorInfo->pszName, STRSAFE_MAX_CCH, &cbName));
+ CHR(SizeTAdd(cbName, 1, &cbName));
+ CHR(SizeTMult(cbName, sizeof(WCHAR), &cbName));
+ *ppszName = (LPWSTR)CoTaskMemAlloc (cbName);
+ CHR_MEMALLOC(*ppszName);
+ StringCbCopy(*ppszName, cbName, pCursorInfo->pszName);
+
+ *pId = pCursorInfo->id;
+ *pfInverted = pCursorInfo->fInverted;
+
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetCursorButtonCount(INT iCursor, __out INT * pcButtons)
+{
+ DHR;
+
+ switch (iCursor)
+ {
+ case LOCK_TABLET_EXT:
+ {
+ // DDVSO:514949
+ // Calling this ensures that the CStdIdentity for this IPimcTablet3 is
+ // not released if we hit a COM rundown due to OSGVSO:10779198.
+ m_tabletLock = ComLockableWrapper(this, ComApartmentVerifier::CurrentSta());
+ CHR(m_tabletLock.Lock());
+ }
+ break;
+ case RELEASE_TABLET_EXT:
+ {
+ CHR(m_tabletLock.Unlock());
+ }
+ break;
+ case QUERY_WISP_TABLET_KEY:
+ {
+ if (nullptr == pcButtons)
+ {
+ CHR(E_INVALIDARG);
+ }
+ else
+ {
+ *pcButtons = m_wispTabletLock.GetCookie();
+ }
+ }
+ break;
+ case QUERY_WISP_MANAGER_KEY:
+ {
+ if (nullptr == pcButtons)
+ {
+ CHR(E_INVALIDARG);
+ }
+ else
+ {
+ *pcButtons = m_pMgr->m_wispManagerLock.GetCookie();
+ }
+ }
+ break;
+ default:
+ {
+ CHR(GetCursorButtonCountImpl(iCursor, pcButtons));
+ }
+ }
+
+CLEANUP:
+ RHR;
+}
+
+STDMETHODIMP CPimcTablet::GetCursorButtonCountImpl(INT iCursor, __out INT * pcButtons)
+{
+ DHR;
+ CHR(iCursor >= 0 ? S_OK : E_INVALIDARG);
+ CHR((DWORD)iCursor < m_cCursors ? S_OK : E_INVALIDARG);
+ CHR(pcButtons ? S_OK : E_INVALIDARG);
+ // iCursor value is checked above, disable prefast signedness warning
+#pragma prefast(suppress: 37001 37002 37003)
+ *pcButtons = m_apCursorInfo[iCursor]->cButtons;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetCursorButtonInfo(INT iCursor, INT iButton, __out LPWSTR * ppszName, __out GUID * pGuid)
+{
+ DHR;
+ size_t cbName = 0;
+ LPWSTR pszNameSrc = nullptr;
+ PCURSORBUTTONINFO pButtonInfo = nullptr;
+ CHR(iCursor >= 0 ? S_OK : E_INVALIDARG);
+ CHR((DWORD)iCursor < m_cCursors ? S_OK : E_INVALIDARG);
+ CHR(iButton >= 0 ? S_OK : E_INVALIDARG);
+
+ // iCursor is checked for underflow above, disable prefast signedness warnings
+#pragma prefast(suppress: 37001 37002 37003)
+ CHR(iButton < m_apCursorInfo[iCursor]->cButtons ? S_OK : E_INVALIDARG);
+ CHR(ppszName ? S_OK : E_INVALIDARG);
+ CHR(pGuid ? S_OK : E_INVALIDARG);
+
+ // iButton and iCursor are checked for underflow above, disable prefast signedness warnings
+#pragma prefast(suppress: 37001 37002 37003)
+ pButtonInfo = m_apCursorInfo[iCursor]->apButtonInfo[iButton];
+
+ pszNameSrc = pButtonInfo->pszName;
+ CHR(StringCchLength(pszNameSrc, STRSAFE_MAX_CCH, &cbName));
+ CHR(SizeTAdd(cbName, 1, &cbName));
+ CHR(SizeTMult(cbName, sizeof(WCHAR), &cbName));
+ *ppszName = (LPWSTR)CoTaskMemAlloc (cbName);
+ CHR_MEMALLOC(*ppszName);
+ StringCbCopy(*ppszName, cbName, pszNameSrc);
+
+ *pGuid = pButtonInfo->guid;
+
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::IsPropertySupported(GUID guid, __out BOOL * pfSupported)
+{
+ DHR;
+ CHR(pfSupported ? S_OK : E_INVALIDARG);
+ PROPERTY_METRICS metric;
+ *pfSupported = S_OK == m_pTabS->GetPropertyMetrics(guid, &metric);
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetPropertyInfo(GUID guid, __out INT * piMin, __out INT * piMax, __out INT * piUnit, __out FLOAT *pflResolution)
+{
+ DHR;
+ PROPERTY_METRICS metric;
+ CHR(piMin ? S_OK : E_INVALIDARG);
+ CHR(piMax ? S_OK : E_INVALIDARG);
+ CHR(piUnit ? S_OK : E_INVALIDARG);
+ CHR(pflResolution ? S_OK : E_INVALIDARG);
+ CHR(m_pTabS->GetPropertyMetrics(guid, &metric));
+ *piMin = metric.nLogicalMin;
+ *piMax = metric.nLogicalMax;
+ *piUnit = metric.Units;
+ *pflResolution = metric.fResolution;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetPacketDescriptionInfo(__out INT * pcProps, __out INT * pcButtons)
+{
+ DHR;
+ CHR(pcProps ? S_OK : E_INVALIDARG);
+ CHR(pcButtons ? S_OK : E_INVALIDARG);
+
+ if (m_pTabS)
+ {
+ if (!m_pTCS)
+ {
+ CHR(m_pTabS->GetDefaultContextSettings(&m_pTCS));
+ EnsureNoDuplicates(m_pTCS);
+ EnsureXYPressureOrder(m_pTCS);
+ CHR(m_pTCS ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, E_GETDEFAULTCONTEXT_CALL));
+ }
+
+ *pcProps = m_pTCS->cPktProps;
+ *pcButtons = m_pTCS->cPktBtns;
+ }
+ else
+ {
+ // No wisptis case, so return mouse settings
+ *pcProps = 3;
+ *pcButtons = 2;
+ }
+
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetPacketPropertyInfo(INT iProp, __out GUID * pGuid, __out INT * piMin, __out INT * piMax, __out INT * piUnits, __out FLOAT *pflResolution)
+{
+ DHR;
+
+ CHR(0 <= iProp && (DWORD)iProp < (m_pTCS ? m_pTCS->cPktProps : 3) ? S_OK : E_INVALIDARG);
+ CHR(pGuid ? S_OK : E_INVALIDARG);
+ CHR(piMin ? S_OK : E_INVALIDARG);
+ CHR(piMax ? S_OK : E_INVALIDARG);
+ CHR(piUnits ? S_OK : E_INVALIDARG);
+ CHR(pflResolution ? S_OK : E_INVALIDARG);
+
+ // iProp is checked for overflow/underflow above, disable prefast signedness warnings
+#pragma prefast(suppress: 37001 37002 37003)
+ *pGuid = m_pTCS ? m_pTCS->pguidPktProps[iProp] : s_guids[iProp];
+ *piMin = 0; // pProp->PropertyMetrics.nLogicalMin;
+ *piMax = 0; // pProp->PropertyMetrics.nLogicalMax;
+ *piUnits = 0; // pProp->PropertyMetrics.Units;
+ *pflResolution = 0.0f; // pProp->PropertyMetrics.fResolution;
+CLEANUP:
+ RHR;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP CPimcTablet::GetPacketButtonInfo(INT iButton, __out GUID * pGuid)
+{
+ DHR;
+ CHR(0 <= iButton && (DWORD)iButton < (m_pTCS ? m_pTCS->cPktBtns : 2) ? S_OK : E_INVALIDARG);
+ CHR(pGuid ? S_OK : E_INVALIDARG);
+
+ // Value of iButton is checked above. Since iButton is within known limits we assume the addition of 3 is accounted
+ // for and will not produce overflow. Disable prefast warnings
+#pragma prefast(suppress: 37001 37002 37003)
+ *pGuid = m_pTCS ?
+ m_pTCS->pguidPktBtns[iButton] : // if we have context descr
+ s_guids[3+iButton]; // TipButton or BarrelButton equals index 3 or 4
+CLEANUP:
+ RHR;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CPimcTablet::ReleasePacketDescription()
+{
+ if (m_pTCS)
+ {
+ if (m_pTCS->pguidPktProps)
+ CoTaskMemFree(m_pTCS->pguidPktProps);
+ if (m_pTCS->pguidPktBtns)
+ CoTaskMemFree(m_pTCS->pguidPktBtns);
+ if (m_pTCS->pdwBtnDnMask)
+ CoTaskMemFree(m_pTCS->pdwBtnDnMask);
+ if (m_pTCS->pdwBtnUpMask)
+ CoTaskMemFree(m_pTCS->pdwBtnUpMask);
+
+ CoTaskMemFree(m_pTCS);
+ m_pTCS = NULL;
+ }
+}
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcTablet.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcTablet.h
new file mode 100644
index 00000000000..b9e6ecb5d44
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcTablet.h
@@ -0,0 +1,148 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// PimcTablet.h : Declaration of the CPimcTablet
+
+#pragma once
+#include
+#include "resource.h" // main symbols
+
+#include "PenImc.h"
+#include "PimcManager.h"
+#include "ComLockableWrapper.hpp"
+#include "GitComLockableWrapper.hpp"
+
+/////////////////////////////////////////////////////////////////////////////
+// CPimcTablet
+
+class ATL_NO_VTABLE CPimcTablet :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IPimcTablet3
+{
+public:
+ /////////////////////////////////////////////////////////////////////////
+
+ CPimcTablet();
+ HRESULT FinalConstruct() { return S_OK; };
+ void FinalRelease();
+
+ // DDVSO:174153
+ // Cleanup initialization to use CComPtr throughout. This fixes COM reference count issues
+ // that arise due to conversion from round-tripping conversions from CComPtr to raw and back.
+ HRESULT Init(__in CComPtr pTabS, __in CComPtr pMgr);
+ void ReleaseCursorInfo();
+ void ReleasePacketDescription();
+
+ STDMETHOD(GetKey)(__out INT * pKey);
+ STDMETHOD(GetName)(__out LPWSTR * ppszName);
+ STDMETHOD(GetPlugAndPlayId)(__out LPWSTR * ppszPlugAndPlayId);
+ STDMETHOD(GetTabletAndDisplaySize)(__out INT * piTabletWidth, __out INT * piTabletHeight, __out INT * piDisplayWidth, __out INT * piDisplayHeight);
+ STDMETHOD(GetHardwareCaps)(__out INT * pdwCaps);
+ STDMETHOD(GetDeviceType)(__out INT * pKind);
+ STDMETHOD(RefreshCursorInfo)();
+ STDMETHOD(GetCursorCount)(__out INT * pcCursors);
+ STDMETHOD(GetCursorInfo)(INT iCursor, __out LPWSTR * ppszName, __out INT * pId, __out BOOL * pfInverted);
+ STDMETHOD(GetCursorButtonCount)(INT iCursor, __out INT * pcButtons);
+ STDMETHOD(GetCursorButtonCountImpl)(INT iCursor, __out INT * pcButtons);
+ STDMETHOD(GetCursorButtonInfo)(INT iCursor, INT iButton, __out LPWSTR * ppszName, __out GUID * pGuid);
+ STDMETHOD(IsPropertySupported)(GUID guid, __out BOOL * pfSupported);
+ STDMETHOD(GetPropertyInfo)(GUID guid, __out INT * piMin, __out INT * piMax, __out INT * piUnit, __out FLOAT *pflResolution);
+ STDMETHOD(CreateContext)(__typefix(HWND) __in INT_PTR pwnd, BOOL fEnable, UINT uiTimeout, __deref_out IPimcContext3** ppCtx, __out INT * pId, __out INT64 *pCommHandle);
+ STDMETHOD(GetPacketDescriptionInfo)(__out INT * pcProps, __out INT * pcButtons);
+ STDMETHOD(GetPacketPropertyInfo)(INT iProp, __out GUID * pGuid, __out INT * piMin, __out INT * piMax, __out INT * piUnits, __out FLOAT *pflResolution);
+ STDMETHOD(GetPacketButtonInfo)(INT iButton, __out GUID * pGuid);
+
+ /////////////////////////////////////////////////////////////////////////
+
+BEGIN_COM_MAP(CPimcTablet)
+ COM_INTERFACE_ENTRY(IPimcTablet3)
+END_COM_MAP()
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ /////////////////////////////////////////////////////////////////////////
+
+ struct CURSORBUTTONINFO
+ {
+ LPWSTR pszName;
+ GUID guid;
+
+ CURSORBUTTONINFO()
+ {
+ pszName = nullptr;
+ ZeroMemory(&guid, sizeof(guid));
+ }
+
+ void Clear()
+ {
+ if (nullptr != pszName)
+ {
+ CoTaskMemFree(pszName);
+ pszName = nullptr;
+ }
+ }
+ };
+ typedef CURSORBUTTONINFO * PCURSORBUTTONINFO;
+
+ /////////////////////////////////////////////////////////////////////////
+
+ struct CURSORINFO
+ {
+ LPWSTR pszName;
+ CURSOR_ID id;
+ BOOL fInverted;
+ INT cButtons;
+ PCURSORBUTTONINFO * apButtonInfo;
+
+ CURSORINFO()
+ {
+ pszName = nullptr;
+ id = 0;
+ fInverted = false;
+ cButtons = 0;
+ apButtonInfo = nullptr;
+ }
+
+ void Clear()
+ {
+ if (nullptr != pszName)
+ {
+ CoTaskMemFree(pszName);
+ pszName = nullptr;
+ }
+ for (INT i = 0; i < cButtons; i++)
+ {
+ if (nullptr != apButtonInfo[i])
+ {
+ apButtonInfo[i]->Clear();
+ delete apButtonInfo[i];
+ apButtonInfo[i] = nullptr;
+ }
+ }
+ delete [] apButtonInfo;
+ }
+ };
+ typedef CURSORINFO * PCURSORINFO;
+
+ /////////////////////////////////////////////////////////////////////////
+
+ CComPtr m_pMgr;
+ CComPtr m_pTabS;
+ ComUtils::GitComLockableWrapper m_wispTabletLock;
+ DWORD m_cCursors;
+ PCURSORINFO * m_apCursorInfo;
+ TABLET_CONTEXT_SETTINGS * m_pTCS;
+ ComUtils::ComLockableWrapper m_tabletLock;
+
+ // DDVSO:514949
+ // Special param flags for COM operations in GetCursorButtonCount
+ const static int RELEASE_TABLET_EXT = -1;
+ const static int QUERY_WISP_TABLET_KEY = -2;
+ const static int QUERY_WISP_MANAGER_KEY = -3;
+ const static int LOCK_TABLET_EXT = -4;
+};
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/SxSCOMRegistration.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/SxSCOMRegistration.cpp
new file mode 100644
index 00000000000..0e97f1dded4
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/SxSCOMRegistration.cpp
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#include "stdafx.h"
+#include "peninc.h"
+
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+
+// Creates an ActivationContext using the embedded manifest and pushes it on the
+// context stack. The ActivationContext cookie is returned to the caller: a non-zero value
+// indicates success; zero indicates failure. Caller is responsible for deactivating
+// the context.
+extern "C" ULONG_PTR WINAPI RegisterDllForSxSCOM()
+{
+ // Get the full path to this Dll
+ WCHAR moduleFullPath[MAX_PATH] = {0};
+ if (!GetModuleFileNameW((HINSTANCE)&__ImageBase, moduleFullPath, _countof(moduleFullPath)))
+ {
+ return 0;
+ }
+
+ // ACTCTX.lpResourceName must be 'ISOLATIONAWARE_MANIFEST_RESOURCE_ID' for Dlls.
+ // Defined as: ISOLATIONAWARE_MANIFEST_RESOURCE_ID MAKEINTRESOURCE(2)
+ ACTCTX activationContext = {};
+ activationContext.cbSize = sizeof(activationContext);
+ activationContext.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_APPLICATION_NAME_VALID;
+ activationContext.lpSource = moduleFullPath;
+ activationContext.lpResourceName = ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
+
+ // Create and activate context : context is added to the top of the context stack
+ HANDLE activationContextHandle = ::CreateActCtxW(&activationContext);
+ if (INVALID_HANDLE_VALUE == activationContextHandle)
+ {
+ return 0;
+ }
+
+ ULONG_PTR activationContextCookie = 0;
+ BOOL activateActCtxResult = ::ActivateActCtx(activationContextHandle, &activationContextCookie);
+ if (activateActCtxResult == FALSE)
+ {
+ return 0;
+ }
+
+ // Return the context cookie : caller is responsible for deactivating the context.
+ return activationContextCookie;
+}
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/WispComLockExports.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/WispComLockExports.cpp
new file mode 100644
index 00000000000..cb86b9c9cac
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/WispComLockExports.cpp
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#include "stdafx.h"
+
+#include "ComApartmentVerifier.hpp"
+#include "GitComLockableWrapper.hpp"
+
+using namespace ComUtils;
+
+// Exported call to lock WISP objects stored in the GIT
+extern "C" BOOL WINAPI LockWispObjectFromGit(__in DWORD gitKey)
+{
+ GitComLockableWrapper git(gitKey, ComApartmentVerifier::Mta());
+ HRESULT hr = git.Lock();
+
+ return SUCCEEDED(hr);
+}
+
+// Exported call to unlock WISP objects stored in the GIT
+extern "C" BOOL WINAPI UnlockWispObjectFromGit(__in DWORD gitKey)
+{
+ GitComLockableWrapper git(gitKey, ComApartmentVerifier::Mta());
+ HRESULT hr = git.Unlock();
+
+ return SUCCEEDED(hr);
+}
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/compressstub.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/compressstub.cpp
new file mode 100644
index 00000000000..9ed8fcc1b9f
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/compressstub.cpp
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// compressstub.cpp : Implementation of compress.lib (and hopefully in
+// the future shared.lib stubs)
+//
+// NOTE: Currently I could not directly export functions declared in a .lib
+// file we link in so stubs have been created to which reference the .lib
+// routines we want to use and thing then get resolved properly and we can
+// then export these stubs (with a rename trick in the .def file).
+// If we can figure out how to directly expose .lib functions then these
+// stubs can be removed.
+
+#include "stdafx.h"
+#include
+
+// Stubs to allow us to resolve to the compress.lib routines we want to expose from our
+// DLL.
+
+extern "C" ISF_RESULT IsfCompressPropertyData_stub(
+ IN const BYTE * pbInput, // Input data
+ IN ULONG cbInput, // Number of bytes in buffer
+ IN OUT BYTE * pnAlgoByte, // in: desired alg. identifier byte, out: really the best
+ IN OUT ULONG * pcbOutput, // in: cb of the buffer; out: cb needed to compress
+ OUT BYTE * pbOutput // OUT, output buffer
+ )
+{
+ return IsfCompressPropertyData(pbInput,cbInput,pnAlgoByte,pcbOutput,pbOutput);
+}
+
+extern "C" ISF_RESULT IsfDecompressPropertyData_stub(
+ IN const BYTE * pbCompressed, // in, compressed input bytes
+ IN ULONG cbCompressed, // in: size of the input bytes
+ OUT ULONG * pcbOutput, // in: cb in pbOutput, out: required
+ OUT BYTE * pbOutput, // Uncompressed data
+ OUT BYTE * pnAlgoByte // Algorithm used
+ )
+{
+ return IsfDecompressPropertyData(pbCompressed, cbCompressed, pcbOutput, pbOutput, pnAlgoByte);
+}
+
+extern "C" ISF_RESULT IsfCompressPacketData_stub(
+ IN HCOMPRESS hCompress, // compressor handle,
+ IN const LONG * pbInput, // Input data, always LONG
+ IN ULONG cInCount, // Number of LONGs in buffer
+ IN OUT BYTE * pnAlgoByte, // in: preferred algo byte out: really the best
+ IN OUT ULONG * pcbOutput, // in: cb of the buffer; out: cb needed to compress
+ OUT BYTE * pbOutput // OUT, output buffer
+ )
+{
+ return IsfCompressPacketData(hCompress, pbInput, cInCount, pnAlgoByte, pcbOutput, pbOutput);
+}
+
+extern "C" ISF_RESULT IsfDecompressPacketData_stub(
+ IN HCOMPRESS hCompress, // Compressor handle
+ IN const BYTE * pbCompressed, // Compressed input bytes
+ IN OUT ULONG * pcbCompressed, // in: cb of the input bytes out: cb read
+ IN ULONG cInCount, // Number of elements in input buffer
+ OUT LONG * pbOutput, // Uncompressed data
+ OUT BYTE * pnAlgoData // Algorithm used
+ )
+{
+ return IsfDecompressPacketData(hCompress, pbCompressed, pcbCompressed, cInCount, pbOutput, pnAlgoData);
+}
+
+extern "C" HCOMPRESS IsfLoadCompressor_stub(
+ IN const BYTE * pbInput,
+ IN ULONG * pcbInput
+ )
+{
+ return IsfLoadCompressor(pbInput, pcbInput);
+}
+
+
+extern "C" void IsfReleaseCompressor_stub(HCOMPRESS hCompress)
+{
+ IsfReleaseCompressor(hCompress);
+}
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dir.targets b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dir.targets
new file mode 100644
index 00000000000..5236e7c6faf
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dir.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dlldatax.c b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dlldatax.c
new file mode 100644
index 00000000000..dee4aaa1c98
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dlldatax.c
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// wrapper for dlldata.c
+
+#ifdef _MERGE_PROXYSTUB // merge proxy stub DLL
+
+#define REGISTER_PROXY_DLL //DllRegisterServer, etc.
+
+#define USE_STUBLESS_PROXY //defined only with MIDL switch /Oicf
+
+// 'rpcndr' is a deprecated lib; link to rpcns4.lib and rpcrt4.lib instead.
+#pragma comment(lib, "rpcns4.lib")
+#pragma comment(lib, "rpcrt4.lib")
+
+#define ENTRY_PREFIX Prx
+
+#include "dlldata.c"
+#include
+
+#endif //_MERGE_PROXYSTUB
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dlldatax.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dlldatax.h
new file mode 100644
index 00000000000..90a06ed9cc1
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/dlldatax.h
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#pragma once
+
+#ifdef _MERGE_PROXYSTUB
+
+extern "C"
+{
+BOOL WINAPI PrxDllMain(HINSTANCE hInstance, DWORD dwReason,
+ LPVOID lpReserved);
+STDAPI PrxDllCanUnloadNow(void);
+STDAPI PrxDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
+STDAPI PrxDllRegisterServer(void);
+STDAPI PrxDllUnregisterServer(void);
+}
+
+#endif
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/resource.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/resource.h
new file mode 100644
index 00000000000..9ad9cc82b34
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/resource.h
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by PenImc.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_PENIMC 101
+#define IDR_PIMCMANAGER 102
+#define IDR_PIMCSURROGATE 105
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 106
+#endif
+#endif
+
+
+// Custom HRESULTS...
+//
+#define E_CREATEEVENT_CALL 0x301
+#define E_GETCURRENTPROCESSID_CALL 0x302
+#define E_QUEUEUSERAPC_CALL 0x303
+#define E_USESHAREDMEMORYCOM_CALL 0x304
+#define E_SHAREDMEMORYHEADER_NULL 0x305
+#define E_SHAREDMEMORYRAWDATA_NULL 0x306
+#define E_CANNOTCREATERESETEVENT 0x307
+#define E_GETDEFAULTCONTEXT_CALL 0x308
+#define E_MONITORFROMWINDOW_CALL 0x309
+#define E_GETMONITORINFO_CALL 0x310
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/stdafx.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/stdafx.cpp
new file mode 100644
index 00000000000..5ee5118c602
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/stdafx.cpp
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// stdafx.cpp : source file that includes just the standard includes
+// PenImc.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/dll/stdafx.h b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/stdafx.h
new file mode 100644
index 00000000000..f386cc075cf
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/dll/stdafx.h
@@ -0,0 +1,91 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef STRICT
+#define STRICT
+#endif
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.
+#define WINVER 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target Windows XP or later.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
+#define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later.
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define _ATL_SINGLE_THREADED // #define _ATL_APARTMENT_THREADED // #define _ATL_FREE_THREADED
+
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+#define _ATL_ALL_WARNINGS // turns off ATL's hiding of some common and often safely ignored warning messages
+
+#include
+#include "resource.h"
+#include
+#include
+
+using namespace ATL;
+
+#include
+
+#define WM_UNINITMENUPOPUP 0x0125
+
+/////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+#include
+
+// #define DELIVERY_PROFILING // DO NOT LEAVE ENABLED in the checked in code
+
+#if 1 // from csutil.h //..WIP (alexz) proper includes
+#define WISPTIS_SHAREDMEMORY_MAXPACKETS 64
+
+#define WISPTIS_SHAREDMEMORY_AVAILABLE 0xFFFFFFFF
+
+struct SHAREDMEMORY_HEADER
+{
+ DWORD cbTotal;
+ DWORD cbOffsetSns;
+
+ DWORD idxEvent;
+ DWORD dwEvent;
+
+ CURSOR_ID cid;
+ DWORD sn;
+ SYSTEM_EVENT sysEvt;
+ SYSTEM_EVENT_DATA sysEvtData;
+ DWORD cPackets;
+ DWORD cbPackets;
+ BOOL fSnsPresent;
+
+ void Clear()
+ {
+ INT cbUnclearable = 2 * sizeof(DWORD);
+ ZeroMemory(((BYTE*)this) + cbUnclearable, sizeof(*this) - cbUnclearable);
+ }
+};
+#endif
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabAssert.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabAssert.h
new file mode 100644
index 00000000000..a561cd43973
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabAssert.h
@@ -0,0 +1,454 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+//
+// Module:
+// TabAssert.h
+//
+// Description:
+// To facilitate the debugging of Tablet Platform built binaries, we
+// needed a common set of functionallity for ASSERTs and debug logging.
+// This header file represents that collection of functionallity.
+//
+// Additionally, the testing team has requested the ability to turn
+// off ASSERTs programmatically.
+//
+//
+// Comments:
+//
+// Under HKEY_CLASSES_ROOT\TpgDebug, there are currently 8 values:
+//
+// AssertMode
+// AssertFile
+// DumpInfoMode
+// DumpInfoFile
+// FuncTraceMode
+// FuncTraceFile
+// HRFailMode
+// HRFailFile
+//
+// These Modes are a bitwise OR of 3 possible values which correspond
+// to the CRT Debug libraries definitions of
+//
+// _CRTDBG_MODE_FILE 0x1 (file)
+// _CRTDBG_MODE_DEBUG 0x2 (trace window)
+// _CRTDBG_MODE_WNDW 0x4 (dialog window)
+//
+// The File values (AssertFile, HRFailFile) are used if bit 0x1 is set
+// for a corresponding Mode.
+//
+// In the default settings (if you've never modified your registry by
+// hand or programatically), the values would be:
+//
+// AssertMode = 4
+// AssertFile = "C:\TPGDEBUG.LOG"
+// DumpInfoMode = 2
+// DumpInfoFile = "C:\TPGDEBUG.LOG"
+// FuncTraceMode = 0
+// FuncTraceFile = "C:\TPGDEBUG.LOG"
+// HRFailMode = 2
+// HRFailFile = "C:\TPGDEBUG.LOG"
+//
+// This would result in Assert failures being displayed in a dialog window
+// (because 0x4 is set in AssertMode and 0x4 corresponds to WNDW above).
+//
+// If you wanted to turn off the dialog window based asserts, but you still
+// wanted them logged to a file and sent to the debugger output window, you
+// could set AssertMode = 3 (which is 0x1 | 0x2, or written symbolically as
+// FILE | DEBUG from above).
+//
+// Additionally, there is a fifth value under TpgDebug, called
+// AssertSettingsReReadEachTime. This is a boolean value and is used in
+// speical cases when the test team wants to programmatically change
+// the AssertMode at runtime while the binaries are running. The default
+// for this value is 0 and as such, all the TpgDebug registry settings
+// are read at startup. If AssertSettingsReReadEachTime is set to 1,
+// most of the TpgDebug values are read at startup, with the exception of
+// AssertMode/AssertFile. This allows the testers to log the assert values
+// to specific locations. Care should be used when enabling this setting,
+// though, because this is a huge performance hit.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#ifndef _TABASSERT_HEADER
+
+#include
+
+#include
+#include
+#include
+
+#if 0 // #ifdef DBG
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int WINAPI MyCrtSetReportMode(
+ int nRptType,
+ int fMode
+ );
+
+_HFILE WINAPI MyCrtSetReportFile(
+ int nRptType,
+ _HFILE hFile
+ );
+
+int WINAPI MyCrtDbgReportA(
+ int nRptType,
+ const char * szFile,
+ int nLine,
+ const char * szModule,
+ const char * szFormat,
+ ...
+ );
+
+int WINAPI MyCrtDbgReportW(
+ int nRptType,
+ const WCHAR * wzFile,
+ int nLine,
+ const WCHAR * wzModule,
+ const WCHAR * wzFormat,
+ ...
+ );
+
+void WINAPI MyCrtDbgBreak(
+ void
+ );
+
+BOOL WINAPI TpgDebugAssertEnter();
+BOOL WINAPI TpgDebugAssertLeave();
+BOOL WINAPI TpgDebugDumpInfoEnter();
+BOOL WINAPI TpgDebugDumpInfoLeave();
+BOOL WINAPI TpgDebugFuncTraceEnter();
+BOOL WINAPI TpgDebugFuncTraceLeave();
+BOOL WINAPI TpgDebugHRFailEnter();
+BOOL WINAPI TpgDebugHRFailLeave();
+
+int WINAPI DoTheAssert(
+ const char * pszFile,
+ int nLine,
+ const char * szExpr,
+ BOOL fHaveHR,
+ HRESULT hr
+ );
+
+void WINAPI DoTheHRFail(
+ const char *pszFile,
+ int nLine,
+ HRESULT hr);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // DBG
+
+//=== User macros ==============================================================
+
+#if 0 // #ifdef DBG
+
+// Push current pragma settings
+#pragma push
+
+// Turn off "conditional expression is constant" because of while(0).
+#pragma warning ( disable : 4127 )
+
+#if defined __cplusplus && !defined _PREFAST_
+
+// Turn off "local variable 'hr' used without having been initialized" because of HRESULT hr; statements
+#pragma warning ( disable : 4700 )
+
+// C++ compatible assert that includes HR value.
+#define TPDBG_ASSERTSZ(expr,szDescription) \
+ do \
+ { \
+ if (!(expr)) \
+ { \
+ if (TpgDebugAssertEnter()) \
+ { \
+ static DWORD dwDisableAssert; \
+ if (dwDisableAssert == 0) \
+ { \
+ __if_exists(hr) \
+ { \
+ int iRet = DoTheAssert( \
+ __FILE__, \
+ __LINE__, \
+ szDescription, \
+ TRUE, \
+ hr ); \
+ } \
+ __if_not_exists(hr) \
+ { \
+ int iRet = DoTheAssert( \
+ __FILE__, \
+ __LINE__, \
+ szDescription, \
+ FALSE, \
+ 0); \
+ } \
+ if (iRet == 1) \
+ { \
+ MyCrtDbgBreak(); \
+ } \
+ else if (iRet == 2) \
+ { \
+ dwDisableAssert = 1; \
+ } \
+ } \
+ TpgDebugAssertLeave(); \
+ } \
+ } \
+ } \
+ while (0)
+
+#else
+
+// C compatible assert that does not includes HR value.
+// Prefast compatible version (prefast also complains about uninitialized hr variables).
+#define TPDBG_ASSERTSZ(expr,szDescription) \
+ do \
+ { \
+ if (!(expr)) \
+ { \
+ if (TpgDebugAssertEnter()) \
+ { \
+ static DWORD dwDisableAssert; \
+ if (dwDisableAssert == 0) \
+ { \
+ int iRet = DoTheAssert( \
+ __FILE__, \
+ __LINE__, \
+ szDescription, \
+ FALSE, \
+ 0); \
+ if (iRet == 1) \
+ { \
+ MyCrtDbgBreak(); \
+ } \
+ else if (iRet == 2) \
+ { \
+ dwDisableAssert = 1; \
+ } \
+ } \
+ TpgDebugAssertLeave(); \
+ } \
+ } \
+ } \
+ while (0)
+
+#endif
+
+// Restore pragma settings.
+#pragma pop
+
+#define TPDBG_ASSERT(expr) \
+ TPDBG_ASSERTSZ(expr, #expr)
+
+#define TPDBG_VERIFY(expr) \
+ TPDBG_ASSERT(expr)
+
+#ifdef ASSERT
+#undef ASSERT
+#endif // ASSERT
+
+#define ASSERT(expr) \
+ TPDBG_ASSERT(expr)
+
+#ifdef ASSERTSZ
+#undef ASSERTSZ
+#endif // ASSERTSZ
+
+#define ASSERTSZ(expr, szDescription) \
+ TPDBG_ASSERTSZ(expr, szDescription)
+
+#define TPDBG_RPT(rptno, msg) \
+ do { if ((1 == MyCrtDbgReportW(rptno, NULL, 0, NULL, L"%s", msg))) \
+ MyCrtDbgBreak(); } while (0)
+
+#define TPDBG_RPT0(rptno, msg) \
+ do { if ((1 == MyCrtDbgReportA(rptno, NULL, 0, NULL, "%s", msg))) \
+ MyCrtDbgBreak(); } while (0)
+
+#define TPDBG_RPT1(rptno, msg, arg1) \
+ do { if ((1 == MyCrtDbgReportA(rptno, NULL, 0, NULL, msg, arg1))) \
+ MyCrtDbgBreak(); } while (0)
+
+#define TPDBG_RPT2(rptno, msg, arg1, arg2) \
+ do { if ((1 == MyCrtDbgReportA(rptno, NULL, 0, NULL, msg, arg1, arg2))) \
+ MyCrtDbgBreak(); } while (0)
+
+#define TPDBG_RPT3(rptno, msg, arg1, arg2, arg3) \
+ do { if ((1 == MyCrtDbgReportA(rptno, NULL, 0, NULL, msg, arg1, arg2, arg3))) \
+ MyCrtDbgBreak(); } while (0)
+
+#define TPDBG_RPT4(rptno, msg, arg1, arg2, arg3, arg4) \
+ do { if ((1 == MyCrtDbgReportA(rptno, NULL, 0, NULL, msg, arg1, arg2, arg3, arg4))) \
+ MyCrtDbgBreak(); } while (0)
+
+void DMSG(WCHAR *wzformat, ...);
+
+#define TPDBG_DMSG0(format) \
+ do \
+ { \
+ if (TpgDebugDumpInfoEnter()) \
+ { \
+ TPDBG_RPT0(_CRT_WARN, format); \
+ TpgDebugDumpInfoLeave(); \
+ } \
+ } while (0)
+#define TPDBG_DMSG1(format, arg1) \
+ do \
+ { \
+ if (TpgDebugDumpInfoEnter()) \
+ { \
+ TPDBG_RPT1(_CRT_WARN, format, arg1); \
+ TpgDebugDumpInfoLeave(); \
+ } \
+ } while (0)
+#define TPDBG_DMSG2(format, arg1, arg2) \
+ do \
+ { \
+ if (TpgDebugDumpInfoEnter()) \
+ { \
+ TPDBG_RPT2(_CRT_WARN, format, arg1, arg2); \
+ TpgDebugDumpInfoLeave(); \
+ } \
+ } while (0)
+#define TPDBG_DMSG3(format, arg1, arg2, arg3) \
+ do \
+ { \
+ if (TpgDebugDumpInfoEnter()) \
+ { \
+ TPDBG_RPT3(_CRT_WARN, format, arg1, arg2, arg3); \
+ TpgDebugDumpInfoLeave(); \
+ } \
+ } while (0)
+#define TPDBG_DMSG4(format, arg1, arg2, arg3, arg4) \
+ do \
+ { \
+ if (TpgDebugDumpInfoEnter()) \
+ { \
+ TPDBG_RPT4(_CRT_WARN, format, arg1, arg2, arg3, arg4); \
+ TpgDebugDumpInfoLeave(); \
+ } \
+ } while (0)
+
+#define TPDBG_FUNC_ENTER(name) \
+ do \
+ { \
+ if (TpgDebugFuncTraceEnter()) \
+ { \
+ TPDBG_RPT2(_CRT_WARN, "0x%x: Entering Function: %s\r\n", GetCurrentThreadId(), name); \
+ TpgDebugFuncTraceLeave(); \
+ } \
+ } while (0)
+
+#define TPDBG_FUNC_LEAVE(name) \
+ do \
+ { \
+ if (TpgDebugFuncTraceEnter()) \
+ { \
+ TPDBG_RPT2(_CRT_WARN, "0x%x: Leaving Function: %s\r\n", GetCurrentThreadId(), name); \
+ TpgDebugFuncTraceLeave(); \
+ } \
+ } while (0)
+
+#ifdef __cplusplus
+
+class CTpgFuncTrace
+{
+public:
+
+ CTpgFuncTrace(char * pszFuncName) : m_pszFuncName(pszFuncName) { TPDBG_FUNC_ENTER(m_pszFuncName); }
+ ~CTpgFuncTrace() { TPDBG_FUNC_LEAVE(m_pszFuncName); }
+
+private:
+ char * m_pszFuncName;
+};
+
+#define TPDBG_FUNC(name) \
+ CTpgFuncTrace functrace(name)
+
+#define DBGFUNC \
+ CTpgFuncTrace functrace(__FUNCTION__)
+
+#endif // __cplusplus
+
+
+#define TPDBG_REPORT_ON_FAIL(hr) \
+ do \
+ { \
+ HRESULT _hr = (hr); \
+ if (FAILED(_hr) && TpgDebugHRFailEnter()) \
+ { \
+ DoTheHRFail( \
+ __FILE__, \
+ __LINE__, \
+ _hr); \
+ TpgDebugHRFailLeave(); \
+ } \
+ } while (0)
+
+#define TPDBG_RETURN(hr) \
+ { \
+ HRESULT __hr = (hr); \
+ if (FAILED(__hr)) \
+ { \
+ TPDBG_REPORT_ON_FAIL(__hr); \
+ } \
+ return __hr; \
+ }
+
+#else // DBG
+
+#define TPDBG_ASSERT(expr)
+#define TPDBG_VERIFY(expr) (expr)
+
+#ifdef ASSERT
+#undef ASSERT
+#endif // ASSERT
+
+#define ASSERT(expr)
+
+#ifdef ASSERTSZ
+#undef ASSERTSZ
+#endif //ASSERTSZ
+
+#define ASSERTSZ(expr, szDescription)
+
+#define TPDBG_RPT0(rptno, msg)
+#define TPDBG_RPT1(rptno, msg, arg1)
+#define TPDBG_RPT2(rptno, msg, arg1, arg2)
+#define TPDBG_RPT3(rptno, msg, arg1, arg2, arg3)
+#define TPDBG_RPT4(rptno, msg, arg1, arg2, arg3, arg4)
+
+#define TPDBG_DMSG0(format)
+#define TPDBG_DMSG1(format, arg1)
+#define TPDBG_DMSG2(format, arg1, arg2)
+#define TPDBG_DMSG3(format, arg1, arg2, arg3)
+#define TPDBG_DMSG4(format, arg1, arg2, arg3, arg4)
+
+#define TPDBG_FUNC_ENTER(name)
+#define TPDBG_FUNC_LEAVE(name)
+
+#ifdef __cplusplus
+#define TPDBG_FUNC(name)
+#define DBGFUNC
+#endif // __cplusplus
+
+#define TPDBG_REPORT_ON_FAIL(hr)
+#define TPDBG_RETURN(hr) return (hr)
+
+#endif // DBG
+
+#endif //_TABASSERT_HEADER
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabInc.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabInc.h
new file mode 100644
index 00000000000..55165579061
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabInc.h
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#ifndef __TABINC_H_
+#define __TABINC_H_
+
+#include
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// SECURITY
+//
+
+#define TPGSECURE(X, DEVELOPERS, REVIEW_DATE, EXPLANATION_WHY_SECURE) X
+
+//
+// Example:
+//
+// pszFoo = new TCHAR[_tcslen(pszBar) + 1]
+// _tcscpy(pszFoo, pszBar);
+// change to:
+// pszFoo = new TCHAR[_tcslen(pszBar) + 1]
+// TPGSECURE(_tcscpy(pszFoo, pszBar), "JohnDoe", "2/12/2002", "pszFoo is allocated using length of pszBar");
+//
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// HR and return value handling
+//
+
+#define IGNORERESULT(result) (void)result
+
+// (using inlines for IGNOREHR, VERIFYHR, VERIFYBOOL to have type checking)
+
+_inline void IGNOREHR(HRESULT hr)
+{
+hr;
+}
+
+_inline void VERIFYHR(HRESULT hr)
+{
+ hr;
+#ifdef DBG
+ ASSERT(SUCCEEDED(hr));
+#endif
+}
+
+_inline void VERIFYBOOL(BOOL br)
+{
+ br;
+#ifdef DBG
+ ASSERT(br);
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Additional String Primitives
+//
+
+HRESULT StringAllocateWithNewAndCopy (__out LPTSTR * ppszDestination, __in LPTSTR pszSource);
+HRESULT StringAllocateWithMallocAndCopy(__out LPTSTR * ppszDestination, __in LPTSTR pszSource);
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// SAFE primitives
+//
+
+#define ZEROSTRUCT(X) ZeroMemory(X, sizeof(*(X)))
+
+#define SIZEOFSZ(X) (sizeof(X[0]) * (_tcslen(X) + 1))
+#define SIZEOFSTRUCT(X) (sizeof(X))
+#define SIZEOFARRAY(X) (sizeof(X))
+
+#define LENGTHOFARRAY(X) (sizeof(X) / sizeof(X[0]))
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+// Not all of the projects that include tabinc.h use ole automation;
+// so "BSTR" wouldn't be defined for them. We check here for "_OLEAUTO_H_"
+// to determine if ole automation is used. For this reason, tabinc.h
+// should be included after oleauto.h
+
+#ifdef _OLEAUTO_H_
+
+BOOL IsBadReadBstr(BSTR bstr, BOOL fCheckForAndDisallowEmbeddedNulls); // implemented in tablib.cpp
+
+_inline BOOL IsBadWriteBstr(BSTR * pbstr)
+{
+ return FALSE; // Banned API -> IsBadWritePtr(pbstr, sizeof(*pbstr));
+}
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+// Macros and helpers for CRITICAL_SECTION
+
+#define TPG_INITIALIZE_CRITICAL_SECTION_PREALLOC(pCritSect) InitializeCriticalSectionAndSpinCount(pCritSect, (0x8001000 | 4000))
+#define TPG_INITIALIZE_CRITICAL_SECTION_NOPREALLOC(pCritSect) InitializeCriticalSectionAndSpinCount(pCritSect, (0x8000000 | 4000))
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+// closes the *pHandle, if it's not NULL, and NULLs it out
+void SafeCloseHandle(__inout HANDLE * pHandle);
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif // __TABINC_H_
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabletPCVer.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabletPCVer.h
new file mode 100644
index 00000000000..1da7870bab8
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/TabletPCVer.h
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// This files must be include inside all RC files prior to including "common.ver"
+//
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef VER_FILEDESCRIPTION_STR
+#define VER_FILEDESCRIPTION_STR "Microsoft Tablet PC Component"
+#endif
+
+#ifndef VER_LEGALCOPYRIGHT_STR
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corp."
+#endif
+
+#include
+#include
+#include
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/peninc.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/peninc.h
new file mode 100644
index 00000000000..c9ce0f79968
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/peninc.h
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#ifndef __PENINC_H_
+#define __PENINC_H_
+
+#define STRSAFE_NO_DEPRECATE
+#include
+#include
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define MIN_SPACE64_X 0
+#define MIN_SPACE64_Y 0
+#define MAX_SPACE64_X 65535
+#define MAX_SPACE64_Y 65535
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef unsigned (__stdcall *PTHREAD_START) (void *);
+
+#define chBEGINTHREADEX(lpsa, cbStack, lpStartAddr, \
+ lpvThreadParm, fdwCreate, lpIDThread) \
+ ((HANDLE)_beginthreadex( \
+ (void *) (lpsa), \
+ (unsigned) (cbStack), \
+ (PTHREAD_START) (lpStartAddr), \
+ (void *) (lpvThreadParm), \
+ (unsigned) (fdwCreate), \
+ (unsigned *) (lpIDThread)))
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define MICROSOFT_TABLETPENSERVICE_PROPERTY _T("MicrosoftTabletPenServiceProperty")
+
+#define WISPTIS_PRESS_AND_HOLD_DISABLE_MASK 0x01
+#define WISPTIS_SYSTEM_GESTURE_WM_DISABLE_MASK 0x02
+#define WISPTIS_FLICK_LEARNING_MODE_MASK 0x04
+
+#define PENPROCESS_COMMANDLINE _T("/ProcessActivate:%p;%p; /ProcessDeActivate:%p;%p; /EndSessionInfo:%p;%p;")
+
+#define PENPROCESS_ACTIVATEINFO _T("/ProcessActivate:")
+#define PENPROCESS_DEACTIVATEINFO _T("/ProcessDeActivate:")
+#define PENPROCESS_ENDSESSIONINFO _T("/EndSessionInfo:")
+
+#define PENPROCESS_PATH _T("\\SYSTEM32\\WISPTIS.EXE")
+
+#define WISPTIS_WITHNOINTEGRATEDDEVICE _T("/EndSessionInfo:%p;%p;")
+#define WISPTIS_ENDSESSIONINFO _T("/EndSessionInfo:")
+
+#define WISPTIS_DEBUGGING _T("/Debugging")
+#define WISPTIS_DEBUGGING _T("/Debugging")
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// HR etc helpers
+//
+
+#define DHR \
+ HRESULT hr = S_OK;
+
+#define RHR \
+ return hr;
+
+#define CHR(hr_op) \
+ { \
+ hr = hr_op; \
+ if (FAILED(hr)) \
+ goto CLEANUP; \
+ }
+
+#define CHR_VERIFY(hr_op) \
+ { \
+ CHR(hr_op); \
+ ASSERT (SUCCEEDED(hr)); \
+ }
+
+#define CHR_MEMALLOC(pv_op) \
+ { \
+ CHR((pv_op) != NULL ? S_OK : E_OUTOFMEMORY); \
+ }
+
+#define CHR_WIN32(bool_or_handle_op) \
+ { \
+ CHR((bool_or_handle_op) ? \
+ S_OK : \
+ HRESULT_FROM_WIN32(GetLastError())); \
+ }
+
+// Shared by Wisptis and PenImc
+#define WISPTIS_SM_MORE_DATA_EVENT_NAME _T("wisptis-1-%d-%u")
+#define WISPTIS_SM_MUTEX_NAME _T("wisptis-2-%d-%u")
+#define WISPTIS_SM_SECTION_NAME _T("wisptis-3-%d-%u")
+#define WISPTIS_SM_THREAD_EVENT_NAME _T("wisptis-4-%u")
+
+#endif // __PENINC_H_
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/pentypes.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/pentypes.h
new file mode 100644
index 00000000000..7bf7e65104c
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/pentypes.h
@@ -0,0 +1,214 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 7.00.0498 */
+/* Compiler settings for pentypes.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 500
+#endif
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCSAL_H_VERSION__
+#define __REQUIRED_RPCSAL_H_VERSION__ 100
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of
+#endif // __RPCNDR_H_VERSION__
+
+
+#ifndef __pentypes_h__
+#define __pentypes_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+/* header files for imported files */
+#include "oaidl.h"
+#include "ocidl.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+/* interface __MIDL_itf_pentypes_0000_0000 */
+/* [local] */
+
+#include "tpcshrd.h"
+#define TCXO_MARGIN 0x00000001
+#define TCXO_PREHOOK 0x00000002
+#define TCXO_CURSOR_STATE 0x00000004
+#define TCXO_NO_CURSOR_DOWN 0x00000008
+#define TCXO_NON_INTEGRATED 0x00000010
+#define TCXO_POSTHOOK 0x00000020
+#define TCXO_DONT_SHOW_CURSOR 0x00000080
+#define TCXO_DONT_VALIDATE_TCS 0x00000100
+#define TCXO_REPORT_RECT_MAPPING_CHANGE 0x00000200
+#define TCXO_ALLOW_FLICKS 0x00000400
+#define TCXO_ALLOW_FEEDBACK_TAPS 0x00000800
+#define TCXO_ALLOW_FEEDBACK_BARREL 0x00001000
+#define TCXO_ALLOW_ALL_TOUCH 0x00002000
+#define TCXO_ALL (TCXO_MARGIN | TCXO_PREHOOK | TCXO_CURSOR_STATE | TCXO_NO_CURSOR_DOWN | TCXO_NON_INTEGRATED | TCXO_POSTHOOK | TCXO_DONT_SHOW_CURSOR | TCXO_DONT_VALIDATE_TCS | TCXO_REPORT_RECT_MAPPING_CHANGE | TCXO_ALLOW_FLICKS | TCXO_ALLOW_FEEDBACK_TAPS | TCXO_ALLOW_FEEDBACK_BARREL | TCXO_ALLOW_ALL_TOUCH)
+#define TCXO_HOOK (TCXO_PREHOOK | TCXO_POSTHOOK)
+#define TCXS_DISABLED 0x00000001
+#define THWC_INTEGRATED 0x00000001
+#define THWC_CSR_MUST_TOUCH 0x00000002
+#define THWC_HARD_PROXIMITY 0x00000004
+#define THWC_PHYSID_CSRS 0x00000008
+#define IP_CURSOR_DOWN 0x00000001
+#define IP_INVERTED 0x00000002
+#define IP_MARGIN 0x00000004
+#define IP_BARREL_DOWN 0x00000008
+#define IP_RECT_MAPPING_CHANGED 0x00000010
+#define IP_ALL_STATUS_BITS (IP_CURSOR_DOWN | IP_INVERTED | IP_MARGIN | IP_BARREL_DOWN | IP_RECT_MAPPING_CHANGED)
+#define TAB_SETTING_LINEARIZATION 0x00000001
+#define TAB_SETTING_PORTRAIT_USERTILT 0x00000002
+#define TAB_SETTING_LANDSCAPE_USERTILT 0x00000004
+#define TAB_SETTING_DISPLAY_ORIENTATION_DEFAULT_USERTILT 0x00000008
+#define TAB_SETTING_DISPLAY_ORIENTATION_90_USERTILT 0x00000010
+#define TAB_SETTING_DISPLAY_ORIENTATION_180_USERTILT 0x00000100
+#define TAB_SETTING_DISPLAY_ORIENTATION_270_USERTILT 0x00001000
+#define SE_TAP 0x00000010
+#define SE_DBL_TAP 0x00000011
+#define SE_RIGHT_TAP 0x00000012
+#define SE_DRAG 0x00000013
+#define SE_RIGHT_DRAG 0x00000014
+#define SE_HOLD_ENTER 0x00000015
+#define SE_HOLD_LEAVE 0x00000016
+#define SE_HOVER_ENTER 0x00000017
+#define SE_HOVER_LEAVE 0x00000018
+#define SE_MIDDLE_CLICK 0x00000019
+#define SE_KEY 0x0000001A
+#define SE_MODIFIER_KEY 0x0000001B
+#define SE_GESTURE_MODE 0x0000001C
+#define SE_CURSOR 0x0000001D
+#define SE_FLICK 0x0000001F
+#define SE_MODIFIER_CTRL 0x00000001
+#define SE_MODIFIER_ALT 0x00000002
+#define SE_MODIFIER_SHIFT 0x00000004
+#define SE_NORMAL_CURSOR 0x00000001
+#define SE_ERASER_CURSOR 0x00000002
+#define SE_SYSTEMEVENT 0x00000001
+#define SE_TYPE_MOUSE 0x00000000
+#define SE_TYPE_KEYBOARD 0x00000001
+#define SE_DELAY_PACKET 0x0000000F
+#define SE_PRE_TAPDRAG 0x0000001E
+#define WM_TABLET_DEFBASE 0x02C0
+#define WM_TABLET_MAXOFFSET 0x20
+#define WM_TABLET_CONTEXTCREATE (WM_TABLET_DEFBASE + 0)
+#define WM_TABLET_CONTEXTDESTROY (WM_TABLET_DEFBASE + 1)
+#define WM_TABLET_CURSORNEW (WM_TABLET_DEFBASE + 2)
+#define WM_TABLET_CURSORINRANGE (WM_TABLET_DEFBASE + 3)
+#define WM_TABLET_CURSOROUTOFRANGE (WM_TABLET_DEFBASE + 4)
+#define WM_TABLET_CURSORDOWN (WM_TABLET_DEFBASE + 5)
+#define WM_TABLET_CURSORUP (WM_TABLET_DEFBASE + 6)
+#define WM_TABLET_PACKET (WM_TABLET_DEFBASE + 7)
+#define WM_TABLET_ADDED (WM_TABLET_DEFBASE + 8)
+#define WM_TABLET_DELETED (WM_TABLET_DEFBASE + 9)
+#define WM_TABLET_SYSTEMEVENT (WM_TABLET_DEFBASE + 10)
+#define WM_TABLET_MAX (WM_TABLET_DEFBASE + WM_TABLET_MAXOFFSET)
+#define TABLET_MESSAGE_EXTRA_INFO_MASK_PEN_OR_TOUCH 0xFF515700
+#define TABLET_MESSAGE_EXTRA_INFO_MASK_TOUCH 0xFF515780
+#define TABLET_MESSAGE_EXTRA_INFO_MASK_TIP 0xFF575100
+#define MICROSOFT_TABLETPENSERVICE_PROPERTY _T("MicrosoftTabletPenServiceProperty")
+#define TABLET_DISABLE_PRESSANDHOLD 0x00000001
+#define TABLET_DISABLE_PENTAPFEEDBACK 0x00000008
+#define TABLET_DISABLE_PENBARRELFEEDBACK 0x00000010
+#define TABLET_DISABLE_TOUCHUIFORCEON 0x00000100
+#define TABLET_DISABLE_TOUCHUIFORCEOFF 0x00000200
+#define TABLET_DISABLE_TOUCHSWITCH 0x00008000
+#define TABLET_DISABLE_FLICKS 0x00010000
+#define TABLET_ENABLE_FLICKSONCONTEXT 0x00020000
+#define TABLET_ENABLE_FLICKLEARNINGMODE 0x00040000
+#define TABLET_DISABLE_SMOOTHSCROLLING 0x00080000
+#define WISP_WINTAB_ERROR MAKE_HRESULT(1, FACILITY_ITF, 0x201)
+#define WISP_PACKET_BUFFER_TOO_SMALL MAKE_HRESULT(1, FACILITY_ITF, 0x211)
+#define WISP_NO_DEFAULT_TABLET MAKE_HRESULT(1, FACILITY_ITF, 0x212)
+#define WISP_TABLET_CONTEXT_NOT_FOUND MAKE_HRESULT(1, FACILITY_ITF, 0x213)
+#define WISP_CURSOR_NOT_FOUND MAKE_HRESULT(1, FACILITY_ITF, 0x214)
+#define WISP_INVALID_TABLET_INDEX MAKE_HRESULT(1, FACILITY_ITF, 0x215)
+#define WISP_INVALID_TABLET_CONTEXT_INDEX MAKE_HRESULT(1, FACILITY_ITF, 0x216)
+#define WISP_INVALID_CURSOR_INDEX MAKE_HRESULT(1, FACILITY_ITF, 0x217)
+#define WISP_INVALID_BUTTON_INDEX MAKE_HRESULT(1, FACILITY_ITF, 0x218)
+#define WISP_INVALID_PACKET_SERIAL_NUM MAKE_HRESULT(1, FACILITY_ITF, 0x219)
+#define WISP_INVALID_WINDOW_HANDLE MAKE_HRESULT(1, FACILITY_ITF, 0x21a)
+#define WISP_INVALID_INPUT_RECT MAKE_HRESULT(1, FACILITY_ITF, 0x21b)
+#define WISP_INVALID_TABLET_CONTEXT_SETTINGS MAKE_HRESULT(1, FACILITY_ITF, 0x21c)
+#define WISP_UNKNOWN_PROPERTY MAKE_HRESULT(1, FACILITY_ITF, 0x21d)
+#define WISP_UNITS_CONVERSION_UNDEFINED MAKE_HRESULT(1, FACILITY_ITF, 0x21e)
+#define SZ_REGKEY_PERSIST TEXT("Software\\Microsoft\\Wisp\\Pen\\Persist")
+#define SZ_REGVAL_TYPE TEXT("type")
+#define SZ_REGVAL_WINTABDEVICEID TEXT("WintabDeviceId")
+#define SZ_REGVAL_HIDDEVICEPATH TEXT("HidDevicePath")
+#define SZ_REGVAL_WINTABCURSORTYPE TEXT("WintabCursorType")
+#define SZ_REGVAL_WINTABCURSORPHYSID TEXT("WintabCursorPhysid")
+#define SZ_REGVAL_HIDCURSORID TEXT("HidCursorId")
+#define SZ_REGVAL_HIDDEVICE TEXT("HidDevice")
+#define SZ_REGVAL_NAME TEXT("Name")
+typedef
+enum _CONTEXT_ENABLE_TYPE
+ { CONTEXT_ENABLE = 1,
+ CONTEXT_DISABLE = 2
+ } CONTEXT_ENABLE_TYPE;
+
+typedef enum _CONTEXT_ENABLE_TYPE *PCONTEXT_ENABLE_TYPE;
+
+typedef struct _TABLET_CONTEXT_SETTINGS
+ {
+ ULONG cPktProps;
+ GUID *pguidPktProps;
+ ULONG cPktBtns;
+ GUID *pguidPktBtns;
+ DWORD *pdwBtnDnMask;
+ DWORD *pdwBtnUpMask;
+ LONG lXMargin;
+ LONG lYMargin;
+ } TABLET_CONTEXT_SETTINGS;
+
+typedef /* [unique] */ __RPC_unique_pointer TABLET_CONTEXT_SETTINGS *PTABLET_CONTEXT_SETTINGS;
+
+#define SZ_EVENT_TABLETHARDWAREPRESENT TEXT("Global\\TabletHardwarePresent")
+
+
+extern RPC_IF_HANDLE __MIDL_itf_pentypes_0000_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_pentypes_0000_0000_v0_0_s_ifspec;
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpcpen.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpcpen.h
new file mode 100644
index 00000000000..8ed0083c55f
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpcpen.h
@@ -0,0 +1,1809 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 7.00.0498 */
+/* Compiler settings for tpcpen.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 500
+#endif
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCSAL_H_VERSION__
+#define __REQUIRED_RPCSAL_H_VERSION__ 100
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of
+#endif // __RPCNDR_H_VERSION__
+
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __tpcpen_h__
+#define __tpcpen_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifndef __ITabletEventSink_FWD_DEFINED__
+#define __ITabletEventSink_FWD_DEFINED__
+typedef interface ITabletEventSink ITabletEventSink;
+#endif /* __ITabletEventSink_FWD_DEFINED__ */
+
+
+#ifndef __AsyncITabletEventSink_FWD_DEFINED__
+#define __AsyncITabletEventSink_FWD_DEFINED__
+typedef interface AsyncITabletEventSink AsyncITabletEventSink;
+#endif /* __AsyncITabletEventSink_FWD_DEFINED__ */
+
+
+#ifndef __ITabletManager_FWD_DEFINED__
+#define __ITabletManager_FWD_DEFINED__
+typedef interface ITabletManager ITabletManager;
+#endif /* __ITabletManager_FWD_DEFINED__ */
+
+
+#ifndef __ITablet_FWD_DEFINED__
+#define __ITablet_FWD_DEFINED__
+typedef interface ITablet ITablet;
+#endif /* __ITablet_FWD_DEFINED__ */
+
+
+#ifndef __ITablet2_FWD_DEFINED__
+#define __ITablet2_FWD_DEFINED__
+typedef interface ITablet2 ITablet2;
+#endif /* __ITablet2_FWD_DEFINED__ */
+
+
+#ifndef __ITabletSettings_FWD_DEFINED__
+#define __ITabletSettings_FWD_DEFINED__
+typedef interface ITabletSettings ITabletSettings;
+#endif /* __ITabletSettings_FWD_DEFINED__ */
+
+
+#ifndef __ITabletContext_FWD_DEFINED__
+#define __ITabletContext_FWD_DEFINED__
+typedef interface ITabletContext ITabletContext;
+#endif /* __ITabletContext_FWD_DEFINED__ */
+
+
+#ifndef __ITabletCursor_FWD_DEFINED__
+#define __ITabletCursor_FWD_DEFINED__
+typedef interface ITabletCursor ITabletCursor;
+#endif /* __ITabletCursor_FWD_DEFINED__ */
+
+
+#ifndef __ITabletCursorButton_FWD_DEFINED__
+#define __ITabletCursorButton_FWD_DEFINED__
+typedef interface ITabletCursorButton ITabletCursorButton;
+#endif /* __ITabletCursorButton_FWD_DEFINED__ */
+
+
+#ifndef __ITabletEventSink_FWD_DEFINED__
+#define __ITabletEventSink_FWD_DEFINED__
+typedef interface ITabletEventSink ITabletEventSink;
+#endif /* __ITabletEventSink_FWD_DEFINED__ */
+
+
+#ifndef __ITabletManager_FWD_DEFINED__
+#define __ITabletManager_FWD_DEFINED__
+typedef interface ITabletManager ITabletManager;
+#endif /* __ITabletManager_FWD_DEFINED__ */
+
+
+#ifndef __ITablet_FWD_DEFINED__
+#define __ITablet_FWD_DEFINED__
+typedef interface ITablet ITablet;
+#endif /* __ITablet_FWD_DEFINED__ */
+
+
+#ifndef __ITabletContext_FWD_DEFINED__
+#define __ITabletContext_FWD_DEFINED__
+typedef interface ITabletContext ITabletContext;
+#endif /* __ITabletContext_FWD_DEFINED__ */
+
+
+#ifndef __ITabletCursor_FWD_DEFINED__
+#define __ITabletCursor_FWD_DEFINED__
+typedef interface ITabletCursor ITabletCursor;
+#endif /* __ITabletCursor_FWD_DEFINED__ */
+
+
+#ifndef __ITabletCursorButton_FWD_DEFINED__
+#define __ITabletCursorButton_FWD_DEFINED__
+typedef interface ITabletCursorButton ITabletCursorButton;
+#endif /* __ITabletCursorButton_FWD_DEFINED__ */
+
+
+#ifndef __TabletManager_FWD_DEFINED__
+#define __TabletManager_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class TabletManager TabletManager;
+#else
+typedef struct TabletManager TabletManager;
+#endif /* __cplusplus */
+
+#endif /* __TabletManager_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "oaidl.h"
+#include "ocidl.h"
+#include "tpcshrd.h"
+#include "pentypes.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+/* interface __MIDL_itf_tpcpen_0000_0000 */
+/* [local] */
+
+
+#pragma once
+
+
+
+
+
+
+
+extern RPC_IF_HANDLE __MIDL_itf_tpcpen_0000_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_tpcpen_0000_0000_v0_0_s_ifspec;
+
+#ifndef __ITabletEventSink_INTERFACE_DEFINED__
+#define __ITabletEventSink_INTERFACE_DEFINED__
+
+/* interface ITabletEventSink */
+/* [unique][helpstring][async_uuid][uuid][object] */
+
+typedef /* [unique] */ __RPC_unique_pointer ITabletEventSink *PTABLETEVENTSINK;
+
+
+EXTERN_C const IID IID_ITabletEventSink;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("788459C8-26C8-4666-BF57-04AD3A0A5EB5")
+ ITabletEventSink : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ContextCreate(
+ /* [in] */ TABLET_CONTEXT_ID tcid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ContextDestroy(
+ /* [in] */ TABLET_CONTEXT_ID tcid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CursorNew(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CursorInRange(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CursorOutOfRange(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CursorDown(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ ULONG nSerialNumber,
+ /* [in] */ ULONG cbPkt,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkt) BYTE *pbPkt) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CursorUp(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ ULONG nSerialNumber,
+ /* [in] */ ULONG cbPkt,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkt) BYTE *pbPkt) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Packets(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][unique][in] */ __RPC__in_ecount_full_opt(cPkts) ULONG *pnSerialNumbers,
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SystemEvent(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ SYSTEM_EVENT event,
+ /* [in] */ SYSTEM_EVENT_DATA eventdata) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletEventSinkVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletEventSink * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletEventSink * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ContextCreate )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ContextDestroy )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CursorNew )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CursorInRange )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CursorOutOfRange )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CursorDown )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ ULONG nSerialNumber,
+ /* [in] */ ULONG cbPkt,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkt) BYTE *pbPkt);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CursorUp )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ ULONG nSerialNumber,
+ /* [in] */ ULONG cbPkt,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkt) BYTE *pbPkt);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Packets )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][unique][in] */ __RPC__in_ecount_full_opt(cPkts) ULONG *pnSerialNumbers,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SystemEvent )(
+ ITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ SYSTEM_EVENT event,
+ /* [in] */ SYSTEM_EVENT_DATA eventdata);
+
+ END_INTERFACE
+ } ITabletEventSinkVtbl;
+
+ interface ITabletEventSink
+ {
+ CONST_VTBL struct ITabletEventSinkVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletEventSink_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletEventSink_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletEventSink_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletEventSink_ContextCreate(This,tcid) \
+ ( (This)->lpVtbl -> ContextCreate(This,tcid) )
+
+#define ITabletEventSink_ContextDestroy(This,tcid) \
+ ( (This)->lpVtbl -> ContextDestroy(This,tcid) )
+
+#define ITabletEventSink_CursorNew(This,tcid,cid) \
+ ( (This)->lpVtbl -> CursorNew(This,tcid,cid) )
+
+#define ITabletEventSink_CursorInRange(This,tcid,cid) \
+ ( (This)->lpVtbl -> CursorInRange(This,tcid,cid) )
+
+#define ITabletEventSink_CursorOutOfRange(This,tcid,cid) \
+ ( (This)->lpVtbl -> CursorOutOfRange(This,tcid,cid) )
+
+#define ITabletEventSink_CursorDown(This,tcid,cid,nSerialNumber,cbPkt,pbPkt) \
+ ( (This)->lpVtbl -> CursorDown(This,tcid,cid,nSerialNumber,cbPkt,pbPkt) )
+
+#define ITabletEventSink_CursorUp(This,tcid,cid,nSerialNumber,cbPkt,pbPkt) \
+ ( (This)->lpVtbl -> CursorUp(This,tcid,cid,nSerialNumber,cbPkt,pbPkt) )
+
+#define ITabletEventSink_Packets(This,tcid,cPkts,cbPkts,pbPkts,pnSerialNumbers,cid) \
+ ( (This)->lpVtbl -> Packets(This,tcid,cPkts,cbPkts,pbPkts,pnSerialNumbers,cid) )
+
+#define ITabletEventSink_SystemEvent(This,tcid,cid,event,eventdata) \
+ ( (This)->lpVtbl -> SystemEvent(This,tcid,cid,event,eventdata) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletEventSink_INTERFACE_DEFINED__ */
+
+
+#ifndef __AsyncITabletEventSink_INTERFACE_DEFINED__
+#define __AsyncITabletEventSink_INTERFACE_DEFINED__
+
+/* interface AsyncITabletEventSink */
+/* [uuid][unique][helpstring][object] */
+
+
+EXTERN_C const IID IID_AsyncITabletEventSink;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("CDF7D7D6-2E5D-47c7-90FC-C638C7FA3FC4")
+ AsyncITabletEventSink : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_ContextCreate(
+ /* [in] */ TABLET_CONTEXT_ID tcid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_ContextCreate( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_ContextDestroy(
+ /* [in] */ TABLET_CONTEXT_ID tcid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_ContextDestroy( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_CursorNew(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_CursorNew( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_CursorInRange(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_CursorInRange( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_CursorOutOfRange(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_CursorOutOfRange( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_CursorDown(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ ULONG nSerialNumber,
+ /* [in] */ ULONG cbPkt,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkt) BYTE *pbPkt) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_CursorDown( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_CursorUp(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ ULONG nSerialNumber,
+ /* [in] */ ULONG cbPkt,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkt) BYTE *pbPkt) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_CursorUp( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_Packets(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][unique][in] */ __RPC__in_ecount_full_opt(cPkts) ULONG *pnSerialNumbers,
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_Packets( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Begin_SystemEvent(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ SYSTEM_EVENT event,
+ /* [in] */ SYSTEM_EVENT_DATA eventdata) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Finish_SystemEvent( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct AsyncITabletEventSinkVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ AsyncITabletEventSink * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ AsyncITabletEventSink * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_ContextCreate )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_ContextCreate )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_ContextDestroy )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_ContextDestroy )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_CursorNew )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_CursorNew )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_CursorInRange )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_CursorInRange )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_CursorOutOfRange )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_CursorOutOfRange )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_CursorDown )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ ULONG nSerialNumber,
+ /* [in] */ ULONG cbPkt,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkt) BYTE *pbPkt);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_CursorDown )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_CursorUp )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ ULONG nSerialNumber,
+ /* [in] */ ULONG cbPkt,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkt) BYTE *pbPkt);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_CursorUp )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_Packets )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][unique][in] */ __RPC__in_ecount_full_opt(cPkts) ULONG *pnSerialNumbers,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_Packets )(
+ AsyncITabletEventSink * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Begin_SystemEvent )(
+ AsyncITabletEventSink * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [in] */ CURSOR_ID cid,
+ /* [in] */ SYSTEM_EVENT event,
+ /* [in] */ SYSTEM_EVENT_DATA eventdata);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Finish_SystemEvent )(
+ AsyncITabletEventSink * This);
+
+ END_INTERFACE
+ } AsyncITabletEventSinkVtbl;
+
+ interface AsyncITabletEventSink
+ {
+ CONST_VTBL struct AsyncITabletEventSinkVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define AsyncITabletEventSink_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define AsyncITabletEventSink_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define AsyncITabletEventSink_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define AsyncITabletEventSink_Begin_ContextCreate(This,tcid) \
+ ( (This)->lpVtbl -> Begin_ContextCreate(This,tcid) )
+
+#define AsyncITabletEventSink_Finish_ContextCreate(This) \
+ ( (This)->lpVtbl -> Finish_ContextCreate(This) )
+
+#define AsyncITabletEventSink_Begin_ContextDestroy(This,tcid) \
+ ( (This)->lpVtbl -> Begin_ContextDestroy(This,tcid) )
+
+#define AsyncITabletEventSink_Finish_ContextDestroy(This) \
+ ( (This)->lpVtbl -> Finish_ContextDestroy(This) )
+
+#define AsyncITabletEventSink_Begin_CursorNew(This,tcid,cid) \
+ ( (This)->lpVtbl -> Begin_CursorNew(This,tcid,cid) )
+
+#define AsyncITabletEventSink_Finish_CursorNew(This) \
+ ( (This)->lpVtbl -> Finish_CursorNew(This) )
+
+#define AsyncITabletEventSink_Begin_CursorInRange(This,tcid,cid) \
+ ( (This)->lpVtbl -> Begin_CursorInRange(This,tcid,cid) )
+
+#define AsyncITabletEventSink_Finish_CursorInRange(This) \
+ ( (This)->lpVtbl -> Finish_CursorInRange(This) )
+
+#define AsyncITabletEventSink_Begin_CursorOutOfRange(This,tcid,cid) \
+ ( (This)->lpVtbl -> Begin_CursorOutOfRange(This,tcid,cid) )
+
+#define AsyncITabletEventSink_Finish_CursorOutOfRange(This) \
+ ( (This)->lpVtbl -> Finish_CursorOutOfRange(This) )
+
+#define AsyncITabletEventSink_Begin_CursorDown(This,tcid,cid,nSerialNumber,cbPkt,pbPkt) \
+ ( (This)->lpVtbl -> Begin_CursorDown(This,tcid,cid,nSerialNumber,cbPkt,pbPkt) )
+
+#define AsyncITabletEventSink_Finish_CursorDown(This) \
+ ( (This)->lpVtbl -> Finish_CursorDown(This) )
+
+#define AsyncITabletEventSink_Begin_CursorUp(This,tcid,cid,nSerialNumber,cbPkt,pbPkt) \
+ ( (This)->lpVtbl -> Begin_CursorUp(This,tcid,cid,nSerialNumber,cbPkt,pbPkt) )
+
+#define AsyncITabletEventSink_Finish_CursorUp(This) \
+ ( (This)->lpVtbl -> Finish_CursorUp(This) )
+
+#define AsyncITabletEventSink_Begin_Packets(This,tcid,cPkts,cbPkts,pbPkts,pnSerialNumbers,cid) \
+ ( (This)->lpVtbl -> Begin_Packets(This,tcid,cPkts,cbPkts,pbPkts,pnSerialNumbers,cid) )
+
+#define AsyncITabletEventSink_Finish_Packets(This) \
+ ( (This)->lpVtbl -> Finish_Packets(This) )
+
+#define AsyncITabletEventSink_Begin_SystemEvent(This,tcid,cid,event,eventdata) \
+ ( (This)->lpVtbl -> Begin_SystemEvent(This,tcid,cid,event,eventdata) )
+
+#define AsyncITabletEventSink_Finish_SystemEvent(This) \
+ ( (This)->lpVtbl -> Finish_SystemEvent(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __AsyncITabletEventSink_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletManager_INTERFACE_DEFINED__
+#define __ITabletManager_INTERFACE_DEFINED__
+
+/* interface ITabletManager */
+/* [unique][helpstring][uuid][object] */
+
+typedef /* [unique] */ __RPC_unique_pointer ITabletManager *PTABLETMANAGER;
+
+
+EXTERN_C const IID IID_ITabletManager;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("764DE8AA-1867-47C1-8F6A-122445ABD89A")
+ ITabletManager : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDefaultTablet(
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetTabletCount(
+ /* [out] */ __RPC__out ULONG *pcTablets) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetTablet(
+ /* [in] */ ULONG iTablet,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetTabletContextById(
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [out] */ __RPC__deref_out_opt ITabletContext **ppContext) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetCursorById(
+ /* [in] */ CURSOR_ID cid,
+ /* [out] */ __RPC__deref_out_opt ITabletCursor **ppCursor) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletManagerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletManager * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletManager * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletManager * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetDefaultTablet )(
+ ITabletManager * This,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTabletCount )(
+ ITabletManager * This,
+ /* [out] */ __RPC__out ULONG *pcTablets);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTablet )(
+ ITabletManager * This,
+ /* [in] */ ULONG iTablet,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTabletContextById )(
+ ITabletManager * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [out] */ __RPC__deref_out_opt ITabletContext **ppContext);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetCursorById )(
+ ITabletManager * This,
+ /* [in] */ CURSOR_ID cid,
+ /* [out] */ __RPC__deref_out_opt ITabletCursor **ppCursor);
+
+ END_INTERFACE
+ } ITabletManagerVtbl;
+
+ interface ITabletManager
+ {
+ CONST_VTBL struct ITabletManagerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletManager_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletManager_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletManager_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletManager_GetDefaultTablet(This,ppTablet) \
+ ( (This)->lpVtbl -> GetDefaultTablet(This,ppTablet) )
+
+#define ITabletManager_GetTabletCount(This,pcTablets) \
+ ( (This)->lpVtbl -> GetTabletCount(This,pcTablets) )
+
+#define ITabletManager_GetTablet(This,iTablet,ppTablet) \
+ ( (This)->lpVtbl -> GetTablet(This,iTablet,ppTablet) )
+
+#define ITabletManager_GetTabletContextById(This,tcid,ppContext) \
+ ( (This)->lpVtbl -> GetTabletContextById(This,tcid,ppContext) )
+
+#define ITabletManager_GetCursorById(This,cid,ppCursor) \
+ ( (This)->lpVtbl -> GetCursorById(This,cid,ppCursor) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletManager_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITablet_INTERFACE_DEFINED__
+#define __ITablet_INTERFACE_DEFINED__
+
+/* interface ITablet */
+/* [unique][helpstring][uuid][object] */
+
+typedef /* [unique] */ __RPC_unique_pointer ITablet *PTABLET;
+
+
+EXTERN_C const IID IID_ITablet;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("1CB2EFC3-ABC7-4172-8FCB-3BC9CB93E29F")
+ ITablet : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDefaultContextSettings(
+ /* [out] */ __RPC__deref_out_opt TABLET_CONTEXT_SETTINGS **ppTCS) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateContext(
+ /* [in] */ __RPC__in HWND hWnd,
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput,
+ /* [in] */ DWORD dwOptions,
+ /* [unique][in] */ __RPC__in_opt TABLET_CONTEXT_SETTINGS *pTCS,
+ /* [in] */ CONTEXT_ENABLE_TYPE cet,
+ /* [out] */ __RPC__deref_out_opt ITabletContext **ppCtx,
+ /* [unique][out][in] */ __RPC__inout_opt TABLET_CONTEXT_ID *pTcid,
+ /* [unique][out][in] */ __RPC__deref_opt_inout_opt PACKET_DESCRIPTION **ppPD,
+ /* [unique][in] */ __RPC__in_opt ITabletEventSink *pSink) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetName(
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMaxInputRect(
+ /* [out] */ __RPC__out RECT *prcInput) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetHardwareCaps(
+ /* [out] */ __RPC__out DWORD *pdwCaps) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPropertyMetrics(
+ /* [in] */ __RPC__in REFGUID rguid,
+ /* [out] */ __RPC__out PROPERTY_METRICS *pPM) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPlugAndPlayId(
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszPPId) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetCursorCount(
+ /* [out] */ __RPC__out ULONG *pcCurs) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetCursor(
+ /* [in] */ ULONG iCur,
+ /* [out] */ __RPC__deref_out_opt ITabletCursor **ppCur) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITablet * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITablet * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITablet * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetDefaultContextSettings )(
+ ITablet * This,
+ /* [out] */ __RPC__deref_out_opt TABLET_CONTEXT_SETTINGS **ppTCS);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateContext )(
+ ITablet * This,
+ /* [in] */ __RPC__in HWND hWnd,
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput,
+ /* [in] */ DWORD dwOptions,
+ /* [unique][in] */ __RPC__in_opt TABLET_CONTEXT_SETTINGS *pTCS,
+ /* [in] */ CONTEXT_ENABLE_TYPE cet,
+ /* [out] */ __RPC__deref_out_opt ITabletContext **ppCtx,
+ /* [unique][out][in] */ __RPC__inout_opt TABLET_CONTEXT_ID *pTcid,
+ /* [unique][out][in] */ __RPC__deref_opt_inout_opt PACKET_DESCRIPTION **ppPD,
+ /* [unique][in] */ __RPC__in_opt ITabletEventSink *pSink);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ ITablet * This,
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetMaxInputRect )(
+ ITablet * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetHardwareCaps )(
+ ITablet * This,
+ /* [out] */ __RPC__out DWORD *pdwCaps);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPropertyMetrics )(
+ ITablet * This,
+ /* [in] */ __RPC__in REFGUID rguid,
+ /* [out] */ __RPC__out PROPERTY_METRICS *pPM);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPlugAndPlayId )(
+ ITablet * This,
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszPPId);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetCursorCount )(
+ ITablet * This,
+ /* [out] */ __RPC__out ULONG *pcCurs);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetCursor )(
+ ITablet * This,
+ /* [in] */ ULONG iCur,
+ /* [out] */ __RPC__deref_out_opt ITabletCursor **ppCur);
+
+ END_INTERFACE
+ } ITabletVtbl;
+
+ interface ITablet
+ {
+ CONST_VTBL struct ITabletVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITablet_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITablet_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITablet_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITablet_GetDefaultContextSettings(This,ppTCS) \
+ ( (This)->lpVtbl -> GetDefaultContextSettings(This,ppTCS) )
+
+#define ITablet_CreateContext(This,hWnd,prcInput,dwOptions,pTCS,cet,ppCtx,pTcid,ppPD,pSink) \
+ ( (This)->lpVtbl -> CreateContext(This,hWnd,prcInput,dwOptions,pTCS,cet,ppCtx,pTcid,ppPD,pSink) )
+
+#define ITablet_GetName(This,ppwszName) \
+ ( (This)->lpVtbl -> GetName(This,ppwszName) )
+
+#define ITablet_GetMaxInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> GetMaxInputRect(This,prcInput) )
+
+#define ITablet_GetHardwareCaps(This,pdwCaps) \
+ ( (This)->lpVtbl -> GetHardwareCaps(This,pdwCaps) )
+
+#define ITablet_GetPropertyMetrics(This,rguid,pPM) \
+ ( (This)->lpVtbl -> GetPropertyMetrics(This,rguid,pPM) )
+
+#define ITablet_GetPlugAndPlayId(This,ppwszPPId) \
+ ( (This)->lpVtbl -> GetPlugAndPlayId(This,ppwszPPId) )
+
+#define ITablet_GetCursorCount(This,pcCurs) \
+ ( (This)->lpVtbl -> GetCursorCount(This,pcCurs) )
+
+#define ITablet_GetCursor(This,iCur,ppCur) \
+ ( (This)->lpVtbl -> GetCursor(This,iCur,ppCur) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITablet_INTERFACE_DEFINED__ */
+
+
+/* interface __MIDL_itf_tpcpen_0000_0003 */
+/* [local] */
+
+typedef
+enum _TABLET_DEVICE_KIND
+ { TABLET_DEVICE_MOUSE = 0,
+ TABLET_DEVICE_PEN = ( TABLET_DEVICE_MOUSE + 1 ) ,
+ TABLET_DEVICE_TOUCH = ( TABLET_DEVICE_PEN + 1 )
+ } TABLET_DEVICE_KIND;
+
+
+
+extern RPC_IF_HANDLE __MIDL_itf_tpcpen_0000_0003_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_tpcpen_0000_0003_v0_0_s_ifspec;
+
+#ifndef __ITablet2_INTERFACE_DEFINED__
+#define __ITablet2_INTERFACE_DEFINED__
+
+/* interface ITablet2 */
+/* [unique][helpstring][uuid][object] */
+
+typedef /* [unique] */ __RPC_unique_pointer ITablet2 *PTABLET2;
+
+
+EXTERN_C const IID IID_ITablet2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C247F616-BBEB-406A-AED3-F75E656599AE")
+ ITablet2 : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDeviceKind(
+ /* [out] */ __RPC__out TABLET_DEVICE_KIND *pKind) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMatchingScreenRect(
+ /* [out] */ __RPC__out RECT *prcInput) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITablet2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITablet2 * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITablet2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITablet2 * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetDeviceKind )(
+ ITablet2 * This,
+ /* [out] */ __RPC__out TABLET_DEVICE_KIND *pKind);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetMatchingScreenRect )(
+ ITablet2 * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ END_INTERFACE
+ } ITablet2Vtbl;
+
+ interface ITablet2
+ {
+ CONST_VTBL struct ITablet2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITablet2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITablet2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITablet2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITablet2_GetDeviceKind(This,pKind) \
+ ( (This)->lpVtbl -> GetDeviceKind(This,pKind) )
+
+#define ITablet2_GetMatchingScreenRect(This,prcInput) \
+ ( (This)->lpVtbl -> GetMatchingScreenRect(This,prcInput) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITablet2_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletSettings_INTERFACE_DEFINED__
+#define __ITabletSettings_INTERFACE_DEFINED__
+
+/* interface ITabletSettings */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletSettings *PTABLETSETTINGS;
+
+
+EXTERN_C const IID IID_ITabletSettings;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("120ae7c9-36f7-4be6-93da-e5f266847b01")
+ ITabletSettings : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetProperty(
+ /* [in] */ DWORD dwProperty,
+ /* [out][in] */ __RPC__inout DWORD *pcbData,
+ /* [length_is][size_is][unique][out][in] */ __RPC__inout_ecount_part_opt(*pcbData, *pcbData) BYTE *pbData) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetProperty(
+ /* [in] */ DWORD dwProperty,
+ /* [in] */ DWORD cbData,
+ /* [size_is][unique][in] */ __RPC__in_ecount_full_opt(cbData) BYTE *pbData) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletSettingsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletSettings * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletSettings * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletSettings * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetProperty )(
+ ITabletSettings * This,
+ /* [in] */ DWORD dwProperty,
+ /* [out][in] */ __RPC__inout DWORD *pcbData,
+ /* [length_is][size_is][unique][out][in] */ __RPC__inout_ecount_part_opt(*pcbData, *pcbData) BYTE *pbData);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetProperty )(
+ ITabletSettings * This,
+ /* [in] */ DWORD dwProperty,
+ /* [in] */ DWORD cbData,
+ /* [size_is][unique][in] */ __RPC__in_ecount_full_opt(cbData) BYTE *pbData);
+
+ END_INTERFACE
+ } ITabletSettingsVtbl;
+
+ interface ITabletSettings
+ {
+ CONST_VTBL struct ITabletSettingsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletSettings_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletSettings_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletSettings_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletSettings_GetProperty(This,dwProperty,pcbData,pbData) \
+ ( (This)->lpVtbl -> GetProperty(This,dwProperty,pcbData,pbData) )
+
+#define ITabletSettings_SetProperty(This,dwProperty,cbData,pbData) \
+ ( (This)->lpVtbl -> SetProperty(This,dwProperty,cbData,pbData) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletSettings_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletContext_INTERFACE_DEFINED__
+#define __ITabletContext_INTERFACE_DEFINED__
+
+/* interface ITabletContext */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletContext *PTABLETCONTEXT;
+
+
+EXTERN_C const IID IID_ITabletContext;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("45AAAF04-9D6F-41AE-8ED1-ECD6D4B2F17F")
+ ITabletContext : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetId(
+ /* [out] */ __RPC__out TABLET_CONTEXT_ID *pTcid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetWindow(
+ /* [out] */ __RPC__deref_out_opt HWND *pHwnd) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetSettings(
+ /* [out] */ __RPC__deref_out_opt TABLET_CONTEXT_SETTINGS **ppTCS) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetTablet(
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Enable(
+ /* [in] */ CONTEXT_ENABLE_TYPE cet) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetOptions(
+ /* [out] */ __RPC__out DWORD *pdwOptions) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPacketDescription(
+ /* [out] */ __RPC__deref_out_opt PACKET_DESCRIPTION **ppPD) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetStatus(
+ /* [out] */ __RPC__out DWORD *pdwStatus) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetInputRect(
+ /* [out] */ __RPC__out RECT *prcInput) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetInputRect(
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetDevInputRect(
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDevInputRect(
+ /* [out] */ __RPC__out RECT *prcInput) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetCapture( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ReleaseCapture( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetCursorCapture(
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ReleaseCursorCapture(
+ /* [in] */ CURSOR_ID cid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPackets(
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out][in] */ __RPC__inout ULONG *pcPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [out] */ __RPC__out CURSOR_ID *pCid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PeekPackets(
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out][in] */ __RPC__inout ULONG *pcPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [out] */ __RPC__out CURSOR_ID *pCid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FlushPackets(
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FlushQueue( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPacketCount(
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out] */ __RPC__out ULONG *pcPkts) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPacketQueueInfo(
+ /* [out] */ __RPC__out ULONG *pnBegin,
+ /* [out] */ __RPC__out ULONG *pnEnd,
+ /* [out] */ __RPC__out ULONG *pcPkts) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ForwardPackets(
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE InjectPackets(
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cPkts) CURSOR_ID *pCids) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ModifyPackets(
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertToScreenCoordinates(
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cPkts) POINT *pPointsInScreen) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletContextVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletContext * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletContext * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletContext * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetId )(
+ ITabletContext * This,
+ /* [out] */ __RPC__out TABLET_CONTEXT_ID *pTcid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetWindow )(
+ ITabletContext * This,
+ /* [out] */ __RPC__deref_out_opt HWND *pHwnd);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetSettings )(
+ ITabletContext * This,
+ /* [out] */ __RPC__deref_out_opt TABLET_CONTEXT_SETTINGS **ppTCS);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTablet )(
+ ITabletContext * This,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Enable )(
+ ITabletContext * This,
+ /* [in] */ CONTEXT_ENABLE_TYPE cet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetOptions )(
+ ITabletContext * This,
+ /* [out] */ __RPC__out DWORD *pdwOptions);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPacketDescription )(
+ ITabletContext * This,
+ /* [out] */ __RPC__deref_out_opt PACKET_DESCRIPTION **ppPD);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetStatus )(
+ ITabletContext * This,
+ /* [out] */ __RPC__out DWORD *pdwStatus);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetInputRect )(
+ ITabletContext * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetInputRect )(
+ ITabletContext * This,
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetDevInputRect )(
+ ITabletContext * This,
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetDevInputRect )(
+ ITabletContext * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetCapture )(
+ ITabletContext * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ReleaseCapture )(
+ ITabletContext * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetCursorCapture )(
+ ITabletContext * This,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ReleaseCursorCapture )(
+ ITabletContext * This,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPackets )(
+ ITabletContext * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out][in] */ __RPC__inout ULONG *pcPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [out] */ __RPC__out CURSOR_ID *pCid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PeekPackets )(
+ ITabletContext * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out][in] */ __RPC__inout ULONG *pcPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [out] */ __RPC__out CURSOR_ID *pCid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FlushPackets )(
+ ITabletContext * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FlushQueue )(
+ ITabletContext * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPacketCount )(
+ ITabletContext * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out] */ __RPC__out ULONG *pcPkts);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPacketQueueInfo )(
+ ITabletContext * This,
+ /* [out] */ __RPC__out ULONG *pnBegin,
+ /* [out] */ __RPC__out ULONG *pnEnd,
+ /* [out] */ __RPC__out ULONG *pcPkts);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ForwardPackets )(
+ ITabletContext * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *InjectPackets )(
+ ITabletContext * This,
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cPkts) CURSOR_ID *pCids);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ModifyPackets )(
+ ITabletContext * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertToScreenCoordinates )(
+ ITabletContext * This,
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cPkts) POINT *pPointsInScreen);
+
+ END_INTERFACE
+ } ITabletContextVtbl;
+
+ interface ITabletContext
+ {
+ CONST_VTBL struct ITabletContextVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletContext_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletContext_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletContext_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletContext_GetId(This,pTcid) \
+ ( (This)->lpVtbl -> GetId(This,pTcid) )
+
+#define ITabletContext_GetWindow(This,pHwnd) \
+ ( (This)->lpVtbl -> GetWindow(This,pHwnd) )
+
+#define ITabletContext_GetSettings(This,ppTCS) \
+ ( (This)->lpVtbl -> GetSettings(This,ppTCS) )
+
+#define ITabletContext_GetTablet(This,ppTablet) \
+ ( (This)->lpVtbl -> GetTablet(This,ppTablet) )
+
+#define ITabletContext_Enable(This,cet) \
+ ( (This)->lpVtbl -> Enable(This,cet) )
+
+#define ITabletContext_GetOptions(This,pdwOptions) \
+ ( (This)->lpVtbl -> GetOptions(This,pdwOptions) )
+
+#define ITabletContext_GetPacketDescription(This,ppPD) \
+ ( (This)->lpVtbl -> GetPacketDescription(This,ppPD) )
+
+#define ITabletContext_GetStatus(This,pdwStatus) \
+ ( (This)->lpVtbl -> GetStatus(This,pdwStatus) )
+
+#define ITabletContext_GetInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> GetInputRect(This,prcInput) )
+
+#define ITabletContext_SetInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> SetInputRect(This,prcInput) )
+
+#define ITabletContext_SetDevInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> SetDevInputRect(This,prcInput) )
+
+#define ITabletContext_GetDevInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> GetDevInputRect(This,prcInput) )
+
+#define ITabletContext_SetCapture(This) \
+ ( (This)->lpVtbl -> SetCapture(This) )
+
+#define ITabletContext_ReleaseCapture(This) \
+ ( (This)->lpVtbl -> ReleaseCapture(This) )
+
+#define ITabletContext_SetCursorCapture(This,cid) \
+ ( (This)->lpVtbl -> SetCursorCapture(This,cid) )
+
+#define ITabletContext_ReleaseCursorCapture(This,cid) \
+ ( (This)->lpVtbl -> ReleaseCursorCapture(This,cid) )
+
+#define ITabletContext_GetPackets(This,nBegin,nEnd,pcPkts,cbPkts,pbPkts,pCid) \
+ ( (This)->lpVtbl -> GetPackets(This,nBegin,nEnd,pcPkts,cbPkts,pbPkts,pCid) )
+
+#define ITabletContext_PeekPackets(This,nBegin,nEnd,pcPkts,cbPkts,pbPkts,pCid) \
+ ( (This)->lpVtbl -> PeekPackets(This,nBegin,nEnd,pcPkts,cbPkts,pbPkts,pCid) )
+
+#define ITabletContext_FlushPackets(This,nBegin,nEnd) \
+ ( (This)->lpVtbl -> FlushPackets(This,nBegin,nEnd) )
+
+#define ITabletContext_FlushQueue(This) \
+ ( (This)->lpVtbl -> FlushQueue(This) )
+
+#define ITabletContext_GetPacketCount(This,nBegin,nEnd,pcPkts) \
+ ( (This)->lpVtbl -> GetPacketCount(This,nBegin,nEnd,pcPkts) )
+
+#define ITabletContext_GetPacketQueueInfo(This,pnBegin,pnEnd,pcPkts) \
+ ( (This)->lpVtbl -> GetPacketQueueInfo(This,pnBegin,pnEnd,pcPkts) )
+
+#define ITabletContext_ForwardPackets(This,nBegin,nEnd) \
+ ( (This)->lpVtbl -> ForwardPackets(This,nBegin,nEnd) )
+
+#define ITabletContext_InjectPackets(This,cPkts,cbPkts,pbPkts,pCids) \
+ ( (This)->lpVtbl -> InjectPackets(This,cPkts,cbPkts,pbPkts,pCids) )
+
+#define ITabletContext_ModifyPackets(This,nBegin,nEnd,cbPkts,pbPkts) \
+ ( (This)->lpVtbl -> ModifyPackets(This,nBegin,nEnd,cbPkts,pbPkts) )
+
+#define ITabletContext_ConvertToScreenCoordinates(This,cPkts,cbPkts,pbPkts,pPointsInScreen) \
+ ( (This)->lpVtbl -> ConvertToScreenCoordinates(This,cPkts,cbPkts,pbPkts,pPointsInScreen) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletContext_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletCursor_INTERFACE_DEFINED__
+#define __ITabletCursor_INTERFACE_DEFINED__
+
+/* interface ITabletCursor */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletCursor *PTABLETCURSOR;
+
+
+EXTERN_C const IID IID_ITabletCursor;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("EF9953C6-B472-4B02-9D22-D0E247ADE0E8")
+ ITabletCursor : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetName(
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE IsInverted( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetId(
+ /* [out] */ __RPC__out CURSOR_ID *pCid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetTablet(
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetButtonCount(
+ /* [out] */ __RPC__out ULONG *pcButtons) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetButton(
+ /* [in] */ ULONG iButton,
+ /* [out] */ __RPC__deref_out_opt ITabletCursorButton **ppButton) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletCursorVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletCursor * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletCursor * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletCursor * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ ITabletCursor * This,
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *IsInverted )(
+ ITabletCursor * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetId )(
+ ITabletCursor * This,
+ /* [out] */ __RPC__out CURSOR_ID *pCid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTablet )(
+ ITabletCursor * This,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetButtonCount )(
+ ITabletCursor * This,
+ /* [out] */ __RPC__out ULONG *pcButtons);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetButton )(
+ ITabletCursor * This,
+ /* [in] */ ULONG iButton,
+ /* [out] */ __RPC__deref_out_opt ITabletCursorButton **ppButton);
+
+ END_INTERFACE
+ } ITabletCursorVtbl;
+
+ interface ITabletCursor
+ {
+ CONST_VTBL struct ITabletCursorVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletCursor_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletCursor_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletCursor_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletCursor_GetName(This,ppwszName) \
+ ( (This)->lpVtbl -> GetName(This,ppwszName) )
+
+#define ITabletCursor_IsInverted(This) \
+ ( (This)->lpVtbl -> IsInverted(This) )
+
+#define ITabletCursor_GetId(This,pCid) \
+ ( (This)->lpVtbl -> GetId(This,pCid) )
+
+#define ITabletCursor_GetTablet(This,ppTablet) \
+ ( (This)->lpVtbl -> GetTablet(This,ppTablet) )
+
+#define ITabletCursor_GetButtonCount(This,pcButtons) \
+ ( (This)->lpVtbl -> GetButtonCount(This,pcButtons) )
+
+#define ITabletCursor_GetButton(This,iButton,ppButton) \
+ ( (This)->lpVtbl -> GetButton(This,iButton,ppButton) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletCursor_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletCursorButton_INTERFACE_DEFINED__
+#define __ITabletCursorButton_INTERFACE_DEFINED__
+
+/* interface ITabletCursorButton */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletCursorButton *PTABLETCURSORBUTTON;
+
+
+EXTERN_C const IID IID_ITabletCursorButton;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("997A992E-8B6C-4945-BC17-A1EE563B3AB7")
+ ITabletCursorButton : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetName(
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetGuid(
+ /* [out] */ __RPC__out GUID *pguidBtn) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletCursorButtonVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletCursorButton * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletCursorButton * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletCursorButton * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ ITabletCursorButton * This,
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetGuid )(
+ ITabletCursorButton * This,
+ /* [out] */ __RPC__out GUID *pguidBtn);
+
+ END_INTERFACE
+ } ITabletCursorButtonVtbl;
+
+ interface ITabletCursorButton
+ {
+ CONST_VTBL struct ITabletCursorButtonVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletCursorButton_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletCursorButton_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletCursorButton_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletCursorButton_GetName(This,ppwszName) \
+ ( (This)->lpVtbl -> GetName(This,ppwszName) )
+
+#define ITabletCursorButton_GetGuid(This,pguidBtn) \
+ ( (This)->lpVtbl -> GetGuid(This,pguidBtn) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletCursorButton_INTERFACE_DEFINED__ */
+
+
+
+#ifndef __TABLETLib_LIBRARY_DEFINED__
+#define __TABLETLib_LIBRARY_DEFINED__
+
+/* library TABLETLib */
+/* [helpstring][version][uuid] */
+
+
+
+
+
+
+
+
+EXTERN_C const IID LIBID_TABLETLib;
+
+EXTERN_C const CLSID CLSID_TabletManager;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("786CDB70-1628-44A0-853C-5D340A499137")
+TabletManager;
+#endif
+#endif /* __TABLETLib_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+unsigned long __RPC_USER HWND_UserSize( unsigned long *, unsigned long , HWND * );
+unsigned char * __RPC_USER HWND_UserMarshal( unsigned long *, unsigned char *, HWND * );
+unsigned char * __RPC_USER HWND_UserUnmarshal(unsigned long *, unsigned char *, HWND * );
+void __RPC_USER HWND_UserFree( unsigned long *, HWND * );
+
+unsigned long __RPC_USER HWND_UserSize64( unsigned long *, unsigned long , HWND * );
+unsigned char * __RPC_USER HWND_UserMarshal64( unsigned long *, unsigned char *, HWND * );
+unsigned char * __RPC_USER HWND_UserUnmarshal64(unsigned long *, unsigned char *, HWND * );
+void __RPC_USER HWND_UserFree64( unsigned long *, HWND * );
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpcpen_i.c b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpcpen_i.c
new file mode 100644
index 00000000000..b65145f11e7
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpcpen_i.c
@@ -0,0 +1,113 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+
+/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
+
+/* link this file in with the server and any clients */
+
+
+ /* File created by MIDL compiler version 7.00.0499 */
+/* Compiler settings for tpcpen.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#include
+#include
+
+#ifdef _MIDL_USE_GUIDDEF_
+
+#ifndef INITGUID
+#define INITGUID
+#include
+#undef INITGUID
+#else
+#include
+#endif
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
+
+#else // !_MIDL_USE_GUIDDEF_
+
+#ifndef __IID_DEFINED__
+#define __IID_DEFINED__
+
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+#endif // __IID_DEFINED__
+
+#ifndef CLSID_DEFINED
+#define CLSID_DEFINED
+typedef IID CLSID;
+#endif // CLSID_DEFINED
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+
+#endif !_MIDL_USE_GUIDDEF_
+
+MIDL_DEFINE_GUID(IID, IID_ITabletEventSink,0x788459C8,0x26C8,0x4666,0xBF,0x57,0x04,0xAD,0x3A,0x0A,0x5E,0xB5);
+
+
+MIDL_DEFINE_GUID(IID, IID_AsyncITabletEventSink,0xCDF7D7D6,0x2E5D,0x47c7,0x90,0xFC,0xC6,0x38,0xC7,0xFA,0x3F,0xC4);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletManager,0x764DE8AA,0x1867,0x47C1,0x8F,0x6A,0x12,0x24,0x45,0xAB,0xD8,0x9A);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITablet,0x1CB2EFC3,0xABC7,0x4172,0x8F,0xCB,0x3B,0xC9,0xCB,0x93,0xE2,0x9F);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITablet2,0xC247F616,0xBBEB,0x406A,0xAE,0xD3,0xF7,0x5E,0x65,0x65,0x99,0xAE);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletSettings,0x120ae7c9,0x36f7,0x4be6,0x93,0xda,0xe5,0xf2,0x66,0x84,0x7b,0x01);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletContext,0x45AAAF04,0x9D6F,0x41AE,0x8E,0xD1,0xEC,0xD6,0xD4,0xB2,0xF1,0x7F);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletCursor,0xEF9953C6,0xB472,0x4B02,0x9D,0x22,0xD0,0xE2,0x47,0xAD,0xE0,0xE8);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletCursorButton,0x997A992E,0x8B6C,0x4945,0xBC,0x17,0xA1,0xEE,0x56,0x3B,0x3A,0xB7);
+
+
+MIDL_DEFINE_GUID(IID, LIBID_TABLETLib,0xC3F76406,0x6CA5,0x4BCD,0x85,0xE4,0x0E,0x7F,0x9E,0x05,0xD5,0x08);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_TabletManager,0x786CDB70,0x1628,0x44A0,0x85,0x3C,0x5D,0x34,0x0A,0x49,0x91,0x37);
+
+#undef MIDL_DEFINE_GUID
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpguuid.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpguuid.h
new file mode 100644
index 00000000000..051fb8ea33c
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/tpguuid.h
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#pragma once
+
+// None of the interfaces should change but...
+
+#define TABLETMANAGERP_INTERFACE uuid(663C73A5-8715-4499-B809-43689A93086B)
+#define TABLETP_INTERFACE uuid(E65752FA-600B-43bd-8BFE-6A686FA3A201)
+#define TABLETCONTEXTP_INTERFACE uuid(22F74D0A-694F-4f47-A5CE-AE08A6409AC8)
+#define TABLETCURSORP_INTERFACE uuid(35DE0002-232C-4629-A915-7E600E80CD88)
+#define TABLETCURSORBUTTONP_INTERFACE uuid(FCA502B0-5409-434d-8C35-A96C76CCA99C)
+#define TABLETEVENTSINKP_INTERFACE uuid(287A9E67-8D1D-4a65-8DB4-51915395D019)
+#define RECOPRIVATE_INTERFACE uuid(D3BD1CEE-2BAC-4114-94AF-D1541B032046)
+#define RECOGNIZERPRIVATE_INTERFACE uuid(709AD3A5-7A2B-4edf-8939-D7BF6FF02327)
+#define RECOMANAGER_INTERFACE uuid(C2E8F101-5D03-42EE-B90A-352557831039)
+#define USERLEXICONMANAGER_INTERFACE uuid(1207B722-009D-495b-8C98-3A130F6DBE47)
+#define ALTERNATE_INTERFACE uuid(A5055FC1-1A22-4F22-B306-76151BD53850)
+#define RECOASYNCRESULTS_INTERFACE uuid(250CEF9C-121F-493d-ADCD-7A2A6823C0FD)
+#define RECOCONTEXT_INTERFACE uuid(E6DAB875-75AF-4C8A-9665-2B6A44DD0F26)
+#define RECOGNIZER_INTERFACE uuid(3A182AD6-596A-4070-A574-73941817B674)
+#define LATTICE_INTERFACE uuid(946665F9-71E3-447B-A896-3359DA411532)
+#define RECOWORDLIST_INTERFACE uuid(37ADC645-ACE6-4a31-B6A1-FD1F4EF48012)
+#define CLASSIC_WISP_INTERFACE uuid(663265C9-6B4D-428c-8266-8058D11C2691)
+#define INKOBJECT_INTERFACE uuid(B9C4A0C1-16ED-4DC2-B34A-4E830326587E)
+#define INKSTROKE_INTERFACE uuid(251F1257-1DCB-4AD0-A826-4F9E326fE490)
+#define INKPOINT_INTERFACE uuid(3776F33D-6BF8-4ADD-9C7E-946AB4A7718D)
+#define INKCOLLECT_INTERFACE uuid(E0ABA4C5-1726-4240-8E00-5EE31788A11B)
+#define RENDERINK_INTERFACE uuid(538A9C7B-858A-4FF1-9769-62B6D74993D9)
+#define INKCLIPBOARD_INTERFACE uuid(D499C1B0-9E97-4CC4-AE10-F8DCCCE1DE09)
+#define STROKESET_INTERFACE uuid(2080FF4F-297F-4F66-AA83-CACA65F67216)
+#define DRAWATTRS_INTERFACE uuid(051A0FA4-FCEE-4E18-BF46-89726728FB26)
+#define TRANSFORMINK_INTERFACE uuid(8341F277-756B-433B-A78E-2221A2577339)
+#define STROKEGEOMETERY_INTERFACE uuid(11F962C5-242E-4D4D-B205-0F3AB3562FDE)
+#define RENDERINGCONTEXT_INTERFACE uuid(4E6B4F16-5A0C-4815-9AA2-DE231F5AAA26)
+#define INKSETTINGS_INTERFACE uuid(A5558507-9B96-46BA-94ED-982E684A9A6B)
+#define TABLETEVENTSINK_INTERFACE uuid(788459C8-26C8-4666-BF57-04AD3A0A5EB5)
+#define TABLETEVENTSINK_ASYNC async_uuid(CDF7D7D6-2E5D-47c7-90FC-C638C7FA3FC4)
+#define TABLETMANAGER_INTERFACE uuid(764DE8AA-1867-47C1-8F6A-122445ABD89A)
+#define TABLET_INTERFACE uuid(1CB2EFC3-ABC7-4172-8FCB-3BC9CB93E29F)
+#define TABLET2_INTERFACE uuid(C247F616-BBEB-406A-AED3-F75E656599AE)
+#define TABLETSETTINGS_INTERFACE uuid(120ae7c9-36f7-4be6-93da-e5f266847b01)
+#define TABLETCONTEXT_INTERFACE uuid(45AAAF04-9D6F-41AE-8ED1-ECD6D4B2F17F)
+#define TABLETCURSOR_INTERFACE uuid(EF9953C6-B472-4B02-9D22-D0E247ADE0E8)
+#define TABLETCURSORBUTTON_INTERFACE uuid(997A992E-8B6C-4945-BC17-A1EE563B3AB7)
+
+//
+// Classic WISP APIs. These GUIDs are different between 1.0 and 2.0
+//
+#define WISP_CLIENT_TYPELIB uuid(D48CA453-5D1A-4BF9-B9BA-6CE8CB16F10A)
+#define TABLETMANAGER_CLASS uuid(786CDB70-1628-44A0-853C-5D340A499137)
+#define CLASSIC_WISP_TYPELIB uuid(DFD61F94-B7C7-4e15-8F27-0F2C9BCB420C)
+#define CLASSIC_WISP_CLASS uuid(3336B8BF-45AF-429f-85CB-8C435FBF21E4)
+#define RECOCOM_TYPELIB uuid(9E52A566-D72F-4342-99B9-DBCA6780385F)
+#define RECOMANAGER_CLASS uuid(DE815B00-9460-4F6E-9471-892ED2275EA5)
+#define USERLEXICONMANAGER_CLASS uuid(176D323D-E591-4535-9A09-26F698E5AC5D)
+#define GENERICRECOGNIZER_CLASS uuid(EFB4A0CB-A01F-451C-B6B7-56F02F77D76F)
+#define LATTICE_CLASS uuid(632A2D3D-86AF-411A-8654-7511B51B3D5F)
+#define RECOUSERDICT_CLASS uuid(836FA1B6-1190-4005-B434-7ED921BE2026)
+#define TPCINK_TYPELIB uuid(194508A0-B8D1-473E-A9B6-851AAF726A6D)
+#define INKOBJECT_CLASS uuid(3EE60F5C-9BAD-4CD8-8E21-AD2D001D06EB)
+#define INKSETTINGS_CLASS uuid(242025BB-8546-48B6-B9B0-F4406C54ACFC)
+#define DRAWATTRS_CLASS uuid(524B13ED-2E57-40B8-B801-5FA35122EB5C)
+#define INKSTROKE_CLASS uuid(4831CABD-F171-47F1-8D3C-0CBC8AFCB788)
+#define STROKESET_CLASS uuid(DC4D7DD2-97B1-4CD5-BD6E-E34DD57F767D)
+#define RENDERINGCONTEXT_CLASS uuid(07081630-B202-4C48-B8B7-4F6C99B8CACE)
+#define TABLET_TYPELIB uuid(C3F76406-6CA5-4BCD-85E4-0E7F9E05D508)
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptics.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptics.h
new file mode 100644
index 00000000000..ed0fe1af6c8
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptics.h
@@ -0,0 +1,1366 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 7.00.0498 */
+/* Compiler settings for wisptics.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 500
+#endif
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCSAL_H_VERSION__
+#define __REQUIRED_RPCSAL_H_VERSION__ 100
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of
+#endif // __RPCNDR_H_VERSION__
+
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __wisptics_h__
+#define __wisptics_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifndef __ITabletManagerP_FWD_DEFINED__
+#define __ITabletManagerP_FWD_DEFINED__
+typedef interface ITabletManagerP ITabletManagerP;
+#endif /* __ITabletManagerP_FWD_DEFINED__ */
+
+
+#ifndef __ITabletManagerDrt_FWD_DEFINED__
+#define __ITabletManagerDrt_FWD_DEFINED__
+typedef interface ITabletManagerDrt ITabletManagerDrt;
+#endif /* __ITabletManagerDrt_FWD_DEFINED__ */
+
+
+#ifndef __ITabletP_FWD_DEFINED__
+#define __ITabletP_FWD_DEFINED__
+typedef interface ITabletP ITabletP;
+#endif /* __ITabletP_FWD_DEFINED__ */
+
+
+#ifndef __ITabletP2_FWD_DEFINED__
+#define __ITabletP2_FWD_DEFINED__
+typedef interface ITabletP2 ITabletP2;
+#endif /* __ITabletP2_FWD_DEFINED__ */
+
+
+#ifndef __ITabletContextP_FWD_DEFINED__
+#define __ITabletContextP_FWD_DEFINED__
+typedef interface ITabletContextP ITabletContextP;
+#endif /* __ITabletContextP_FWD_DEFINED__ */
+
+
+#ifndef __ITabletCursorP_FWD_DEFINED__
+#define __ITabletCursorP_FWD_DEFINED__
+typedef interface ITabletCursorP ITabletCursorP;
+#endif /* __ITabletCursorP_FWD_DEFINED__ */
+
+
+#ifndef __ITabletCursorButtonP_FWD_DEFINED__
+#define __ITabletCursorButtonP_FWD_DEFINED__
+typedef interface ITabletCursorButtonP ITabletCursorButtonP;
+#endif /* __ITabletCursorButtonP_FWD_DEFINED__ */
+
+
+#ifndef __ITabletEventSinkP_FWD_DEFINED__
+#define __ITabletEventSinkP_FWD_DEFINED__
+typedef interface ITabletEventSinkP ITabletEventSinkP;
+#endif /* __ITabletEventSinkP_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "oaidl.h"
+#include "ocidl.h"
+#include "tpcpen.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+/* interface __MIDL_itf_wisptics_0000_0000 */
+/* [local] */
+
+#pragma once
+
+
+
+
+
+
+
+
+extern RPC_IF_HANDLE __MIDL_itf_wisptics_0000_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_wisptics_0000_0000_v0_0_s_ifspec;
+
+#ifndef __ITabletManagerP_INTERFACE_DEFINED__
+#define __ITabletManagerP_INTERFACE_DEFINED__
+
+/* interface ITabletManagerP */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletManagerP *PTABLETMANAGERP;
+
+
+EXTERN_C const IID IID_ITabletManagerP;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("663C73A5-8715-4499-B809-43689A93086B")
+ ITabletManagerP : public ITabletManager
+ {
+ public:
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletManagerPVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletManagerP * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletManagerP * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletManagerP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetDefaultTablet )(
+ ITabletManagerP * This,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTabletCount )(
+ ITabletManagerP * This,
+ /* [out] */ __RPC__out ULONG *pcTablets);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTablet )(
+ ITabletManagerP * This,
+ /* [in] */ ULONG iTablet,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTabletContextById )(
+ ITabletManagerP * This,
+ /* [in] */ TABLET_CONTEXT_ID tcid,
+ /* [out] */ __RPC__deref_out_opt ITabletContext **ppContext);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetCursorById )(
+ ITabletManagerP * This,
+ /* [in] */ CURSOR_ID cid,
+ /* [out] */ __RPC__deref_out_opt ITabletCursor **ppCursor);
+
+ END_INTERFACE
+ } ITabletManagerPVtbl;
+
+ interface ITabletManagerP
+ {
+ CONST_VTBL struct ITabletManagerPVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletManagerP_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletManagerP_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletManagerP_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletManagerP_GetDefaultTablet(This,ppTablet) \
+ ( (This)->lpVtbl -> GetDefaultTablet(This,ppTablet) )
+
+#define ITabletManagerP_GetTabletCount(This,pcTablets) \
+ ( (This)->lpVtbl -> GetTabletCount(This,pcTablets) )
+
+#define ITabletManagerP_GetTablet(This,iTablet,ppTablet) \
+ ( (This)->lpVtbl -> GetTablet(This,iTablet,ppTablet) )
+
+#define ITabletManagerP_GetTabletContextById(This,tcid,ppContext) \
+ ( (This)->lpVtbl -> GetTabletContextById(This,tcid,ppContext) )
+
+#define ITabletManagerP_GetCursorById(This,cid,ppCursor) \
+ ( (This)->lpVtbl -> GetCursorById(This,cid,ppCursor) )
+
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletManagerP_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletManagerDrt_INTERFACE_DEFINED__
+#define __ITabletManagerDrt_INTERFACE_DEFINED__
+
+/* interface ITabletManagerDrt */
+/* [unique][helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_ITabletManagerDrt;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("A56AB812-2AC7-443d-A87A-F1EE1CD5A0E6")
+ ITabletManagerDrt : public IUnknown
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE IsTabletPresent(
+ __RPC__in BSTR bstrTablet,
+ /* [out] */ __RPC__out BOOL *pfPresent) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SimulatePacket(
+ __RPC__in BSTR bstrTablet,
+ LONG x,
+ LONG y,
+ BOOL fCursorDown) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE EnablePacketsTransfer(
+ BOOL fEnable) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SimulateCursorInRange(
+ DWORD cursorKey) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SimulateCursorOutOfRange(
+ DWORD cursorKey) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetTabletRectangle(
+ __RPC__in BSTR bstrTablet,
+ /* [out] */ __RPC__out RECT *prc) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FindTablet(
+ __RPC__in BSTR bstrTablet,
+ /* [out] */ __RPC__out ULONG *piTablet) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SimulatePacketWithButton(
+ __RPC__in BSTR bstrTablet,
+ LONG x,
+ LONG y,
+ BOOL fCursorDown,
+ BOOL fBarrelButton) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SimulateCursorInRangeForTablet(
+ __RPC__in BSTR bstrTablet,
+ DWORD cursorKey) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SimulateCursorOutOfRangeForTablet(
+ __RPC__in BSTR bstrTablet,
+ DWORD cursorKey) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE EnsureTablet(
+ __RPC__in BSTR bstrTablet) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletManagerDrtVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletManagerDrt * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletManagerDrt * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletManagerDrt * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *IsTabletPresent )(
+ ITabletManagerDrt * This,
+ __RPC__in BSTR bstrTablet,
+ /* [out] */ __RPC__out BOOL *pfPresent);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SimulatePacket )(
+ ITabletManagerDrt * This,
+ __RPC__in BSTR bstrTablet,
+ LONG x,
+ LONG y,
+ BOOL fCursorDown);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *EnablePacketsTransfer )(
+ ITabletManagerDrt * This,
+ BOOL fEnable);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SimulateCursorInRange )(
+ ITabletManagerDrt * This,
+ DWORD cursorKey);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SimulateCursorOutOfRange )(
+ ITabletManagerDrt * This,
+ DWORD cursorKey);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTabletRectangle )(
+ ITabletManagerDrt * This,
+ __RPC__in BSTR bstrTablet,
+ /* [out] */ __RPC__out RECT *prc);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FindTablet )(
+ ITabletManagerDrt * This,
+ __RPC__in BSTR bstrTablet,
+ /* [out] */ __RPC__out ULONG *piTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SimulatePacketWithButton )(
+ ITabletManagerDrt * This,
+ __RPC__in BSTR bstrTablet,
+ LONG x,
+ LONG y,
+ BOOL fCursorDown,
+ BOOL fBarrelButton);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SimulateCursorInRangeForTablet )(
+ ITabletManagerDrt * This,
+ __RPC__in BSTR bstrTablet,
+ DWORD cursorKey);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SimulateCursorOutOfRangeForTablet )(
+ ITabletManagerDrt * This,
+ __RPC__in BSTR bstrTablet,
+ DWORD cursorKey);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *EnsureTablet )(
+ ITabletManagerDrt * This,
+ __RPC__in BSTR bstrTablet);
+
+ END_INTERFACE
+ } ITabletManagerDrtVtbl;
+
+ interface ITabletManagerDrt
+ {
+ CONST_VTBL struct ITabletManagerDrtVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletManagerDrt_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletManagerDrt_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletManagerDrt_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletManagerDrt_IsTabletPresent(This,bstrTablet,pfPresent) \
+ ( (This)->lpVtbl -> IsTabletPresent(This,bstrTablet,pfPresent) )
+
+#define ITabletManagerDrt_SimulatePacket(This,bstrTablet,x,y,fCursorDown) \
+ ( (This)->lpVtbl -> SimulatePacket(This,bstrTablet,x,y,fCursorDown) )
+
+#define ITabletManagerDrt_EnablePacketsTransfer(This,fEnable) \
+ ( (This)->lpVtbl -> EnablePacketsTransfer(This,fEnable) )
+
+#define ITabletManagerDrt_SimulateCursorInRange(This,cursorKey) \
+ ( (This)->lpVtbl -> SimulateCursorInRange(This,cursorKey) )
+
+#define ITabletManagerDrt_SimulateCursorOutOfRange(This,cursorKey) \
+ ( (This)->lpVtbl -> SimulateCursorOutOfRange(This,cursorKey) )
+
+#define ITabletManagerDrt_GetTabletRectangle(This,bstrTablet,prc) \
+ ( (This)->lpVtbl -> GetTabletRectangle(This,bstrTablet,prc) )
+
+#define ITabletManagerDrt_FindTablet(This,bstrTablet,piTablet) \
+ ( (This)->lpVtbl -> FindTablet(This,bstrTablet,piTablet) )
+
+#define ITabletManagerDrt_SimulatePacketWithButton(This,bstrTablet,x,y,fCursorDown,fBarrelButton) \
+ ( (This)->lpVtbl -> SimulatePacketWithButton(This,bstrTablet,x,y,fCursorDown,fBarrelButton) )
+
+#define ITabletManagerDrt_SimulateCursorInRangeForTablet(This,bstrTablet,cursorKey) \
+ ( (This)->lpVtbl -> SimulateCursorInRangeForTablet(This,bstrTablet,cursorKey) )
+
+#define ITabletManagerDrt_SimulateCursorOutOfRangeForTablet(This,bstrTablet,cursorKey) \
+ ( (This)->lpVtbl -> SimulateCursorOutOfRangeForTablet(This,bstrTablet,cursorKey) )
+
+#define ITabletManagerDrt_EnsureTablet(This,bstrTablet) \
+ ( (This)->lpVtbl -> EnsureTablet(This,bstrTablet) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletManagerDrt_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletP_INTERFACE_DEFINED__
+#define __ITabletP_INTERFACE_DEFINED__
+
+/* interface ITabletP */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletP *PTABLETP;
+
+
+EXTERN_C const IID IID_ITabletP;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("E65752FA-600B-43bd-8BFE-6A686FA3A201")
+ ITabletP : public ITablet
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetId(
+ /* [out] */ __RPC__out DWORD *pId) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletPVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletP * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletP * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetDefaultContextSettings )(
+ ITabletP * This,
+ /* [out] */ __RPC__deref_out_opt TABLET_CONTEXT_SETTINGS **ppTCS);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateContext )(
+ ITabletP * This,
+ /* [in] */ __RPC__in HWND hWnd,
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput,
+ /* [in] */ DWORD dwOptions,
+ /* [unique][in] */ __RPC__in_opt TABLET_CONTEXT_SETTINGS *pTCS,
+ /* [in] */ CONTEXT_ENABLE_TYPE cet,
+ /* [out] */ __RPC__deref_out_opt ITabletContext **ppCtx,
+ /* [unique][out][in] */ __RPC__inout_opt TABLET_CONTEXT_ID *pTcid,
+ /* [unique][out][in] */ __RPC__deref_opt_inout_opt PACKET_DESCRIPTION **ppPD,
+ /* [unique][in] */ __RPC__in_opt ITabletEventSink *pSink);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ ITabletP * This,
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetMaxInputRect )(
+ ITabletP * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetHardwareCaps )(
+ ITabletP * This,
+ /* [out] */ __RPC__out DWORD *pdwCaps);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPropertyMetrics )(
+ ITabletP * This,
+ /* [in] */ __RPC__in REFGUID rguid,
+ /* [out] */ __RPC__out PROPERTY_METRICS *pPM);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPlugAndPlayId )(
+ ITabletP * This,
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszPPId);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetCursorCount )(
+ ITabletP * This,
+ /* [out] */ __RPC__out ULONG *pcCurs);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetCursor )(
+ ITabletP * This,
+ /* [in] */ ULONG iCur,
+ /* [out] */ __RPC__deref_out_opt ITabletCursor **ppCur);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetId )(
+ ITabletP * This,
+ /* [out] */ __RPC__out DWORD *pId);
+
+ END_INTERFACE
+ } ITabletPVtbl;
+
+ interface ITabletP
+ {
+ CONST_VTBL struct ITabletPVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletP_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletP_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletP_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletP_GetDefaultContextSettings(This,ppTCS) \
+ ( (This)->lpVtbl -> GetDefaultContextSettings(This,ppTCS) )
+
+#define ITabletP_CreateContext(This,hWnd,prcInput,dwOptions,pTCS,cet,ppCtx,pTcid,ppPD,pSink) \
+ ( (This)->lpVtbl -> CreateContext(This,hWnd,prcInput,dwOptions,pTCS,cet,ppCtx,pTcid,ppPD,pSink) )
+
+#define ITabletP_GetName(This,ppwszName) \
+ ( (This)->lpVtbl -> GetName(This,ppwszName) )
+
+#define ITabletP_GetMaxInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> GetMaxInputRect(This,prcInput) )
+
+#define ITabletP_GetHardwareCaps(This,pdwCaps) \
+ ( (This)->lpVtbl -> GetHardwareCaps(This,pdwCaps) )
+
+#define ITabletP_GetPropertyMetrics(This,rguid,pPM) \
+ ( (This)->lpVtbl -> GetPropertyMetrics(This,rguid,pPM) )
+
+#define ITabletP_GetPlugAndPlayId(This,ppwszPPId) \
+ ( (This)->lpVtbl -> GetPlugAndPlayId(This,ppwszPPId) )
+
+#define ITabletP_GetCursorCount(This,pcCurs) \
+ ( (This)->lpVtbl -> GetCursorCount(This,pcCurs) )
+
+#define ITabletP_GetCursor(This,iCur,ppCur) \
+ ( (This)->lpVtbl -> GetCursor(This,iCur,ppCur) )
+
+
+#define ITabletP_GetId(This,pId) \
+ ( (This)->lpVtbl -> GetId(This,pId) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletP_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletP2_INTERFACE_DEFINED__
+#define __ITabletP2_INTERFACE_DEFINED__
+
+/* interface ITabletP2 */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletP2 *PTABLETP2;
+
+
+EXTERN_C const IID IID_ITabletP2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("de5d1ed5-41d4-475d-bdd8-ea749677b3a1")
+ ITabletP2 : public ITablet2
+ {
+ public:
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletP2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletP2 * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletP2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletP2 * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetDeviceKind )(
+ ITabletP2 * This,
+ /* [out] */ __RPC__out TABLET_DEVICE_KIND *pKind);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetMatchingScreenRect )(
+ ITabletP2 * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ END_INTERFACE
+ } ITabletP2Vtbl;
+
+ interface ITabletP2
+ {
+ CONST_VTBL struct ITabletP2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletP2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletP2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletP2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletP2_GetDeviceKind(This,pKind) \
+ ( (This)->lpVtbl -> GetDeviceKind(This,pKind) )
+
+#define ITabletP2_GetMatchingScreenRect(This,prcInput) \
+ ( (This)->lpVtbl -> GetMatchingScreenRect(This,prcInput) )
+
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletP2_INTERFACE_DEFINED__ */
+
+
+/* interface __MIDL_itf_wisptics_0000_0004 */
+/* [local] */
+
+typedef
+enum _CONTEXT_TYPE
+ { WINTAB = 1,
+ HID = ( WINTAB + 1 ) ,
+ MOUSE = ( HID + 1 )
+ } CONTEXT_TYPE;
+
+
+
+extern RPC_IF_HANDLE __MIDL_itf_wisptics_0000_0004_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_wisptics_0000_0004_v0_0_s_ifspec;
+
+#ifndef __ITabletContextP_INTERFACE_DEFINED__
+#define __ITabletContextP_INTERFACE_DEFINED__
+
+/* interface ITabletContextP */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletContextP *PTABLETCONTEXTP;
+
+
+EXTERN_C const IID IID_ITabletContextP;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("22F74D0A-694F-4f47-A5CE-AE08A6409AC8")
+ ITabletContextP : public ITabletContext
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Overlap(
+ /* [in] */ BOOL bTop,
+ /* [out] */ __RPC__out DWORD *pdwtcid) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetType(
+ /* [out] */ __RPC__out CONTEXT_TYPE *pct) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE TrackInputRect(
+ /* [out] */ __RPC__out RECT *prcInput) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE IsTopMostHook( void) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetEventSink(
+ /* [out] */ __RPC__deref_out_opt ITabletEventSink **ppSink) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UseSharedMemoryCommunications(
+ /* [in] */ DWORD pid,
+ /* [out] */ __RPC__out DWORD *phEventMoreData,
+ /* [out] */ __RPC__out DWORD *phEventClientReady,
+ /* [out] */ __RPC__out DWORD *phMutexAccess,
+ /* [out] */ __RPC__out DWORD *phFileMapping) = 0;
+
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UseNamedSharedMemoryCommunications(
+ /* [in] */ DWORD pid,
+ /* [string][in] */ __RPC__in LPCTSTR szSid,
+ /* [string][in] */ __RPC__in LPCTSTR sdIlSid,
+ /* [out] */ __RPC__out DWORD *pdwEventMoreDataId,
+ /* [out] */ __RPC__out DWORD *pdwEventClientReadyId,
+ /* [out] */ __RPC__out DWORD *pdwMutexAccessId,
+ /* [out] */ __RPC__out DWORD *pdwFileMappingId) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletContextPVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletContextP * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletContextP * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletContextP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetId )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__out TABLET_CONTEXT_ID *pTcid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetWindow )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__deref_out_opt HWND *pHwnd);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetSettings )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__deref_out_opt TABLET_CONTEXT_SETTINGS **ppTCS);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTablet )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Enable )(
+ ITabletContextP * This,
+ /* [in] */ CONTEXT_ENABLE_TYPE cet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetOptions )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__out DWORD *pdwOptions);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPacketDescription )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__deref_out_opt PACKET_DESCRIPTION **ppPD);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetStatus )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__out DWORD *pdwStatus);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetInputRect )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetInputRect )(
+ ITabletContextP * This,
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetDevInputRect )(
+ ITabletContextP * This,
+ /* [unique][in] */ __RPC__in_opt RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetDevInputRect )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetCapture )(
+ ITabletContextP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ReleaseCapture )(
+ ITabletContextP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetCursorCapture )(
+ ITabletContextP * This,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ReleaseCursorCapture )(
+ ITabletContextP * This,
+ /* [in] */ CURSOR_ID cid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPackets )(
+ ITabletContextP * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out][in] */ __RPC__inout ULONG *pcPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [out] */ __RPC__out CURSOR_ID *pCid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PeekPackets )(
+ ITabletContextP * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out][in] */ __RPC__inout ULONG *pcPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [out] */ __RPC__out CURSOR_ID *pCid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FlushPackets )(
+ ITabletContextP * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FlushQueue )(
+ ITabletContextP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPacketCount )(
+ ITabletContextP * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [out] */ __RPC__out ULONG *pcPkts);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPacketQueueInfo )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__out ULONG *pnBegin,
+ /* [out] */ __RPC__out ULONG *pnEnd,
+ /* [out] */ __RPC__out ULONG *pcPkts);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ForwardPackets )(
+ ITabletContextP * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *InjectPackets )(
+ ITabletContextP * This,
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cPkts) CURSOR_ID *pCids);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ModifyPackets )(
+ ITabletContextP * This,
+ /* [in] */ ULONG nBegin,
+ /* [in] */ ULONG nEnd,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertToScreenCoordinates )(
+ ITabletContextP * This,
+ /* [in] */ ULONG cPkts,
+ /* [in] */ ULONG cbPkts,
+ /* [size_is][in] */ __RPC__in_ecount_full(cbPkts) BYTE *pbPkts,
+ /* [size_is][out] */ __RPC__out_ecount_full(cPkts) POINT *pPointsInScreen);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Overlap )(
+ ITabletContextP * This,
+ /* [in] */ BOOL bTop,
+ /* [out] */ __RPC__out DWORD *pdwtcid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetType )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__out CONTEXT_TYPE *pct);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *TrackInputRect )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__out RECT *prcInput);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *IsTopMostHook )(
+ ITabletContextP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetEventSink )(
+ ITabletContextP * This,
+ /* [out] */ __RPC__deref_out_opt ITabletEventSink **ppSink);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UseSharedMemoryCommunications )(
+ ITabletContextP * This,
+ /* [in] */ DWORD pid,
+ /* [out] */ __RPC__out DWORD *phEventMoreData,
+ /* [out] */ __RPC__out DWORD *phEventClientReady,
+ /* [out] */ __RPC__out DWORD *phMutexAccess,
+ /* [out] */ __RPC__out DWORD *phFileMapping);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UseNamedSharedMemoryCommunications )(
+ ITabletContextP * This,
+ /* [in] */ DWORD pid,
+ /* [string][in] */ __RPC__in LPCTSTR szSid,
+ /* [string][in] */ __RPC__in LPCTSTR sdIlSid,
+ /* [out] */ __RPC__out DWORD *pdwEventMoreDataId,
+ /* [out] */ __RPC__out DWORD *pdwEventClientReadyId,
+ /* [out] */ __RPC__out DWORD *pdwMutexAccessId,
+ /* [out] */ __RPC__out DWORD *pdwFileMappingId);
+
+ END_INTERFACE
+ } ITabletContextPVtbl;
+
+ interface ITabletContextP
+ {
+ CONST_VTBL struct ITabletContextPVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletContextP_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletContextP_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletContextP_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletContextP_GetId(This,pTcid) \
+ ( (This)->lpVtbl -> GetId(This,pTcid) )
+
+#define ITabletContextP_GetWindow(This,pHwnd) \
+ ( (This)->lpVtbl -> GetWindow(This,pHwnd) )
+
+#define ITabletContextP_GetSettings(This,ppTCS) \
+ ( (This)->lpVtbl -> GetSettings(This,ppTCS) )
+
+#define ITabletContextP_GetTablet(This,ppTablet) \
+ ( (This)->lpVtbl -> GetTablet(This,ppTablet) )
+
+#define ITabletContextP_Enable(This,cet) \
+ ( (This)->lpVtbl -> Enable(This,cet) )
+
+#define ITabletContextP_GetOptions(This,pdwOptions) \
+ ( (This)->lpVtbl -> GetOptions(This,pdwOptions) )
+
+#define ITabletContextP_GetPacketDescription(This,ppPD) \
+ ( (This)->lpVtbl -> GetPacketDescription(This,ppPD) )
+
+#define ITabletContextP_GetStatus(This,pdwStatus) \
+ ( (This)->lpVtbl -> GetStatus(This,pdwStatus) )
+
+#define ITabletContextP_GetInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> GetInputRect(This,prcInput) )
+
+#define ITabletContextP_SetInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> SetInputRect(This,prcInput) )
+
+#define ITabletContextP_SetDevInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> SetDevInputRect(This,prcInput) )
+
+#define ITabletContextP_GetDevInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> GetDevInputRect(This,prcInput) )
+
+#define ITabletContextP_SetCapture(This) \
+ ( (This)->lpVtbl -> SetCapture(This) )
+
+#define ITabletContextP_ReleaseCapture(This) \
+ ( (This)->lpVtbl -> ReleaseCapture(This) )
+
+#define ITabletContextP_SetCursorCapture(This,cid) \
+ ( (This)->lpVtbl -> SetCursorCapture(This,cid) )
+
+#define ITabletContextP_ReleaseCursorCapture(This,cid) \
+ ( (This)->lpVtbl -> ReleaseCursorCapture(This,cid) )
+
+#define ITabletContextP_GetPackets(This,nBegin,nEnd,pcPkts,cbPkts,pbPkts,pCid) \
+ ( (This)->lpVtbl -> GetPackets(This,nBegin,nEnd,pcPkts,cbPkts,pbPkts,pCid) )
+
+#define ITabletContextP_PeekPackets(This,nBegin,nEnd,pcPkts,cbPkts,pbPkts,pCid) \
+ ( (This)->lpVtbl -> PeekPackets(This,nBegin,nEnd,pcPkts,cbPkts,pbPkts,pCid) )
+
+#define ITabletContextP_FlushPackets(This,nBegin,nEnd) \
+ ( (This)->lpVtbl -> FlushPackets(This,nBegin,nEnd) )
+
+#define ITabletContextP_FlushQueue(This) \
+ ( (This)->lpVtbl -> FlushQueue(This) )
+
+#define ITabletContextP_GetPacketCount(This,nBegin,nEnd,pcPkts) \
+ ( (This)->lpVtbl -> GetPacketCount(This,nBegin,nEnd,pcPkts) )
+
+#define ITabletContextP_GetPacketQueueInfo(This,pnBegin,pnEnd,pcPkts) \
+ ( (This)->lpVtbl -> GetPacketQueueInfo(This,pnBegin,pnEnd,pcPkts) )
+
+#define ITabletContextP_ForwardPackets(This,nBegin,nEnd) \
+ ( (This)->lpVtbl -> ForwardPackets(This,nBegin,nEnd) )
+
+#define ITabletContextP_InjectPackets(This,cPkts,cbPkts,pbPkts,pCids) \
+ ( (This)->lpVtbl -> InjectPackets(This,cPkts,cbPkts,pbPkts,pCids) )
+
+#define ITabletContextP_ModifyPackets(This,nBegin,nEnd,cbPkts,pbPkts) \
+ ( (This)->lpVtbl -> ModifyPackets(This,nBegin,nEnd,cbPkts,pbPkts) )
+
+#define ITabletContextP_ConvertToScreenCoordinates(This,cPkts,cbPkts,pbPkts,pPointsInScreen) \
+ ( (This)->lpVtbl -> ConvertToScreenCoordinates(This,cPkts,cbPkts,pbPkts,pPointsInScreen) )
+
+
+#define ITabletContextP_Overlap(This,bTop,pdwtcid) \
+ ( (This)->lpVtbl -> Overlap(This,bTop,pdwtcid) )
+
+#define ITabletContextP_GetType(This,pct) \
+ ( (This)->lpVtbl -> GetType(This,pct) )
+
+#define ITabletContextP_TrackInputRect(This,prcInput) \
+ ( (This)->lpVtbl -> TrackInputRect(This,prcInput) )
+
+#define ITabletContextP_IsTopMostHook(This) \
+ ( (This)->lpVtbl -> IsTopMostHook(This) )
+
+#define ITabletContextP_GetEventSink(This,ppSink) \
+ ( (This)->lpVtbl -> GetEventSink(This,ppSink) )
+
+#define ITabletContextP_UseSharedMemoryCommunications(This,pid,phEventMoreData,phEventClientReady,phMutexAccess,phFileMapping) \
+ ( (This)->lpVtbl -> UseSharedMemoryCommunications(This,pid,phEventMoreData,phEventClientReady,phMutexAccess,phFileMapping) )
+
+#define ITabletContextP_UseNamedSharedMemoryCommunications(This,pid,szSid,sdIlSid,pdwEventMoreDataId,pdwEventClientReadyId,pdwMutexAccessId,pdwFileMappingId) \
+ ( (This)->lpVtbl -> UseNamedSharedMemoryCommunications(This,pid,szSid,sdIlSid,pdwEventMoreDataId,pdwEventClientReadyId,pdwMutexAccessId,pdwFileMappingId) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletContextP_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletCursorP_INTERFACE_DEFINED__
+#define __ITabletCursorP_INTERFACE_DEFINED__
+
+/* interface ITabletCursorP */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletCursorP *PTABLETCURSORP;
+
+
+EXTERN_C const IID IID_ITabletCursorP;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("35DE0002-232C-4629-A915-7E600E80CD88")
+ ITabletCursorP : public ITabletCursor
+ {
+ public:
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletCursorPVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletCursorP * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletCursorP * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletCursorP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ ITabletCursorP * This,
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *IsInverted )(
+ ITabletCursorP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetId )(
+ ITabletCursorP * This,
+ /* [out] */ __RPC__out CURSOR_ID *pCid);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetTablet )(
+ ITabletCursorP * This,
+ /* [out] */ __RPC__deref_out_opt ITablet **ppTablet);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetButtonCount )(
+ ITabletCursorP * This,
+ /* [out] */ __RPC__out ULONG *pcButtons);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetButton )(
+ ITabletCursorP * This,
+ /* [in] */ ULONG iButton,
+ /* [out] */ __RPC__deref_out_opt ITabletCursorButton **ppButton);
+
+ END_INTERFACE
+ } ITabletCursorPVtbl;
+
+ interface ITabletCursorP
+ {
+ CONST_VTBL struct ITabletCursorPVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletCursorP_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletCursorP_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletCursorP_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletCursorP_GetName(This,ppwszName) \
+ ( (This)->lpVtbl -> GetName(This,ppwszName) )
+
+#define ITabletCursorP_IsInverted(This) \
+ ( (This)->lpVtbl -> IsInverted(This) )
+
+#define ITabletCursorP_GetId(This,pCid) \
+ ( (This)->lpVtbl -> GetId(This,pCid) )
+
+#define ITabletCursorP_GetTablet(This,ppTablet) \
+ ( (This)->lpVtbl -> GetTablet(This,ppTablet) )
+
+#define ITabletCursorP_GetButtonCount(This,pcButtons) \
+ ( (This)->lpVtbl -> GetButtonCount(This,pcButtons) )
+
+#define ITabletCursorP_GetButton(This,iButton,ppButton) \
+ ( (This)->lpVtbl -> GetButton(This,iButton,ppButton) )
+
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletCursorP_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletCursorButtonP_INTERFACE_DEFINED__
+#define __ITabletCursorButtonP_INTERFACE_DEFINED__
+
+/* interface ITabletCursorButtonP */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletCursorButtonP *PTABLETCURSORBUTTONP;
+
+
+EXTERN_C const IID IID_ITabletCursorButtonP;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("FCA502B0-5409-434d-8C35-A96C76CCA99C")
+ ITabletCursorButtonP : public ITabletCursorButton
+ {
+ public:
+ virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetId(
+ /* [out] */ __RPC__out DWORD *pId) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletCursorButtonPVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletCursorButtonP * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletCursorButtonP * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletCursorButtonP * This);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ ITabletCursorButtonP * This,
+ /* [out] */ __RPC__deref_out_opt LPWSTR *ppwszName);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetGuid )(
+ ITabletCursorButtonP * This,
+ /* [out] */ __RPC__out GUID *pguidBtn);
+
+ /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetId )(
+ ITabletCursorButtonP * This,
+ /* [out] */ __RPC__out DWORD *pId);
+
+ END_INTERFACE
+ } ITabletCursorButtonPVtbl;
+
+ interface ITabletCursorButtonP
+ {
+ CONST_VTBL struct ITabletCursorButtonPVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletCursorButtonP_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletCursorButtonP_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletCursorButtonP_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ITabletCursorButtonP_GetName(This,ppwszName) \
+ ( (This)->lpVtbl -> GetName(This,ppwszName) )
+
+#define ITabletCursorButtonP_GetGuid(This,pguidBtn) \
+ ( (This)->lpVtbl -> GetGuid(This,pguidBtn) )
+
+
+#define ITabletCursorButtonP_GetId(This,pId) \
+ ( (This)->lpVtbl -> GetId(This,pId) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletCursorButtonP_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITabletEventSinkP_INTERFACE_DEFINED__
+#define __ITabletEventSinkP_INTERFACE_DEFINED__
+
+/* interface ITabletEventSinkP */
+/* [unique][helpstring][uuid][object] */
+
+typedef ITabletEventSinkP *PTABLETEVENTSINKP;
+
+
+EXTERN_C const IID IID_ITabletEventSinkP;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("287A9E67-8D1D-4a65-8DB4-51915395D019")
+ ITabletEventSinkP : public IUnknown
+ {
+ public:
+ };
+
+#else /* C style interface */
+
+ typedef struct ITabletEventSinkPVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ITabletEventSinkP * This,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */
+ __RPC__deref_out void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ITabletEventSinkP * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ITabletEventSinkP * This);
+
+ END_INTERFACE
+ } ITabletEventSinkPVtbl;
+
+ interface ITabletEventSinkP
+ {
+ CONST_VTBL struct ITabletEventSinkPVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITabletEventSinkP_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ITabletEventSinkP_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ITabletEventSinkP_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ITabletEventSinkP_INTERFACE_DEFINED__ */
+
+
+/* Additional Prototypes for ALL interfaces */
+
+unsigned long __RPC_USER BSTR_UserSize( unsigned long *, unsigned long , BSTR * );
+unsigned char * __RPC_USER BSTR_UserMarshal( unsigned long *, unsigned char *, BSTR * );
+unsigned char * __RPC_USER BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * );
+void __RPC_USER BSTR_UserFree( unsigned long *, BSTR * );
+
+unsigned long __RPC_USER BSTR_UserSize64( unsigned long *, unsigned long , BSTR * );
+unsigned char * __RPC_USER BSTR_UserMarshal64( unsigned long *, unsigned char *, BSTR * );
+unsigned char * __RPC_USER BSTR_UserUnmarshal64(unsigned long *, unsigned char *, BSTR * );
+void __RPC_USER BSTR_UserFree64( unsigned long *, BSTR * );
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptics_i.c b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptics_i.c
new file mode 100644
index 00000000000..5c3540ba631
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptics_i.c
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+
+/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
+
+/* link this file in with the server and any clients */
+
+
+ /* File created by MIDL compiler version 7.00.0498 */
+/* Compiler settings for wisptics.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#include
+#include
+
+#ifdef _MIDL_USE_GUIDDEF_
+
+#ifndef INITGUID
+#define INITGUID
+#include
+#undef INITGUID
+#else
+#include
+#endif
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
+
+#else // !_MIDL_USE_GUIDDEF_
+
+#ifndef __IID_DEFINED__
+#define __IID_DEFINED__
+
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+#endif // __IID_DEFINED__
+
+#ifndef CLSID_DEFINED
+#define CLSID_DEFINED
+typedef IID CLSID;
+#endif // CLSID_DEFINED
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+
+#endif !_MIDL_USE_GUIDDEF_
+
+MIDL_DEFINE_GUID(IID, IID_ITabletManagerP,0x663C73A5,0x8715,0x4499,0xB8,0x09,0x43,0x68,0x9A,0x93,0x08,0x6B);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletManagerDrt,0xA56AB812,0x2AC7,0x443d,0xA8,0x7A,0xF1,0xEE,0x1C,0xD5,0xA0,0xE6);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletP,0xE65752FA,0x600B,0x43bd,0x8B,0xFE,0x6A,0x68,0x6F,0xA3,0xA2,0x01);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletP2,0xde5d1ed5,0x41d4,0x475d,0xbd,0xd8,0xea,0x74,0x96,0x77,0xb3,0xa1);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletContextP,0x22F74D0A,0x694F,0x4f47,0xA5,0xCE,0xAE,0x08,0xA6,0x40,0x9A,0xC8);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletCursorP,0x35DE0002,0x232C,0x4629,0xA9,0x15,0x7E,0x60,0x0E,0x80,0xCD,0x88);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletCursorButtonP,0xFCA502B0,0x5409,0x434d,0x8C,0x35,0xA9,0x6C,0x76,0xCC,0xA9,0x9C);
+
+
+MIDL_DEFINE_GUID(IID, IID_ITabletEventSinkP,0x287A9E67,0x8D1D,0x4a65,0x8D,0xB4,0x51,0x91,0x53,0x95,0xD0,0x19);
+
+#undef MIDL_DEFINE_GUID
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptis.h b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptis.h
new file mode 100644
index 00000000000..be8bd2e45a6
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptis.h
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 7.00.0498 */
+/* Compiler settings for wisptis.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 500
+#endif
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCSAL_H_VERSION__
+#define __REQUIRED_RPCSAL_H_VERSION__ 100
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of
+#endif // __RPCNDR_H_VERSION__
+
+
+#ifndef __wisptis_h__
+#define __wisptis_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifndef __TabletManagerS_FWD_DEFINED__
+#define __TabletManagerS_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class TabletManagerS TabletManagerS;
+#else
+typedef struct TabletManagerS TabletManagerS;
+#endif /* __cplusplus */
+
+#endif /* __TabletManagerS_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "oaidl.h"
+#include "ocidl.h"
+#include "tpcpen.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+
+#ifndef __WISPTISLib_LIBRARY_DEFINED__
+#define __WISPTISLib_LIBRARY_DEFINED__
+
+/* library WISPTISLib */
+/* [helpstring][version][uuid] */
+
+
+
+
+
+
+
+
+EXTERN_C const IID LIBID_WISPTISLib;
+
+EXTERN_C const CLSID CLSID_TabletManagerS;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("A5B020FD-E04B-4e67-B65A-E7DEED25B2CF")
+TabletManagerS;
+#endif
+#endif /* __WISPTISLib_LIBRARY_DEFINED__ */
+
+/* interface __MIDL_itf_wisptis_0000_0000 */
+/* [local] */
+
+#define SZ_REGKEY_PROFILE TEXT("Software\\Microsoft\\Wisp\\Pen\\Profile")
+
+
+extern RPC_IF_HANDLE __MIDL_itf_wisptis_0000_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_wisptis_0000_0000_v0_0_s_ifspec;
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptis_i.c b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptis_i.c
new file mode 100644
index 00000000000..f3ba1b7a837
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/inc/wisptis_i.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+
+/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
+
+/* link this file in with the server and any clients */
+
+
+ /* File created by MIDL compiler version 7.00.0498 */
+/* Compiler settings for wisptis.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run)
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+//@@MIDL_FILE_HEADING( )
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#include
+#include
+
+#ifdef _MIDL_USE_GUIDDEF_
+
+#ifndef INITGUID
+#define INITGUID
+#include
+#undef INITGUID
+#else
+#include
+#endif
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
+
+#else // !_MIDL_USE_GUIDDEF_
+
+#ifndef __IID_DEFINED__
+#define __IID_DEFINED__
+
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+#endif // __IID_DEFINED__
+
+#ifndef CLSID_DEFINED
+#define CLSID_DEFINED
+typedef IID CLSID;
+#endif // CLSID_DEFINED
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+
+#endif !_MIDL_USE_GUIDDEF_
+
+MIDL_DEFINE_GUID(IID, LIBID_WISPTISLib,0x773F1B9A,0x35B9,0x4E95,0x83,0xA0,0xA2,0x10,0xF2,0xDE,0x3B,0x37);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_TabletManagerS,0xA5B020FD,0xE04B,0x4e67,0xB6,0x5A,0xE7,0xDE,0xED,0x25,0xB2,0xCF);
+
+#undef MIDL_DEFINE_GUID
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/TabLib.vcxproj b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/TabLib.vcxproj
new file mode 100644
index 00000000000..ccc746299f3
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/TabLib.vcxproj
@@ -0,0 +1,49 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+ StaticLibrary
+ false
+
+
+
+ 15.0
+ {8F91EB3A-C530-4CEA-90BF-AFC8165B6456}
+ Win32Proj
+ TabLib
+
+
+
+
+
+
+
+
+ NotUsing
+ %(AdditionalIncludeDirectories);$(WpfSourceDir)PenImc\inc\
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/dir.targets b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/dir.targets
new file mode 100644
index 00000000000..5236e7c6faf
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/dir.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/scope.h b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/scope.h
new file mode 100644
index 00000000000..399a02d3206
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/scope.h
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+#pragma once
+
+template
+class Scope
+{
+ public:
+ Scope() :
+ m_t(P::DefaultValue())
+ {
+ }
+
+ Scope(const T& t) :
+ m_t(t)
+ {
+ }
+
+ ~Scope()
+ {
+ P::Close(m_t);
+ }
+
+ public:
+ T& get()
+ {
+ return m_t;
+ }
+
+ public:
+ operator T()
+ {
+ return m_t;
+ }
+
+ bool operator==(const T& t) const
+ {
+ return m_t == t;
+ }
+
+ bool operator!=(const T& t) const
+ {
+ return m_t != t;
+ }
+
+ private:
+ T m_t;
+
+ private: //not implemented
+ Scope(const Scope& o) {}
+ Scope& operator=(const Scope& o) {}
+};
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/scopes.h b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/scopes.h
new file mode 100644
index 00000000000..ef45551e85c
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/scopes.h
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+#pragma once
+
+#include "scope.h"
+
+template
+class ScopedArrayPolicy
+{
+ public:
+ static T DefaultValue()
+ {
+ return NULL;
+ }
+
+ static void Close(T t)
+ {
+ delete [] t;
+ }
+};
+
+typedef Scope > ScopedString;
+
+template
+class ScopedLocalPolicy
+{
+ public:
+ static T DefaultValue()
+ {
+ return NULL;
+ }
+
+ static void Close(T t)
+ {
+ LocalFree(t);
+ }
+};
+
+typedef Scope > ScopedLocalString;
+
+typedef Scope > ScopedSecurityDescriptor;
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/sidutils.cpp b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/sidutils.cpp
new file mode 100644
index 00000000000..8ac7f722235
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/sidutils.cpp
@@ -0,0 +1,198 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+#include "sidutils.h"
+#include "sddl.h"
+#include
+
+HRESULT
+GetUserSid(__inout LPTSTR* sid)
+{
+ ASSERT(sid != NULL);
+
+ if(sid == NULL)
+ return E_POINTER;
+
+ HRESULT hr = E_FAIL;
+
+ HANDLE hToken = NULL;
+ BOOL bResult = OpenProcessToken(
+ GetCurrentProcess(),
+ TOKEN_QUERY,
+ &hToken);
+
+ if(bResult)
+ {
+ DWORD dwLength = 0;
+ bResult = GetTokenInformation(
+ hToken,
+ TokenUser,
+ NULL,
+ 0,
+ &dwLength);
+
+ if(!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ TOKEN_USER* ptu = (TOKEN_USER*)new char[dwLength];
+
+ if(ptu != NULL)
+ {
+ bResult = GetTokenInformation(
+ hToken,
+ TokenUser,
+ ptu,
+ dwLength,
+ &dwLength);
+
+ if(bResult)
+ {
+ bResult = ConvertSidToStringSid(ptu->User.Sid, sid);
+
+ if(bResult)
+ hr = S_OK;
+ }
+
+ delete [] (char*)ptu;
+ }
+ }
+
+ CloseHandle(hToken);
+ }
+
+ return hr;
+}
+
+
+HRESULT
+GetMandatoryLabel(__inout LPTSTR* sid)
+{
+ ASSERT(sid != NULL);
+
+ if(sid == NULL)
+ return E_POINTER;
+
+ HRESULT hr = E_FAIL;
+
+ HANDLE hToken = NULL;
+ BOOL bResult = OpenProcessToken(
+ GetCurrentProcess(),
+ TOKEN_QUERY,
+ &hToken);
+
+ if(bResult)
+ {
+ DWORD dwLength = 0;
+ bResult = GetTokenInformation(
+ hToken,
+ TokenIntegrityLevel,
+ NULL,
+ 0,
+ &dwLength);
+
+ if(!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ TOKEN_MANDATORY_LABEL* ptml = (TOKEN_MANDATORY_LABEL*)new char[dwLength];
+
+ if(ptml != NULL)
+ {
+ bResult = GetTokenInformation(
+ hToken,
+ TokenIntegrityLevel,
+ ptml,
+ dwLength,
+ &dwLength);
+
+ if(bResult)
+ {
+ bResult = ConvertSidToStringSid(ptml->Label.Sid, sid);
+
+ if(bResult)
+ hr = S_OK;
+ }
+
+ delete [] (char*)ptml;
+ }
+ }
+
+ CloseHandle(hToken);
+ }
+
+ return hr;
+}
+
+HRESULT
+GetLogonSessionSid(__inout LPTSTR* sid)
+{
+ ASSERT(sid != NULL);
+
+ if(sid == NULL)
+ return E_POINTER;
+
+ HRESULT hr = E_FAIL;
+
+ HANDLE hToken = NULL;
+ BOOL bResult = OpenProcessToken(
+ GetCurrentProcess(),
+ TOKEN_QUERY,
+ &hToken);
+
+ if(bResult)
+ {
+ hr = GetLogonSessionSid(hToken, sid);
+ CloseHandle(hToken);
+ }
+
+ return hr;
+}
+
+HRESULT
+GetLogonSessionSid(HANDLE hToken, __inout LPTSTR* sid)
+{
+ ASSERT(sid != NULL);
+
+ if(sid == NULL)
+ return E_POINTER;
+
+ HRESULT hr = E_FAIL;
+
+ DWORD dwLength = 0;
+ BOOL bResult = GetTokenInformation(
+ hToken,
+ TokenLogonSid,
+ NULL,
+ 0,
+ &dwLength);
+
+ if(!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ TOKEN_GROUPS* ptg = (TOKEN_GROUPS*)new char[dwLength];
+
+ if(ptg != NULL)
+ {
+ bResult = GetTokenInformation(
+ hToken,
+ TokenLogonSid,
+ ptg,
+ dwLength,
+ &dwLength);
+
+ if(bResult && ptg->GroupCount == 1)
+ {
+ PSID pSid = ptg->Groups[0].Sid;
+
+ bResult = ConvertSidToStringSid(pSid, sid);
+
+ if(bResult)
+ hr = S_OK;
+ }
+
+ delete [] (char*)ptg;
+ }
+ }
+
+ return hr;
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/sidutils.h b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/sidutils.h
new file mode 100644
index 00000000000..9890afb6299
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PenImc/tablib/sidutils.h
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+#pragma once
+
+#include "windows.h"
+
+// sid must be freed via LocalFree
+HRESULT GetUserSid(__inout LPTSTR* sid);
+HRESULT GetMandatoryLabel(__inout LPTSTR* sid);
+HRESULT GetLogonSessionSid(__inout LPTSTR* sid);
+HRESULT GetLogonSessionSid(HANDLE hToken, __inout LPTSTR* sid);
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TrustManagement/readme.txt b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TrustManagement/readme.txt
deleted file mode 100644
index cc47ba8189e..00000000000
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TrustManagement/readme.txt
+++ /dev/null
@@ -1 +0,0 @@
-TrustManagement files used to live here.