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..c100e79d395 100644
--- a/Microsoft.Dotnet.Wpf.sln
+++ b/Microsoft.Dotnet.Wpf.sln
@@ -159,6 +159,86 @@ 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
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WpfGfx", "WpfGfx", "{B0402399-ECAA-4B09-A35F-847FDE525555}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{69EB6E48-568A-4352-A6DA-A1438781E2AB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\api\api.vcxproj", "{B223A106-1959-4C59-8A8F-844DE370A589}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "av", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\av\av.vcxproj", "{A55F3AC3-B56B-4958-890F-D0EBA02DA390}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\common\common.vcxproj", "{19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wpfgfx", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\dll\wpfgfx.vcxproj", "{875C13F8-C8CF-470C-ADEF-9C63E15E8F34}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{075957B5-C7BD-435C-9DCE-72E20D6BDD81}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicCall", "src\Microsoft.DotNet.Wpf\src\WpfGfx\common\DynamicCall\DynamicCall.vcxproj", "{D57D0AA9-1452-46E6-B105-24A15038566F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "effects", "src\Microsoft.DotNet.Wpf\src\WpfGfx\common\effects\effects.vcxproj", "{904E36D2-A7F7-41D9-8685-E703714C7CAB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scanop", "src\Microsoft.DotNet.Wpf\src\WpfGfx\common\scanop\scanop.vcxproj", "{9AFD2BD4-5662-4004-B29C-5D0085B34506}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "src\Microsoft.DotNet.Wpf\src\WpfGfx\common\shared\shared.vcxproj", "{73F780DF-9216-4691-BB7E-1518878098DB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "util", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\control\util\util.vcxproj", "{51BD2BFD-44C4-431E-A5DB-B4BA6665B672}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fxjit", "fxjit", "{2091594B-341A-45C5-90BD-E6C238BFF4F5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Collector", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\fxjit\Collector\Collector.vcxproj", "{DEC6B122-7619-471F-A87E-F594E011C059}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Compiler", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\fxjit\Compiler\Compiler.vcxproj", "{AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PixelShader", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\fxjit\PixelShader\PixelShader.vcxproj", "{C1C84336-C109-433C-A439-3C17BDC7585E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Platform", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\fxjit\Platform\Platform.vcxproj", "{129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Geometry", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\geometry\Geometry.vcxproj", "{C5391057-4B69-4560-AC30-D269D862A5B2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glyph", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\glyph\glyph.vcxproj", "{11B3469F-3D04-40E2-B322-32B1D29F4A6F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hw", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\hw\hw.vcxproj", "{A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "meta", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\meta\meta.vcxproj", "{A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "resources", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\resources\resources.vcxproj", "{B3E8407E-5529-456F-9039-EDCC65E1C2DC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sw", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\sw\swlib\sw.vcxproj", "{CC977117-523F-48B7-B012-01E61B1F8328}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "targets", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\targets\targets.vcxproj", "{4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uce", "src\Microsoft.DotNet.Wpf\src\WpfGfx\core\uce\uce.vcxproj", "{D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{465213EF-515F-4272-AB70-A6FB5A7E73D3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DebugLib", "src\Microsoft.DotNet.Wpf\src\WpfGfx\shared\debug\DebugLib\DebugLib.vcxproj", "{AC8E779F-C95F-4855-839D-25EFA1651337}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllUtil", "src\Microsoft.DotNet.Wpf\src\WpfGfx\shared\util\DllUtil\DllUtil.vcxproj", "{73BC0730-8D78-495D-A7F6-D2C45C268D0F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UtilLib", "src\Microsoft.DotNet.Wpf\src\WpfGfx\shared\util\UtilLib\UtilLib.vcxproj", "{B802113C-EA89-406C-9AF1-9808CAA0F0AD}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{7EE0E965-7DA4-4A94-9441-801E8D2CC1CD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OSVersionHelper", "src\Microsoft.DotNet.Wpf\src\Shared\OSVersionHelper\OSVersionHelper.vcxproj", "{3801B5AE-6871-4A72-B400-1F6ABCBF9045}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PresentationNative", "src\Microsoft.DotNet.Wpf\redist\PresentationNative\PresentationNative.vcxproj", "{AF9084C3-BF37-4A56-A851-89F3BAE731B3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -925,24 +1005,570 @@ 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|x64.Deploy.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|x64.Deploy.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|x64.Deploy.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|x64.Deploy.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|x64.Deploy.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|x64.Deploy.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|x64.Deploy.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|x64.Deploy.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
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|Any CPU.Build.0 = Debug|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|x64.ActiveCfg = Debug|x64
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|x64.Build.0 = Debug|x64
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|x64.Deploy.0 = Debug|x64
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|x86.ActiveCfg = Debug|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|x86.Build.0 = Debug|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Debug|x86.Deploy.0 = Debug|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|Any CPU.ActiveCfg = Release|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|Any CPU.Build.0 = Release|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|Any CPU.Deploy.0 = Release|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|x64.ActiveCfg = Release|x64
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|x64.Build.0 = Release|x64
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|x64.Deploy.0 = Release|x64
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|x86.ActiveCfg = Release|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|x86.Build.0 = Release|Win32
+ {B223A106-1959-4C59-8A8F-844DE370A589}.Release|x86.Deploy.0 = Release|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|Any CPU.Build.0 = Debug|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|x64.ActiveCfg = Debug|x64
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|x64.Build.0 = Debug|x64
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|x64.Deploy.0 = Debug|x64
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|x86.ActiveCfg = Debug|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|x86.Build.0 = Debug|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Debug|x86.Deploy.0 = Debug|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|Any CPU.ActiveCfg = Release|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|Any CPU.Build.0 = Release|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|Any CPU.Deploy.0 = Release|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|x64.ActiveCfg = Release|x64
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|x64.Build.0 = Release|x64
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|x64.Deploy.0 = Release|x64
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|x86.ActiveCfg = Release|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|x86.Build.0 = Release|Win32
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390}.Release|x86.Deploy.0 = Release|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|Any CPU.Build.0 = Debug|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|x64.ActiveCfg = Debug|x64
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|x64.Build.0 = Debug|x64
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|x64.Deploy.0 = Debug|x64
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|x86.ActiveCfg = Debug|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|x86.Build.0 = Debug|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Debug|x86.Deploy.0 = Debug|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|Any CPU.ActiveCfg = Release|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|Any CPU.Build.0 = Release|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|Any CPU.Deploy.0 = Release|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|x64.ActiveCfg = Release|x64
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|x64.Build.0 = Release|x64
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|x64.Deploy.0 = Release|x64
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|x86.ActiveCfg = Release|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|x86.Build.0 = Release|Win32
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D}.Release|x86.Deploy.0 = Release|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|Any CPU.Build.0 = Debug|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|x64.ActiveCfg = Debug|x64
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|x64.Build.0 = Debug|x64
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|x64.Deploy.0 = Debug|x64
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|x86.ActiveCfg = Debug|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|x86.Build.0 = Debug|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Debug|x86.Deploy.0 = Debug|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|Any CPU.ActiveCfg = Release|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|Any CPU.Build.0 = Release|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|Any CPU.Deploy.0 = Release|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|x64.ActiveCfg = Release|x64
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|x64.Build.0 = Release|x64
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|x64.Deploy.0 = Release|x64
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|x86.ActiveCfg = Release|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|x86.Build.0 = Release|Win32
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34}.Release|x86.Deploy.0 = Release|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|Any CPU.Build.0 = Debug|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|x64.ActiveCfg = Debug|x64
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|x64.Build.0 = Debug|x64
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|x64.Deploy.0 = Debug|x64
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|x86.ActiveCfg = Debug|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|x86.Build.0 = Debug|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Debug|x86.Deploy.0 = Debug|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|Any CPU.ActiveCfg = Release|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|Any CPU.Build.0 = Release|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|Any CPU.Deploy.0 = Release|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|x64.ActiveCfg = Release|x64
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|x64.Build.0 = Release|x64
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|x64.Deploy.0 = Release|x64
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|x86.ActiveCfg = Release|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|x86.Build.0 = Release|Win32
+ {D57D0AA9-1452-46E6-B105-24A15038566F}.Release|x86.Deploy.0 = Release|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Debug|Any CPU.Build.0 = Debug|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Debug|x64.ActiveCfg = Debug|x64
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Debug|x64.Build.0 = Debug|x64
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Debug|x64.Deploy.0 = Debug|x64
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Debug|x86.ActiveCfg = Debug|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Debug|x86.Build.0 = Debug|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Debug|x86.Deploy.0 = Debug|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|Any CPU.ActiveCfg = Release|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|Any CPU.Build.0 = Release|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|Any CPU.Deploy.0 = Release|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|x64.ActiveCfg = Release|x64
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|x64.Build.0 = Release|x64
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|x64.Deploy.0 = Release|x64
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|x86.ActiveCfg = Release|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|x86.Build.0 = Release|Win32
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB}.Release|x86.Deploy.0 = Release|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|Any CPU.Build.0 = Debug|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|x64.ActiveCfg = Debug|x64
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|x64.Build.0 = Debug|x64
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|x64.Deploy.0 = Debug|x64
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|x86.ActiveCfg = Debug|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|x86.Build.0 = Debug|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Debug|x86.Deploy.0 = Debug|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|Any CPU.ActiveCfg = Release|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|Any CPU.Build.0 = Release|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|Any CPU.Deploy.0 = Release|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|x64.ActiveCfg = Release|x64
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|x64.Build.0 = Release|x64
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|x64.Deploy.0 = Release|x64
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|x86.ActiveCfg = Release|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|x86.Build.0 = Release|Win32
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506}.Release|x86.Deploy.0 = Release|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|Any CPU.Build.0 = Debug|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|x64.ActiveCfg = Debug|x64
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|x64.Build.0 = Debug|x64
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|x64.Deploy.0 = Debug|x64
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|x86.ActiveCfg = Debug|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|x86.Build.0 = Debug|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Debug|x86.Deploy.0 = Debug|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|Any CPU.ActiveCfg = Release|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|Any CPU.Build.0 = Release|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|Any CPU.Deploy.0 = Release|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|x64.ActiveCfg = Release|x64
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|x64.Build.0 = Release|x64
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|x64.Deploy.0 = Release|x64
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|x86.ActiveCfg = Release|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|x86.Build.0 = Release|Win32
+ {73F780DF-9216-4691-BB7E-1518878098DB}.Release|x86.Deploy.0 = Release|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|Any CPU.Build.0 = Debug|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|x64.ActiveCfg = Debug|x64
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|x64.Build.0 = Debug|x64
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|x64.Deploy.0 = Debug|x64
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|x86.ActiveCfg = Debug|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|x86.Build.0 = Debug|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Debug|x86.Deploy.0 = Debug|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|Any CPU.ActiveCfg = Release|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|Any CPU.Build.0 = Release|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|Any CPU.Deploy.0 = Release|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|x64.ActiveCfg = Release|x64
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|x64.Build.0 = Release|x64
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|x64.Deploy.0 = Release|x64
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|x86.ActiveCfg = Release|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|x86.Build.0 = Release|Win32
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672}.Release|x86.Deploy.0 = Release|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|Any CPU.Build.0 = Debug|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|x64.ActiveCfg = Debug|x64
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|x64.Build.0 = Debug|x64
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|x64.Deploy.0 = Debug|x64
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|x86.ActiveCfg = Debug|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|x86.Build.0 = Debug|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Debug|x86.Deploy.0 = Debug|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|Any CPU.ActiveCfg = Release|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|Any CPU.Build.0 = Release|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|Any CPU.Deploy.0 = Release|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|x64.ActiveCfg = Release|x64
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|x64.Build.0 = Release|x64
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|x64.Deploy.0 = Release|x64
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|x86.ActiveCfg = Release|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|x86.Build.0 = Release|Win32
+ {DEC6B122-7619-471F-A87E-F594E011C059}.Release|x86.Deploy.0 = Release|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|Any CPU.Build.0 = Debug|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|x64.ActiveCfg = Debug|x64
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|x64.Build.0 = Debug|x64
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|x64.Deploy.0 = Debug|x64
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|x86.ActiveCfg = Debug|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|x86.Build.0 = Debug|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Debug|x86.Deploy.0 = Debug|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|Any CPU.ActiveCfg = Release|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|Any CPU.Build.0 = Release|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|Any CPU.Deploy.0 = Release|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|x64.ActiveCfg = Release|x64
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|x64.Build.0 = Release|x64
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|x64.Deploy.0 = Release|x64
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|x86.ActiveCfg = Release|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|x86.Build.0 = Release|Win32
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8}.Release|x86.Deploy.0 = Release|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|Any CPU.Build.0 = Debug|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|x64.ActiveCfg = Debug|x64
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|x64.Build.0 = Debug|x64
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|x64.Deploy.0 = Debug|x64
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|x86.ActiveCfg = Debug|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|x86.Build.0 = Debug|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Debug|x86.Deploy.0 = Debug|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|Any CPU.ActiveCfg = Release|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|Any CPU.Build.0 = Release|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|Any CPU.Deploy.0 = Release|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|x64.ActiveCfg = Release|x64
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|x64.Build.0 = Release|x64
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|x64.Deploy.0 = Release|x64
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|x86.ActiveCfg = Release|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|x86.Build.0 = Release|Win32
+ {C1C84336-C109-433C-A439-3C17BDC7585E}.Release|x86.Deploy.0 = Release|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|Any CPU.Build.0 = Debug|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|x64.ActiveCfg = Debug|x64
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|x64.Build.0 = Debug|x64
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|x64.Deploy.0 = Debug|x64
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|x86.ActiveCfg = Debug|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|x86.Build.0 = Debug|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Debug|x86.Deploy.0 = Debug|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|Any CPU.ActiveCfg = Release|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|Any CPU.Build.0 = Release|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|Any CPU.Deploy.0 = Release|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|x64.ActiveCfg = Release|x64
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|x64.Build.0 = Release|x64
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|x64.Deploy.0 = Release|x64
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|x86.ActiveCfg = Release|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|x86.Build.0 = Release|Win32
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC}.Release|x86.Deploy.0 = Release|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|Any CPU.Build.0 = Debug|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|x64.ActiveCfg = Debug|x64
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|x64.Build.0 = Debug|x64
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|x64.Deploy.0 = Debug|x64
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|x86.ActiveCfg = Debug|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|x86.Build.0 = Debug|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Debug|x86.Deploy.0 = Debug|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|Any CPU.ActiveCfg = Release|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|Any CPU.Build.0 = Release|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|Any CPU.Deploy.0 = Release|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|x64.ActiveCfg = Release|x64
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|x64.Build.0 = Release|x64
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|x64.Deploy.0 = Release|x64
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|x86.ActiveCfg = Release|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|x86.Build.0 = Release|Win32
+ {C5391057-4B69-4560-AC30-D269D862A5B2}.Release|x86.Deploy.0 = Release|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|Any CPU.Build.0 = Debug|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|x64.ActiveCfg = Debug|x64
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|x64.Build.0 = Debug|x64
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|x64.Deploy.0 = Debug|x64
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|x86.ActiveCfg = Debug|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|x86.Build.0 = Debug|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Debug|x86.Deploy.0 = Debug|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|Any CPU.ActiveCfg = Release|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|Any CPU.Build.0 = Release|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|Any CPU.Deploy.0 = Release|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|x64.ActiveCfg = Release|x64
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|x64.Build.0 = Release|x64
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|x64.Deploy.0 = Release|x64
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|x86.ActiveCfg = Release|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|x86.Build.0 = Release|Win32
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F}.Release|x86.Deploy.0 = Release|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|Any CPU.Build.0 = Debug|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|x64.ActiveCfg = Debug|x64
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|x64.Build.0 = Debug|x64
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|x64.Deploy.0 = Debug|x64
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|x86.ActiveCfg = Debug|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|x86.Build.0 = Debug|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Debug|x86.Deploy.0 = Debug|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|Any CPU.ActiveCfg = Release|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|Any CPU.Build.0 = Release|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|Any CPU.Deploy.0 = Release|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|x64.ActiveCfg = Release|x64
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|x64.Build.0 = Release|x64
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|x64.Deploy.0 = Release|x64
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|x86.ActiveCfg = Release|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|x86.Build.0 = Release|Win32
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35}.Release|x86.Deploy.0 = Release|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|Any CPU.Build.0 = Debug|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|x64.ActiveCfg = Debug|x64
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|x64.Build.0 = Debug|x64
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|x64.Deploy.0 = Debug|x64
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|x86.ActiveCfg = Debug|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|x86.Build.0 = Debug|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Debug|x86.Deploy.0 = Debug|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|Any CPU.ActiveCfg = Release|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|Any CPU.Build.0 = Release|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|Any CPU.Deploy.0 = Release|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|x64.ActiveCfg = Release|x64
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|x64.Build.0 = Release|x64
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|x64.Deploy.0 = Release|x64
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|x86.ActiveCfg = Release|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|x86.Build.0 = Release|Win32
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE}.Release|x86.Deploy.0 = Release|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|Any CPU.Build.0 = Debug|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|x64.ActiveCfg = Debug|x64
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|x64.Build.0 = Debug|x64
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|x64.Deploy.0 = Debug|x64
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|x86.ActiveCfg = Debug|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|x86.Build.0 = Debug|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Debug|x86.Deploy.0 = Debug|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|Any CPU.ActiveCfg = Release|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|Any CPU.Build.0 = Release|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|Any CPU.Deploy.0 = Release|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|x64.ActiveCfg = Release|x64
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|x64.Build.0 = Release|x64
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|x64.Deploy.0 = Release|x64
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|x86.ActiveCfg = Release|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|x86.Build.0 = Release|Win32
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC}.Release|x86.Deploy.0 = Release|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|Any CPU.Build.0 = Debug|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|x64.ActiveCfg = Debug|x64
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|x64.Build.0 = Debug|x64
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|x64.Deploy.0 = Debug|x64
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|x86.ActiveCfg = Debug|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|x86.Build.0 = Debug|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Debug|x86.Deploy.0 = Debug|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|Any CPU.ActiveCfg = Release|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|Any CPU.Build.0 = Release|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|Any CPU.Deploy.0 = Release|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|x64.ActiveCfg = Release|x64
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|x64.Build.0 = Release|x64
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|x64.Deploy.0 = Release|x64
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|x86.ActiveCfg = Release|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|x86.Build.0 = Release|Win32
+ {CC977117-523F-48B7-B012-01E61B1F8328}.Release|x86.Deploy.0 = Release|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|Any CPU.Build.0 = Debug|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|x64.ActiveCfg = Debug|x64
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|x64.Build.0 = Debug|x64
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|x64.Deploy.0 = Debug|x64
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|x86.ActiveCfg = Debug|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|x86.Build.0 = Debug|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Debug|x86.Deploy.0 = Debug|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|Any CPU.ActiveCfg = Release|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|Any CPU.Build.0 = Release|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|Any CPU.Deploy.0 = Release|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|x64.ActiveCfg = Release|x64
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|x64.Build.0 = Release|x64
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|x64.Deploy.0 = Release|x64
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|x86.ActiveCfg = Release|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|x86.Build.0 = Release|Win32
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5}.Release|x86.Deploy.0 = Release|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|Any CPU.Build.0 = Debug|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|x64.ActiveCfg = Debug|x64
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|x64.Build.0 = Debug|x64
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|x64.Deploy.0 = Debug|x64
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|x86.ActiveCfg = Debug|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|x86.Build.0 = Debug|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Debug|x86.Deploy.0 = Debug|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|Any CPU.ActiveCfg = Release|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|Any CPU.Build.0 = Release|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|Any CPU.Deploy.0 = Release|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|x64.ActiveCfg = Release|x64
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|x64.Build.0 = Release|x64
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|x64.Deploy.0 = Release|x64
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|x86.ActiveCfg = Release|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|x86.Build.0 = Release|Win32
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84}.Release|x86.Deploy.0 = Release|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|Any CPU.Build.0 = Debug|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|x64.ActiveCfg = Debug|x64
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|x64.Build.0 = Debug|x64
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|x64.Deploy.0 = Debug|x64
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|x86.ActiveCfg = Debug|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|x86.Build.0 = Debug|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Debug|x86.Deploy.0 = Debug|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|Any CPU.ActiveCfg = Release|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|Any CPU.Build.0 = Release|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|Any CPU.Deploy.0 = Release|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|x64.ActiveCfg = Release|x64
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|x64.Build.0 = Release|x64
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|x64.Deploy.0 = Release|x64
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|x86.ActiveCfg = Release|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|x86.Build.0 = Release|Win32
+ {AC8E779F-C95F-4855-839D-25EFA1651337}.Release|x86.Deploy.0 = Release|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|Any CPU.Build.0 = Debug|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|x64.ActiveCfg = Debug|x64
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|x64.Build.0 = Debug|x64
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|x64.Deploy.0 = Debug|x64
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|x86.ActiveCfg = Debug|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|x86.Build.0 = Debug|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Debug|x86.Deploy.0 = Debug|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|Any CPU.ActiveCfg = Release|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|Any CPU.Build.0 = Release|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|Any CPU.Deploy.0 = Release|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|x64.ActiveCfg = Release|x64
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|x64.Build.0 = Release|x64
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|x64.Deploy.0 = Release|x64
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|x86.ActiveCfg = Release|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|x86.Build.0 = Release|Win32
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F}.Release|x86.Deploy.0 = Release|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|Any CPU.Build.0 = Debug|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|x64.ActiveCfg = Debug|x64
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|x64.Build.0 = Debug|x64
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|x64.Deploy.0 = Debug|x64
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|x86.ActiveCfg = Debug|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|x86.Build.0 = Debug|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Debug|x86.Deploy.0 = Debug|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|Any CPU.ActiveCfg = Release|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|Any CPU.Build.0 = Release|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|Any CPU.Deploy.0 = Release|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|x64.ActiveCfg = Release|x64
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|x64.Build.0 = Release|x64
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|x64.Deploy.0 = Release|x64
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|x86.ActiveCfg = Release|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|x86.Build.0 = Release|Win32
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD}.Release|x86.Deploy.0 = Release|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Debug|Any CPU.Build.0 = Debug|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {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|x64.Deploy.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}.Debug|x86.Deploy.0 = Debug|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|Any CPU.ActiveCfg = Release|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|Any CPU.Build.0 = Release|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|Any CPU.Deploy.0 = Release|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|x64.Deploy.0 = Release|x64
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x86.ActiveCfg = Release|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x86.Build.0 = Release|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x86.Deploy.0 = Release|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Debug|Any CPU.Build.0 = Debug|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Debug|Any CPU.Deploy.0 = Debug|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Debug|x64.ActiveCfg = Debug|x64
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Debug|x64.Build.0 = Debug|x64
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Debug|x86.ActiveCfg = Debug|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Debug|x86.Build.0 = Debug|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Debug|x86.Deploy.0 = Debug|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Release|Any CPU.ActiveCfg = Release|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Release|Any CPU.Build.0 = Release|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Release|Any CPU.Deploy.0 = Release|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Release|x64.ActiveCfg = Release|x64
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Release|x64.Build.0 = Release|x64
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Release|x86.ActiveCfg = Release|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.Release|x86.Build.0 = Release|Win32
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3}.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 +1597,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 +1609,55 @@ 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}
+ {B0402399-ECAA-4B09-A35F-847FDE525555} = {4557C5C6-10B1-475C-8279-5511955D1C29}
+ {69EB6E48-568A-4352-A6DA-A1438781E2AB} = {B0402399-ECAA-4B09-A35F-847FDE525555}
+ {B223A106-1959-4C59-8A8F-844DE370A589} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {A55F3AC3-B56B-4958-890F-D0EBA02DA390} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {19F853CB-C936-40BE-8F9D-E6BED3CF8A3D} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {875C13F8-C8CF-470C-ADEF-9C63E15E8F34} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {075957B5-C7BD-435C-9DCE-72E20D6BDD81} = {B0402399-ECAA-4B09-A35F-847FDE525555}
+ {D57D0AA9-1452-46E6-B105-24A15038566F} = {075957B5-C7BD-435C-9DCE-72E20D6BDD81}
+ {904E36D2-A7F7-41D9-8685-E703714C7CAB} = {075957B5-C7BD-435C-9DCE-72E20D6BDD81}
+ {9AFD2BD4-5662-4004-B29C-5D0085B34506} = {075957B5-C7BD-435C-9DCE-72E20D6BDD81}
+ {73F780DF-9216-4691-BB7E-1518878098DB} = {075957B5-C7BD-435C-9DCE-72E20D6BDD81}
+ {51BD2BFD-44C4-431E-A5DB-B4BA6665B672} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {2091594B-341A-45C5-90BD-E6C238BFF4F5} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {DEC6B122-7619-471F-A87E-F594E011C059} = {2091594B-341A-45C5-90BD-E6C238BFF4F5}
+ {AE5D4CFE-D301-49E0-AA6B-E22F07238BA8} = {2091594B-341A-45C5-90BD-E6C238BFF4F5}
+ {C1C84336-C109-433C-A439-3C17BDC7585E} = {2091594B-341A-45C5-90BD-E6C238BFF4F5}
+ {129BEEA2-3636-49EE-B38C-8A72C0C8C5EC} = {2091594B-341A-45C5-90BD-E6C238BFF4F5}
+ {C5391057-4B69-4560-AC30-D269D862A5B2} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {11B3469F-3D04-40E2-B322-32B1D29F4A6F} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {A27AF0F3-CA2A-42CF-A962-A3F3B0E83D35} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {A97154B3-D1CB-4CE3-8A4D-D985C7571CFE} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {B3E8407E-5529-456F-9039-EDCC65E1C2DC} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {CC977117-523F-48B7-B012-01E61B1F8328} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {4ED31E2C-BB2C-4888-8725-6BB7527ED0C5} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {D5E56AF3-EA01-49EC-BEB1-1BB6BB272A84} = {69EB6E48-568A-4352-A6DA-A1438781E2AB}
+ {465213EF-515F-4272-AB70-A6FB5A7E73D3} = {B0402399-ECAA-4B09-A35F-847FDE525555}
+ {AC8E779F-C95F-4855-839D-25EFA1651337} = {465213EF-515F-4272-AB70-A6FB5A7E73D3}
+ {73BC0730-8D78-495D-A7F6-D2C45C268D0F} = {465213EF-515F-4272-AB70-A6FB5A7E73D3}
+ {B802113C-EA89-406C-9AF1-9808CAA0F0AD} = {465213EF-515F-4272-AB70-A6FB5A7E73D3}
+ {7EE0E965-7DA4-4A94-9441-801E8D2CC1CD} = {4557C5C6-10B1-475C-8279-5511955D1C29}
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045} = {7EE0E965-7DA4-4A94-9441-801E8D2CC1CD}
+ {AF9084C3-BF37-4A56-A851-89F3BAE731B3} = {DDED00A7-24FD-4AEF-B264-2150F0E59B4D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B4340004-DAC0-497D-B69D-CFA7CD93F567}
diff --git a/NuGet.config b/NuGet.config
index 18346d30a11..cd911f3d27b 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -7,6 +7,7 @@
+
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 44e3f8c6bcd..6473e9ca5b7 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -38,6 +38,7 @@ trigger:
- release/3.0
- release/3.0-preview9
- release/3.1
+ - experimental/*
# - arcade
paths:
exclude:
@@ -53,6 +54,7 @@ pr:
- internal/release/3.*
- release/3.1
- internal/release/*
+ - experimental/*
paths:
exclude:
- Documentation/*
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index f15ef4980c2..bdc1bb84e6f 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,89 +1,85 @@
-
+
https://github.com/dotnet/winforms
- 0d9f2f88ddb3bccf9da205fba24c7bac8dfd42f9
+ 8818624e86a7aa64dbcd06fe78e406fa8caf008a
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
- https://github.com/dotnet/core-setup
- 4ace84dbf94128b4825c76cdd09b46dba7473478
-
-
+
https://github.com/dotnet/arcade
- 56e162725058d80918f7aa7e0e689e1fde5c2106
+ 8fed91a4435cae29ab0f0e4f18a291cd38b0f23e
-
+
https://github.com/dotnet/arcade
- 56e162725058d80918f7aa7e0e689e1fde5c2106
+ 8fed91a4435cae29ab0f0e4f18a291cd38b0f23e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-wpf-int
- 109547474d0f0044343f9bb392597013f61790cc
+ 938955fce440d685530393579f95ca8cefc24095
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
-
+
https://github.com/dotnet/coreclr
b415b57a15b0c6ba77e63df901823bb46b8aafda
@@ -95,21 +91,25 @@
https://github.com/dotnet/coreclr
b415b57a15b0c6ba77e63df901823bb46b8aafda
-
+
https://github.com/dotnet/arcade
- 56e162725058d80918f7aa7e0e689e1fde5c2106
+ 8fed91a4435cae29ab0f0e4f18a291cd38b0f23e
-
+
https://github.com/dotnet/arcade
- 56e162725058d80918f7aa7e0e689e1fde5c2106
+ 8fed91a4435cae29ab0f0e4f18a291cd38b0f23e
-
+
https://github.com/dotnet/arcade
- 56e162725058d80918f7aa7e0e689e1fde5c2106
+ 8fed91a4435cae29ab0f0e4f18a291cd38b0f23e
-
+
https://github.com/dotnet/corefx
8d21b79b924d29088dbde46d42737a657d466b5e
+
+ https://github.com/dotnet/core-setup
+ 4ace84dbf94128b4825c76cdd09b46dba7473478
+
diff --git a/eng/Versions.props b/eng/Versions.props
index bb6681c7c32..15e5ba7bb1b 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -19,7 +19,7 @@
- 5.0.0-alpha1.19514.1
+ 5.0.0-alpha1.19514.1
5.0.0-alpha1.19512.1
5.0.0-alpha1.19512.1
5.0.0-alpha1.19512.1
@@ -41,9 +41,9 @@
- 5.0.0-beta.20110.11
- 5.0.0-beta.20110.11
- 5.0.0-beta.20110.11
+ 5.0.0-beta.20110.5
+ 5.0.0-beta.20110.5
+ 5.0.0-beta.20110.5
@@ -96,26 +96,7 @@
System.IO.Packaging
System.Reflection.MetadataLoadContext
-
- 5.0.0-preview.1.20111.2
+ 5.0.0-preview.1.20111.15
diff --git a/eng/WpfArcadeSdk/tools/ShippingProjects.props b/eng/WpfArcadeSdk/tools/ShippingProjects.props
index f6af7da3698..4cff4856c0f 100644
--- a/eng/WpfArcadeSdk/tools/ShippingProjects.props
+++ b/eng/WpfArcadeSdk/tools/ShippingProjects.props
@@ -29,21 +29,22 @@
PresentationFramework.Luna;
PresentationFramework.Royale;
WindowsFormsIntegration;
+ PenImc;
+ wpfgfx;
+ D3DCompiler;
+ VCRuntime
$(InternalShippingLibProjects);
+ bilinearspan
-
+
$(InternalShippingLibProjects);
- PenImc;
PresentationNative;
- WpfGfx;
- D3DCompiler;
- VCRuntime
-
+
$(ExternalShippingProjects);
$(InternalShippingProjects)
diff --git a/global.json b/global.json
index 188ed4b79c5..a8113daf9a1 100644
--- a/global.json
+++ b/global.json
@@ -4,7 +4,7 @@
"runtimes": {
"dotnet": [
"2.1.7",
- "$(MicrosoftNETCoreAppVersion)"
+ "$(MicrosoftNetCoreAppInternalVersion)"
]
},
"vs": {
@@ -12,8 +12,8 @@
}
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20110.11",
- "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20110.11"
+ "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20110.5",
+ "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20110.5"
},
"native-tools": {
"strawberry-perl": "5.28.1.1-1",
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/PresentationNative/PresentationNative.vcxproj b/src/Microsoft.DotNet.Wpf/redist/PresentationNative/PresentationNative.vcxproj
new file mode 100644
index 00000000000..1e9872632c8
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/redist/PresentationNative/PresentationNative.vcxproj
@@ -0,0 +1,82 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ DynamicLibrary
+ false
+
+
+
+
+
+ External
+
+
+
+
+
+
+ PresentationNative$(WpfVersionSuffix)
+ 16.0
+ {af9084c3-bf37-4a56-a851-89f3bae731b3}
+ Win32Proj
+
+
+
+
+
+
+ <_PresentationNative Include="$(TargetName)" />
+
+
+
+
+
+
+ <_PresentationNativeFilePaths Include="@(_PresentationNativeFiles->'%(FilePath)')" />
+
+ <_PresentationNativeDll Include="@(_PresentationNativeFilePaths)"
+ Condition="'%(_PresentationNativeFilePaths.Extension)'=='.dll'"/>
+
+ <_PresentationNativePdb Include="@(_PresentationNativeFilePaths)"
+ Condition="'%(_PresentationNativeFilePaths.Extension)'=='.pdb'"/>
+
+
+
+
+ @(_PresentationNativeDll)
+
+
+
+
+
+ $([System.IO.Path]::GetDirectoryName(`$(TargetPath)`))
+
+
+
+
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.
diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/OSVersionHelper.sln b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/OSVersionHelper.sln
new file mode 100644
index 00000000000..756fe5fa99b
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/OSVersionHelper.sln
@@ -0,0 +1,33 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28406.54
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OSVersionHelper", "OSVersionHelper.vcxproj", "{3801B5AE-6871-4A72-B400-1F6ABCBF9045}"
+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|x64.Deploy.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|x64.Deploy.0 = Release|x64
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x86.ActiveCfg = Release|Win32
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {41E29FDE-533E-46AF-A13A-D7EDF663BB41}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/OSVersionHelper.vcxproj b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/OSVersionHelper.vcxproj
new file mode 100644
index 00000000000..bbffbcb7e3e
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/OSVersionHelper.vcxproj
@@ -0,0 +1,46 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+ 15.0
+ {3801B5AE-6871-4A72-B400-1F6ABCBF9045}
+ Win32Proj
+ OSVersionHelper
+ StaticLibrary
+
+
+
+
+
+
+
+
+
+ NotUsing
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/osversionhelper.cpp b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/osversionhelper.cpp
new file mode 100644
index 00000000000..1cc927d3213
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/osversionhelper.cpp
@@ -0,0 +1,205 @@
+// 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 "wpfntddk.h"
+#include "wpfsdkddkver.h"
+#include "osversionhelper.h"
+
+// Adding a new OS
+// See in the Windows SDK and re-use the appropriate code from there.
+// See OperatingSystemVersion.cs for instructions on porting to managed checks
+
+
+bool WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(ULONG wMajorVersion, ULONG wMinorVersion, USHORT wServicePackMajor, ULONG wBuildNumber)
+{
+ RTL_OSVERSIONINFOEXW osvi =
+ {
+ sizeof(osvi), // dwOSVersionInfoSize
+ wMajorVersion, // dwMajorVersion
+ wMinorVersion, // dwMinorVersion
+ wBuildNumber, // dwBuildNumber
+ 0, // dwPlatformId
+ { 0 }, // szCSDVersion[128]
+ wServicePackMajor, // wServicePackMajor
+ 0, // wServicePackMinor
+ 0, // wSuiteMask
+ 0, // wProductType
+ 0 // wReserved
+ };
+
+ ULONGLONG dwlConditionMask = 0;
+ VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+
+ auto dwFlags = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
+
+ if (wBuildNumber > 0)
+ {
+ VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
+ dwFlags |= VER_BUILDNUMBER;
+ }
+
+ return RtlVerifyVersionInfo(&osvi, dwFlags, dwlConditionMask) == STATUS_SUCCESS;
+}
+
+bool WPFUtils::OSVersionHelper::IsWindowsXPOrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindowsXPSP1OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindowsXPSP2OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindowsXPSP3OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindowsVistaOrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindowsVistaSP1OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindowsVistaSP2OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows7OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows7SP1OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows8OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows8Point1OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows10OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows10TH1OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, _TH1_BUILD_NUMBER);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows10TH2OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, _TH2_BUILD_NUMBER);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows10RS1OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, _RS1_BUILD_NUMBER);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows10RS2OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, _RS2_BUILD_NUMBER);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows10RS3OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, _RS3_BUILD_NUMBER);
+}
+
+bool WPFUtils::OSVersionHelper::IsWindows10RS5OrGreater()
+{
+ return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, _RS5_BUILD_NUMBER);
+}
+
+// This function is a template for checking the version for an unreleased version of Windows via a strictly greater than comparison from the previous known build.
+//bool WPFUtils::OSVersionHelper::IsWindows1019H1OrGreater()
+//{
+// //
+// // 19H1 will have a build number strictly greater than _RS5_BUILD_NUMBER.
+// // Once the precise build number for 19H1 is known at/after RTM, this method should be updated to
+// // something like this:
+// //
+// // return WPFUtils::OSVersionHelper::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, _19H1_BUILD_NUMBER);
+// //
+//
+// ULONG wMajorVersion = HIBYTE(_WIN32_WINNT_WIN10);
+// ULONG wMinorVersion = LOBYTE(_WIN32_WINNT_WIN10);
+// USHORT wServicePackMajor = 0;
+// ULONG wBuildNumber = _RS5_BUILD_NUMBER;
+//
+// RTL_OSVERSIONINFOEXW osvi =
+// {
+// sizeof(osvi), // dwOSVersionInfoSize
+// wMajorVersion, // dwMajorVersion
+// wMinorVersion, // dwMinorVersion
+// wBuildNumber, // dwBuildNumber
+// 0, // dwPlatformId
+// { 0 }, // szCSDVersion[128]
+// wServicePackMajor, // wServicePackMajor
+// 0, // wServicePackMinor
+// 0, // wSuiteMask
+// 0, // wProductType
+// 0 // wReserved
+// };
+//
+// ULONGLONG dwlConditionMask = 0;
+// VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
+// VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
+// VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+// VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER);
+//
+// return
+// STATUS_SUCCESS == RtlVerifyVersionInfo(
+// &osvi,
+// VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_BUILDNUMBER,
+// dwlConditionMask);
+//}
+
+bool WPFUtils::OSVersionHelper::IsWindowsServer()
+{
+ // We'd like to test for any version that does NOT match VER_NT_WORKSTATION
+ RTL_OSVERSIONINFOEXW osvi =
+ {
+ sizeof(osvi), // dwOSVersionInfoSize
+ 0, // dwMajorVersion
+ 0, // dwMinorVersion
+ 0, // dwBuildNumber
+ 0, // dwPlatformId
+ { 0 }, // szCSDVersion[128]
+ 0, // wServicePackMajor
+ 0, // wServicePackMinor
+ 0, // wSuiteMask
+ VER_NT_WORKSTATION, // wProductType
+ 0 // wReserved
+ };
+
+ ULONGLONG dwlConditionMask = 0;
+ VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
+
+ return RtlVerifyVersionInfo(&osvi, VER_PRODUCT_TYPE, dwlConditionMask) != STATUS_SUCCESS;
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/watsonreportinghelper.cpp b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/watsonreportinghelper.cpp
new file mode 100644
index 00000000000..287f069a098
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/watsonreportinghelper.cpp
@@ -0,0 +1,61 @@
+// 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 "wpfntddk.h"
+#include "wpfsdkddkver.h"
+#include "osversionhelper.h"
+
+using namespace WatsonReportingHelper;
+using namespace WatsonReportingHelper::HelperTypes;
+
+OSVersion* OSVersion::singleton = new OSVersion();
+
+OSVersion::OSVersion()
+{
+ RTL_OSVERSIONINFOEXW osvi = {0};
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+
+ if (RtlGetVersion(reinterpret_cast(&osvi)) == STATUS_SUCCESS)
+ {
+ majorVersion = osvi.dwMajorVersion;
+ minorVersion = osvi.dwMinorVersion;
+ buildNumber = osvi.dwBuildNumber;
+ servicePackMajor = osvi.wServicePackMajor;
+ servicePackMinor = osvi.wServicePackMinor;
+ }
+}
+
+DWORD OSVersion::GetMajorVersion()
+{
+ return singleton->majorVersion;
+}
+
+DWORD OSVersion::GetMinorVersion()
+{
+ return singleton->minorVersion;
+}
+
+DWORD OSVersion::GetBuildNumber()
+{
+ return singleton->buildNumber;
+}
+
+USHORT OSVersion::GetServicePackMajor()
+{
+ return singleton->servicePackMajor;
+}
+
+USHORT OSVersion::GetServicePackMinor()
+{
+ return singleton->servicePackMinor;
+}
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/wpfntddk.h b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/wpfntddk.h
new file mode 100644
index 00000000000..0b27bba2426
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/wpfntddk.h
@@ -0,0 +1,220 @@
+// 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
+
+#if !defined(STATUS_PROCEDURE_NOT_FOUND)
+#define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS)0xC000007AL)
+#endif
+
+#if !defined (STATUS_SUCCESS)
+//
+// MessageId: STATUS_SUCCESS
+//
+// MessageText:
+//
+// STATUS_SUCCESS
+//
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+#endif
+
+//
+// RtlVerifyVersionInfo() conditions
+//
+
+#if !defined(VER_EQUAL)
+#define VER_EQUAL 1
+#endif
+
+#if !defined(VER_GREATER)
+#define VER_GREATER 2
+#endif
+
+#if !defined(VER_GREATER_EQUAL)
+#define VER_GREATER_EQUAL 3
+#endif
+
+#if !defined(VER_LESS)
+#define VER_LESS 4
+#endif
+
+#if !defined(VER_LESS_EQUAL)
+#define VER_LESS_EQUAL 5
+#endif
+
+#if !defined(VER_AND)
+#define VER_AND 6
+#endif
+
+#if !defined(VER_OR)
+#define VER_OR 7
+#endif
+
+#if !defined(VER_CONDITION_MASK)
+#define VER_CONDITION_MASK 7
+#endif
+
+#if !defined(VER_NUM_BITS_PER_CONDITION_MASK)
+#define VER_NUM_BITS_PER_CONDITION_MASK 3
+#endif
+//
+// RtlVerifyVersionInfo() type mask bits
+//
+
+#if !defined(VER_MINORVERSION)
+#define VER_MINORVERSION 0x0000001
+#endif
+
+#if !defined(VER_MAJORVERSION)
+#define VER_MAJORVERSION 0x0000002
+#endif
+
+#if !defined(VER_BUILDNUMBER)
+#define VER_BUILDNUMBER 0x0000004
+#endif
+
+#if !defined(VER_PLATFORMID)
+#define VER_PLATFORMID 0x0000008
+#endif
+
+#if !defined(VER_SERVICEPACKMINOR)
+#define VER_SERVICEPACKMINOR 0x0000010
+#endif
+
+#if !defined(VER_SERVICEPACKMAJOR)
+#define VER_SERVICEPACKMAJOR 0x0000020
+#endif
+
+#if !defined(VER_SUITENAME)
+#define VER_SUITENAME 0x0000040
+#endif
+
+#if !defined(VER_PRODUCT_TYPE)
+#define VER_PRODUCT_TYPE 0x0000080
+#endif
+
+//
+// RtlVerifyVersionInfo() os product type values
+//
+
+#if !defined(VER_NT_WORKSTATION)
+#define VER_NT_WORKSTATION 0x0000001
+#endif
+
+#if !defined(VER_NT_DOMAIN_CONTROLLER)
+#define VER_NT_DOMAIN_CONTROLLER 0x0000002
+#endif
+
+#if !defined(VER_NT_SERVER)
+#define VER_NT_SERVER 0x0000003
+#endif
+
+//
+// dwPlatformId defines:
+//
+
+#if !defined(VER_PLATFORM_WIN32s)
+#define VER_PLATFORM_WIN32s 0
+#endif
+
+#if !defined(VER_PLATFORM_WIN32_WINDOWS)
+#define VER_PLATFORM_WIN32_WINDOWS 1
+#endif
+
+#if !defined(VER_PLATFORM_WIN32_NT)
+#define VER_PLATFORM_WIN32_NT 2
+#endif
+
+#pragma region Desktop Family or OneCore Family
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
+
+//
+//
+// VerifyVersionInfo() macro to set the condition mask
+//
+// For documentation sakes here's the old version of the macro that got
+// changed to call an API
+// #define VER_SET_CONDITION(_m_,_t_,_c_) _m_=(_m_|(_c_<<(1<<_t_)))
+//
+
+#if !defined(VER_SET_CONDITION)
+
+#define VER_SET_CONDITION(_m_,_t_,_c_) \
+ ((_m_)=VerSetConditionMask((_m_),(_t_),(_c_)))
+
+#endif
+#endif
+#pragma endregion
+
+#if (NTDDI_VERSION >= NTDDI_WIN2K)
+
+inline
+_IRQL_requires_max_(PASSIVE_LEVEL)
+_Must_inspect_result_
+NTSTATUS
+NTAPI
+RtlVerifyVersionInfo(
+ _In_ PRTL_OSVERSIONINFOEXW VersionInfo,
+ _In_ ULONG TypeMask,
+ _In_ ULONGLONG ConditionMask
+)
+{
+ NTSTATUS result = STATUS_PROCEDURE_NOT_FOUND;
+
+ auto hModule = LoadLibraryW(L"ntdll.dll");
+ if (hModule != nullptr)
+ {
+ auto pFarProc = GetProcAddress(hModule, "RtlVerifyVersionInfo");
+ if (pFarProc != nullptr)
+ {
+ auto pRtlVerifyVersionInfo = reinterpret_cast(pFarProc);
+ result = pRtlVerifyVersionInfo(VersionInfo, TypeMask, ConditionMask);
+ }
+ FreeLibrary(hModule);
+ }
+
+ return result;
+}
+
+inline
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS
+NTAPI
+RtlGetVersion(
+ _Out_
+ _At_(lpVersionInformation->dwOSVersionInfoSize, _Pre_ _Valid_)
+ _When_(lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW),
+ _At_((PRTL_OSVERSIONINFOEXW)lpVersionInformation, _Out_))
+ PRTL_OSVERSIONINFOW lpVersionInformation
+)
+{
+ NTSTATUS result = STATUS_PROCEDURE_NOT_FOUND;
+
+ auto hModule = LoadLibraryW(L"ntdll.dll");
+ if (hModule != nullptr)
+ {
+ auto pFarProc = GetProcAddress(hModule, "RtlGetVersion");
+ if (pFarProc != nullptr)
+ {
+ auto pRtlVerifyVersionInfo = reinterpret_cast(pFarProc);
+ result = pRtlVerifyVersionInfo(lpVersionInformation);
+ }
+ FreeLibrary(hModule);
+ }
+
+ return result;
+}
+
+#endif
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/wpfsdkddkver.h b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/wpfsdkddkver.h
new file mode 100644
index 00000000000..35f30fc944a
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/Shared/OSVersionHelper/wpfsdkddkver.h
@@ -0,0 +1,17 @@
+// 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
+#if !defined(_WPF_SDKDDKVER_H_)
+#define _WPF_SDKDDKVER_H_
+
+#define _TH1_BUILD_NUMBER 10240
+#define _TH2_BUILD_NUMBER 10586
+#define _RS1_BUILD_NUMBER 14393
+#define _RS2_BUILD_NUMBER 15063
+#define _RS3_BUILD_NUMBER 16299
+#define _RS5_BUILD_NUMBER 17763
+
+#endif // _WPF_SDKDDKVER_H_
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/DbgXHelper.vcxproj b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/DbgXHelper.vcxproj
new file mode 100644
index 00000000000..00a38dafc7c
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/DbgXHelper.vcxproj
@@ -0,0 +1,61 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+ StaticLibrary
+ false
+
+
+
+
+
+
+
+ 15.0
+ {5b21a951-88f4-460c-b6f2-5b3d7edfe13a}
+ Win32Proj
+ DbgXHelper
+
+
+
+
+ Use
+ precomp.hxx
+ %(AdditionalIncludeDirectories);$(MsBuildThisFileDirectory)
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbghelpers.cxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbghelpers.cxx
new file mode 100644
index 00000000000..5e3752d61a7
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbghelpers.cxx
@@ -0,0 +1,295 @@
+// 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.
+
+
+//---------------------------------------------------------------------------------
+//
+
+//
+// File: helpers.cxx
+//---------------------------------------------------------------------------------
+
+#include "precomp.hxx"
+
+
+/**************************************************************************\
+* OutputInstance
+*
+* Output an instance of a type.
+*
+* Wrote it.
+\**************************************************************************/
+void OutputInstance(
+ PDEBUG_CLIENT Client,
+ PCSTR typeName,
+ ULONG64 typeAddress,
+ bool fVerbose
+ )
+{
+ OutputControl OutCtl(Client);
+
+ if (fVerbose)
+ {
+ char szDTCommand[1000];
+
+ if (SUCCEEDED(StringCchPrintfA(szDTCommand, ARRAYSIZE(szDTCommand), "dt %s %p", typeName, typeAddress)))
+ {
+ OutCtl.Output("%s\n", szDTCommand);
+ OutCtl.Execute(szDTCommand, 0);
+ }
+ }
+ else
+ {
+ OutCtl.Output("%s %p\n", typeName, typeAddress);
+ }
+}
+
+/**************************************************************************\
+* GetFieldOffset
+*
+* Gets the offset of a field from a given type.
+*
+* Wrote it.
+\**************************************************************************/
+HRESULT GetFieldOffset(
+ PDEBUG_CLIENT Client,
+ PCSTR typeName,
+ PCSTR fieldName,
+ __out ULONG* pFieldOffset
+ )
+{
+ HRESULT hr = S_OK;
+ OutputControl OutCtl(Client);
+ PDEBUG_SYMBOLS Symbols = NULL;
+ ULONG typeId;
+ ULONG64 module;
+
+ *pFieldOffset = ULONG_MAX;
+
+ if (FAILED(hr = Client->QueryInterface(__uuidof(IDebugSymbols), (void **)&Symbols))) goto Cleanup;
+
+ if (FAILED(hr = Symbols->GetSymbolTypeId(typeName, &typeId, &module)))
+ {
+ OutCtl.Output("Couldn't find type %s: %p\n", typeName, hr);
+ goto Cleanup;
+ }
+
+ if (FAILED(hr = Symbols->GetFieldOffset(module, typeId, fieldName, pFieldOffset)))
+ {
+ OutCtl.Output("Couldn't find field %s on type %s: %p\n", fieldName, typeName, hr);
+ goto Cleanup;
+ }
+
+Cleanup:
+ ReleaseInterface(Symbols);
+ return hr;
+}
+
+/**************************************************************************\
+* ReadPointerField
+*
+* Reads a pointer-sized field for a type from a specified address.
+*
+* Wrote it.
+\**************************************************************************/
+HRESULT ReadPointerField(
+ PDEBUG_CLIENT Client,
+ ULONG64 typeAddress,
+ PCSTR typeName,
+ PCSTR fieldName,
+ __out ULONG64* pFieldValue
+ )
+{
+ HRESULT hr = S_OK;
+ OutputControl OutCtl(Client);
+ PDEBUG_DATA_SPACES Data = NULL;
+ ULONG fieldOffset;
+
+ if (FAILED(hr = Client->QueryInterface(__uuidof(IDebugDataSpaces), (void **)&Data))) goto Cleanup;
+
+ if (FAILED(hr = GetFieldOffset(Client, typeName, fieldName, &fieldOffset))) goto Cleanup;
+
+ if (FAILED(hr = Data->ReadPointersVirtual(1, typeAddress + fieldOffset, pFieldValue)))
+ {
+ //OutCtl.Output("Couldn't read %s.%s off pointer %p (offset %p): %p\n", typeName, fieldName, typeAddress, fieldOffset, hr);
+ goto Cleanup;
+ }
+
+Cleanup:
+ ReleaseInterface(Data);
+ return hr;
+}
+
+/**************************************************************************\
+* ReadNonPointerField
+*
+* Reads a specified-sized field for a type from a specified address.
+*
+* Wrote it.
+\**************************************************************************/
+HRESULT ReadNonPointerField(
+ PDEBUG_CLIENT Client,
+ ULONG64 typeAddress,
+ PCSTR typeName,
+ PCSTR fieldName,
+ ULONG fieldSize,
+ __out VOID* pFieldValue
+ )
+{
+ HRESULT hr = S_OK;
+ OutputControl OutCtl(Client);
+ PDEBUG_DATA_SPACES Data = NULL;
+ ULONG fieldOffset;
+
+ if (FAILED(hr = Client->QueryInterface(__uuidof(IDebugDataSpaces), (void **)&Data))) goto Cleanup;
+
+ if (FAILED(hr = GetFieldOffset(Client, typeName, fieldName, &fieldOffset))) goto Cleanup;
+
+ if (FAILED(hr = Data->ReadVirtual(typeAddress + fieldOffset, pFieldValue, fieldSize, NULL)))
+ {
+ //OutCtl.Output("Couldn't read %s.%s off pointer %p (offset %p, size %p): %p\n", typeName, fieldName, typeAddress, fieldOffset, fieldSize, hr);
+ goto Cleanup;
+ }
+
+Cleanup:
+ ReleaseInterface(Data);
+ return hr;
+}
+
+
+//+-----------------------------------------------------------------------------
+//
+// Function:
+// ReadSymbolNameByOffset
+//
+// Synopsis:
+// Reads the symbol name given an offset.
+//
+//------------------------------------------------------------------------------
+
+HRESULT
+ReadSymbolNameByOffset(
+ PDEBUG_CLIENT client,
+ ULONG64 offset,
+ ULONG nameBufferSize,
+ __out_ecount_part(nameBufferSize, *pNameSize) PSTR nameBuffer,
+ __out_ecount(1) ULONG *pNameSize
+ )
+{
+ HRESULT hr = S_OK;
+
+ OutputControl OutCtl(client);
+
+ PDEBUG_SYMBOLS Symbols = NULL;
+ PDEBUG_DATA_SPACES Data = NULL;
+
+ ULONG64 symbol = 0;
+
+ IFC(client->QueryInterface(__uuidof(IDebugSymbols), (void **)&Symbols));
+ IFC(client->QueryInterface(__uuidof(IDebugDataSpaces), (void **)&Data));
+
+ if (FAILED(hr = Data->ReadPointersVirtual(1, offset, &symbol)))
+ {
+ OutCtl.Output("ReadSymbolNameByOffset: failed to read symbol value from offset %p with HRESULT 0x%08x\n", offset, hr);
+ goto Cleanup;
+ }
+
+ if (FAILED(hr = Symbols->GetNameByOffset(
+ symbol,
+ nameBuffer,
+ nameBufferSize,
+ pNameSize,
+ NULL // Displacement
+ )))
+ {
+ OutCtl.Output("ReadSymbolNameByOffset: failed to read name by offset %p with HRESULT 0x%08x\n", offset, hr);
+ goto Cleanup;
+ }
+
+Cleanup:
+ ReleaseInterface(Symbols);
+ ReleaseInterface(Data);
+
+ return hr;
+}
+
+
+/**************************************************************************\
+* SearchTable
+*
+* Searches an NTRTL table for a particular value
+*
+* Wrote it.
+\**************************************************************************/
+HRESULT SearchTable(
+ PDEBUG_CLIENT Client,
+ ULONG64 ulpTableRoot,
+ ULONG ulFieldOffset,
+ ULONG64 ulValueToLookFor,
+ __out ULONG64* ulpEntry
+ )
+{
+ HRESULT hr = S_OK;
+
+ OutputControl OutCtl(Client);
+ PDEBUG_DATA_SPACES Data = NULL;
+
+ if (FAILED(hr = Client->QueryInterface(__uuidof(IDebugDataSpaces), (void **)&Data))) goto Cleanup;
+
+ ULONG offsetInsertOrderList;
+ ULONG offsetFlink = 0;
+ const int MAX_ELEMENTS = 5000;
+ int numElements = 0;
+
+ *ulpEntry = NULL;
+
+ if (FAILED(hr = GetFieldOffset(Client, "RTL_GENERIC_TABLE", "InsertOrderList", &offsetInsertOrderList))) goto Cleanup;
+
+ ULONG64 InsertOrderList = ulpTableRoot + offsetInsertOrderList;
+
+ ULONG64 listCurrent = InsertOrderList;
+ ULONG offsetToUserData = (OutCtl.IsPointer64Bit() == S_OK) ? 16 : 12;
+
+ do
+ {
+ ULONG64 currentFieldValue;
+ if (OutCtl.GetInterrupt() == S_OK)
+ {
+ OutCtl.Output("\n\nStop on user-interrupt.\n\n");
+ hr = E_ABORT;
+ break;
+ }
+
+ if (FAILED(hr = Data->ReadPointersVirtual(1, listCurrent+offsetFlink, &listCurrent)))
+ {
+ OutCtl.Output("Couldn't read listCurrent->Flink (pointer = %p): hr = %p\n", listCurrent, hr);
+ break;
+ }
+
+ if (FAILED(hr = Data->ReadPointersVirtual(1, listCurrent + offsetToUserData + ulFieldOffset, ¤tFieldValue)))
+ {
+ OutCtl.Output("Couldn't read field off table element pointer = %p, offset = %p: hr = %p\n", listCurrent, offsetToUserData + ulFieldOffset, hr);
+ break;
+ }
+
+ if (currentFieldValue == ulValueToLookFor)
+ {
+ *ulpEntry = listCurrent + offsetToUserData;
+ break;
+ }
+ } while (listCurrent != InsertOrderList && ++numElements < MAX_ELEMENTS);
+
+ if (numElements >= MAX_ELEMENTS)
+ {
+ OutCtl.Output("\n\nReached max number of elements, stopping.\n\n");
+ }
+
+Cleanup:
+ ReleaseInterface(Data);
+ return hr;
+}
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbghelpers.hxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbghelpers.hxx
new file mode 100644
index 00000000000..9377508ba65
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbghelpers.hxx
@@ -0,0 +1,73 @@
+// 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.
+
+
+//---------------------------------------------------------------------------------
+//
+
+//
+// File: helpers.hxx
+//---------------------------------------------------------------------------------
+
+void OutputInstance(
+ PDEBUG_CLIENT Client,
+ PCSTR typeName,
+ ULONG64 typeAddress,
+ bool fVerbose
+ );
+
+HRESULT GetFieldOffset(
+ PDEBUG_CLIENT Client,
+ PCSTR typeName,
+ PCSTR fieldName,
+ __out ULONG* pFieldOffset
+ );
+
+HRESULT ReadPointerField(
+ PDEBUG_CLIENT Client,
+ ULONG64 typeAddress,
+ PCSTR typeName,
+ PCSTR fieldName,
+ __out ULONG64* pFieldValue
+ );
+
+HRESULT ReadNonPointerField(
+ PDEBUG_CLIENT Client,
+ ULONG64 typeAddress,
+ PCSTR typeName,
+ PCSTR fieldName,
+ ULONG fieldSize,
+ __out VOID* pFieldValue
+ );
+
+template
+HRESULT ReadTypedField(
+ PDEBUG_CLIENT Client,
+ ULONG64 typeAddress,
+ PCSTR typeName,
+ PCSTR fieldName,
+ __out T* pFieldValue
+ )
+{
+ return ReadNonPointerField(Client, typeAddress, typeName, fieldName, sizeof(*pFieldValue), pFieldValue);
+}
+
+HRESULT ReadSymbolNameByOffset(
+ PDEBUG_CLIENT client,
+ ULONG64 offset,
+ ULONG nameBufferSize,
+ __out_ecount_part(nameBufferSize, *pNameSize) PSTR nameBuffer,
+ __out_ecount(1) ULONG *pNameSize
+ );
+
+HRESULT SearchTable(
+ PDEBUG_CLIENT Client,
+ ULONG64 ulpTableRoot,
+ ULONG ulFieldOffset,
+ ULONG64 ulValueToLookFor,
+ __out ULONG64* ulpEntry
+ );
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbgxhelper.h b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbgxhelper.h
new file mode 100644
index 00000000000..9bc87d70826
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/dbgxhelper.h
@@ -0,0 +1,169 @@
+// 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.
+
+
+//+----------------------------------------------------------------------------
+//
+
+//
+// Abstract:
+//
+
+
+// This is a 64 bit aware debugger extension library
+#define KDEXT_64BIT
+
+
+#pragma warning (push)
+// 4245: 'argument' : conversion from 'NTSTATUS' to 'DWORD', signed/unsigned mismatch
+#pragma warning (disable : 4245)
+#include
+#pragma warning (pop)
+// When using the structures in wdbgexts.h UCHARs are
+// used. For C++ we need to get the type right.
+#define DbgStr(s) (PUCHAR)s
+
+#include
+
+
+//+----------------------------------------------------------------------------
+//
+// Structure: ModuleParameters
+//
+// Synopsis:
+//
+//-----------------------------------------------------------------------------
+
+typedef struct {
+ ULONG64 Base;
+ ULONG Index;
+ __nullterminated CHAR Name[MAX_PATH];
+ __nullterminated CHAR Ext[4];
+ DEBUG_MODULE_PARAMETERS DbgModParams;
+} ModuleParameters;
+
+
+//
+// Global data consumed by DbgXHelper.lib and must be defined by ext DLL.
+//
+
+extern ModuleParameters UM_Module;
+
+
+//
+// Prototypes for initialize event callbacks that must be defined by ext DLL.
+//
+
+HRESULT OnExtensionInitialize(
+ __inout PDEBUG_CLIENT DebugClient
+ );
+
+void OnExtensionUninitialize();
+
+HRESULT OnSymbolInitialize(
+ __in HRESULT hrCurrent,
+ __inout PDEBUG_CLIENT Client
+ );
+
+
+//
+// Global data provided by DbgXHelper.lib
+//
+
+extern HINSTANCE ghDllInst;
+
+extern ULONG TargetMachine;
+extern ULONG TargetClass;
+extern ULONG PlatformId;
+extern ULONG MajorVer;
+extern ULONG MinorVer;
+extern ULONG SrvPack;
+extern ULONG BuildNo;
+
+extern ModuleParameters Type_Module;
+
+
+//
+// Macros to define extension methods
+//
+
+//
+// undef the wdbgexts
+//
+#undef DECLARE_API
+
+#define DECLARE_API(extension) \
+CPPMOD HRESULT CALLBACK extension(__inout PDEBUG_CLIENT Client, __in PCSTR args)
+
+#define BEGIN_API(extension) InitAPI(Client, #extension);
+
+
+//
+// General helper routines provided by DbgXHelper.lib
+//
+
+
+HRESULT
+InitAPI(
+ __inout PDEBUG_CLIENT Client,
+ __in PCSTR ExtName
+ );
+
+
+HRESULT
+GetDebugClient(
+ __deref_out PDEBUG_CLIENT *pClient
+ );
+
+HRESULT
+SymbolInit(
+ __inout PDEBUG_CLIENT Client
+ );
+
+HRESULT
+GetModuleParameters(
+ __inout PDEBUG_CLIENT Client,
+ __out ModuleParameters *Module,
+ BOOL TryReload
+ );
+
+HRESULT
+GetTypeId(
+ __inout PDEBUG_CLIENT Client,
+ __in PCSTR Type,
+ __out PULONG TypeId,
+ __out_opt PULONG64 Module
+ );
+
+
+#define EVALUATE_DEFAULT_TYPE DEBUG_VALUE_INVALID
+#define EVALUATE_DEFAULT_RADIX 0
+
+#define EVALUATE_COMPACT_EXPR 1
+#define EVALUATE_DEFAULT_FLAGS 0
+
+HRESULT
+Evaluate(
+ __inout PDEBUG_CLIENT Client,
+ __in PCSTR Expression,
+ ULONG DesiredType,
+ ULONG Radix,
+ __out PDEBUG_VALUE Value,
+ __out_opt PULONG RemainderIndex = NULL,
+ __out_opt PULONG StartIndex = NULL,
+ FLONG Flags = EVALUATE_DEFAULT_FLAGS
+ );
+
+
+//
+// Other DbgXHelper.lib provided routines and classes
+//
+
+#include "event.hxx"
+#include "output.hxx"
+#include "flags.hxx"
+#include "input.hxx"
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/debug.cxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/debug.cxx
new file mode 100644
index 00000000000..3e72c74aadf
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/debug.cxx
@@ -0,0 +1,81 @@
+// 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 Name:
+
+ debug.cxx
+
+Abstract:
+
+ This file contains debug routines to debug extenstion problems.
+
+
+--*/
+
+
+#include
+
+
+#if DBG
+
+const char NoIndent[] = "";
+
+void
+vPrintNativeFieldInfo(
+ PFIELD_INFO pFI,
+ const char *pszIndent)
+{
+ if (!pFI) return;
+
+ DbgPrint(" %sPUCHAR fName = \"%s\"\n", pszIndent, pFI->fName);
+ DbgPrint(" %sPUCHAR printName = \"%s\"\n", pszIndent, pFI->printName);
+ DbgPrint(" %sULONG size = 0x%x\n", pszIndent, pFI->size);
+ DbgPrint(" %sULONG fOptions = 0x%08x\n", pszIndent, pFI->fOptions);
+ DbgPrint(" %sULONG64 address = 0x%I64x\n", pszIndent, pFI->address);
+ DbgPrint(" %sPVOID fieldCallBack = 0x%p\n", pszIndent, pFI->fieldCallBack);
+}
+
+
+void
+vPrintNativeSymDumpParam(
+ PSYM_DUMP_PARAM pSDP,
+ BOOL bDumpFields,
+ const char *pszIndent)
+{
+ if (!pSDP) return;
+
+ char pszNextIndent[80];
+
+ StringCchPrintfA(pszNextIndent, ARRAY_SIZE(pszNextIndent), "%s ", pszIndent);
+
+ DbgPrint(" %sULONG size = 0x%x\n", pszIndent, pSDP->size);
+ DbgPrint(" %sPUCHAR sName = \"%s\"\n", pszIndent, pSDP->sName);
+ DbgPrint(" %sULONG Options = 0x%08x\n", pszIndent, pSDP->Options);
+ DbgPrint(" %sULONG64 addr = 0x%I64x\n", pszIndent, pSDP->addr);
+ DbgPrint(" %sPFIELD_INFO listLink = 0x%p\n", pszIndent, pSDP->listLink);
+ DbgPrint(" %sPVOID Context = 0x%p\n", pszIndent, pSDP->Context);
+ DbgPrint(" %sPSYM_DUMP_FIELD_CALLBACK CallbackRoutine = 0x%p\n", pszIndent, pSDP->CallbackRoutine);
+ DbgPrint(" %sULONG nFields = %d\n", pszIndent, pSDP->nFields);
+ DbgPrint(" %sPFIELD_INFO Fields = 0x%p\n", pszIndent, pSDP->Fields);
+
+ if (bDumpFields && pSDP->Fields)
+ {
+ for (ULONG nField = 0; nField < pSDP->nFields; nField++)
+ {
+ DbgPrint(" %sFIELD_INFO Fields[%d] = {\n", pszIndent, nField);
+ vPrintNativeFieldInfo(&pSDP->Fields[nField], pszNextIndent);
+ DbgPrint(" %s}\n", pszIndent);
+ }
+ }
+}
+
+#endif DBG
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/debug.hxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/debug.hxx
new file mode 100644
index 00000000000..b0f17cfb64d
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/debug.hxx
@@ -0,0 +1,107 @@
+// 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 Name:
+
+ debug.hxx
+
+Abstract:
+
+ This file header contains prototypes for debug routines to
+ debug extenstion problems.
+
+
+--*/
+
+#pragma once
+
+#include
+
+#if DBG
+
+extern const char NoIndent[];
+
+void
+vPrintNativeFieldInfo(
+ PFIELD_INFO pFI,
+ const char *pszIndent = NoIndent);
+
+void
+vPrintNativeSymDumpParam(
+ PSYM_DUMP_PARAM pSDP,
+ BOOL bDumpFields = TRUE,
+ const char *pszIndent = NoIndent);
+
+#define RIP(msg) \
+ do { \
+ DbgPrint(msg); \
+ DbgBreakPoint(); \
+ } while (0)
+
+#else
+
+// Disable DbgPrint from NT RTL
+#define DbgPrint
+
+#define RIP(msg)
+
+#define vPrintNativeFieldInfo
+#define vPrintNativeSymDumpParam
+
+#endif DBG
+
+
+
+#define MILX_ENABLE_TRACING 0
+
+#if MILX_ENABLE_TRACING
+
+ #define MILX_TRACE_RETURN \
+ pOutCtl->OutVerb("[trace return from %s @ %s:%i]\n", __FUNCTION__, __FILE__, __LINE__)
+
+ #define MILX_TRACE_ENTRY { pOutCtl->OutVerb("[trace entry in %s @ %s:%i]\n", __FUNCTION__, __FILE__, __LINE__); }
+
+ #define MILX_TRACE { pOutCtl->OutVerb("[trace in %s @ %s:%i]\n", __FUNCTION__, __FILE__, __LINE__); }
+
+#else
+
+ #define MILX_TRACE_RETURN
+ #define MILX_TRACE_ENTRY
+ #define MILX_TRACE
+
+#endif
+
+
+#define RRETURN(HR) \
+ { \
+ HRESULT __hr = (HR); \
+ __if_exists (pOutCtl) \
+ { \
+ if (pOutCtl) \
+ { \
+ if (FAILED(__hr)) { \
+ pOutCtl->OutErr("[failure in %s @ %s:%i -- returning error code 0x%08x]\n", __FUNCTION__, __FILE__, __LINE__, __hr); \
+ } else { \
+ MILX_TRACE_RETURN; \
+ } \
+ } \
+ } \
+ \
+ return __hr; \
+ }
+
+
+HRESULT ResolveHMilResource(
+ PDEBUG_CLIENT Client,
+ ULONG64 ulhResource,
+ ULONG64 ulpMilChannel,
+ __out ULONG64* pulpHANDLE_ENTRY
+ );
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/event.cxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/event.cxx
new file mode 100644
index 00000000000..c258ff1560b
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/event.cxx
@@ -0,0 +1,568 @@
+// 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 Name:
+
+ event.cxx
+
+Abstract:
+
+ This file contains the routines to track and handle
+ debugger events.
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include "precomp.hxx"
+
+BOOL gbSymbolsNotLoaded = TRUE;
+
+ULONG UniqueTargetState = INVALID_UNIQUE_STATE;
+
+#if DBG && 0
+ULONG
+DbgEventPrint(
+ IN PCHAR Format,
+ ...
+ )
+{
+ va_list arglist;
+
+ va_start(arglist, Format);
+ return vDbgPrintExWithPrefix("Event: ", -1, 0, Format, arglist);
+}
+
+#else
+#define DbgEventPrint
+#endif
+
+typedef struct {
+ PDEBUG_CLIENT Client;
+ BOOL ParamsRead;
+} MonitorThreadParams;
+
+
+DWORD WINAPI EventMonitorThread(MonitorThreadParams *);
+
+
+class EventMonitorCallbacks : public DebugBaseEventCallbacks
+{
+private:
+ ULONG RefCount;
+
+public:
+
+ EventMonitorCallbacks()
+ {
+ RefCount = 1;
+ }
+
+ // IUnknown
+ STDMETHOD_(ULONG, AddRef)(
+ THIS
+ )
+ {
+ RefCount++;
+
+ return RefCount;
+ }
+
+ STDMETHOD_(ULONG, Release)(
+ THIS
+ )
+ {
+ RefCount--;
+
+ if (RefCount == 0)
+ {
+ delete this;
+ return 0;
+ }
+
+ return RefCount;
+ }
+
+
+ // IDebugEventCallbacks.
+
+ STDMETHOD(GetInterestMask)(
+ THIS_
+ OUT PULONG Mask
+ )
+ {
+ DbgEventPrint("GetInterestMask\n");
+
+ if (Mask != NULL)
+ {
+ *Mask = DEBUG_EVENT_SESSION_STATUS |
+ DEBUG_EVENT_CHANGE_DEBUGGEE_STATE |
+ DEBUG_EVENT_CHANGE_ENGINE_STATE |
+ DEBUG_EVENT_CHANGE_SYMBOL_STATE |
+ DEBUG_EVENT_UNLOAD_MODULE;
+ }
+
+ return S_OK;
+ }
+
+ STDMETHOD(Breakpoint)(
+ THIS_
+ IN PDEBUG_BREAKPOINT /*Bp*/
+ )
+ {
+ DbgEventPrint("BP\n");
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(Exception)(
+ THIS_
+ IN PEXCEPTION_RECORD64 /*Exception*/,
+ IN ULONG /*FirstChance*/
+ )
+ {
+ DbgEventPrint("Exception\n");
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(CreateThread)(
+ THIS_
+ IN ULONG64 /*Handle*/,
+ IN ULONG64 /*DataOffset*/,
+ IN ULONG64 /*StartOffset*/
+ )
+ {
+ DbgEventPrint("CreateThread\n");
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(ExitThread)(
+ THIS_
+ IN ULONG /*ExitCode*/
+ )
+ {
+ DbgEventPrint("ExitThread\n");
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(CreateProcess)(
+ THIS_
+ IN ULONG64 /*ImageFileHandle*/,
+ IN ULONG64 /*Handle*/,
+ IN ULONG64 /*BaseOffset*/,
+ IN ULONG /*ModuleSize*/,
+ IN PCSTR /*ModuleName*/,
+ IN PCSTR /*ImageName*/,
+ IN ULONG /*CheckSum*/,
+ IN ULONG /*TimeDateStamp*/,
+ IN ULONG64 /*InitialThreadHandle*/,
+ IN ULONG64 /*ThreadDataOffset*/,
+ IN ULONG64 /*StartOffset*/
+ )
+ {
+ DbgEventPrint("CreateProcess\n");
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(ExitProcess)(
+ THIS_
+ IN ULONG /*ExitCode*/
+ )
+ {
+ DbgEventPrint("ExitProcess\n");
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(LoadModule)(
+ THIS_
+ IN ULONG64 /*ImageFileHandle*/,
+ IN ULONG64 BaseOffset,
+ IN ULONG /*ModuleSize*/,
+ IN PCSTR ModuleName,
+ IN PCSTR ImageName,
+ IN ULONG /*CheckSum*/,
+ IN ULONG /*TimeDateStamp*/
+ )
+ {
+ DbgEventPrint("LoadModule:\n"
+ " ModuleName: %s\n"
+ " ImageName: %s\n"
+ " BaseOffset: %I64x\n",
+ ModuleName, ImageName, BaseOffset);
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(UnloadModule)(
+ THIS_
+ IN PCSTR /*ImageBaseName*/,
+ IN ULONG64 BaseOffset
+ )
+ {
+ // Don't use Image base name for now - Debugger bug
+ //DbgEventPrint("UnloadModule %s @ %I64x\n", ImageBaseName, BaseOffset);
+ DbgEventPrint("UnloadModule ? @ %I64x\n", BaseOffset);
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(SystemError)(
+ THIS_
+ IN ULONG Error,
+ IN ULONG Level
+ )
+ {
+ DbgEventPrint("SystemError(%lu, %lu)\n", Error, Level);
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(SessionStatus)(
+ THIS_
+ IN ULONG Status
+ )
+ {
+ DbgEventPrint("SessionStatus(%lu)\n", Status);
+ if (Status == DEBUG_SESSION_ACTIVE) DbgEventPrint("DEBUG_SESSION_ACTIVE\n");
+ if (Status == DEBUG_SESSION_END_SESSION_ACTIVE_TERMINATE) DbgEventPrint("DEBUG_SESSION_END_SESSION_ACTIVE_TERMINATE\n");
+ if (Status == DEBUG_SESSION_END_SESSION_ACTIVE_DETACH) DbgEventPrint("DEBUG_SESSION_END_SESSION_ACTIVE_DETACH\n");
+ if (Status == DEBUG_SESSION_END_SESSION_PASSIVE) DbgEventPrint("DEBUG_SESSION_END_SESSION_PASSIVE\n");
+ if (Status == DEBUG_SESSION_END) DbgEventPrint("DEBUG_SESSION_END\n");
+ if (Status == DEBUG_SESSION_REBOOT) DbgEventPrint("DEBUG_SESSION_REBOOT\n");
+ if (Status == DEBUG_SESSION_HIBERNATE) DbgEventPrint("DEBUG_SESSION_HIBERNATE\n");
+ if (Status == DEBUG_SESSION_FAILURE) DbgEventPrint("DEBUG_SESSION_FAILURE\n");
+ return DEBUG_STATUS_NO_CHANGE;
+ }
+
+ STDMETHOD(ChangeDebuggeeState)(
+ THIS_
+ IN ULONG Flags,
+ IN ULONG64 Argument
+ )
+ {
+ DbgEventPrint("ChangeDebuggeeState(0x%lx, 0x%I64x)\n", Flags, Argument);
+ if (Flags == DEBUG_CDS_ALL)
+ {
+ DbgEventPrint("DEBUG_CDS_ALL\n");
+ UniqueTargetState++;
+ }
+ else
+ {
+ if (Flags & DEBUG_CDS_REGISTERS) DbgEventPrint("DEBUG_CDS_REGISTERS\n");
+ if (Flags & DEBUG_CDS_DATA)
+ {
+ DbgEventPrint("DEBUG_CDS_DATA\n");
+ UniqueTargetState++;
+ }
+ }
+ if (UniqueTargetState==INVALID_UNIQUE_STATE) UniqueTargetState++;
+ return S_OK;
+ }
+
+ STDMETHOD(ChangeEngineState)(
+ THIS_
+ IN ULONG Flags,
+ IN ULONG64 Argument
+ )
+ {
+ //DbgEventPrint("ChangeEngineState(0x%lx, 0x%I64x)\n", Flags, Argument);
+ if (Flags == DEBUG_CES_ALL)
+ {
+ DbgEventPrint("DEBUG_CES_ALL\n");
+ UniqueTargetState++;
+ if (UniqueTargetState==INVALID_UNIQUE_STATE) UniqueTargetState++;
+ }
+ else
+ {
+ if (Flags & DEBUG_CES_CURRENT_THREAD) DbgEventPrint("DEBUG_CES_CURRENT_THREAD\n");
+ if (Flags & DEBUG_CES_EFFECTIVE_PROCESSOR) DbgEventPrint("DEBUG_CES_EFFECTIVE_PROCESSOR\n");
+ if (Flags & DEBUG_CES_BREAKPOINTS) DbgEventPrint("DEBUG_CES_BREAKPOINTS\n");
+ if (Flags & DEBUG_CES_CODE_LEVEL) DbgEventPrint("DEBUG_CES_CODE_LEVEL\n");
+ if (Flags & DEBUG_CES_EXECUTION_STATUS)
+ {
+ DbgEventPrint("DEBUG_CES_EXECUTION_STATUS\n");
+ switch (Argument & DEBUG_STATUS_MASK)
+ {
+ case DEBUG_STATUS_NO_CHANGE: DbgPrint("Exec Status: DEBUG_STATUS_NO_CHANGE\n"); break;
+ case DEBUG_STATUS_GO: DbgPrint("Exec Status: DEBUG_STATUS_GO\n"); break;
+ case DEBUG_STATUS_GO_HANDLED: DbgPrint("Exec Status: DEBUG_STATUS_GO_HANDLED\n"); break;
+ case DEBUG_STATUS_GO_NOT_HANDLED: DbgPrint("Exec Status: DEBUG_STATUS_GO_NOT_HANDLED\n"); break;
+ case DEBUG_STATUS_STEP_OVER: DbgPrint("Exec Status: DEBUG_STATUS_STEP_OVER\n"); break;
+ case DEBUG_STATUS_STEP_INTO: DbgPrint("Exec Status: DEBUG_STATUS_STEP_INTO\n"); break;
+ case DEBUG_STATUS_BREAK: DbgPrint("Exec Status: DEBUG_STATUS_BREAK\n"); break;
+ case DEBUG_STATUS_NO_DEBUGGEE: DbgPrint("Exec Status: DEBUG_STATUS_NO_DEBUGGEE\n"); break;
+ case DEBUG_STATUS_STEP_BRANCH: DbgPrint("Exec Status: DEBUG_STATUS_STEP_BRANCH\n"); break;
+ case DEBUG_STATUS_IGNORE_EVENT: DbgPrint("Exec Status: DEBUG_STATUS_IGNORE_EVENT\n"); break;
+ default: DbgPrint("Exec Status: Unknown\n"); break;
+ }
+ if (Argument & DEBUG_STATUS_INSIDE_WAIT) DbgPrint("Exec Status: DEBUG_STATUS_INSIDE_WAIT\n");
+ if ((Argument & DEBUG_STATUS_MASK) != DEBUG_STATUS_NO_CHANGE)
+ {
+ UniqueTargetState++;
+ if (UniqueTargetState==INVALID_UNIQUE_STATE) UniqueTargetState++;
+ }
+ }
+ if (Flags & DEBUG_CES_ENGINE_OPTIONS) DbgEventPrint("DEBUG_CES_ENGINE_OPTIONS\n");
+ if (Flags & DEBUG_CES_LOG_FILE) DbgEventPrint("DEBUG_CES_LOG_FILE\n");
+ //if (Flags & DEBUG_CES_RADIX) DbgEventPrint("DEBUG_CES_RADIX\n");
+ if (Flags & DEBUG_CES_EVENT_FILTERS) DbgEventPrint("DEBUG_CES_EVENT_FILTERS\n");
+ if (Flags & DEBUG_CES_PROCESS_OPTIONS) DbgEventPrint("DEBUG_CES_PROCESS_OPTIONS\n");
+ if (Flags & DEBUG_CES_EXTENSIONS) DbgEventPrint("DEBUG_CES_EXTENSIONS\n");
+ }
+ return S_OK;
+ }
+
+ STDMETHOD(ChangeSymbolState)(
+ THIS_
+ IN ULONG Flags,
+ IN ULONG64 Argument
+ )
+ {
+ DbgEventPrint("ChangeSymbolState(0x%lx, 0x%I64x)\n", Flags, Argument);
+ gbSymbolsNotLoaded = gbSymbolsNotLoaded || (Flags & DEBUG_CSS_UNLOADS);
+ UniqueTargetState++;
+ if (UniqueTargetState==INVALID_UNIQUE_STATE) UniqueTargetState++;
+ return S_OK;
+ }
+};
+
+enum MonitorState {
+ NO_DISPATCHING,
+ NEED_DISPATCH,
+ DISPATCHED
+};
+
+LONG g_MonitorState = NO_DISPATCHING;
+PDEBUG_CLIENT g_pMonitorClient = NULL;
+BOOL g_MonitorThreadSet = FALSE;
+
+DWORD
+WINAPI
+EventMonitorThread(
+ MonitorThreadParams *Params
+ )
+{
+ HRESULT hr = S_OK;
+ PDEBUG_CLIENT Client;
+ MonitorThreadParams ParamCopy;
+ HMODULE hModule = NULL;
+ TCHAR ModulePath[256];
+
+ if (Params != NULL && Params->Client != NULL)
+ {
+ ASSERTMSG("EventMonitorThread not started with NEED_DISPATCH.\n", g_MonitorState == NEED_DISPATCH);
+
+ if (GetModuleFileName(ghDllInst, ModulePath, sizeof(ModulePath)/sizeof(TCHAR)) == 0)
+ {
+ DbgPrint("EventMonitorThread failed to get Module path.\n");
+ hr = S_FALSE;
+ }
+ else
+ {
+ // LoadLibrary so we have a reference while this thread lives
+ hModule = LoadLibrary(ModulePath);
+
+ if (hModule != ghDllInst)
+ {
+ DbgPrint("EventMonitorThread retrieving an hModule different from ghDllInst.\n");
+ hr = S_FALSE;
+ }
+ }
+
+ if (hr == S_OK)
+ {
+ Params->Client->AddRef();
+
+ ParamCopy = *Params;
+ MemoryBarrier();
+ Params->ParamsRead = TRUE;
+ Params = &ParamCopy;
+
+ hr = Params->Client->CreateClient(&Client);
+ DbgPrint("EventMonitorThread created client %p.\n", Client);
+
+ Params->Client->Release();
+
+ if (hr == S_OK)
+ {
+ EventMonitorCallbacks *EventMonitor = new EventMonitorCallbacks;
+
+ if (EventMonitor != NULL)
+ {
+ hr = Client->SetEventCallbacks(EventMonitor);
+
+ if (hr == S_OK)
+ {
+ // Pass monitoring client back to caller.
+ Client->AddRef();
+ if (InterlockedCompareExchangePointer((PVOID*)&g_pMonitorClient, Client, NULL) == NULL &&
+ InterlockedCompareExchange(&g_MonitorState, DISPATCHED, NEED_DISPATCH) == NEED_DISPATCH)
+ {
+ DbgPrint("EventMonitorThread dispatching for client %p.\n", Client);
+ UniqueTargetState++;
+ hr = Client->DispatchCallbacks(INFINITE);
+ }
+ else
+ {
+ // Another EventMonitorThread has already started or
+ // ReleaseEventCallbacks has already been called; so,
+ // release this client and
+ // NULL global monitor client if we set it
+ DbgPrint("EventMonitorThread exiting instead of dispatching for client %p.\n", Client);
+ InterlockedCompareExchangePointer((PVOID*)&g_pMonitorClient, NULL, Client);
+ Client->Release();
+ }
+
+ // Remove Client's reference to EventMonitor
+ Client->SetEventCallbacks(NULL);
+ }
+ else
+ {
+ OutputControl OutCtl(Client);
+ OutCtl.OutErr("EventMonitorThread callbacks setup failed, %s.\n", pszHRESULT(hr));
+ }
+
+#if DBG
+ ULONG DbgRemaingReferences =
+#endif
+ EventMonitor->Release();
+#if DBG
+ ASSERTMSG("Unexpected outstanding references to EventMonitor.\n",
+ DbgRemaingReferences == 0);
+#endif
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ Client->Release();
+ }
+ }
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ DbgPrint("EventMonitorThread calling ExitThread().\n");
+
+ FreeLibraryAndExitThread(hModule, (DWORD)hr);
+}
+
+
+void
+ReleaseEventCallbacks(
+ PDEBUG_CLIENT Client
+ )
+{
+ if (g_MonitorThreadSet)
+ {
+ if (InterlockedExchange(&g_MonitorState, NO_DISPATCHING) == DISPATCHED)
+ {
+ PDEBUG_CLIENT pMonitorClient;
+
+ #pragma warning(push)
+ // InterlockedExchangePointer is not /Wp64 happy
+ #pragma warning(disable : 4312)
+ pMonitorClient = (PDEBUG_CLIENT)InterlockedExchangePointer((PVOID *)&g_pMonitorClient, NULL);
+ #pragma warning(pop)
+
+ ASSERTMSG("g_MonitorState shows g_pMonitorClient should be set.\n", pMonitorClient != NULL);
+
+ if (Client == NULL)
+ {
+ if (GetDebugClient(&Client) != S_OK)
+ {
+ Client = pMonitorClient;
+ Client->AddRef();
+ }
+ }
+ else
+ {
+ Client->AddRef();
+ }
+
+ Client->ExitDispatch(pMonitorClient);
+ pMonitorClient->Release();
+ Client->Release();
+ }
+
+ g_MonitorThreadSet = FALSE;
+ }
+}
+
+
+HRESULT
+SetEventCallbacks(
+ PDEBUG_CLIENT Client
+ )
+{
+ HRESULT hr = S_FALSE;
+
+ if (!g_MonitorThreadSet)
+ {
+ MonitorThreadParams NewThreadParams = { Client, FALSE };
+ HANDLE hThread;
+ DWORD ThreadID;
+ LONG PrevMonitorState;
+
+ PrevMonitorState = InterlockedExchange(&g_MonitorState, NEED_DISPATCH);
+ ASSERTMSG("Previous EventMonitor thread was never shutdown properly.\n", PrevMonitorState != DISPATCHED);
+ ASSERTMSG("Previous EventMonitor thread never completed setup.\n", PrevMonitorState != NEED_DISPATCH);
+
+ g_pMonitorClient = NULL;
+
+ hThread = CreateThread(NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)EventMonitorThread,
+ &NewThreadParams,
+ 0,
+ &ThreadID);
+
+ if (hThread)
+ {
+ // Default ExitCode to STILL_ACTIVE since it doesn't matter
+ // if the Params were read before we started checking.
+ DWORD ExitCode = STILL_ACTIVE;
+
+ while (!NewThreadParams.ParamsRead)
+ {
+ ExitCode = 0;
+ if (!GetExitCodeThread(hThread, &ExitCode))
+ DbgPrint("GetExitCodeThread returned error %lx.\n", GetLastError());
+ if (ExitCode != STILL_ACTIVE)
+ {
+ break;
+ }
+
+ Sleep(10);
+ }
+
+ if (ExitCode == STILL_ACTIVE)
+ {
+ hr = S_OK;
+ g_MonitorThreadSet = TRUE;
+ }
+
+ CloseHandle(hThread);
+ }
+ }
+
+ return hr;
+}
+
+
+HRESULT
+EventCallbacksReady(
+ PDEBUG_CLIENT /*Client*/
+ )
+{
+ return (g_MonitorThreadSet && g_MonitorState == DISPATCHED) ? S_OK : S_FALSE;
+}
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/event.hxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/event.hxx
new file mode 100644
index 00000000000..c985eb15105
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/event.hxx
@@ -0,0 +1,37 @@
+// 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 Name:
+
+ event.hxx
+
+Abstract:
+
+ This header file declares event callback routines and classes.
+
+
+--*/
+
+
+#ifndef _EVENT_HXX_
+#define _EVENT_HXX_
+
+#define INVALID_UNIQUE_STATE 0
+
+HRESULT SetEventCallbacks(PDEBUG_CLIENT Client);
+void ReleaseEventCallbacks(PDEBUG_CLIENT Client);
+HRESULT EventCallbacksReady(PDEBUG_CLIENT Client);
+
+extern BOOL gbSymbolsNotLoaded;
+extern ULONG UniqueTargetState;
+
+#endif _EVENT_HXX_
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/flags.cxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/flags.cxx
new file mode 100644
index 00000000000..054acbad5a7
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/flags.cxx
@@ -0,0 +1,366 @@
+// 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.
+
+
+//+----------------------------------------------------------------------------
+//
+
+//
+// Abstract:
+//
+
+#include "precomp.hxx"
+
+
+#define CASEENUM(x) case x: psz = #x; break
+
+static char achFlags[100];
+
+char *pszHRESULT(HRESULT hr)
+{
+ char *psz;
+
+ switch (hr)
+ {
+ case 0: psz = "OK"; break;
+ CASEENUM(S_FALSE);
+ CASEENUM(E_NOTIMPL);
+ CASEENUM(E_OUTOFMEMORY);
+ CASEENUM(E_INVALIDARG);
+ CASEENUM(E_NOINTERFACE);
+ CASEENUM(E_ABORT);
+ CASEENUM(E_FAIL);
+ default:
+ switch (hr & 0xCFFFFFFF)
+ {
+ CASEENUM(STATUS_UNSUCCESSFUL);
+ default:
+ StringCchPrintfA(achFlags, ARRAYSIZE(achFlags), "unknown HRESULT 0x%08lx", hr);
+ psz = achFlags;
+ break;
+ }
+ break;
+ }
+ return(psz);
+}
+
+
+char *pszWinDbgError(ULONG ulError)
+{
+ char *psz;
+
+ switch (ulError)
+ {
+ case 0: psz = "no error"; break;
+ CASEENUM(MEMORY_READ_ERROR);
+ CASEENUM(SYMBOL_TYPE_INDEX_NOT_FOUND);
+ CASEENUM(SYMBOL_TYPE_INFO_NOT_FOUND);
+ CASEENUM(FIELDS_DID_NOT_MATCH);
+ CASEENUM(NULL_SYM_DUMP_PARAM);
+ CASEENUM(NULL_FIELD_NAME);
+ CASEENUM(INCORRECT_VERSION_INFO);
+ CASEENUM(EXIT_ON_CONTROLC);
+ CASEENUM(CANNOT_ALLOCATE_MEMORY);
+ default:
+ StringCchPrintfA(achFlags, ARRAYSIZE(achFlags), "unknown WinDbg error 0x08%x", ulError);
+ psz = achFlags;
+ break;
+ }
+ return(psz);
+}
+
+
+
+/******************************Public*Routine******************************\
+* output standard flags
+*
+*
+\**************************************************************************/
+
+ULONG64
+OutputFlags(
+ __inout OutputControl *OutCtl,
+ __in __nullterminated const FLAGDEF *pFlagDef,
+ ULONG64 fl,
+ BOOL SingleLine
+ )
+{
+ ULONG64 FlagsFound = 0;
+
+ if (fl == 0)
+ {
+ while (pFlagDef->psz != NULL)
+ {
+ if (pFlagDef->fl == 0)
+ {
+ if (!SingleLine) OutCtl->Output("\n ");
+ OutCtl->Output("%s",pFlagDef->psz);
+ }
+
+ pFlagDef++;
+ }
+ }
+ else
+ {
+ while (pFlagDef->psz != NULL)
+ {
+ if (pFlagDef->fl & fl)
+ {
+ if (!SingleLine)
+ {
+ OutCtl->Output("\n ");
+ }
+ else if (FlagsFound)
+ {
+ OutCtl->Output(" | ");
+ }
+
+ OutCtl->Output("%s",pFlagDef->psz);
+
+ if (FlagsFound & pFlagDef->fl)
+ {
+ OutCtl->Output(" (SHARED FLAG)");
+ }
+ FlagsFound |= pFlagDef->fl;
+ }
+
+ pFlagDef++;
+ }
+ }
+
+ return fl & ~FlagsFound;
+}
+
+
+/******************************Public*Routine******************************\
+* output standard enum values
+*
+*
+\**************************************************************************/
+
+BOOL
+OutputEnum(
+ __inout OutputControl *OutCtl,
+ __in __nullterminated const ENUMDEF *pEnumDef,
+ ULONG64 ul
+ )
+{
+ while (pEnumDef->psz != NULL)
+ {
+ if (pEnumDef->ul == ul)
+ {
+ OutCtl->Output(pEnumDef->psz);
+ return (TRUE);
+ }
+
+ pEnumDef++;
+ }
+
+ return (FALSE);
+}
+
+BOOL
+OutputEnumWithParenthesis(
+ __inout OutputControl *OutCtl,
+ __in __nullterminated const ENUMDEF *pEnumDef,
+ ULONG64 ul
+ )
+{
+ while (pEnumDef->psz != NULL)
+ {
+ if (pEnumDef->ul == ul)
+ {
+ OutCtl->Output("(%s)", pEnumDef->psz);
+ return (TRUE);
+ }
+
+ pEnumDef++;
+ }
+
+ return (FALSE);
+}
+
+
+/******************************Public*Routine******************************\
+* Output interpretation of pszField's value if found in pEFEntry
+*
+*
+\**************************************************************************/
+
+BOOL
+OutputFieldValue(
+ __inout OutputControl *OutCtl,
+ __in const EnumFlagEntry *pEFEntry,
+ __in PCSTR pszField,
+ __in const DEBUG_VALUE *Value,
+ __inout PDEBUG_CLIENT Client,
+ BOOL Compact
+ )
+{
+ EnumFlagField *pEFField;
+ DEBUG_VALUE ConvValue;
+
+ if (OutCtl == NULL ||
+ pEFEntry == NULL ||
+ pszField == NULL ||
+ Value == NULL ||
+ Value->Type == DEBUG_VALUE_INVALID)
+ {
+ return FALSE;
+ }
+
+ for (ULONG i = 0; i < pEFEntry->FieldEntries; i++)
+ {
+ pEFField = &pEFEntry->FieldEntry[i];
+
+ if (pEFField->EFType == PARENT_FIELDS)
+ {
+ if (OutputFieldValue(OutCtl, pEFField->Parent, pszField, Value, Client, Compact))
+ {
+ return TRUE;
+ }
+ }
+ else if (strcmp(pszField, pEFField->FieldName) == 0)
+ {
+ switch (pEFField->EFType)
+ {
+ case FLAG_FIELD:
+ {
+ ULONG64 flRem;
+
+ if (Value->Type != DEBUG_VALUE_INT64)
+ {
+ if (OutCtl->CoerceValue(Value, DEBUG_VALUE_INT64, &ConvValue) != S_OK)
+ {
+ return FALSE;
+ }
+ Value = &ConvValue;
+ }
+
+ if (Compact)
+ {
+ OutCtl->Output(" (");
+ }
+ flRem = OutputFlags(OutCtl, pEFField->FlagDef, Value->I64, Compact);
+ if (flRem && ((flRem != 0xffffffff00000000) || !(Value->I64 & 0x80000000)))
+ {
+ if (!Compact) OutCtl->Output("\n ");
+ OutCtl->Output(" Unknown Flags: 0x%I64x", flRem);
+ }
+ if (Compact)
+ {
+ OutCtl->Output(")");
+ }
+ return TRUE;
+ }
+
+ case ENUM_FIELD:
+ case ENUM_FIELD_LIMITED:
+ {
+ if (Value->Type != DEBUG_VALUE_INT64)
+ {
+ if (OutCtl->CoerceValue(Value, DEBUG_VALUE_INT64, &ConvValue) != S_OK)
+ {
+ return FALSE;
+ }
+ Value = &ConvValue;
+ }
+
+ OutCtl->Output(" ");
+ if (!OutputEnumWithParenthesis(OutCtl, pEFField->EnumDef, Value->I64))
+ {
+ if (pEFField->EFType != ENUM_FIELD_LIMITED)
+ {
+ OutCtl->Output("(Unknown Value)", Value->I64);
+ }
+ }
+ return TRUE;
+ }
+
+ case CALL_FUNC:
+ OutCtl->Output(" ");
+ pEFField->EFFunc(OutCtl, Client, Value);
+ return TRUE;
+
+ default:
+ OutCtl->OutErr(" Unknown database entry type.\n");
+ break;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+/******************************Public*Routine******************************\
+* Output interpretations of known fields as stored in EFDatabase
+* (Known flags & enum values as well some special fields.)
+*
+*
+\**************************************************************************/
+
+BOOL
+OutputTypeFieldValue(
+ __inout OutputControl *OutCtl,
+ __in PCSTR pszType,
+ __in PCSTR pszField,
+ __in const DEBUG_VALUE *Value,
+ __inout PDEBUG_CLIENT Client,
+ BOOL Compact,
+ __in __nullterminated const EnumFlagEntry *pEFDatabase
+ )
+{
+ if (OutCtl == NULL ||
+ Value == NULL ||
+ Value->Type == DEBUG_VALUE_INVALID)
+ {
+ return FALSE;
+ }
+
+ BOOL FoundType = FALSE;
+ const EnumFlagEntry *pEFEntry = pEFDatabase;
+
+ for (pEFEntry = pEFDatabase;
+ pEFEntry->TypeName[0] != '\0';
+ pEFEntry++)
+ {
+ if (strcmp(pszType, pEFEntry->TypeName) == 0)
+ {
+ FoundType = TRUE;
+ break;
+ }
+ }
+
+ if (!FoundType)
+ {
+ // Check if this type is a clean typedef
+ // (Test it against database with prefixed
+ // '_'s and 'tag's removed.)
+ for (pEFEntry = pEFDatabase;
+ pEFEntry->TypeName[0] != '\0';
+ pEFEntry++)
+ {
+ if ((pEFEntry->TypeName[0] == '_') ?
+ (strcmp(pszType, &pEFEntry->TypeName[1]) == 0) :
+ (pEFEntry->TypeName[0] == 't' &&
+ pEFEntry->TypeName[1] == 'a' &&
+ pEFEntry->TypeName[2] == 'g' &&
+ strcmp(pszType, &pEFEntry->TypeName[3]) == 0))
+ {
+ FoundType = TRUE;
+ break;
+ }
+ }
+
+ }
+
+ return (FoundType) ?
+ OutputFieldValue(OutCtl, pEFEntry, pszField, Value, Client, Compact) :
+ FALSE;
+}
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/flags.hxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/flags.hxx
new file mode 100644
index 00000000000..b08e70abcb5
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/flags.hxx
@@ -0,0 +1,136 @@
+// 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.
+
+
+//+----------------------------------------------------------------------------
+//
+
+//
+// Abstract:
+//
+
+#pragma once
+
+
+
+typedef struct _ENUMDEF {
+ char *psz; // description
+ ULONG64 ul; // enum value
+} ENUMDEF;
+
+// The following define expands 'ENUM(x)' to '"x", x':
+
+#define ENUM(x) { #x, x }
+
+#define END_ENUM { 0, 0 }
+
+
+typedef struct _FLAGDEF {
+ char *psz; // description
+ ULONG64 fl; // flag
+} FLAGDEF;
+
+// The following define expands 'FLAG(x)' to '"x", x':
+
+#define FLAG(x) { #x, x }
+
+#define END_FLAG { 0, 0 }
+
+
+
+
+extern char *pszHRESULT(HRESULT hr);
+extern char *pszWinDbgError(ULONG ulError);
+
+
+enum EnumFlagType {
+ ENUM_FIELD,
+ ENUM_FIELD_LIMITED, // Enum list is not a complete list of valid values
+ FLAG_FIELD,
+ PARENT_FIELDS,
+ CALL_FUNC
+};
+
+
+typedef struct _EnumFlagEntry EnumFlagEntry;
+
+typedef struct _EnumFlagField {
+ CHAR FieldName[MAX_PATH];
+
+ EnumFlagType EFType;
+
+ union {
+ void *Param; // To alleviate casting in declarations
+ FLAGDEF *FlagDef;
+ ENUMDEF *EnumDef;
+ EnumFlagEntry *Parent;
+ HRESULT (*EFFunc)(__inout OutputControl*, __inout PDEBUG_CLIENT, __in const DEBUG_VALUE *);
+ };
+
+} EnumFlagField;
+
+
+typedef struct _EnumFlagEntry {
+ __nullterminated CHAR TypeName[MAX_PATH];
+ ULONG TypeId;
+ ULONG FieldEntries;
+ EnumFlagField *FieldEntry;
+} EnumFlagEntry;
+
+#define EFTypeEntry(type) { #type, 0, ARRAYSIZE(aeff##type), aeff##type}
+
+
+
+ULONG64
+OutputFlags(
+ __inout OutputControl *OutCtl,
+ __in __nullterminated const FLAGDEF *pFlagDef,
+ ULONG64 fl,
+ BOOL SingleLine
+ );
+
+BOOL
+OutputEnum(
+ __inout OutputControl *OutCtl,
+ __in __nullterminated const ENUMDEF *pEnumDef,
+ ULONG64 ul
+ );
+
+BOOL
+OutputEnumWithParenthesis(
+ __inout OutputControl *OutCtl,
+ __in __nullterminated const ENUMDEF *pEnumDef,
+ ULONG64 ul
+ );
+
+BOOL
+OutputFieldValue(
+ __inout OutputControl *OutCtl,
+ __in const EnumFlagEntry *pEFEntry,
+ __in PCSTR pszField,
+ __in const DEBUG_VALUE *Value,
+ __inout PDEBUG_CLIENT Client,
+ BOOL Compact
+ );
+
+//
+// This global must be defined by caller of OutputTypeFieldValue unless
+// pEFDatabase is always passed in.
+// The final value in the array must be { "", 0, 0, NULL}
+//
+extern EnumFlagEntry EFDatabase[];
+
+BOOL
+OutputTypeFieldValue(
+ __inout OutputControl *OutCtl,
+ __in PCSTR pszType,
+ __in PCSTR pszField,
+ __in const DEBUG_VALUE *Value,
+ __inout PDEBUG_CLIENT Client,
+ BOOL Compact,
+ __in __nullterminated const EnumFlagEntry *pEFDatabase = EFDatabase
+ );
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/input.cxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/input.cxx
new file mode 100644
index 00000000000..5096157cd58
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/input.cxx
@@ -0,0 +1,78 @@
+// 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 Name:
+
+ input.cxx
+
+Abstract:
+
+ This file contains the routines to get user input.
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include "precomp.hxx"
+
+
+
+HRESULT
+GetYNInput(
+ PDEBUG_CONTROL Control,
+ PCSTR Prompt
+ )
+{
+ HRESULT hr;
+ CHAR Response[4];
+ ULONG ResponseLen;
+
+ Control->Output(DEBUG_OUTPUT_NORMAL, "%s yn\n", Prompt);
+
+ do
+ {
+ hr = Control->Input(Response, sizeof(Response), &ResponseLen);
+
+ if (hr == E_ABORT) break;
+
+ if (hr == S_OK)
+ {
+ if (ResponseLen != 2)
+ {
+ hr = E_INVALIDARG;
+ }
+ else
+ {
+ Response[0] = (CHAR)tolower(Response[0]);
+
+ if (Response[0] != 'y' && Response[0] != 'n')
+ {
+ hr = E_INVALIDARG;
+ }
+ }
+ }
+
+ if (hr != S_OK)
+ {
+ Control->Output(DEBUG_OUTPUT_WARNING, " Please answer y or n.\n");
+ }
+ } while (hr != S_OK);
+
+ if (hr == S_OK && Response[0] != 'y')
+ {
+ hr = S_FALSE;
+ }
+
+ return hr;
+}
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/input.hxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/input.hxx
new file mode 100644
index 00000000000..210edc17447
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/input.hxx
@@ -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.
+
+
+/*++
+
+
+
+Module Name:
+
+ input.hxx
+
+Abstract:
+
+ This header file declares routine for getting user input.
+
+--*/
+
+
+#ifndef _INPUT_HXX_
+#define _INPUT_HXX_
+
+HRESULT GetYNInput(PDEBUG_CONTROL Control, PCSTR Prompt);
+
+#endif _INPUT_HXX_
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/minnt.h b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/minnt.h
new file mode 100644
index 00000000000..09d1f19386a
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/minnt.h
@@ -0,0 +1,105 @@
+// 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.
+
+
+//-----------------------------------------------------------------------------
+//
+
+//
+// The following are copied from various NT headers, primarily wdm.h. I could
+// not figure out a way of including wdm.h and windows.h together.
+//
+// These APIs are primarily intended for device drivers, but are technically
+// available to user mode code via exports in ntdll.dll.
+//
+//-----------------------------------------------------------------------------
+
+#define DbgBreakPoint __debugbreak
+
+extern "C" {
+ ULONG __cdecl DbgPrint(PCSTR, ...);
+ __declspec(dllimport) void __stdcall RtlAssert(PVOID, PVOID, ULONG, PSTR);
+}
+
+#if DBG
+#define ASSERTMSG( msg, exp ) \
+ ((!(exp)) ? \
+ (RtlAssert( #exp, __FILE__, __LINE__, msg ),FALSE) : \
+ TRUE)
+#else
+#define ASSERTMSG( msg, exp ) ((void) 0)
+#endif // DBG
+
+#define NTSTATUS LONG
+#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
+#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL)
+#define STATUS_COMMITMENT_LIMIT ((NTSTATUS)0xC000012DL)
+
+FORCEINLINE
+VOID
+InitializeListHead(
+ __out PLIST_ENTRY ListHead
+ )
+{
+ ListHead->Flink = ListHead->Blink = ListHead;
+}
+
+__checkReturn
+BOOLEAN
+FORCEINLINE
+IsListEmpty(
+ __in const LIST_ENTRY * ListHead
+ )
+{
+ return (BOOLEAN)(ListHead->Flink == ListHead);
+}
+
+FORCEINLINE
+BOOLEAN
+RemoveEntryList(
+ __in PLIST_ENTRY Entry
+ )
+{
+ PLIST_ENTRY Blink;
+ PLIST_ENTRY Flink;
+
+ Flink = Entry->Flink;
+ Blink = Entry->Blink;
+ Blink->Flink = Flink;
+ Flink->Blink = Blink;
+ return (BOOLEAN)(Flink == Blink);
+}
+
+FORCEINLINE
+PLIST_ENTRY
+RemoveHeadList(
+ __inout PLIST_ENTRY ListHead
+ )
+{
+ PLIST_ENTRY Flink;
+ PLIST_ENTRY Entry;
+
+ Entry = ListHead->Flink;
+ Flink = Entry->Flink;
+ ListHead->Flink = Flink;
+ Flink->Blink = ListHead;
+ return Entry;
+}
+
+FORCEINLINE
+VOID
+InsertTailList(
+ __inout PLIST_ENTRY ListHead,
+ __inout __drv_aliasesMem PLIST_ENTRY Entry
+ )
+{
+ PLIST_ENTRY Blink;
+
+ Blink = ListHead->Blink;
+ Entry->Flink = ListHead;
+ Entry->Blink = Blink;
+ Blink->Flink = Entry;
+ ListHead->Blink = Entry;
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/output.cxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/output.cxx
new file mode 100644
index 00000000000..741ed178fbe
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/output.cxx
@@ -0,0 +1,1675 @@
+// 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 Name:
+
+ output.cxx
+
+Abstract:
+
+ This file contains output state control and output callback classes.
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include "precomp.hxx"
+
+
+HRESULT
+OutputControl::SetControl(
+ ULONG OutputControl,
+ __in_opt PDEBUG_CLIENT Client
+ )
+{
+ ULONG SendMask = OutputControl & DEBUG_OUTCTL_SEND_MASK;
+
+ if (OutputControl != DEBUG_OUTCTL_AMBIENT &&
+ (
+#if DEBUG_OUTCTL_THIS_CLIENT > 0
+ SendMask < DEBUG_OUTCTL_THIS_CLIENT ||
+#endif
+ SendMask > DEBUG_OUTCTL_LOG_ONLY ||
+ (OutputControl & ~(DEBUG_OUTCTL_SEND_MASK |
+ DEBUG_OUTCTL_NOT_LOGGED |
+ DEBUG_OUTCTL_OVERRIDE_MASK))))
+ {
+ return E_INVALIDARG;
+ }
+
+ if (Client != NULL)
+ {
+ HRESULT hr;
+ PDEBUG_CONTROL NewControl;
+
+ // Switch to new client
+ if ((hr = Client->QueryInterface(__uuidof(IDebugControl),
+ (void **)&NewControl)) != S_OK)
+ {
+ return hr;
+ }
+
+ if (Control != NULL) Control->Release();
+ Control = NewControl;
+ }
+
+ OutCtl = OutputControl;
+
+ return S_OK;
+}
+
+
+HRESULT
+OutputControl::SetOutputLinePrefix(
+ __in_opt PCSTR Prefix
+ )
+{
+ HRESULT hr = S_OK;
+
+ size_t PrefixLength = 0;
+
+ if (Prefix)
+ {
+ PrefixLength = strlen(Prefix) + 1;
+ }
+
+ if (!Prefix || PrefixLength > 0)
+ {
+ delete [] OutputLinePrefix;
+ OutputLinePrefix = NULL;
+ }
+
+ if (PrefixLength > 0)
+ {
+ OutputLinePrefix = new char[PrefixLength];
+ if (!OutputLinePrefix)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ hr = StringCchCopyA(OutputLinePrefix, PrefixLength, Prefix);
+ }
+ }
+
+ return hr;
+}
+
+
+HRESULT
+OutputControl::Output(
+ ULONG Mask,
+ __in PCSTR Format,
+ ...
+ )
+{
+ HRESULT hr;
+ va_list Args;
+
+ if (Control == NULL) return E_FAIL;
+
+ va_start(Args, Format);
+ if (OutCtl == DEBUG_OUTCTL_AMBIENT)
+ {
+ if (OutputLinePrefix)
+ {
+ Control->Output(Mask, "%s", OutputLinePrefix);
+ }
+ hr = Control->OutputVaList(Mask, Format, Args);
+ }
+ else
+ {
+ hr = Control->ControlledOutputVaList(OutCtl, Mask, Format, Args);
+ }
+ va_end(Args);
+
+ return hr;
+}
+
+HRESULT
+OutputControl::OutputVaList(
+ ULONG Mask,
+ __in PCSTR Format,
+ va_list Args
+ )
+{
+ HRESULT hr;
+
+ if (Control == NULL) return E_FAIL;
+
+ if (OutCtl == DEBUG_OUTCTL_AMBIENT)
+ {
+ if (OutputLinePrefix)
+ {
+ Control->Output(Mask, "%s", OutputLinePrefix);
+ }
+ hr = Control->OutputVaList(Mask, Format, Args);
+ }
+ else
+ {
+ hr = Control->ControlledOutputVaList(OutCtl, Mask, Format, Args);
+ }
+
+ return hr;
+}
+
+HRESULT
+OutputControl::Output(
+ __in PCSTR Format,
+ ...
+ )
+{
+ HRESULT hr;
+ va_list Args;
+
+ va_start(Args, Format);
+ hr = OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
+ va_end(Args);
+
+ return hr;
+}
+
+HRESULT
+OutputControl::OutErr(
+ __in PCSTR Format,
+ ...
+ )
+{
+ HRESULT hr;
+ va_list Args;
+
+ va_start(Args, Format);
+ hr = OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args);
+ va_end(Args);
+
+ return hr;
+}
+
+HRESULT
+OutputControl::OutWarn(
+ __in PCSTR Format,
+ ...
+ )
+{
+ HRESULT hr;
+ va_list Args;
+
+ va_start(Args, Format);
+ hr = OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args);
+ va_end(Args);
+
+ return hr;
+}
+
+HRESULT
+OutputControl::OutVerb(
+ __in PCSTR Format,
+ ...
+ )
+{
+ HRESULT hr;
+ va_list Args;
+
+ va_start(Args, Format);
+ hr = OutputVaList(DEBUG_OUTPUT_VERBOSE, Format, Args);
+ va_end(Args);
+
+ return hr;
+}
+
+HRESULT
+OutputControl::OutExtWarn(
+ __in PCSTR Format,
+ ...
+ )
+{
+ HRESULT hr;
+ va_list Args;
+
+ va_start(Args, Format);
+ hr = OutputVaList(DEBUG_OUTPUT_EXTENSION_WARNING, Format, Args);
+ va_end(Args);
+
+ return hr;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// OutputControl::OutputOffset
+//
+// Synopsis:
+// Output an offset stylized to targets native pointer size
+//
+//-----------------------------------------------------------------------------
+
+HRESULT
+OutputControl::OutputOffset(
+ ULONG64 Offset
+ )
+{
+ HRESULT hr = IsPointer64Bit();
+
+ if (SUCCEEDED(hr))
+ {
+ if (hr == S_OK)
+ {
+ hr = Output("%08x`%08x", HIDWORD(Offset), LODWORD(Offset));
+ }
+ else
+ {
+ hr = Output("%08x", LODWORD(Offset));
+ }
+ }
+
+ return hr;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// OutputControl::OutputStackTrace
+//
+// Synopsis:
+// Output stack trace under curent control setting
+//
+//-----------------------------------------------------------------------------
+
+HRESULT
+OutputControl::OutputStackTrace(
+ __in_ecount_opt(FramesSize) PDEBUG_STACK_FRAME Frames,
+ ULONG FramesSize,
+ ULONG Flags
+ )
+{
+ return Control->OutputStackTrace(
+ OutCtl,
+ Frames,
+ FramesSize,
+ Flags
+ );
+}
+
+
+HRESULT
+OutputControl::GetInterrupt(
+ )
+{
+ return (Control == NULL) ?
+ E_FAIL :
+ Control->GetInterrupt();
+}
+
+
+HRESULT
+OutputControl::SetInterrupt(
+ ULONG Flags
+ )
+{
+ return (Control == NULL) ?
+ E_FAIL :
+ Control->SetInterrupt(Flags);
+}
+
+
+HRESULT
+OutputControl::Evaluate(
+ __in PCSTR Expression,
+ ULONG DesiredType,
+ __out PDEBUG_VALUE Value,
+ __out_opt PULONG RemainderIndex
+ )
+{
+ return (Control == NULL) ?
+ E_FAIL :
+ Control->Evaluate(Expression,
+ DesiredType,
+ Value,
+ RemainderIndex);
+}
+
+HRESULT
+OutputControl::Execute(
+ __in PCSTR Command,
+ ULONG Flags
+ )
+{
+ return (Control == NULL) ?
+ E_FAIL :
+ Control->Execute(OutCtl, Command, Flags);
+}
+
+
+HRESULT
+OutputControl::CoerceValue(
+ __in const DEBUG_VALUE *In,
+ ULONG OutType,
+ __out PDEBUG_VALUE Out
+ )
+{
+ return (Control == NULL) ?
+ E_FAIL :
+ Control->CoerceValue(const_cast(In),
+ OutType,
+ Out);
+}
+
+
+HRESULT
+OutputControl::IsPointer64Bit(
+ )
+{
+ return (Control == NULL) ?
+ E_FAIL :
+ Control->IsPointer64Bit();
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Class: OutputState
+//
+// Synopsis:
+//
+//-----------------------------------------------------------------------------
+
+OutputState::OutputState(
+ __in_opt PDEBUG_CLIENT OrgClient,
+ BOOL SameClient
+ )
+{
+ hrInit = S_FALSE;
+ Client = NULL;
+ Control = NULL;
+ Symbols = NULL;
+
+ SetCallbacks = FALSE;
+
+ CreatedClient = FALSE;
+ Saved = FALSE;
+
+ if (OrgClient != NULL)
+ {
+ if (SameClient)
+ {
+ Client = OrgClient;
+ Client->AddRef();
+ CreatedClient = TRUE;
+ hrInit = S_OK;
+ }
+ else
+ {
+ hrInit = OrgClient->CreateClient(&Client);
+ }
+ }
+}
+
+
+OutputState::~OutputState()
+{
+ if (!CreatedClient) Restore();
+
+ if (Symbols) { Symbols->Release(); }
+ if (Control) { Control->Release(); }
+
+ // If Client was newly created for OutputState, then
+ // there shouldn't be any other references to Client.
+ if (CreatedClient)
+ {
+ ULONG RemainingRefs;
+
+ RemainingRefs = Client->AddRef();
+ if (RemainingRefs > 2)
+ {
+ DbgPrint("OutputState: %lu refs outstanding on created client.\n",
+ RemainingRefs-2);
+ DbgBreakPoint();
+
+ // As a precaution, Restore the callbacks;
+ // so, any set callback may be cleaned up.
+ Restore();
+ }
+ Client->Release();
+ }
+
+ if (Client != NULL) Client->Release();
+}
+
+
+HRESULT
+OutputState::Setup(
+ ULONG OutMask,
+ __in_opt PDEBUG_OUTPUT_CALLBACKS OutCallbacks
+ )
+{
+ HRESULT hr = hrInit;
+ ULONG LastOutMask;
+
+ if (hr == S_OK)
+ {
+ if (CreatedClient && !Saved)
+ {
+ if ((hr = Client->GetOutputMask(&OrgOutMask)) == S_OK &&
+ (hr = Client->GetOutputCallbacks(&OrgOutCallbacks)) == S_OK)
+ {
+ Saved = TRUE;
+ }
+ }
+
+ if (hr == S_OK &&
+ (hr = Client->GetOutputMask(&LastOutMask)) == S_OK &&
+ (hr = Client->SetOutputMask(OutMask)) == S_OK)
+ {
+ if (!Saved && !SetCallbacks)
+ {
+ OrgOutMask = LastOutMask;
+ OrgOutCallbacks = NULL;
+ }
+
+ if ((hr = Client->SetOutputCallbacks(OutCallbacks)) == S_OK)
+ {
+ SetCallbacks = TRUE;
+ }
+ else
+ {
+ Client->SetOutputMask(LastOutMask);
+ }
+ }
+ }
+
+
+ if (hr == S_OK &&
+ Symbols == NULL)
+ {
+ hr = Client->QueryInterface(__uuidof(IDebugSymbols), (void **)&Symbols);
+ }
+
+ return hr;
+}
+
+
+HRESULT
+OutputState::Execute(
+ __in PCSTR pszCommand
+ )
+{
+ HRESULT hr = hrInit;
+
+ if (hr == S_OK)
+ {
+ if (Control == NULL)
+ {
+ hr = Client->QueryInterface(__uuidof(IDebugControl), (void **)&Control);
+ }
+
+ if (hr == S_OK)
+ {
+ hr = Control->Execute(DEBUG_OUTCTL_THIS_CLIENT |
+ DEBUG_OUTCTL_NOT_LOGGED |
+ DEBUG_OUTCTL_OVERRIDE_MASK,
+ pszCommand,
+ DEBUG_EXECUTE_NOT_LOGGED |
+ DEBUG_EXECUTE_NO_REPEAT);
+
+ if (hr != S_OK)
+ {
+ DbgPrint("IDebugControl::Execute returned %s.\n",
+ pszHRESULT(hr));
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+HRESULT
+OutputState::OutputType(
+ BOOL Physical,
+ ULONG64 Offset,
+ __in PCSTR Type,
+ ULONG Flags
+ )
+{
+ HRESULT hr = hrInit;
+
+ if (hr == S_OK)
+ {
+ if (Symbols == NULL)
+ {
+ hr = Client->QueryInterface(__uuidof(IDebugSymbols), (void **)&Symbols);
+ }
+
+ if (hr == S_OK)
+ {
+ ULONG64 Module;
+ ULONG TypeId;
+
+ hr = GetTypeId(Client, Type, &TypeId, &Module);
+
+ if (hr != S_OK)
+ {
+ OutputControl OutCtl(Client);
+ ULONG ModuleIndex = 0;
+
+ while ((hr = Symbols->GetModuleByIndex(ModuleIndex, &Module)) == S_OK &&
+ (Module != 0))
+ {
+ if ((hr = Symbols->GetTypeId(Module, Type, &TypeId)) == S_OK)
+ {
+ OutCtl.OutVerb("Found %s: TypeId 0x%lx in module @ %p.\n",
+ Type, TypeId, Module);
+ break;
+ }
+
+ ModuleIndex++;
+ Module = 0;
+ }
+
+ if (hr == S_OK &&
+ (Module == 0 || TypeId == 0))
+ {
+ hr = S_FALSE;
+ }
+
+ if (hr != S_OK)
+ {
+ OutCtl.OutVerb("Couldn't find %s in any of %lu modules.\n",
+ Type, ModuleIndex);
+ }
+ }
+
+ if (hr == S_OK)
+ {
+ hr = OutputType(Physical, Offset, Module, TypeId, Flags);
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+HRESULT
+OutputState::OutputType(
+ BOOL Physical,
+ ULONG64 Offset,
+ ULONG64 Module,
+ ULONG TypeId,
+ ULONG Flags
+ )
+{
+ HRESULT hr = hrInit;
+
+ if (hr == S_OK)
+ {
+ if (Symbols == NULL)
+ {
+ hr = Client->QueryInterface(__uuidof(IDebugSymbols), (void **)&Symbols);
+ }
+
+ if (hr == S_OK)
+ {
+ if (Physical)
+ {
+ hr = Symbols->OutputTypedDataPhysical(DEBUG_OUTCTL_THIS_CLIENT |
+ DEBUG_OUTCTL_NOT_LOGGED |
+ DEBUG_OUTCTL_OVERRIDE_MASK,
+ Offset,
+ Module,
+ TypeId,
+ Flags);
+ }
+ else
+ {
+ hr = Symbols->OutputTypedDataVirtual(DEBUG_OUTCTL_THIS_CLIENT |
+ DEBUG_OUTCTL_NOT_LOGGED |
+ DEBUG_OUTCTL_OVERRIDE_MASK,
+ Offset,
+ Module,
+ TypeId,
+ Flags);
+ }
+
+ if (hr != S_OK)
+ {
+ DbgPrint("IDebugSymbols::OutputTypedData%s returned %s for 0x%I64x.\n",
+ (Physical ? "Physical" : "Virtual"),
+ pszHRESULT(hr),
+ Offset);
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+void OutputState::Restore()
+{
+ if (SetCallbacks)
+ {
+ Client->SetOutputCallbacks(OrgOutCallbacks);
+ Client->SetOutputMask(OrgOutMask);
+
+ SetCallbacks = FALSE;
+ }
+
+ if (Saved)
+ {
+ if (OrgOutCallbacks != NULL) OrgOutCallbacks->Release();
+ Saved = FALSE;
+ }
+}
+
+
+
+//----------------------------------------------------------------------------
+//
+// Default output callbacks implementation, provides IUnknown for
+// static classes.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+DefOutputCallbacks::QueryInterface(
+ THIS_
+ IN REFIID InterfaceId,
+ OUT PVOID* Interface
+ )
+{
+ *Interface = NULL;
+
+ if (//(InterfaceId == IID_IUnknown) ||
+ (InterfaceId == __uuidof(IDebugOutputCallbacks)))
+ {
+ *Interface = (IDebugOutputCallbacks *)this;
+ AddRef();
+ return S_OK;
+ }
+ else
+ {
+ return E_NOINTERFACE;
+ }
+}
+
+STDMETHODIMP_(ULONG)
+DefOutputCallbacks::AddRef(
+ THIS
+ )
+{
+ // This class is designed to be allocated on a
+ // stack or statically, but we retain a refcount
+ // for debugging purposes.
+ return ++RefCount;
+}
+
+STDMETHODIMP_(ULONG)
+DefOutputCallbacks::Release(
+ THIS
+ )
+{
+ // This class is designed to be allocated on a
+ // stack or statically, but we retain a refcount
+ // for debugging purposes.
+ RefCount--;
+
+ if (RefCount < 1)
+ {
+ DbgPrint("DefOutputCallbacks@0x%p::RefCount(%lu) < 1.\n", this, RefCount);
+ DbgBreakPoint();
+ }
+
+ return RefCount;
+}
+
+STDMETHODIMP
+DefOutputCallbacks::Output(
+ THIS_
+ IN ULONG /*Mask*/,
+ IN PCSTR /*Text*/
+ )
+{
+ // The default Output ignores all Output calls.
+ return S_OK;
+}
+
+
+//----------------------------------------------------------------------------
+//
+// DebugOutputCallbacks::Output
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+DebugOutputCallbacks::Output(
+ THIS_
+ IN ULONG Mask,
+ IN PCSTR Text
+ )
+{
+ DbgPrint("Mask: 0x%lx\tOutput Begin:\n%s:Output End\n", Mask, Text);
+
+ return S_OK;
+}
+
+
+//----------------------------------------------------------------------------
+//
+// OutputReader
+//
+// General DebugOutputCallback class to parse output.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+OutputReader::Output(
+ THIS_
+ IN ULONG /*Mask*/,
+ IN PCSTR Text
+ )
+{
+ SIZE_T TextLen = strlen(Text);
+
+ if (BufferLeft < TextLen)
+ {
+ PSTR NewBuffer;
+ SIZE_T NewBufferSize;
+
+ if (hHeap == NULL)
+ {
+ hHeap = GetProcessHeap();
+ if (hHeap == NULL) return S_FALSE;
+ }
+
+ // New length we need plus some extra space
+ NewBufferSize = BufferSize + TextLen + 256;
+
+ NewBuffer = (PSTR) ((Buffer == NULL) ?
+ HeapAlloc(hHeap, 0, NewBufferSize):
+ HeapReAlloc(hHeap, 0, Buffer, NewBufferSize));
+
+ if (NewBuffer == NULL)
+ {
+ DbgPrint("Buffer alloc failed.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ // How much was really allocated?
+ NewBufferSize = HeapSize(hHeap, 0, NewBuffer);
+
+ // If this was the first alloc, initialize
+ // buffer and account for terminating zero.
+ if (Buffer == NULL)
+ {
+ NewBuffer[0] = '\0';
+ BufferLeft = static_cast(-1);
+ }
+
+ // Update buffer data
+ Buffer = NewBuffer;
+ BufferLeft += NewBufferSize - BufferSize;
+ BufferSize = NewBufferSize;
+ }
+
+ // Append new text
+ StringCbCatA(Buffer, BufferSize, Text);
+ BufferLeft -= TextLen;
+
+ return S_OK;
+}
+
+
+// Discard any text left unused by Parse
+void
+OutputReader::DiscardOutput()
+{
+ if (Buffer != NULL)
+ {
+ Buffer[0] = '\0';
+ BufferLeft = BufferSize - 1;
+ }
+}
+
+
+// Get a copy of the output buffer
+HRESULT
+OutputReader::GetOutputCopy(
+ __deref_out PSTR *Copy
+ )
+{
+ if (Copy == NULL) return E_INVALIDARG;
+
+ *Copy = NULL;
+
+ if (Buffer == NULL) return S_OK;
+
+ SIZE_T BufferLength = BufferSize - BufferLeft;
+
+ *Copy = reinterpret_cast(HeapAlloc(hHeap, 0, BufferLength));
+
+ if (*Copy != NULL)
+ {
+ RtlCopyMemory(*Copy, Buffer, BufferLength);
+ return S_OK;
+ }
+
+ return E_OUTOFMEMORY;
+}
+
+
+//----------------------------------------------------------------------------
+//
+// OutputParser
+//
+// General DebugOutputCallback class to parse output.
+//
+//----------------------------------------------------------------------------
+
+HRESULT
+OutputParser::ParseOutput(FLONG Flags)
+{
+ HRESULT hr;
+ ULONG TextRemainingIndex;
+
+ if (Buffer == NULL)
+ {
+ return S_OK;
+ }
+
+ if (Flags & PARSE_OUTPUT_ALL)
+ {
+ UnparsedIndex = 0;
+ }
+
+ if ((hr = Parse(Buffer + UnparsedIndex, &TextRemainingIndex)) == S_OK)
+ {
+ UnparsedIndex += TextRemainingIndex;
+
+ if (((Flags & PARSE_OUTPUT_NO_DISCARD) == 0) &&
+ (UnparsedIndex > 0))
+ {
+ RtlMoveMemory(Buffer,
+ Buffer + UnparsedIndex,
+ BufferSize - UnparsedIndex - BufferLeft + 1);
+
+ BufferLeft += UnparsedIndex;
+ UnparsedIndex = 0;
+ }
+ }
+
+ return hr;
+}
+
+
+void
+OutputParser::DiscardOutput()
+{
+ OutputReader::DiscardOutput();
+ UnparsedIndex = 0;
+}
+
+
+//----------------------------------------------------------------------------
+//
+// BasicOutputParser
+//
+// Basic DebugOutputCallback class to parse output looking for
+// string keys and subsequent values.
+//
+//----------------------------------------------------------------------------
+
+HRESULT
+BasicOutputParser::LookFor(
+ PDEBUG_VALUE Value,
+ PCSTR Key,
+ ULONG Type,
+ ULONG Radix
+ )
+{
+ if ((1 > strlen(Key)) || (strlen(Key) >= ARRAYSIZE(Entries->Key)))
+ {
+ return E_INVALIDARG;
+ }
+
+ if (NumEntries >= MaxEntries) return E_OUTOFMEMORY;
+
+ Entries[NumEntries].Value = Value;
+ StringCchCopyA(Entries[NumEntries].Key, ARRAYSIZE(Entries[NumEntries].Key), Key);
+
+ if (Value != NULL)
+ {
+ Value->Type = DEBUG_VALUE_INVALID;
+
+ if (Radix == PARSER_UNSPECIFIED_RADIX)
+ {
+ // Set Radix to Hex since value is likely to be an address
+ // Otherwise type a deafult of decimal.
+ Radix = (Type == DEBUG_VALUE_INT64) ? 16 : 10;
+ }
+
+ Entries[NumEntries].Type = Type;
+ Entries[NumEntries].Radix = Radix;
+ }
+
+ NumEntries++;
+
+ return S_OK;
+}
+
+HRESULT
+BasicOutputParser::Parse(
+ IN PCSTR Text,
+ OUT OPTIONAL PULONG RemainderIndex
+ )
+{
+ HRESULT hr = S_OK;
+ PCSTR pStrUnused = Text;
+ PCSTR pStr;
+ ULONG EvalLen;
+
+// DbgPrint("BasicOutputParser::Parse: Searching \"%s\"\n", pStrUnused);
+
+ while (CurEntry < NumEntries)
+ {
+ pStr = strstr(pStrUnused, Entries[CurEntry].Key);
+ if (pStr == NULL)
+ {
+ break;
+ }
+
+ pStr += strlen(Entries[CurEntry].Key);
+
+ if (Entries[CurEntry].Value != NULL)
+ {
+ hr = Evaluate(Client,
+ pStr,
+ Entries[CurEntry].Type,
+ Entries[CurEntry].Radix,
+ Entries[CurEntry].Value,
+ &EvalLen);
+
+ if (hr != S_OK)
+ {
+ DbgPrint("Evaluate returned HRESULT 0x%lx.\n", hr);
+ break;
+ }
+
+// DbgPrint("BasicOutputParser::Parse: Found 0x%I64x after \"%s\".\n", Entries[CurEntry].Value->I64, Entries[CurEntry].Key);
+
+ pStr += EvalLen;
+ }
+
+ CurEntry++;
+ pStrUnused = pStr;
+ }
+
+ if (RemainderIndex != NULL)
+ {
+ *RemainderIndex = (ULONG)(pStrUnused - Text);
+ }
+
+ return hr;
+}
+
+
+//----------------------------------------------------------------------------
+//
+// BitFieldParser
+//
+// DebugOutputCallback class to parse bitfield type output
+//
+//----------------------------------------------------------------------------
+
+BitFieldParser::BitFieldParser(
+ PDEBUG_CLIENT Client,
+ BitFieldInfo *BFI
+ ) :
+ BitFieldReader(Client, 2)
+{
+ if (BFI != NULL &&
+ BitFieldReader.LookFor(&BitPos, ": Pos ", DEBUG_VALUE_INT32) == S_OK &&
+ BitFieldReader.LookFor(&Bits, ", ", DEBUG_VALUE_INT32) == S_OK)
+ {
+ BitField = BFI;
+ BitField->Valid = FALSE;
+ BitField->BitPos = 0;
+ BitField->Bits = 0;
+ BitField->Mask = 0;
+ }
+ else
+ {
+ BitField = NULL;
+ }
+}
+
+
+HRESULT
+BitFieldParser::Parse(
+ IN PCSTR Text,
+ OUT OPTIONAL PULONG RemainderIndex
+ )
+{
+ PCSTR pStrUnused = Text;
+ ULONG UnusedIndex = 0;
+ PCSTR pStrRemaining;
+ BitFieldInfo Field;
+
+ do
+ {
+ if (BitFieldReader.Complete() == S_OK)
+ {
+ BitFieldReader.Relook();
+ }
+
+ BitFieldReader.Parse(pStrUnused, &UnusedIndex);
+ pStrUnused += UnusedIndex;
+
+ if (BitFieldReader.Complete() != S_OK)
+ {
+ break;
+ }
+
+ if (!BitField->Valid)
+ {
+ BitField->Valid = BitField->Compose(BitPos.I32, Bits.I32);
+ }
+ else
+ {
+ // Full extent of bit fields seen so far
+ BitField->Bits = Bits.I32 + BitPos.I32 - BitField->BitPos;
+
+ // Full mask of bit fields seen so far
+ if (Field.Compose(BitPos.I32, Bits.I32))
+ {
+ BitField->Mask |= Field.Mask;
+ }
+ }
+
+ // See if there is anything else we might want to parse.
+ pStrRemaining = pStrUnused;
+ while (isspace(*reinterpret_cast(pStrRemaining)) || *pStrRemaining == '\n')
+ {
+ pStrRemaining++;
+ }
+ } while (*pStrRemaining != '\0');
+
+ if (RemainderIndex != NULL)
+ {
+ *RemainderIndex = (ULONG)(pStrUnused - Text);
+ }
+
+ return S_OK;
+}
+
+
+
+//----------------------------------------------------------------------------
+//
+// OutputFilter
+//
+// DebugOutputCallback class to filter output
+// by skipping/replacing lines.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+OutputFilter::Output(
+ THIS_
+ IN ULONG Mask,
+ IN PCSTR Text
+ )
+{
+ return (Outputing) ?
+ S_OK :
+ OutputReader::Output(Mask, Text);
+}
+
+
+HRESULT
+OutputFilter::Query(
+ PCSTR Query,
+ PDEBUG_VALUE Value,
+ ULONG Type,
+ ULONG Radix
+ )
+{
+ if (Query == NULL) return E_INVALIDARG;
+
+ if (Buffer == NULL) return S_FALSE;
+
+ HRESULT hr;
+ BasicOutputParser Parser(Client, 1);
+
+ if ((hr = Parser.LookFor(Value, Query, Type, Radix)) == S_OK &&
+ (hr = Parser.Parse(Buffer, NULL)) == S_OK)
+ {
+ hr = Parser.Complete();
+ }
+
+ return hr;
+}
+
+
+OutputFilter::QuerySpec::QuerySpec(
+ ULONG QueryFlags,
+ PCSTR QueryText
+ )
+{
+ Next = NULL;
+ Flags = QueryFlags;
+ QueryLen = (QueryText == NULL) ? 0 : strlen(QueryText);
+ if (QueryLen)
+ {
+ Query = new CHAR[QueryLen + 1];
+ if (Query == NULL)
+ {
+ QueryLen = 0;
+ }
+ else
+ {
+ StringCchCopyA(Query, QueryLen + 1, QueryText);
+ }
+ }
+ else
+ {
+ Query = NULL;
+ }
+}
+
+
+OutputFilter::ReplacementSpec::ReplacementSpec(
+ ULONG QueryFlags,
+ PCSTR QueryText,
+ PCSTR ReplacementText
+ ) : QuerySpec(QueryFlags, QueryText)
+{
+ ReplacementLen = (ReplacementText== NULL) ? 0 : strlen(ReplacementText);
+ if (ReplacementLen)
+ {
+ Replacement = new CHAR[ReplacementLen + 1];
+ if (Replacement == NULL)
+ {
+ ReplacementLen = 0;
+ }
+ else
+ {
+ StringCchCopyA(Replacement, ReplacementLen + 1, ReplacementText);
+ }
+ }
+ else
+ {
+ Replacement = NULL;
+ }
+}
+
+
+__deref_out_opt OutputFilter::QuerySpec **
+OutputFilter::FindPrior(
+ ULONG Flags,
+ __in PCSTR Query,
+ __deref_in_opt QuerySpec **List
+ )
+{
+ QuerySpec **Prior = List;
+ QuerySpec *Next;
+
+ for (Next = *Prior; Next != NULL; Next = Next->Next)
+ {
+ if (Flags > Next->Flags ||
+ (Flags == Next->Flags &&
+ strcmp(Query, Next->Query) >= 0))
+ {
+ break;
+ }
+
+ Prior = &Next->Next;
+ }
+
+ return Prior;
+}
+
+
+HRESULT
+OutputFilter::Replace(
+ ULONG Flags,
+ __in PCSTR Query,
+ __in_opt PCSTR Replacement
+ )
+{
+ if (Query == NULL ||
+ (Flags & OUTFILTER_REPLACE_LINE) == 0 ||
+ (Flags & OUTFILTER_REPLACE_LINE) == (OUTFILTER_REPLACE_BEFORE | OUTFILTER_REPLACE_AFTER))
+ {
+ return E_INVALIDARG;
+ }
+
+ // Don't support replacing one query each time in a single line.
+ // This is ok if there can be no further replacements on a matching line.
+ if (((Flags & (OUTFILTER_REPLACE_ONCE | OUTFILTER_QUERY_ONE_LINE)) ==
+ (OUTFILTER_REPLACE_EVERY | OUTFILTER_QUERY_ONE_LINE)) &&
+ !(Flags & (OUTFILTER_REPLACE_AFTER | OUTFILTER_REPLACE_NEXT_LINE)))
+ {
+ return E_NOTIMPL;
+ }
+
+ // Set priority to level 0 if not specified.
+ if ((Flags & OUTFILTER_REPLACE_PRIORITY(7)) == 0)
+ {
+ Flags |= OUTFILTER_REPLACE_PRIORITY(0);
+ }
+
+ ReplacementSpec **PriorNext;
+ ReplacementSpec *Next;
+ SIZE_T ReplacementLen;
+
+ ReplacementLen = (Replacement == NULL) ? 0 : strlen(Replacement);
+
+ PriorNext = (ReplacementSpec **)FindPrior(Flags, Query, (QuerySpec**)&ReplaceList);
+ Next = *PriorNext;
+
+ if (Next != NULL &&
+ Flags == Next->Flags &&
+ strcmp(Query, Next->Query) == 0)
+ {
+ if (ReplacementLen == 0)
+ {
+ if (Next->Replacement != NULL)
+ {
+ Next->Replacement[0] = '\0';
+ }
+ }
+ else
+ {
+ if (ReplacementLen > Next->ReplacementLen)
+ {
+ PSTR NewReplacement = new CHAR[ReplacementLen+1];
+
+ if (NewReplacement == NULL) return E_OUTOFMEMORY;
+
+ delete[] Next->Replacement;
+ Next->Replacement = NewReplacement;
+ }
+ StringCchCopyA(Next->Replacement, ReplacementLen + 1, Replacement);
+ }
+ Next->ReplacementLen = ReplacementLen;
+ }
+ else
+ {
+ ReplacementSpec *NewQuery;
+
+ NewQuery = new ReplacementSpec(Flags, Query, Replacement);
+
+ if (NewQuery == NULL) return E_OUTOFMEMORY;
+
+ if (NewQuery->Query == NULL ||
+ (ReplacementLen && NewQuery->Replacement == NULL))
+ {
+ delete NewQuery;
+ return E_OUTOFMEMORY;
+ }
+
+ NewQuery->Next = Next;
+ *PriorNext = NewQuery;
+ }
+
+ return S_OK;
+}
+
+HRESULT
+OutputFilter::Skip(
+ ULONG Flags,
+ __in PCSTR Query
+ )
+{
+ if (Query == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ QuerySpec **PriorNext;
+ QuerySpec *Next;
+
+ PriorNext = FindPrior(Flags, Query, &SkipList);
+ Next = *PriorNext;
+
+ if (Next == NULL ||
+ Flags != Next->Flags ||
+ strcmp(Query, Next->Query) != 0)
+ {
+ QuerySpec *NewQuery;
+
+ NewQuery = new QuerySpec(Flags, Query);
+
+ if (NewQuery == NULL) return E_OUTOFMEMORY;
+
+ if (NewQuery->Query == NULL)
+ {
+ delete NewQuery;
+ return E_OUTOFMEMORY;
+ }
+
+ NewQuery->Next = Next;
+ *PriorNext = NewQuery;
+ }
+
+ return S_OK;
+}
+
+OutputFilter::QuerySpec *
+OutputFilter::FindMatch(
+ PCSTR Text,
+ QuerySpec *List,
+ SIZE_T Start,
+ ULONG Flags,
+ __out_opt SIZE_T *MatchPos
+ )
+{
+ SIZE_T Remaining = strlen(Text);
+ PCSTR Search;
+ QuerySpec *Match;
+
+ if (MatchPos != NULL) *MatchPos = 0;
+
+ if (List == NULL ||
+ Text == NULL ||
+ (Remaining = strlen(Text)) <= Start) return NULL;
+
+ Search = Text + Start;
+ Remaining -= Start;
+
+ do
+ {
+ for (Match = List; Match != NULL; Match = Match->Next)
+ {
+ if (Match->Flags & OUTFILTER_QUERY_ENABLED &&
+ Remaining >= Match->QueryLen &&
+ strncmp(Search, Match->Query, Match->QueryLen) == 0)
+ {
+ if (Match->Flags & OUTFILTER_QUERY_WHOLE_WORD)
+ {
+ if ((Search > Text && iscsym(Search[-1])) ||
+ iscsym(Search[Match->QueryLen]))
+ {
+ continue;
+ }
+ }
+/*
+ if (Match->Flags & OUTFILTER_QUERY_ONE_LINE)
+ {
+ Match->Flags &= ~OUTFILTER_QUERY_ENABLED;
+ }
+*/
+ Match->Flags |= OUTFILTER_QUERY_HIT;
+
+ if (MatchPos != NULL)
+ {
+ *MatchPos = (ULONG)(Search - Text);
+ }
+
+ return Match;
+ }
+ }
+
+ Search++;
+ Remaining--;
+ } while (Remaining &&
+ !(Flags & OUTFILTER_FINDMATCH_AT_START));
+
+ return NULL;
+}
+
+
+HRESULT
+OutputFilter::OutputText(
+ OutputControl *OutCtl,
+ ULONG Mask
+ )
+{
+ // 1. Get line of read buffer
+ // 2. Search for a skip query match
+ // 3. Search for any/all replace query matches
+
+ if (Buffer == NULL) return S_OK;
+
+ HRESULT hr;
+ PSTR pNextLine;
+ CHAR EndChar;
+ PSTR pFilter;
+
+ if (OutCtl == NULL)
+ {
+ OutCtl = new OutputControl(Client);
+
+ if (OutCtl == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ OutCtl->AddRef();
+ }
+
+ // Can we quickly just output all text?
+ if (SkipList == NULL && ReplaceList == NULL)
+ {
+ hr = OutCtl->Output(Mask, Buffer);
+ OutCtl->Release();
+ return hr;
+ }
+
+ Outputing = TRUE;
+
+ // Enable all queries and reset hit markings.
+ QuerySpec *Query;
+ for (Query = SkipList; Query != NULL; Query = Query->Next)
+ {
+ Query->Flags = (Query->Flags & ~OUTFILTER_QUERY_HIT) | OUTFILTER_QUERY_ENABLED;
+ }
+ for (Query = (QuerySpec *)ReplaceList; Query != NULL; Query = Query->Next)
+ {
+ Query->Flags = (Query->Flags & ~OUTFILTER_QUERY_HIT) | OUTFILTER_QUERY_ENABLED;
+ }
+
+ hr = S_OK;
+ pNextLine = Buffer;
+
+ while (hr == S_OK && *pNextLine != '\0')
+ {
+ if (OutCtl->GetInterrupt() == S_OK)
+ {
+ OutCtl->SetInterrupt(DEBUG_INTERRUPT_PASSIVE);
+ break;
+ }
+
+ pFilter = pNextLine;
+
+ // Find end of this line
+ while ((*pNextLine != '\0') &&
+ (*pNextLine != '\n') &&
+ (*pNextLine != '\r') &&
+ (*pNextLine != '\f'))
+ {
+ pNextLine++;
+ }
+
+ EndChar = *pNextLine;
+ *pNextLine = '\0';
+
+ // Search for a skip match
+ Query = FindMatch(pFilter, SkipList);
+
+ if (Query != NULL)
+ {
+ DbgPrint("Skipping line with %s.\n", Query->Query);
+
+ if (Query->Flags & OUTFILTER_QUERY_ONE_LINE)
+ {
+ Query->Flags &= ~OUTFILTER_QUERY_ENABLED;
+ }
+
+ *pNextLine = EndChar;
+ if (EndChar != '\0')
+ {
+ pNextLine++;
+ }
+ }
+ else
+ {
+ PSTR pFilterLine = pFilter;
+ SIZE_T MatchPos = 0;
+ ReplacementSpec *Replace;
+
+ for (Replace = ReplaceList;
+ Replace != NULL;
+ Replace = (ReplacementSpec *)Replace->Next)
+ {
+ if (!(Replace->Flags & (OUTFILTER_QUERY_ONE_LINE | OUTFILTER_QUERY_ENABLED)))
+ {
+ Replace->Flags |= OUTFILTER_QUERY_ENABLED;
+ }
+ }
+
+ while (pFilter < pNextLine &&
+ (Replace = (ReplacementSpec *)FindMatch(pFilterLine,
+ ReplaceList,
+ MatchPos,
+ OUTFILTER_FINDMATCH_DEFAULT,
+ &MatchPos)) != NULL)
+ {
+ if (Replace->Flags & (OUTFILTER_QUERY_ONE_LINE | OUTFILTER_REPLACE_ONCE))
+ {
+ Replace->Flags &= ~OUTFILTER_QUERY_ENABLED;
+ }
+
+ if (Replace->Flags & OUTFILTER_REPLACE_BEFORE)
+ {
+ if (Replace->ReplacementLen)
+ {
+ hr = OutCtl->Output(Mask, "%s", Replace->Replacement);
+ }
+
+ pFilter = pFilterLine + MatchPos;
+
+ if (!(Replace->Flags & OUTFILTER_REPLACE_NEXT_LINE) &&
+ !(Replace->Flags & OUTFILTER_REPLACE_ONCE) &&
+ !(Replace->Flags & OUTFILTER_REPLACE_TO_END))
+ {
+ // This replacement leaves the query text intact.
+ // Hence this query will keep matching; so, look for
+ // another query which will actually modify the
+ // query text or the text following it.
+ Replace = (ReplacementSpec *)Replace->Next;
+
+ while (Replace != NULL &&
+ Replace->Flags & OUTFILTER_REPLACE_BEFORE)
+ {
+ Replace = (ReplacementSpec *)Replace->Next;
+ }
+
+ Replace = (ReplacementSpec *)
+ FindMatch(pFilterLine,
+ Replace,
+ MatchPos,
+ OUTFILTER_FINDMATCH_AT_START |
+ OUTFILTER_FINDMATCH_NO_MARK);
+
+ if (Replace == NULL)
+ {
+ // Advance MatchPos, but not filtered text.
+ // This unfiltered text may yet be replaced.
+ MatchPos++;
+ continue;
+ }
+ }
+ }
+
+ if (!(Replace->Flags & OUTFILTER_REPLACE_BEFORE))
+ {
+ CHAR TempHolder;
+ SIZE_T BeginReplacePos = MatchPos;
+
+ if (!(Replace->Flags & OUTFILTER_REPLACE_THIS))
+ {
+ BeginReplacePos += Replace->QueryLen;
+ }
+
+ TempHolder = pFilterLine[BeginReplacePos];
+ pFilterLine[BeginReplacePos] = '\0';
+
+ if ((hr = OutCtl->Output(Mask, "%s", pFilter)) == S_OK &&
+ Replace->ReplacementLen)
+ {
+ hr = OutCtl->Output(Mask, "%s", Replace->Replacement);
+ }
+
+ pFilterLine[BeginReplacePos] = TempHolder;
+ }
+
+ if (Replace->Flags & OUTFILTER_REPLACE_AFTER)
+ {
+ pFilter = pNextLine;
+ }
+ else
+ {
+ if (Replace->Flags & OUTFILTER_REPLACE_THIS)
+ {
+ MatchPos += Replace->QueryLen;
+ }
+ pFilter = pFilterLine + MatchPos;
+ }
+
+ if (Replace->Flags & OUTFILTER_REPLACE_NEXT_LINE) break;
+ }
+
+ *pNextLine = EndChar;
+ if (EndChar != '\0')
+ {
+ pNextLine++;
+
+ // Include any following zero length lines
+ while ((*pNextLine == '\n') ||
+ (*pNextLine == '\r') ||
+ (*pNextLine == '\f'))
+ {
+ pNextLine++;
+ }
+
+ EndChar = *pNextLine;
+ *pNextLine = '\0';
+ }
+
+ // Output remaining portion of filtered line
+ hr = OutCtl->Output(Mask, pFilter);
+
+ if (EndChar != '\0')
+ {
+ *pNextLine = EndChar;
+ }
+ }
+
+ }
+
+ Outputing = FALSE;
+
+ OutCtl->Release();
+
+ return hr;
+}
+
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/output.hxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/output.hxx
new file mode 100644
index 00000000000..6e6457c5d27
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/output.hxx
@@ -0,0 +1,668 @@
+// 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.
+
+
+//+----------------------------------------------------------------------------
+//
+
+//
+// Abstract:
+//
+// This header file declares output classes for callbacks,
+// control, parsing, and filtering.
+//
+
+#pragma once
+
+
+class OutputControl
+{
+public:
+ // IUnknown
+ virtual ULONG STDMETHODCALLTYPE AddRef(THIS) {
+ return ++RefCount;
+ }
+
+ virtual ULONG STDMETHODCALLTYPE Release(void) {
+ ULONG NewCount = RefCount-1;
+ if (NewCount == 0)
+ {
+ delete this;
+ }
+ else
+ {
+ RefCount = NewCount;
+ }
+ return NewCount;
+ }
+
+ OutputControl()
+ {
+ RefCount = 1;
+ OutCtl = DEBUG_OUTCTL_AMBIENT;
+ Control = NULL;
+ OutputLinePrefix = NULL;
+ }
+
+ OutputControl(ULONG OutputControl,
+ __in_opt PDEBUG_CLIENT Client = NULL)
+ {
+ RefCount = 1;
+ OutCtl = DEBUG_OUTCTL_AMBIENT;
+ Control = NULL;
+ OutputLinePrefix = NULL;
+ SetControl(OutputControl, Client);
+ }
+
+ OutputControl(__in_opt PDEBUG_CLIENT Client)
+ {
+ RefCount = 1;
+ OutCtl = DEBUG_OUTCTL_AMBIENT;
+ Control = NULL;
+ OutputLinePrefix = NULL;
+ SetControl(DEBUG_OUTCTL_AMBIENT, Client);
+ }
+
+ virtual ~OutputControl()
+ {
+ if (RefCount != 1)
+ {
+ DbgPrint("OutputControl::RefCount != 1.\n");
+ DbgBreakPoint();
+ }
+
+ if (Control != NULL) Control->Release();
+
+ delete OutputLinePrefix;
+ }
+
+ ULONG GetControl() { return OutCtl; }
+ HRESULT SetControl(ULONG OutputControl, __in_opt PDEBUG_CLIENT Client = NULL);
+
+ HRESULT SetOutputLinePrefix(__in_opt PCSTR Prefix);
+
+ HRESULT Output(ULONG Mask, __in PCSTR Format, ...);
+ HRESULT OutputVaList(ULONG Mask, __in PCSTR Format, va_list Args);
+
+ HRESULT Output(__in PCSTR Format, ...);
+ HRESULT OutErr(__in PCSTR Format, ...);
+ HRESULT OutWarn(__in PCSTR Format, ...);
+ HRESULT OutVerb(__in PCSTR Format, ...);
+ HRESULT OutExtWarn(__in PCSTR Format, ...);
+
+ // Output an offset stylized to targets native pointer size
+ HRESULT OutputOffset(ULONG64 Offset);
+
+ HRESULT OutputStackTrace(
+ __in_ecount_opt(FramesSize) PDEBUG_STACK_FRAME Frames,
+ ULONG FramesSize,
+ ULONG Flags
+ );
+
+ HRESULT GetInterrupt();
+ HRESULT SetInterrupt(ULONG Flags);
+ HRESULT Evaluate(__in PCSTR Expression, ULONG DesiredType, __out PDEBUG_VALUE Value, __out_opt PULONG RemainderIndex);
+ HRESULT Execute(__in PCSTR Command, ULONG Flags);
+ HRESULT CoerceValue(__in const DEBUG_VALUE *In, ULONG OutType, __out PDEBUG_VALUE Out);
+ HRESULT IsPointer64Bit();
+
+private:
+ ULONG RefCount;
+ PDEBUG_CONTROL Control;
+ ULONG OutCtl;
+ PSTR OutputLinePrefix;
+};
+
+
+class OutputState
+{
+public:
+ OutputState(__in_opt PDEBUG_CLIENT OrgClient, BOOL SameClient=FALSE);
+ ~OutputState();
+
+ HRESULT Setup(ULONG OutMask, __in_opt PDEBUG_OUTPUT_CALLBACKS OutCallbacks);
+
+ HRESULT Execute(__in PCSTR pszCommand);
+
+ HRESULT OutputType(
+ BOOL Physical,
+ ULONG64 Offset,
+ ULONG64 Module,
+ ULONG TypeId,
+ ULONG Flags
+ );
+
+ HRESULT OutputType(
+ BOOL Physical,
+ ULONG64 Offset,
+ __in PCSTR Type,
+ ULONG Flags
+ );
+
+ HRESULT OutputTypePhysical(
+ ULONG64 Offset,
+ ULONG64 Module,
+ ULONG TypeId,
+ ULONG Flags
+ )
+ {
+ return OutputType(TRUE, Offset, Module, TypeId, Flags);
+ }
+
+ HRESULT OutputTypePhysical(
+ IN ULONG64 Offset,
+ IN PCSTR Type,
+ IN ULONG Flags
+ )
+ {
+ return OutputType(TRUE, Offset, Type, Flags);
+ }
+
+ HRESULT OutputTypeVirtual(
+ IN ULONG64 Offset,
+ IN ULONG64 Module,
+ IN ULONG TypeId,
+ IN ULONG Flags
+ )
+ {
+ return OutputType(FALSE, Offset, Module, TypeId, Flags);
+ }
+
+ HRESULT OutputTypeVirtual(
+ IN ULONG64 Offset,
+ IN PCSTR Type,
+ IN ULONG Flags
+ )
+ {
+ return OutputType(FALSE, Offset, Type, Flags);
+ }
+
+ void Restore();
+
+public:
+ PDEBUG_CLIENT Client;
+
+private:
+ HRESULT hrInit;
+ PDEBUG_CONTROL Control;
+ PDEBUG_SYMBOLS Symbols;
+ BOOL CreatedClient;
+ BOOL SetCallbacks;
+ BOOL Saved;
+ ULONG OrgOutMask;
+ PDEBUG_OUTPUT_CALLBACKS OrgOutCallbacks;
+};
+
+
+//----------------------------------------------------------------------------
+//
+// Default output callbacks implementation, provides IUnknown for
+// static classes.
+//
+//----------------------------------------------------------------------------
+
+class DefOutputCallbacks :
+ public IDebugOutputCallbacks
+{
+public:
+ DefOutputCallbacks() { RefCount = 1; }
+ ~DefOutputCallbacks()
+ {
+ if (RefCount != 1)
+ {
+ DbgPrint("DefOutputCallbacks@0x%p::RefCount(%lu) != 1.\n", this, RefCount);
+ DbgBreakPoint();
+ }
+#if DBG
+ RefCount--;
+#endif
+ }
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(
+ THIS_
+ __in REFIID InterfaceId,
+ __out PVOID* Interface
+ );
+ STDMETHOD_(ULONG, AddRef)(
+ THIS
+ );
+ STDMETHOD_(ULONG, Release)(
+ THIS
+ );
+
+ // IDebugOutputCallbacks.
+ STDMETHOD(Output)(
+ THIS_
+ ULONG Mask,
+ __in PCSTR Text
+ );
+
+protected:
+ ULONG RefCount;
+};
+
+
+//----------------------------------------------------------------------------
+//
+// DebugOutputCallbacks.
+//
+//----------------------------------------------------------------------------
+
+class DebugOutputCallbacks : public DefOutputCallbacks
+{
+public:
+ // IDebugOutputCallbacks.
+ STDMETHOD(Output)(
+ THIS_
+ ULONG Mask,
+ __in PCSTR Text
+ );
+};
+
+
+//----------------------------------------------------------------------------
+//
+// OutputReader
+//
+// General DebugOutputCallback class to read output.
+//
+//----------------------------------------------------------------------------
+
+class OutputReader : public DefOutputCallbacks
+{
+public:
+ OutputReader()
+ {
+ hHeap = NULL;
+ Buffer = NULL;
+ BufferSize = 0;
+ BufferLeft = 0;
+ }
+
+ virtual ~OutputReader()
+ {
+ if (Buffer) HeapFree(hHeap, 0, Buffer);
+ }
+
+ // IDebugOutputCallbacks.
+ STDMETHOD(Output)(
+ THIS_
+ ULONG Mask,
+ __in PCSTR Text
+ );
+
+ // Discard any text left unused by Parse
+ virtual void DiscardOutput();
+
+ // Get a copy of the output buffer
+ HRESULT GetOutputCopy(__deref_out PSTR *Copy);
+
+ // Free the copy
+ void FreeOutputCopy(__deref PSTR Copy)
+ {
+ if (hHeap != NULL) { HeapFree(hHeap, 0, Copy); }
+ }
+
+protected:
+ HANDLE hHeap;
+ PSTR Buffer;
+ SIZE_T BufferSize;
+ SIZE_T BufferLeft;
+};
+
+
+//----------------------------------------------------------------------------
+//
+// OutputParser
+//
+// General DebugOutputCallback class to parse output.
+//
+//----------------------------------------------------------------------------
+
+#define PARSE_OUTPUT_DISCARD 0x00000000
+#define PARSE_OUTPUT_NO_DISCARD 0x00000001
+
+#define PARSE_OUTPUT_UNPARSED 0x00000000
+#define PARSE_OUTPUT_ALL 0x00000002
+
+#define PARSE_OUTPUT_DEFAULT (PARSE_OUTPUT_DISCARD | PARSE_OUTPUT_UNPARSED)
+
+class OutputParser : public OutputReader
+{
+public:
+ OutputParser() : OutputReader()
+ {
+ UnparsedIndex = 0;
+ }
+
+ // Send all read text through Parse method
+ // Flags:
+ // PARSE_OUTPUT_DISCARD or PARSE_OUTPUT_NO_DISCARD
+ // PARSE_OUTPUT_UNPARSED or PARSE_OUTPUT_ALL
+ // PARSE_OUTPUT_DEFAULT = PARSE_OUTPUT_DISCARD + PARSE_OUTPUT_UNPARSED
+ HRESULT ParseOutput(FLONG Flags = PARSE_OUTPUT_DEFAULT);
+
+ // Discard any text left unused by Parse
+ void DiscardOutput();
+
+ // Check if ready to look for keys/values
+ virtual HRESULT Ready() PURE;
+
+ // Reset progress counter so we may parse more output
+ virtual void Relook() PURE;
+
+ // Parse line of text and optionally return index to unused portion of text
+ virtual HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex) PURE;
+
+ // Check if all keys/values were found during past reads
+ virtual HRESULT Complete() PURE;
+
+private:
+ DWORD UnparsedIndex;
+};
+
+
+//----------------------------------------------------------------------------
+//
+// BasicOutputParser
+//
+// Basic DebugOutputCallback class to parse output looking for
+// string keys and subsequent values.
+//
+//----------------------------------------------------------------------------
+
+#define PARSER_UNSPECIFIED_RADIX -1
+#define PARSER_DEFAULT_RADIX 0
+
+class BasicOutputParser : public OutputParser
+{
+ typedef struct {
+ PDEBUG_VALUE Value;
+ ULONG Type;
+ ULONG Radix;
+ CHAR Key[80];
+ } LookupEntry;
+
+public:
+ BasicOutputParser(PDEBUG_CLIENT OutputClient, ULONG TotalEntries = 4)
+ {
+ Client = OutputClient;
+
+ Entries = new LookupEntry[TotalEntries];
+ if (!Entries) TotalEntries = 0;
+
+ MaxEntries = TotalEntries;
+ NumEntries = 0;
+ CurEntry = 0;
+ }
+
+ ~BasicOutputParser()
+ {
+ if (Entries) delete[] Entries;
+ }
+
+ HRESULT LookFor(OUT PDEBUG_VALUE Value,
+ IN PCSTR Key,
+ IN ULONG Type = DEBUG_VALUE_INVALID,
+ IN ULONG Radix = PARSER_UNSPECIFIED_RADIX);
+
+ // Check if ready to look for keys/values
+ HRESULT Ready() { return (CurEntry != NumEntries) ? S_OK : S_FALSE; }
+
+ // Reset progress counter so we may parse more output
+ void Relook() { CurEntry = 0; }
+
+ // Parse line of text and optionally return index to unused portion of text
+ HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex);
+
+ // Check if all keys/values were found during past reads
+ HRESULT Complete()
+ {
+ return (Client != NULL &&
+ CurEntry == NumEntries) ?
+ S_OK :
+ S_FALSE;
+ }
+
+private:
+ PDEBUG_CLIENT Client;
+ ULONG MaxEntries;
+ ULONG NumEntries;
+
+ ULONG CurEntry;
+
+ LookupEntry *Entries;
+};
+
+
+//----------------------------------------------------------------------------
+//
+// BitFieldParser
+//
+// DebugOutputCallback class to parse bitfield type output
+//
+//----------------------------------------------------------------------------
+
+class BitFieldInfo {
+public:
+ BitFieldInfo() { Valid = FALSE; };
+ BitFieldInfo(ULONG InitBitPos, ULONG InitBits) {
+ Valid = Compose(InitBitPos, InitBits);
+ }
+
+ BOOL Compose(ULONG CBitPos, ULONG CBits)
+ {
+ BitPos = CBitPos;
+ Bits = CBits;
+ Mask = (((((ULONG64) 1) << Bits) - 1) << BitPos);
+ return TRUE;
+ }
+
+ BOOL Valid;
+ ULONG BitPos;
+ ULONG Bits;
+ ULONG64 Mask;
+};
+
+class BitFieldParser : public OutputParser
+{
+public:
+ BitFieldParser(PDEBUG_CLIENT Client, BitFieldInfo *BFI);
+
+ // Reset progress counter so we may parse more output
+ void Relook()
+ {
+ if (BitField != NULL)
+ {
+ BitField->Valid = FALSE;
+ BitField->BitPos = 0;
+ BitField->Bits = 0;
+ BitField->Mask = 0;
+ }
+ BitFieldReader.Relook();
+ }
+
+ // Check if ready to look for bit fields
+ HRESULT Ready()
+ {
+ return (BitField != NULL) ?
+ BitFieldReader.Ready() :
+ S_FALSE;
+ }
+
+ // Parse line of text and optionally return index to unused portion of text
+ HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex);
+
+ // Check if bit fields were found during past reads
+ HRESULT Complete()
+ {
+ return (BitField != NULL && BitField->Valid) ?
+ BitFieldReader.Complete() :
+ S_FALSE;
+ }
+
+private:
+ BitFieldInfo *BitField;
+ DEBUG_VALUE BitPos;
+ DEBUG_VALUE Bits;
+ BasicOutputParser BitFieldReader;
+};
+
+
+//----------------------------------------------------------------------------
+//
+// OutputFilter
+//
+// DebugOutputCallback class to filter output
+// by skipping/replacing lines.
+//
+//----------------------------------------------------------------------------
+
+// Query Flags
+#define OUTFILTER_QUERY_EVERY_LINE 0x00000000
+#define OUTFILTER_QUERY_ONE_LINE 0x00000001
+
+#define OUTFILTER_QUERY_WHOLE_WORD 0x00000002 // Characters before and after
+ // query must not be C symbols
+ // [a-z,A-A,0-9,_]
+
+#define OUTFILTER_QUERY_ENABLED 0x00000004
+#define OUTFILTER_QUERY_HIT 0x00000008
+
+// Replace Flags
+#define OUTFILTER_REPLACE_EVERY 0x00000000
+#define OUTFILTER_REPLACE_ONCE 0x00010000
+
+#define OUTFILTER_REPLACE_ALL_INSTANCES (OUTFILTER_REPLACE_EVERY | OUTFILTER_QUERY_EVERY_LINE)
+#define OUTFILTER_REPLACE_ONCE_PER_LINE (OUTFILTER_REPLACE_ONCE | OUTFILTER_QUERY_EVERY_LINE)
+#define OUTFILTER_REPLACE_EXACTLY_ONCE (OUTFILTER_REPLACE_ONCE | OUTFILTER_QUERY_ONE_LINE)
+
+#define OUTFILTER_REPLACE_CONTINUE 0x00000000
+#define OUTFILTER_REPLACE_NEXT_LINE 0x00020000 // Stop replacement checks
+ // for current line after
+ // this replacement
+
+#define OUTFILTER_REPLACE_BEFORE 0x04000000 // Replace text in line prior to query match
+#define OUTFILTER_REPLACE_THIS 0x02000000 // Replace query text
+#define OUTFILTER_REPLACE_AFTER 0x01000000 // Replace text following query match
+
+#define OUTFILTER_REPLACE_FROM_START (OUTFILTER_REPLACE_BEFORE | OUTFILTER_REPLACE_THIS)
+#define OUTFILTER_REPLACE_TO_END (OUTFILTER_REPLACE_THIS | OUTFILTER_REPLACE_AFTER)
+#define OUTFILTER_REPLACE_LINE (OUTFILTER_REPLACE_BEFORE | \
+ OUTFILTER_REPLACE_THIS | \
+ OUTFILTER_REPLACE_AFTER)
+
+#define OUTFILTER_REPLACE_PRIORITY(x) (((x+8) & 0xF) << 28) // Higher priority replacement queries
+ // are tested before lower. Priority
+ // range: 7 (high) to -7 (low)
+
+#define OUTFILTER_REPLACE_DEFAULT (OUTFILTER_REPLACE_ALL_INSTANCES | \
+ OUTFILTER_REPLACE_CONTINUE | \
+ OUTFILTER_REPLACE_THIS | \
+ OUTFILTER_REPLACE_PRIORITY(0))
+
+// Skip Flags
+#define OUTFILTER_SKIP_DEFAULT OUTFILTER_QUERY_EVERY_LINE
+
+// FindMatch Flags
+#define OUTFILTER_FINDMATCH_ANYWHERE 0
+#define OUTFILTER_FINDMATCH_AT_START 1
+#define OUTFILTER_FINDMATCH_MARK 0
+#define OUTFILTER_FINDMATCH_NO_MARK 2
+
+#define OUTFILTER_FINDMATCH_DEFAULT (OUTFILTER_FINDMATCH_ANYWHERE | OUTFILTER_FINDMATCH_MARK)
+
+class OutputFilter : public OutputReader
+{
+public:
+ OutputFilter(PDEBUG_CLIENT DbgClient) : OutputReader()
+ {
+ Client = DbgClient;
+ if (Client != NULL) Client->AddRef();
+ SkipList = NULL;
+ ReplaceList = NULL;
+ Outputing = FALSE;
+ }
+ ~OutputFilter()
+ {
+ if (Client != NULL) Client->Release();
+ }
+
+ // IDebugOutputCallbacks.
+ STDMETHOD(Output)(
+ THIS_
+ IN ULONG Mask,
+ IN PCSTR Text
+ );
+
+ HRESULT Query(PCSTR Query,
+ PDEBUG_VALUE Value = NULL,
+ ULONG Type = DEBUG_VALUE_INVALID,
+ ULONG Radix = PARSER_UNSPECIFIED_RADIX);
+
+ HRESULT Replace(ULONG Flags, __in PCSTR Query, __in_opt PCSTR Replacement);
+ HRESULT Skip(ULONG Flags, __in PCSTR Query);
+
+ HRESULT OutputText(OutputControl *OutCtl = NULL, ULONG Mask = DEBUG_OUTPUT_NORMAL);
+
+protected:
+ class QuerySpec
+ {
+ public:
+ QuerySpec(ULONG Flags, PCSTR Query);
+ ~QuerySpec()
+ {
+ if (Query != NULL)
+ {
+ delete[] Query;
+ }
+ }
+
+ QuerySpec *Next;
+ ULONG Flags;
+ SIZE_T QueryLen;
+ PSTR Query;
+ };
+
+ class ReplacementSpec : public QuerySpec
+ {
+ public:
+ ReplacementSpec(ULONG Flags, PCSTR QueryText, PCSTR ReplacementText);
+ ~ReplacementSpec()
+ {
+ if (Replacement != NULL)
+ {
+ delete[] Replacement;
+ }
+ }
+
+// ReplacementSpec *Next;
+ SIZE_T ReplacementLen;
+ PSTR Replacement;
+ };
+
+ __deref_out_opt QuerySpec **FindPrior(
+ ULONG Flags,
+ __in PCSTR Query,
+ __deref_in_opt QuerySpec **List
+ );
+ QuerySpec *FindMatch(PCSTR Text,
+ QuerySpec *List,
+ SIZE_T Start = 0,
+ ULONG Flags = OUTFILTER_FINDMATCH_DEFAULT,
+ __out_opt SIZE_T *MatchPos = NULL);
+
+ PDEBUG_CLIENT Client;
+
+ ReplacementSpec *ReplaceList;
+ QuerySpec *SkipList;
+
+private:
+ BOOL Outputing;
+};
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/precomp.cpp b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/precomp.cpp
new file mode 100644
index 00000000000..9de4deeb939
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/precomp.cpp
@@ -0,0 +1,6 @@
+// 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
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/precomp.hxx b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/precomp.hxx
new file mode 100644
index 00000000000..c4625096aa3
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/DbgXHelper/precomp.hxx
@@ -0,0 +1,45 @@
+// 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
+
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "minnt.h"
+
+#include "DbgXHelper.h"
+#include "debug.hxx"
+
+#undef IFC
+#define IFC(expr) {hr = (expr); if (FAILED(hr)) goto Cleanup;}
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (ARRAYSIZE(a))
+#endif
+
+#ifndef ReleaseInterface
+#define ReleaseInterface(p) if (p) { (p)->Release(); (p) = NULL; }
+#endif
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/Directory.Build.Props b/src/Microsoft.DotNet.Wpf/src/WpfGfx/Directory.Build.Props
new file mode 100644
index 00000000000..be34e6411d3
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/Directory.Build.Props
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/Graphics.Paths.props b/src/Microsoft.DotNet.Wpf/src/WpfGfx/Graphics.Paths.props
new file mode 100644
index 00000000000..fcc4c697d57
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/Graphics.Paths.props
@@ -0,0 +1,7 @@
+
+
+ $(WpfGraphicsPath)Include\
+ $(WpfGraphicsPath)Shared\
+ $(WpfGraphicsSharedPath)inc\
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/Graphics.props b/src/Microsoft.DotNet.Wpf/src/WpfGfx/Graphics.props
new file mode 100644
index 00000000000..954c2235948
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/Graphics.props
@@ -0,0 +1,128 @@
+
+
+
+
+ true
+
+
+
+
+ $(WpfGraphicsIncludePath)processed\
+
+
+
+
+ $(GraphicsIncludePath);
+ $(IncludePath);
+ $(WpfGraphicsIncludePath);
+ $(WpfGraphicsIncludePath)Generated;
+ $(WpfGraphicsSharedIncludePath);
+ $(WpfGraphicsPath)common;
+ $(WpfGraphicsPath)core;
+ $(WpfGraphicsPath)external\inc;
+ $(WpfGraphicsPath)common\DirectXLayer;
+ $(WpfGraphicsPath)common\DirectXLayer\interfaces;
+ $(WpfGraphicsPath)common\DirectXLayer\factories;
+ $(WpfGraphicsPath)common\DirectXLayer\D3DX9;
+ $(WpfGraphicsSharedPath)util\utillib;
+ $(GraphicsIncludeProcessedFilesFolder);
+ $(IntermediateOutputPath);
+
+
+
+
+
+ Level4
+ %(PreprocessorDefinitions);_ALLOW_KEYWORD_MACROS;_WCTYPE_INLINE_DEFINED;override=__override
+ %(PreprocessorDefinitions);PERFMETER=1
+ %(AdditionalIncludeDirectories);$(GraphicsIncludePath)
+
+
+ false
+ false
+
+ %(DisableSpecificWarnings);4239;4595
+
+
+
+
+
+
+ %(DisableSpecificWarnings);4324;;4471
+
+
+
+
+
+
+
+
+
+
+
+
+ %(PreprocessorDefinitions);DIRECTXMATH
+
+
+
+
+
+
+ %(AdditionalDependencies);d3d9.lib;$(D3DCompilerDllBaseName).lib
+ %(AdditionalOptions) /dllrename:$(D3DCompilerDllBaseName)$(D3DCompilerVersion)=$(D3DCompilerDllBaseName)$(D3DCompilerVersion)$(WpfVersionSuffix)
+
+
+
+
+
+
+ Unavailable
+ Unavailable
+
+
+ $(IncludePath);
+ $(D3DXIncludePath)\Include
+
+
+
+
+
+
+
+ %(PreprocessorDefinitions);D3D9EXTENSIONS
+
+
+
+
+ %(AdditionalDependencies);$(D3DXLibPath)\d3dx9.lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/extras/gen_GammaLUTs.bat b/src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/extras/gen_GammaLUTs.bat
new file mode 100644
index 00000000000..9069a3de619
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/extras/gen_GammaLUTs.bat
@@ -0,0 +1,492 @@
+@rem = '
+@perl.exe -w %~f0 %*
+@goto :EOF
+'; undef @rem;
+
+#
+# This program generates LUTs for converting between sRGB and scRGB.
+# Also does round-trip test for sRGB -> scRGB -> sRGB, if both conversions use these tables.
+#
+# Run it from the directory the script is in.
+#
+
+
+use POSIX;
+
+$incfile = "..\\..\\common\\shared\\GammaLUTs.inc";
+$cppfile = "..\\..\\common\\shared\\GammaLUTs.cpp";
+
+# This value is a small bias that can be added to the tosrgb table.
+
+$roundingbias = 0; # We don't need one for this case. (But it might be useful again, like it
+ # has been in the past, if we make changes e.g. increase the table size.)
+
+# LUT sizes.
+#
+# For tosrgb, the size is obtained by searching for a size which passes all the tests.
+# (This was done offline, using the same script, but in "search mode".)
+
+# Set this to non-zero to enable "search mode":
+$search_tosrgb = 0;
+
+# If in "search mode": This is the first size to examine (must be > 1).
+# Otherwise: This is the table size to use (and $end_tblsize_tosrgb is ignored).
+$start_tblsize_tosrgb = 3355;
+
+# If in "search mode": The last size to try in the search
+$end_tblsize_tosrgb = 1 << 15;
+
+# Whether to output test failure results:
+$output_failures = !$search_tosrgb;
+
+
+# The toscrgb table size is obvious because the table is designed for integer inputs from 0..255.
+$tblsize_toscrgb = (1 << 8);
+
+$tblname_tosrgb = "GammaLUT_scRGB_to_sRGB";
+$tblname_toscrgb = "GammaLUT_sRGB_to_scRGB";
+
+
+
+# +++ Begin tosrgb # Mark this code so that we can include it in the generated comments.
+sub scRGBTosRGB
+{
+ my ($x) = @_; # PerlOnly
+ # PerlOnly
+ if (!($x > 0.0)) # Handles NaN case too
+ {
+ return 0.0;
+ }
+ elsif ($x <= 0.0031308)
+ {
+ return $x * 12.92;
+ }
+ elsif ($x < 1.0)
+ {
+ return ((1.055 * pow($x, 1.0/2.4))-0.055);
+ }
+ else
+ {
+ return 1.0;
+ }
+}
+# +++ End
+
+
+# +++ Begin toscrgb # Mark this code so that we can include it in the generated comments.
+sub sRGBToscRGB
+{
+ my ($x) = @_; # PerlOnly
+ # PerlOnly
+ if (!($x > 0.0)) # Handles NaN case too
+ {
+ return 0.0;
+ }
+ elsif ($x <= 0.04045)
+ {
+ return $x / 12.92;
+ }
+ elsif ($x < 1.0)
+ {
+ return pow(($x + 0.055) / 1.055, 2.4);
+ }
+ else
+ {
+ return 1.0;
+ }
+}
+# +++ End
+
+
+# Read the script to capture source code (to be included in LUT comments)
+# Sets %scriptcode.
+#
+# This is probably overengineering - now that we have decided on a gamma function,
+# a bit of cut and paste probably wouldn't hurt here.
+#
+# But during development, it did change surprisingly many times.
+
+sub parseScript
+{
+ open (SCRIPT, $0) || die "Could not open $0\n";
+ $func = "";
+
+ while (