diff --git a/.gitignore b/.gitignore index 902ebd988..5cecb61a6 100644 --- a/.gitignore +++ b/.gitignore @@ -333,6 +333,9 @@ installer/dev/project_reunion_definitions_override.h # Installer test packages !installer/test/testpackages/ +# Local temp storage +temp/ + # Project Reunion specific files Microsoft.WinUI.AppX.targets dev/vsix/extension/LICENSE diff --git a/ProjectReunion.sln b/ProjectReunion.sln index 6e1753012..930337204 100644 --- a/ProjectReunion.sln +++ b/ProjectReunion.sln @@ -33,12 +33,75 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inc", "test\inc\inc.vcxitem EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppLifecycleTestApp", "test\TestApps\AppLifecycleTestApp\AppLifecycleTestApp.vcxproj", "{7C502995-59C3-483B-86BA-815985353633}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DynamicDependency", "DynamicDependency", "{6CD01EF6-D4A4-4801-ADCF-344CF87FF942}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependency", "dev\DynamicDependency\DynamicDependency.vcxitems", "{BF055A59-0919-4E34-9B76-DD055495CC5A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DynamicDependency", "DynamicDependency", "{17B1F036-8FC3-49E6-9464-0C1F96CEAEB9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependency_Test_Win32", "test\DynamicDependency\Test_Win32\DynamicDependency_Test_Win32.vcxproj", "{6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {58E95711-A12F-4C0E-A978-C6B4A0842AC8} = {58E95711-A12F-4C0E-A978-C6B4A0842AC8} + {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {F76B776E-86F5-48C5-8FC7-D2795ECC9746} + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3} = {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProjectReunion_BootstrapDLL", "dev\ProjectReunion_BootstrapDLL\ProjectReunion_BootstrapDLL.vcxproj", "{F76B776E-86F5-48C5-8FC7-D2795ECC9746}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Detours", "dev\Detours\Detours.vcxproj", "{D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "data", "data", "{0C534F12-B076-47E5-A05B-2A711233AC6F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Framework.Math.Add", "test\DynamicDependency\data\Framework.Math.Add\Framework.Math.Add.vcxproj", "{58E95711-A12F-4C0E-A978-C6B4A0842AC8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Framework.Math.Multiply", "test\DynamicDependency\data\Framework.Math.Multiply\Framework.Math.Multiply.vcxproj", "{66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ProjectReunion.Framework", "test\DynamicDependency\data\Microsoft.ProjectReunion.Framework\Microsoft.ProjectReunion.Framework.vcxproj", "{9C1A6C58-52D6-4514-9120-5C339C5DF4BE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DynamicDependencyDataStore", "DynamicDependencyDataStore", "{441A3BB0-7FD2-4902-AEDB-A1C57B528C77}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependency.DataStore", "dev\DynamicDependencyDataStore\DynamicDependency.DataStore\DynamicDependency.DataStore.vcxproj", "{51293DFA-614B-4355-A60D-B30DF3228FD1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependency.DataStore.ProxyStub", "dev\DynamicDependencyDataStore\DynamicDependency.DataStore.ProxyStub\DynamicDependency.DataStore.ProxyStub.vcxproj", "{1A41BB90-CC34-4EDD-9A27-50714CDBC169}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependency.DataStore.Msix", "test\DynamicDependency\data\DynamicDependency.DataStore.Msix\DynamicDependencies.DataStore.Msix.vcxproj", "{B71E818A-882E-456A-87E5-4DE4A6602B99}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DynamicDependencyLifetimeManager", "DynamicDependencyLifetimeManager", "{D043D403-31F1-43F1-B2D4-FA8F7090006D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependencyLifetimeManager", "dev\DynamicDependencyLifetimeManager\DynamicDependencyLifetimeManager\DynamicDependencyLifetimeManager.vcxproj", "{2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependencyLifetimeManager.Msix", "test\DynamicDependency\data\DynamicDependencyLifetimeManager.Msix\DynamicDependencyLifetimeManager.Msix.vcxproj", "{A7391725-4EF5-438F-8DE1-645423E46955}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependencyLifetimeManager.ProxyStub", "dev\DynamicDependencyLifetimeManager\DynamicDependencyLifetimeManager.ProxyStub\DynamicDependencyLifetimeManager.ProxyStub.vcxproj", "{8C79C46D-1577-44CA-83DF-88B74C3E4586}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IDynamicDependencyLifetimeManager", "dev\DynamicDependencyLifetimeManager\IDynamicDependencyLifetimeManager\IDynamicDependencyLifetimeManager.vcxproj", "{CCD23028-B9D3-410B-836E-20B2E7C08451}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DynamicDependency_Test_WinRT", "test\DynamicDependency\Test_WinRT\DynamicDependency_Test_WinRT.vcxproj", "{B2546322-D329-4F6C-9C2E-7EFC3C9ED214}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {58E95711-A12F-4C0E-A978-C6B4A0842AC8} = {58E95711-A12F-4C0E-A978-C6B4A0842AC8} + {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {F76B776E-86F5-48C5-8FC7-D2795ECC9746} + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3} = {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UndockedRegFreeWinRT", "UndockedRegFreeWinRT", "{323E29A9-873F-419B-919E-D18BCE1DE120}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UndockedRegFreeWinRT", "dev\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems", "{56371CA6-144B-4989-A4E9-391AD4FA7651}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution + dev\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems*{56371ca6-144b-4989-a4e9-391ad4fa7651}*SharedItemsImports = 9 test\CppShared\CppShared.vcxitems*{682ded8c-3a27-48cd-866d-e853ea2024de}*SharedItemsImports = 9 test\inc\inc.vcxitems*{7c502995-59c3-483b-86ba-815985353633}*SharedItemsImports = 4 test\AppLifecycle\AppLifecycle.vcxitems*{80e07022-9e99-44fe-b875-901fb6c82f52}*SharedItemsImports = 9 test\inc\inc.vcxitems*{b567fe2e-3a03-48d0-b2b5-760cdec35891}*SharedItemsImports = 9 + dev\DynamicDependency\DynamicDependency.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 + dev\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 + dev\DynamicDependency\DynamicDependency.vcxitems*{bf055a59-0919-4e34-9b76-dd055495cc5a}*SharedItemsImports = 9 test\CppShared\CppShared.vcxitems*{c62688a1-16a0-4729-b6ed-842f4faa29f3}*SharedItemsImports = 4 test\inc\inc.vcxitems*{c62688a1-16a0-4729-b6ed-842f4faa29f3}*SharedItemsImports = 4 dev\AppLifecycle\AppLifecycle.vcxitems*{e3a522a3-6635-4a42-bded-1af46a15f63c}*SharedItemsImports = 9 @@ -103,6 +166,7 @@ Global {C62688A1-16A0-4729-B6ED-842F4FAA29F3}.Debug|ARM.ActiveCfg = Debug|ARM {C62688A1-16A0-4729-B6ED-842F4FAA29F3}.Debug|ARM.Build.0 = Debug|ARM {C62688A1-16A0-4729-B6ED-842F4FAA29F3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C62688A1-16A0-4729-B6ED-842F4FAA29F3}.Debug|ARM64.Build.0 = Debug|ARM64 {C62688A1-16A0-4729-B6ED-842F4FAA29F3}.Debug|x64.ActiveCfg = Debug|x64 {C62688A1-16A0-4729-B6ED-842F4FAA29F3}.Debug|x64.Build.0 = Debug|x64 {C62688A1-16A0-4729-B6ED-842F4FAA29F3}.Debug|x86.ActiveCfg = Debug|Win32 @@ -143,6 +207,378 @@ Global {7C502995-59C3-483B-86BA-815985353633}.Release|x64.Build.0 = Release|x64 {7C502995-59C3-483B-86BA-815985353633}.Release|x86.ActiveCfg = Release|Win32 {7C502995-59C3-483B-86BA-815985353633}.Release|x86.Build.0 = Release|Win32 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|Any CPU.Build.0 = Release|x64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|ARM.ActiveCfg = Debug|ARM + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|ARM.Build.0 = Debug|ARM + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|x64.ActiveCfg = Debug|x64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|x64.Build.0 = Debug|x64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|x86.ActiveCfg = Debug|Win32 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug_test|x86.Build.0 = Debug|Win32 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug|ARM.ActiveCfg = Debug|ARM + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug|x64.ActiveCfg = Debug|x64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug|x64.Build.0 = Debug|x64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug|x86.ActiveCfg = Debug|Win32 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Debug|x86.Build.0 = Debug|Win32 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Release|Any CPU.ActiveCfg = Release|Win32 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Release|ARM.ActiveCfg = Release|ARM + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Release|ARM64.ActiveCfg = Release|ARM64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Release|x64.ActiveCfg = Release|x64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Release|x64.Build.0 = Release|x64 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Release|x86.ActiveCfg = Release|Win32 + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED}.Release|x86.Build.0 = Release|Win32 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|Any CPU.Build.0 = Release|x64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|ARM.ActiveCfg = Debug|ARM + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|ARM.Build.0 = Debug|ARM + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|x64.ActiveCfg = Debug|x64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|x64.Build.0 = Debug|x64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|x86.ActiveCfg = Debug|Win32 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug_test|x86.Build.0 = Debug|Win32 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|ARM.ActiveCfg = Debug|ARM + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|ARM.Build.0 = Debug|ARM + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|ARM64.Build.0 = Debug|ARM64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|x64.ActiveCfg = Debug|x64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|x64.Build.0 = Debug|x64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|x86.ActiveCfg = Debug|Win32 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Debug|x86.Build.0 = Debug|Win32 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|Any CPU.ActiveCfg = Release|Win32 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|ARM.ActiveCfg = Release|ARM + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|ARM.Build.0 = Release|ARM + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|ARM64.ActiveCfg = Release|ARM64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|ARM64.Build.0 = Release|ARM64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|x64.ActiveCfg = Release|x64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|x64.Build.0 = Release|x64 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|x86.ActiveCfg = Release|Win32 + {F76B776E-86F5-48C5-8FC7-D2795ECC9746}.Release|x86.Build.0 = Release|Win32 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|Any CPU.Build.0 = Release|x64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|ARM.ActiveCfg = Debug|ARM + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|ARM.Build.0 = Debug|ARM + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|x64.ActiveCfg = Debug|x64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|x64.Build.0 = Debug|x64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|x86.ActiveCfg = Debug|Win32 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug_test|x86.Build.0 = Debug|Win32 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|ARM.ActiveCfg = Debug|ARM + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|ARM.Build.0 = Debug|ARM + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|ARM64.Build.0 = Debug|ARM64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|x64.ActiveCfg = Debug|x64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|x64.Build.0 = Debug|x64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|x86.ActiveCfg = Debug|Win32 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Debug|x86.Build.0 = Debug|Win32 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|Any CPU.ActiveCfg = Release|Win32 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|ARM.ActiveCfg = Release|ARM + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|ARM.Build.0 = Release|ARM + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|ARM64.ActiveCfg = Release|ARM64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|ARM64.Build.0 = Release|ARM64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|x64.ActiveCfg = Release|x64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|x64.Build.0 = Release|x64 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|x86.ActiveCfg = Release|Win32 + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33}.Release|x86.Build.0 = Release|Win32 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|Any CPU.Build.0 = Release|x64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|ARM.ActiveCfg = Debug|ARM + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|ARM.Build.0 = Debug|ARM + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|x64.ActiveCfg = Debug|x64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|x64.Build.0 = Debug|x64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|x86.ActiveCfg = Debug|Win32 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug_test|x86.Build.0 = Debug|Win32 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|ARM.ActiveCfg = Debug|ARM + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|ARM.Build.0 = Debug|ARM + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|ARM64.Build.0 = Debug|ARM64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|x64.ActiveCfg = Debug|x64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|x64.Build.0 = Debug|x64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|x86.ActiveCfg = Debug|Win32 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Debug|x86.Build.0 = Debug|Win32 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|Any CPU.ActiveCfg = Release|Win32 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|ARM.ActiveCfg = Release|ARM + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|ARM.Build.0 = Release|ARM + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|ARM64.ActiveCfg = Release|ARM64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|ARM64.Build.0 = Release|ARM64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|x64.ActiveCfg = Release|x64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|x64.Build.0 = Release|x64 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|x86.ActiveCfg = Release|Win32 + {58E95711-A12F-4C0E-A978-C6B4A0842AC8}.Release|x86.Build.0 = Release|Win32 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|Any CPU.Build.0 = Release|x64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|ARM.ActiveCfg = Debug|ARM + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|ARM.Build.0 = Debug|ARM + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|x64.ActiveCfg = Debug|x64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|x64.Build.0 = Debug|x64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|x86.ActiveCfg = Debug|Win32 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug_test|x86.Build.0 = Debug|Win32 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|ARM.ActiveCfg = Debug|ARM + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|ARM.Build.0 = Debug|ARM + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|ARM64.Build.0 = Debug|ARM64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|x64.ActiveCfg = Debug|x64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|x64.Build.0 = Debug|x64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|x86.ActiveCfg = Debug|Win32 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Debug|x86.Build.0 = Debug|Win32 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|Any CPU.ActiveCfg = Release|Win32 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|ARM.ActiveCfg = Release|ARM + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|ARM.Build.0 = Release|ARM + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|ARM64.ActiveCfg = Release|ARM64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|ARM64.Build.0 = Release|ARM64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|x64.ActiveCfg = Release|x64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|x64.Build.0 = Release|x64 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|x86.ActiveCfg = Release|Win32 + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3}.Release|x86.Build.0 = Release|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|Any CPU.Build.0 = Release|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|ARM.ActiveCfg = Release|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|ARM.Build.0 = Release|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|ARM64.ActiveCfg = Release|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|ARM64.Build.0 = Release|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|x64.ActiveCfg = Debug|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|x64.Build.0 = Debug|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|x86.ActiveCfg = Debug|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug_test|x86.Build.0 = Debug|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug|ARM.ActiveCfg = Debug|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug|ARM64.ActiveCfg = Debug|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug|x64.ActiveCfg = Debug|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug|x64.Build.0 = Debug|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug|x86.ActiveCfg = Debug|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Debug|x86.Build.0 = Debug|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Release|Any CPU.ActiveCfg = Release|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Release|ARM.ActiveCfg = Release|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Release|ARM64.ActiveCfg = Release|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Release|x64.ActiveCfg = Release|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Release|x64.Build.0 = Release|x64 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Release|x86.ActiveCfg = Release|Win32 + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE}.Release|x86.Build.0 = Release|Win32 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|Any CPU.Build.0 = Release|x64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|ARM.ActiveCfg = Debug|ARM + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|ARM.Build.0 = Debug|ARM + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|x64.ActiveCfg = Debug|x64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|x64.Build.0 = Debug|x64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|x86.ActiveCfg = Debug|Win32 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug_test|x86.Build.0 = Debug|Win32 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|ARM.ActiveCfg = Debug|ARM + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|ARM.Build.0 = Debug|ARM + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|ARM64.Build.0 = Debug|ARM64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|x64.ActiveCfg = Debug|x64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|x64.Build.0 = Debug|x64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|x86.ActiveCfg = Debug|Win32 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Debug|x86.Build.0 = Debug|Win32 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|Any CPU.ActiveCfg = Release|Win32 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|ARM.ActiveCfg = Release|ARM + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|ARM.Build.0 = Release|ARM + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|ARM64.ActiveCfg = Release|ARM64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|ARM64.Build.0 = Release|ARM64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|x64.ActiveCfg = Release|x64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|x64.Build.0 = Release|x64 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|x86.ActiveCfg = Release|Win32 + {51293DFA-614B-4355-A60D-B30DF3228FD1}.Release|x86.Build.0 = Release|Win32 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|Any CPU.Build.0 = Release|x64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|ARM.ActiveCfg = Debug|ARM + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|ARM.Build.0 = Debug|ARM + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|x64.ActiveCfg = Debug|x64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|x64.Build.0 = Debug|x64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|x86.ActiveCfg = Debug|Win32 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug_test|x86.Build.0 = Debug|Win32 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|ARM.ActiveCfg = Debug|ARM + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|ARM.Build.0 = Debug|ARM + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|ARM64.Build.0 = Debug|ARM64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|x64.ActiveCfg = Debug|x64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|x64.Build.0 = Debug|x64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|x86.ActiveCfg = Debug|Win32 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Debug|x86.Build.0 = Debug|Win32 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|Any CPU.ActiveCfg = Release|Win32 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|ARM.ActiveCfg = Release|ARM + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|ARM.Build.0 = Release|ARM + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|ARM64.ActiveCfg = Release|ARM64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|ARM64.Build.0 = Release|ARM64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|x64.ActiveCfg = Release|x64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|x64.Build.0 = Release|x64 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|x86.ActiveCfg = Release|Win32 + {1A41BB90-CC34-4EDD-9A27-50714CDBC169}.Release|x86.Build.0 = Release|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|Any CPU.ActiveCfg = Release|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|Any CPU.Build.0 = Release|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|ARM.ActiveCfg = Release|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|ARM.Build.0 = Release|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|ARM64.ActiveCfg = Release|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|ARM64.Build.0 = Release|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|x64.ActiveCfg = Debug|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|x64.Build.0 = Debug|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|x86.ActiveCfg = Debug|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug_test|x86.Build.0 = Debug|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug|ARM.ActiveCfg = Debug|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug|ARM64.ActiveCfg = Debug|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug|x64.ActiveCfg = Debug|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug|x64.Build.0 = Debug|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug|x86.ActiveCfg = Debug|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Debug|x86.Build.0 = Debug|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Release|Any CPU.ActiveCfg = Release|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Release|ARM.ActiveCfg = Release|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Release|ARM64.ActiveCfg = Release|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Release|x64.ActiveCfg = Release|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Release|x64.Build.0 = Release|x64 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Release|x86.ActiveCfg = Release|Win32 + {B71E818A-882E-456A-87E5-4DE4A6602B99}.Release|x86.Build.0 = Release|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|Any CPU.Build.0 = Debug|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|ARM.ActiveCfg = Debug|ARM + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|ARM.Build.0 = Debug|ARM + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|x64.ActiveCfg = Debug|x64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|x64.Build.0 = Debug|x64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|x86.ActiveCfg = Debug|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug_test|x86.Build.0 = Debug|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|ARM.ActiveCfg = Debug|ARM + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|ARM.Build.0 = Debug|ARM + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|ARM64.Build.0 = Debug|ARM64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|x64.ActiveCfg = Debug|x64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|x64.Build.0 = Debug|x64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|x86.ActiveCfg = Debug|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Debug|x86.Build.0 = Debug|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|Any CPU.ActiveCfg = Release|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|ARM.ActiveCfg = Release|ARM + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|ARM.Build.0 = Release|ARM + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|ARM64.ActiveCfg = Release|ARM64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|ARM64.Build.0 = Release|ARM64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|x64.ActiveCfg = Release|x64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|x64.Build.0 = Release|x64 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|x86.ActiveCfg = Release|Win32 + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86}.Release|x86.Build.0 = Release|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|Any CPU.Build.0 = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|ARM.ActiveCfg = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|ARM.Build.0 = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|ARM64.ActiveCfg = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|ARM64.Build.0 = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|x64.ActiveCfg = Debug|x64 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|x64.Build.0 = Debug|x64 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|x86.ActiveCfg = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug_test|x86.Build.0 = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug|ARM.ActiveCfg = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug|ARM64.ActiveCfg = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug|x64.ActiveCfg = Debug|x64 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug|x64.Build.0 = Debug|x64 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug|x86.ActiveCfg = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Debug|x86.Build.0 = Debug|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Release|Any CPU.ActiveCfg = Release|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Release|ARM.ActiveCfg = Release|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Release|ARM64.ActiveCfg = Release|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Release|x64.ActiveCfg = Release|x64 + {A7391725-4EF5-438F-8DE1-645423E46955}.Release|x64.Build.0 = Release|x64 + {A7391725-4EF5-438F-8DE1-645423E46955}.Release|x86.ActiveCfg = Release|Win32 + {A7391725-4EF5-438F-8DE1-645423E46955}.Release|x86.Build.0 = Release|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|Any CPU.Build.0 = Debug|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|ARM.ActiveCfg = Debug|ARM + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|ARM.Build.0 = Debug|ARM + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|x64.ActiveCfg = Debug|x64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|x64.Build.0 = Debug|x64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|x86.ActiveCfg = Debug|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug_test|x86.Build.0 = Debug|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|ARM.ActiveCfg = Debug|ARM + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|ARM.Build.0 = Debug|ARM + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|ARM64.Build.0 = Debug|ARM64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|x64.ActiveCfg = Debug|x64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|x64.Build.0 = Debug|x64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|x86.ActiveCfg = Debug|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Debug|x86.Build.0 = Debug|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|Any CPU.ActiveCfg = Release|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|ARM.ActiveCfg = Release|ARM + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|ARM.Build.0 = Release|ARM + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|ARM64.ActiveCfg = Release|ARM64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|ARM64.Build.0 = Release|ARM64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|x64.ActiveCfg = Release|x64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|x64.Build.0 = Release|x64 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|x86.ActiveCfg = Release|Win32 + {8C79C46D-1577-44CA-83DF-88B74C3E4586}.Release|x86.Build.0 = Release|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|Any CPU.Build.0 = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|ARM.ActiveCfg = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|ARM.Build.0 = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|ARM64.ActiveCfg = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|ARM64.Build.0 = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|x64.ActiveCfg = Debug|x64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|x64.Build.0 = Debug|x64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|x86.ActiveCfg = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug_test|x86.Build.0 = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|ARM.ActiveCfg = Debug|ARM + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|ARM.Build.0 = Debug|ARM + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|ARM64.Build.0 = Debug|ARM64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|x64.ActiveCfg = Debug|x64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|x64.Build.0 = Debug|x64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|x86.ActiveCfg = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Debug|x86.Build.0 = Debug|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|Any CPU.ActiveCfg = Release|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|ARM.ActiveCfg = Release|ARM + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|ARM.Build.0 = Release|ARM + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|ARM64.ActiveCfg = Release|ARM64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|ARM64.Build.0 = Release|ARM64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|x64.ActiveCfg = Release|x64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|x64.Build.0 = Release|x64 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|x86.ActiveCfg = Release|Win32 + {CCD23028-B9D3-410B-836E-20B2E7C08451}.Release|x86.Build.0 = Release|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|Any CPU.Build.0 = Debug|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|ARM.ActiveCfg = Debug|ARM + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|ARM.Build.0 = Debug|ARM + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|x64.ActiveCfg = Debug|x64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|x64.Build.0 = Debug|x64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|x86.ActiveCfg = Debug|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug_test|x86.Build.0 = Debug|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug|ARM.ActiveCfg = Debug|ARM + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug|x64.ActiveCfg = Debug|x64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug|x64.Build.0 = Debug|x64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug|x86.ActiveCfg = Debug|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Debug|x86.Build.0 = Debug|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Release|Any CPU.ActiveCfg = Release|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Release|ARM.ActiveCfg = Release|ARM + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Release|ARM64.ActiveCfg = Release|ARM64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Release|x64.ActiveCfg = Release|x64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Release|x64.Build.0 = Release|x64 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Release|x86.ActiveCfg = Release|Win32 + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -157,6 +593,28 @@ Global {AC5FFC80-92FE-4933-BED2-EC5519AC4440} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} {B567FE2E-3A03-48D0-B2B5-760CDEC35891} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} {7C502995-59C3-483B-86BA-815985353633} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440} + {6CD01EF6-D4A4-4801-ADCF-344CF87FF942} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} + {BF055A59-0919-4E34-9B76-DD055495CC5A} = {6CD01EF6-D4A4-4801-ADCF-344CF87FF942} + {17B1F036-8FC3-49E6-9464-0C1F96CEAEB9} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} + {6BAC3B29-3A6B-4B3F-A9AB-A316AA4E48ED} = {17B1F036-8FC3-49E6-9464-0C1F96CEAEB9} + {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} + {D6BC25C5-1AA7-4C4A-A02C-B42DEDBFEA33} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} + {0C534F12-B076-47E5-A05B-2A711233AC6F} = {17B1F036-8FC3-49E6-9464-0C1F96CEAEB9} + {58E95711-A12F-4C0E-A978-C6B4A0842AC8} = {0C534F12-B076-47E5-A05B-2A711233AC6F} + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3} = {0C534F12-B076-47E5-A05B-2A711233AC6F} + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {0C534F12-B076-47E5-A05B-2A711233AC6F} + {441A3BB0-7FD2-4902-AEDB-A1C57B528C77} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} + {51293DFA-614B-4355-A60D-B30DF3228FD1} = {441A3BB0-7FD2-4902-AEDB-A1C57B528C77} + {1A41BB90-CC34-4EDD-9A27-50714CDBC169} = {441A3BB0-7FD2-4902-AEDB-A1C57B528C77} + {B71E818A-882E-456A-87E5-4DE4A6602B99} = {0C534F12-B076-47E5-A05B-2A711233AC6F} + {D043D403-31F1-43F1-B2D4-FA8F7090006D} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} + {2E5BF0D2-78FA-4B60-A341-F65A0D58BD86} = {D043D403-31F1-43F1-B2D4-FA8F7090006D} + {A7391725-4EF5-438F-8DE1-645423E46955} = {0C534F12-B076-47E5-A05B-2A711233AC6F} + {8C79C46D-1577-44CA-83DF-88B74C3E4586} = {D043D403-31F1-43F1-B2D4-FA8F7090006D} + {CCD23028-B9D3-410B-836E-20B2E7C08451} = {D043D403-31F1-43F1-B2D4-FA8F7090006D} + {B2546322-D329-4F6C-9C2E-7EFC3C9ED214} = {17B1F036-8FC3-49E6-9464-0C1F96CEAEB9} + {323E29A9-873F-419B-919E-D18BCE1DE120} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} + {56371CA6-144B-4989-A4E9-391AD4FA7651} = {323E29A9-873F-419B-919E-D18BCE1DE120} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77} diff --git a/build/AzurePipelinesTemplates/ProjectReunion-BuildProject-Steps.yml b/build/AzurePipelinesTemplates/ProjectReunion-BuildProject-Steps.yml index bbbd79ab1..914254b63 100644 --- a/build/AzurePipelinesTemplates/ProjectReunion-BuildProject-Steps.yml +++ b/build/AzurePipelinesTemplates/ProjectReunion-BuildProject-Steps.yml @@ -56,6 +56,14 @@ steps: feedsToUse: config nugetConfigPath: ${{ parameters.nugetConfigPath }} + - task: powershell@2 + displayName: 'Create pfx to sign MSIX test packages (DevCheck)' + inputs: + targetType: filePath + filePath: tools\DevCheck.ps1 + arguments: -CheckTestPfx -Clean -Offline -Verbose + workingDirectory: '$(Build.SourcesDirectory)' + - task: VSBuild@1 displayName: 'Build solution ${{ parameters.solutionPath }}' inputs: @@ -66,11 +74,29 @@ steps: msbuildArgs: '/p:AppxPackageDir="${{ parameters.appxPackageDir }}" /p:AppxBundle=Never /p:AppxSymbolPackageEnabled=false /binaryLogger:$(Build.SourcesDirectory)/${{ parameters.solutionPath }}.$(buildPlatform).$(buildConfiguration).binlog /p:ProjectReunionVersionBuild=$(builddate_yymm) /p:ProjectReunionVersionRevision=$(builddate_dd)$(buildrevision) /p:VCToolsInstallDir="$(VCToolsInstallDir)\" /p:PGOBuildMode=$(PGOBuildMode)' - task: CmdLine@2 - displayName: 'Run AppLifeCycleTest' + displayName: 'Install Test Certificate' inputs: - script: 'te.exe CppTest.dll' - workingDirectory: '$(Build.SourcesDirectory)\BuildOutput\$(buildConfiguration)\$(buildPlatform)\CppTest' - condition: or(eq(variables.buildPlatform, 'x64'), eq(variables.buildPlatform, 'x86')) + script: 'certutil.exe -addstore TrustedPeople MSTest.cer' + workingDirectory: '$(Build.SourcesDirectory)\build' + + - task: powershell@2 + displayName: 'Setup TAEF Service (DevCheck)' + inputs: + targetType: filePath + filePath: tools\DevCheck.ps1 + arguments: -CheckTAEFService -Offline -Verbose + workingDirectory: '$(Build.SourcesDirectory)' + +#DISABLED - GitHub runs as a a built-in Administrator (thus Elevated and no split-token) +# TAEF Service can't RunAs:RestrictedUser from this account thus all tests Failed or Blocked +# and Dynamic Dependencies doesn't support Elevation so it's impossible for this test to +# work correctly today. Disabling until we move off GitHub's pipeline for test execution +# - task: CmdLine@2 +# displayName: 'Run AppLifeCycleTest' +# inputs: +# script: 'te.exe CppTest.dll' +# workingDirectory: '$(Build.SourcesDirectory)\BuildOutput\$(buildConfiguration)\$(buildPlatform)\CppTest' +# condition: or(eq(variables.buildPlatform, 'x64'), eq(variables.buildPlatform, 'x86')) - task: PublishBuildArtifacts@1 displayName: 'Publish ${{ parameters.solutionPath }} binlog' diff --git a/build/MSTest.cer b/build/MSTest.cer new file mode 100644 index 000000000..7aae8b5eb Binary files /dev/null and b/build/MSTest.cer differ diff --git a/build/MSTest.spfx b/build/MSTest.spfx new file mode 100644 index 000000000..a867d6ce1 --- /dev/null +++ b/build/MSTest.spfx @@ -0,0 +1,63 @@ +-----BEGIN CERTIFICATE----- +MIILSgIBAzCCCwYGCSqGSIb3DQEHAaCCCvcEggrzMIIK7zCCBggGCSqGSIb3DQEH +AaCCBfkEggX1MIIF8TCCBe0GCyqGSIb3DQEMCgECoIIE/jCCBPowHAYKKoZIhvcN +AQwBAzAOBAjIXdhD2Rgv4AICB9AEggTYfAO/jMECF0pFl2cRPoakYKpKYFPFQeUk +xXCyQhYKzLf9VPOWeboOmmhzQ2CXRfMLkSc2xUPeVkha3SrhLFzTrYIJNd0Fn2JI +V8EyP3hpWdV5B1EDMe0tI/uQS7oBoAGmxuna7681UpeFDskctiJTtWz0cCVLhLcK +amzH+EJi5X1r120fFtGLebb6Fom2ZV0xKNJcEYxZr7cX9e9oE7DtMRZ5DVRd20V0 +ovtqwLY+6TpmS+a7g95h5jSBM9hYEXq4z1S9rl42iyDvdF74pcjG21+5Z20U04Cl +qiySSTcn6GlzWhJevLSEwbREbRWkYEIgE5bZFAfYfgQ3Qas1qI4JadMkcdTkRypR +InrArU6hB+H/X8i/tJ2VeCs2rRTYfDqydlzoU6LormoRvbB50bup6O90yw0bsHD9 +/oIE9fiSnsf8GKzS14JYKMkEpCzrqf7suYYOhV/KwRMqI2E0i5H1ZrlOmGik9vq1 +RYbh6+028QXBYsBBw80VRWr5OKGyrSP8xcK2Qg7XcDB4aLJ7QPRFQLtOOwWkuVOX +SwYJs6N6QXhSvQpfE0dsEgTXyJ3tP7CJuGT6aWEHkHOkwBhH2zQ6lejEMHztWdEv +zXis8vGtP5AxrDVx3f055n9hsamw/0R0pnzHMXmX0OJinb3ZuA2RsevQXK0nwLk+ +Ljok1wcEBVXSUD6Ywd59cB1zdD89F/Tg5zgsNZ8SPhuGUs6ctNL0ymUJMGC3571z +clVVDnvM03FH4zhaZDkn4DAIrukDcQX2/6esLTzTsjGxzRTM4Y9YUAXT3C6LnctV +Sr0t9JpVILYqh68MonLND0jz8H+zVe2KNj0ROwv8IBGcG8a+klt61QBTlAAG8ee9 +plqPrHKI62m98upspKn3MzqKN9xVedfB1v1ijO7MZrD8juNzDrSYzO6VlyA+oMjr +pXyj9CqMqPGy2/sr5tpWcYEQe8LdEWlRQBVZIdelNkIm3C6jSgSSeSxXDB8IXNt6 +fHtzCTCj4s0sJqipIOwECEQaSYVJlUKSZLJTYAfdfBLDy/Lz+G6n5/e9RRvWBeJx +kqnOmJhXlyZ6wZJO5Fvdv1UF/zRCPUYNyorEXkA9Z82yTJ7KdqAOOUs/fRuiNvOg +PezX/qyv2ZzR9LqU0pRrVVhoFV7cyllSDxXqPcR1Iq/a6OdJ3lEc95hUk+4TIioy +ch9eFVDUwHJ98K9+7G78d9zQ7VpruE1a/FK9QOoHUPbfl4qpDxSgQfm/weD+qwo+ +g4jjCby4l4GM23M/dzXbMEL4ilV7BU1tkmqzcF5Zee5zBiIVWLrt/5npuVi/8ZJF +N/T8n1VLaLXGHcn7dlI9pl1+88DW2EKGDXor9CuOOOeH2fi0blgRUzD2mRZXnDjE +4tfB0FTyUtnN5IVsKSvTEhQnywiByFMj6jPzZ+WmEEbxs3KbQHsofModvAVS/UbW +uIojhQ+kT3ncIMZeS2IHbwZTPiAbDn8adg9rFptEQkQMFSyDmHwmRN4HPDGcnQrA +gcBJbNLy5unxlwG+pUfttjJaS9q+z/eWyOhLiPI98aEJYrVZ1EQwyGTSYKN9tQ+C +GajShWYPkVV7rjBNQCoWUDjuokW7GkeYe2YlZ58YwH7tZb0CkDw4j4WPmSoOcUpf +xRd+KVBiGv4Gd/PannezhDGB2zATBgkqhkiG9w0BCRUxBgQEAQAAADBdBgkrBgEE +AYI3EQExUB5OAE0AaQBjAHIAbwBzAG8AZgB0ACAAUwB0AHIAbwBuAGcAIABDAHIA +eQBwAHQAbwBnAHIAYQBwAGgAaQBjACAAUAByAG8AdgBpAGQAZQByMGUGCSqGSIb3 +DQEJFDFYHlYAUAB2AGsAVABtAHAAOgA2ADIAOQBhADgAMQBmADQALQA0AGUAMgAz +AC0ANABjAGQAMgAtADgAZAAxADMALQA2ADEAZQBjAGUANgBmADEAMwA5AGIAODCC +BN8GCSqGSIb3DQEHBqCCBNAwggTMAgEAMIIExQYJKoZIhvcNAQcBMBwGCiqGSIb3 +DQEMAQMwDgQIu/cm7lKUSWsCAgfQgIIEmIsUvJdZcNiVPybOD6v87I/BFOOg6S0K +MV+hJdk9h7yGbIMkYtCW9B1jIHp07Mr/5ANGczkXgkqtPhz2fRqQSzg3LKZJOxpP +2zPjRxvWLT06gEIDKZRbvNf+vesr+hw0WomhBHlzXV54aDgVVECEFZaHZnI1TgiR +NwsnjXliMUkwQefMHfkFBYHv42twhAHHYdiA67Z3hQAMybASPiLeP6zV1MKuuzth +qBwysrPmI3ldBCoAATyE/ythyby9/6NWWODXOy6+ooeMto2eyk+9V1Je3PVW8OKX +bljHnrB8eJIEqM9WxV+Vrqk/Hxhq3+Q/vCm1PKQH+5EKkMQIyDdIrdtMvkR8l9AZ +P51G7V9/ZUF3fn4m2HCKytkBWZBJI9yJXa+6FCZM2fZRxDdKKfXRcde7+0AqTWRr +rSNOhr0cu2ol0bcHKHQHOKjKDNPoDQrVXo6uw+Zhl5+Ly8d50K8zOlqZrru7GpLj +xX/VaVdB+fVpjtZIjGA14URrHux0StqGr7Ex7a5Fp4QB6eHkZX35bGO4ME7oZRHL +QVDXKDEqhn8BXYE0rKl1F+iTQqkxL72YbiBRu0jxyGSzifX8h4oMijG5PfRJgEkP +RLYRjJjxFFKZKJ8E2y5Du4xM0lYdU2td3iQyUkSip+1WVV/88T+ysiWYIa1dp+qt +FNiXxOhriUBJ3OuIcgLNJZ1MaDwYHe2yhr4g8AL5xI9fnbjwy3TSHclLGb5hfT5u +bFYPAWGvmxwVP2ntgnpjWO86AIl0fAMwHQern2CgnfomhEr7L/SLlAbqdrbD6t29 +K94Xfacf6CphD8xgsMRKqG7ZIqOSbvQzSm3/810eLbL3ubEl38w33Kj1JWVHJaSN +HH5NQfsJm6XrL3aDAVTENVqdTcW/Qg9n9XR/rVgyMbFXpfigWPBlO9aOUravzez/ +bdsyLohkaaevbj4adqkCMkTYddIebdBoo/+FyAb4uShV/XaO0W+zs9xvqNBXXDf9 +XJJpJOPn9BK0NTxbb8eA1CwM7dMZNqdoLxGjrc0gRew41ApTUQ+HJDB4+qQxn9Oy +1ZREip2Uw1poxgBlNUlVGq5B5JGrZlqVtaJQygCSNHLWvXxUspF36uWQ6z5dqlO1 +wK0aCziSLsY/gaeqWHvzTEHZvv5yQK3vvMiKT++wgOiiKijNhEoflyoU3hgu1jUR +iNhbnIgByIiJkXdnC7gv2UJKvLlIMT45snnmUvmqvRryowqXZ75r7XezmseJ4I21 +Heamung4U65fojsE1jURlcpt87x33a5coDzluCMTZprODLQZbBj39G4pwE3MKQXh +6Im1O9qR4P2sgMx6lluRK94dkkn8+MvlK1GOso5T6HTwrkGgK1Sfpiz50SmbULx3 +kiA1OVmraipVOrXD5pmT2AFt/vjkWJZMQgis2lOmTpuUz6jfEBUvfXvTXSk48KhG +XRnq60R+ABsiW5FBrbwwGZG3hOhVoBdwhlQ5bBw7JTnGNhSPtvHPA7E3ZwhDxpn3 +4UbIprfWVLrR9BbWayvt34JIN8WZkjH7bwhnZo3Q8yfzN1nk8+gRYkwjgky49UWg +9TA7MB8wBwYFKw4DAhoEFG8Ifc9pvQshFzC3cnRPBTfW+FoHBBT2b3CHfQO0hexn +tBf4/CkiLemo8AICB9A= +-----END CERTIFICATE----- diff --git a/dev/AppLifecycle/ActivatedEventArgsBase.h b/dev/AppLifecycle/ActivatedEventArgsBase.h index 7ee52c346..9dc8e9682 100644 --- a/dev/AppLifecycle/ActivatedEventArgsBase.h +++ b/dev/AppLifecycle/ActivatedEventArgsBase.h @@ -2,7 +2,7 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #pragma once -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { using namespace winrt::Windows::ApplicationModel::Activation; diff --git a/dev/AppLifecycle/ActivationRegistrationManager.cpp b/dev/AppLifecycle/ActivationRegistrationManager.cpp index 1e4cce93b..6d663b672 100644 --- a/dev/AppLifecycle/ActivationRegistrationManager.cpp +++ b/dev/AppLifecycle/ActivationRegistrationManager.cpp @@ -2,14 +2,14 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #include #include -#include +#include #include "LaunchActivatedEventArgs.h" #include "ProtocolActivatedEventArgs.h" #include "FileActivatedEventArgs.h" #include "Association.h" -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { void ActivationRegistrationManager::RegisterForFileTypeActivation( array_view supportedFileTypes, array_view supportedVerbs, diff --git a/dev/AppLifecycle/ActivationRegistrationManager.h b/dev/AppLifecycle/ActivationRegistrationManager.h index 254c377eb..62365c67d 100644 --- a/dev/AppLifecycle/ActivationRegistrationManager.h +++ b/dev/AppLifecycle/ActivationRegistrationManager.h @@ -2,9 +2,9 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #pragma once -#include +#include -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { struct ActivationRegistrationManager { @@ -21,7 +21,7 @@ namespace winrt::Microsoft::ProjectReunion::implementation }; } -namespace winrt::Microsoft::ProjectReunion::factory_implementation +namespace winrt::Microsoft::ApplicationModel::Activation::factory_implementation { struct ActivationRegistrationManager : ActivationRegistrationManagerT diff --git a/dev/AppLifecycle/AppLifecycle.cpp b/dev/AppLifecycle/AppLifecycle.cpp index 7df5a2b1b..c14a8f225 100644 --- a/dev/AppLifecycle/AppLifecycle.cpp +++ b/dev/AppLifecycle/AppLifecycle.cpp @@ -3,14 +3,14 @@ #include #include -#include +#include #include "LaunchActivatedEventArgs.h" #include "ProtocolActivatedEventArgs.h" #include "FileActivatedEventArgs.h" #include "Association.h" -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { std::tuple ParseCommandLine(std::wstring commandLine) { diff --git a/dev/AppLifecycle/AppLifecycle.h b/dev/AppLifecycle/AppLifecycle.h index 636ed0a5c..bba8b9596 100644 --- a/dev/AppLifecycle/AppLifecycle.h +++ b/dev/AppLifecycle/AppLifecycle.h @@ -2,9 +2,9 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #pragma once -#include +#include -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { struct AppLifecycle { @@ -14,7 +14,7 @@ namespace winrt::Microsoft::ProjectReunion::implementation }; } -namespace winrt::Microsoft::ProjectReunion::factory_implementation +namespace winrt::Microsoft::ApplicationModel::Activation::factory_implementation { struct AppLifecycle : AppLifecycleT { diff --git a/dev/AppLifecycle/AppLifecycle.idl b/dev/AppLifecycle/AppLifecycle.idl index e57eb9f3b..0781355bb 100644 --- a/dev/AppLifecycle/AppLifecycle.idl +++ b/dev/AppLifecycle/AppLifecycle.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. -namespace Microsoft.ProjectReunion +namespace Microsoft.ApplicationModel.Activation { static runtimeclass AppLifecycle { diff --git a/dev/AppLifecycle/Association.cpp b/dev/AppLifecycle/Association.cpp index 723a3488b..e393bd5f5 100644 --- a/dev/AppLifecycle/Association.cpp +++ b/dev/AppLifecycle/Association.cpp @@ -3,7 +3,7 @@ #include #include "Association.h" -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { HKEY GetRegistrationRoot() { diff --git a/dev/AppLifecycle/Association.h b/dev/AppLifecycle/Association.h index 6e4932e75..532045a69 100644 --- a/dev/AppLifecycle/Association.h +++ b/dev/AppLifecycle/Association.h @@ -2,7 +2,7 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #pragma once -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { static const std::wstring c_protocolArgumentString = L"ms-protocol"; static const std::wstring c_fileArgumentString = L"ms-file"; diff --git a/dev/AppLifecycle/FileActivatedEventArgs.h b/dev/AppLifecycle/FileActivatedEventArgs.h index f72653c34..dce3722c6 100644 --- a/dev/AppLifecycle/FileActivatedEventArgs.h +++ b/dev/AppLifecycle/FileActivatedEventArgs.h @@ -4,7 +4,7 @@ #include "ActivatedEventArgsBase.h" -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { using namespace winrt::Windows::Foundation::Collections; using namespace winrt::Windows::ApplicationModel::Activation; diff --git a/dev/AppLifecycle/LaunchActivatedEventArgs.h b/dev/AppLifecycle/LaunchActivatedEventArgs.h index 38e9cec94..e5ba8f903 100644 --- a/dev/AppLifecycle/LaunchActivatedEventArgs.h +++ b/dev/AppLifecycle/LaunchActivatedEventArgs.h @@ -4,7 +4,7 @@ #include "ActivatedEventArgsBase.h" -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { using namespace winrt::Windows::ApplicationModel::Activation; diff --git a/dev/AppLifecycle/ProtocolActivatedEventArgs.h b/dev/AppLifecycle/ProtocolActivatedEventArgs.h index d53eaa3cc..b267b85cc 100644 --- a/dev/AppLifecycle/ProtocolActivatedEventArgs.h +++ b/dev/AppLifecycle/ProtocolActivatedEventArgs.h @@ -5,7 +5,7 @@ #include #include "ActivatedEventArgsBase.h" -namespace winrt::Microsoft::ProjectReunion::implementation +namespace winrt::Microsoft::ApplicationModel::Activation::implementation { using namespace winrt::Windows::Foundation::Collections; using namespace winrt::Windows::ApplicationModel::Activation; diff --git a/dev/Detours/Detours.vcxproj b/dev/Detours/Detours.vcxproj new file mode 100644 index 000000000..74fb02869 --- /dev/null +++ b/dev/Detours/Detours.vcxproj @@ -0,0 +1,356 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {d6bc25c5-1aa7-4c4a-a02c-b42dedbfea33} + Detours + 10.0 + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + true + + + false + + + false + + + false + + + false + + + + Level4 + %(PreprocessorDefinitions) + true + NotUsing + pch.h + true + false + true + false + true + false + + + + + true + + + + + Level4 + %(PreprocessorDefinitions) + true + NotUsing + pch.h + true + false + true + false + true + false + + + + + true + + + + + Level4 + true + true + %(PreprocessorDefinitions) + true + NotUsing + pch.h + true + Disabled + false + false + true + false + false + + + + + true + true + true + + + + + Level4 + true + true + %(PreprocessorDefinitions) + true + NotUsing + pch.h + true + Disabled + false + false + true + false + false + + + + + true + true + true + + + + + Level4 + %(PreprocessorDefinitions) + true + NotUsing + pch.h + true + false + true + false + true + false + + + + + true + + + + + Level4 + %(PreprocessorDefinitions) + true + NotUsing + pch.h + true + false + true + false + true + false + + + + + true + + + + + Level4 + true + true + %(PreprocessorDefinitions) + true + NotUsing + pch.h + true + Disabled + false + false + true + false + false + + + + + true + true + true + + + + + Level4 + true + true + %(PreprocessorDefinitions) + true + NotUsing + pch.h + true + Disabled + false + false + true + false + false + + + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/Detours/Detours.vcxproj.filters b/dev/Detours/Detours.vcxproj.filters new file mode 100644 index 000000000..f57b11c3b --- /dev/null +++ b/dev/Detours/Detours.vcxproj.filters @@ -0,0 +1,60 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/dev/Detours/README.md b/dev/Detours/README.md new file mode 100644 index 000000000..80c613449 --- /dev/null +++ b/dev/Detours/README.md @@ -0,0 +1,6 @@ +This is a fork of Detours from https://github.com/microsoft/Detours + +Last forked +----------- +commit e9da64c72f293c0223f293f018067fe68fbdb801 +Date Sat Aug 22 13:21:24 2020 -0700 diff --git a/dev/Detours/creatwth.cpp b/dev/Detours/creatwth.cpp new file mode 100644 index 000000000..300bb2c87 --- /dev/null +++ b/dev/Detours/creatwth.cpp @@ -0,0 +1,1567 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Create a process with a DLL (creatwth.cpp of detours.lib) +// +// Microsoft Research Detours Package, Version 4.0.1 +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +// #define DETOUR_DEBUG 1 +#define DETOURS_INTERNAL +#include "detours.h" +#include + +#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH +#error detours.h version mismatch +#endif + +#define IMPORT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] +#define BOUND_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] +#define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] +#define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT] + +////////////////////////////////////////////////////////////////////////////// +// +const GUID DETOUR_EXE_HELPER_GUID = { /* ea0251b9-5cde-41b5-98d0-2af4a26b0fee */ + 0xea0251b9, 0x5cde, 0x41b5, + { 0x98, 0xd0, 0x2a, 0xf4, 0xa2, 0x6b, 0x0f, 0xee }}; + +////////////////////////////////////////////////////////////////////////////// +// +// Enumate through modules in the target process. +// +static BOOL WINAPI LoadNtHeaderFromProcess(HANDLE hProcess, + HMODULE hModule, + PIMAGE_NT_HEADERS32 pNtHeader) +{ + PBYTE pbModule = (PBYTE)hModule; + + if (pbModule == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + MEMORY_BASIC_INFORMATION mbi; + ZeroMemory(&mbi, sizeof(mbi)); + + if (VirtualQueryEx(hProcess, hModule, &mbi, sizeof(mbi)) == 0) { + return FALSE; + } + + IMAGE_DOS_HEADER idh; + + if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { + DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", + pbModule, pbModule + sizeof(idh), GetLastError())); + return FALSE; + } + + if (idh.e_magic != IMAGE_DOS_SIGNATURE || + (DWORD)idh.e_lfanew > mbi.RegionSize || + (DWORD)idh.e_lfanew < sizeof(idh)) { + + SetLastError(ERROR_BAD_EXE_FORMAT); + return FALSE; + } + + if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, + pNtHeader, sizeof(*pNtHeader), NULL)) { + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p:%p) failed: %d\n", + pbModule + idh.e_lfanew, + pbModule + idh.e_lfanew + sizeof(*pNtHeader), + pbModule, + GetLastError())); + return FALSE; + } + + if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { + SetLastError(ERROR_BAD_EXE_FORMAT); + return FALSE; + } + + return TRUE; +} + +static HMODULE WINAPI EnumerateModulesInProcess(HANDLE hProcess, + HMODULE hModuleLast, + PIMAGE_NT_HEADERS32 pNtHeader) +{ + PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY; + + MEMORY_BASIC_INFORMATION mbi; + ZeroMemory(&mbi, sizeof(mbi)); + + // Find the next memory region that contains a mapped PE image. + // + + for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) { + if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) == 0) { + break; + } + + // Usermode address space has such an unaligned region size always at the + // end and only at the end. + // + if ((mbi.RegionSize & 0xfff) == 0xfff) { + break; + } + if (((PBYTE)mbi.BaseAddress + mbi.RegionSize) < pbLast) { + break; + } + + // Skip uncommitted regions and guard pages. + // + if ((mbi.State != MEM_COMMIT) || + ((mbi.Protect & 0xff) == PAGE_NOACCESS) || + (mbi.Protect & PAGE_GUARD)) { + continue; + } + + if (LoadNtHeaderFromProcess(hProcess, (HMODULE)pbLast, pNtHeader)) { + return (HMODULE)pbLast; + } + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////////// +// +// Find a region of memory in which we can create a replacement import table. +// +static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBase, DWORD cbAlloc) +{ + MEMORY_BASIC_INFORMATION mbi; + ZeroMemory(&mbi, sizeof(mbi)); + + PBYTE pbLast = pbBase; + for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) { + + ZeroMemory(&mbi, sizeof(mbi)); + if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) == 0) { + if (GetLastError() == ERROR_INVALID_PARAMETER) { + break; + } + DETOUR_TRACE(("VirtualQueryEx(%p) failed: %d\n", + pbLast, GetLastError())); + break; + } + // Usermode address space has such an unaligned region size always at the + // end and only at the end. + // + if ((mbi.RegionSize & 0xfff) == 0xfff) { + break; + } + + // Skip anything other than a pure free region. + // + if (mbi.State != MEM_FREE) { + continue; + } + + // Use the max of mbi.BaseAddress and pbBase, in case mbi.BaseAddress < pbBase. + PBYTE pbAddress = (PBYTE)mbi.BaseAddress > pbBase ? (PBYTE)mbi.BaseAddress : pbBase; + + // Round pbAddress up to the nearest MM allocation boundary. + const DWORD_PTR mmGranularityMinusOne = (DWORD_PTR)(MM_ALLOCATION_GRANULARITY -1); + pbAddress = (PBYTE)(((DWORD_PTR)pbAddress + mmGranularityMinusOne) & ~mmGranularityMinusOne); + +#ifdef _WIN64 + // The offset from pbModule to any replacement import must fit into 32 bits. + // For simplicity, we check that the offset to the last byte fits into 32 bits, + // instead of the largest offset we'll actually use. The values are very similar. + const size_t GB4 = ((((size_t)1) << 32) - 1); + if ((size_t)(pbAddress + cbAlloc - 1 - pbModule) > GB4) { + DETOUR_TRACE(("FindAndAllocateNearBase(1) failing due to distance >4GB %p\n", pbAddress)); + return NULL; + } +#else + UNREFERENCED_PARAMETER(pbModule); +#endif + + DETOUR_TRACE(("Free region %p..%p\n", + mbi.BaseAddress, + (PBYTE)mbi.BaseAddress + mbi.RegionSize)); + + for (; pbAddress < (PBYTE)mbi.BaseAddress + mbi.RegionSize; pbAddress += MM_ALLOCATION_GRANULARITY) { + PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc, + MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (pbAlloc == NULL) { + DETOUR_TRACE(("VirtualAllocEx(%p) failed: %d\n", pbAddress, GetLastError())); + continue; + } +#ifdef _WIN64 + // The offset from pbModule to any replacement import must fit into 32 bits. + if ((size_t)(pbAddress + cbAlloc - 1 - pbModule) > GB4) { + DETOUR_TRACE(("FindAndAllocateNearBase(2) failing due to distance >4GB %p\n", pbAddress)); + return NULL; + } +#endif + DETOUR_TRACE(("[%p..%p] Allocated for import table.\n", + pbAlloc, pbAlloc + cbAlloc)); + return pbAlloc; + } + } + return NULL; +} + +static inline DWORD PadToDword(DWORD dw) +{ + return (dw + 3) & ~3u; +} + +static inline DWORD PadToDwordPtr(DWORD dw) +{ + return (dw + 7) & ~7u; +} + +static inline HRESULT ReplaceOptionalSizeA(_Inout_z_count_(cchDest) LPSTR pszDest, + _In_ size_t cchDest, + _In_z_ LPCSTR pszSize) +{ + if (cchDest == 0 || pszDest == NULL || pszSize == NULL || + pszSize[0] == '\0' || pszSize[1] == '\0' || pszSize[2] != '\0') { + + // can not write into empty buffer or with string other than two chars. + return ERROR_INVALID_PARAMETER; + } + + for (; cchDest >= 2; cchDest--, pszDest++) { + if (pszDest[0] == '?' && pszDest[1] == '?') { + pszDest[0] = pszSize[0]; + pszDest[1] = pszSize[1]; + break; + } + } + + return S_OK; +} + +static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTORE& der) +{ + // Save the various headers for DetourRestoreAfterWith. + ZeroMemory(&der, sizeof(der)); + der.cb = sizeof(der); + + der.pidh = (PBYTE)hModule; + der.cbidh = sizeof(der.idh); + if (!ReadProcessMemory(hProcess, der.pidh, &der.idh, sizeof(der.idh), NULL)) { + DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", + der.pidh, der.pidh + der.cbidh, GetLastError())); + return FALSE; + } + DETOUR_TRACE(("IDH: %p..%p\n", der.pidh, der.pidh + der.cbidh)); + + // We read the NT header in two passes to get the full size. + // First we read just the Signature and FileHeader. + der.pinh = der.pidh + der.idh.e_lfanew; + der.cbinh = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader); + if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) { + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", + der.pinh, der.pinh + der.cbinh, GetLastError())); + return FALSE; + } + + // Second we read the OptionalHeader and Section headers. + der.cbinh = (FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + + der.inh.FileHeader.SizeOfOptionalHeader + + der.inh.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)); + + if (der.cbinh > sizeof(der.raw)) { + return FALSE; + } + + if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) { + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", + der.pinh, der.pinh + der.cbinh, GetLastError())); + return FALSE; + } + DETOUR_TRACE(("INH: %p..%p\n", der.pinh, der.pinh + der.cbinh)); + + // Third, we read the CLR header + + if (der.inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (der.inh32.CLR_DIRECTORY.VirtualAddress != 0 && + der.inh32.CLR_DIRECTORY.Size != 0) { + + DETOUR_TRACE(("CLR32.VirtAddr=%x, CLR.Size=%x\n", + der.inh32.CLR_DIRECTORY.VirtualAddress, + der.inh32.CLR_DIRECTORY.Size)); + + der.pclr = ((PBYTE)hModule) + der.inh32.CLR_DIRECTORY.VirtualAddress; + } + } + else if (der.inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + if (der.inh64.CLR_DIRECTORY.VirtualAddress != 0 && + der.inh64.CLR_DIRECTORY.Size != 0) { + + DETOUR_TRACE(("CLR64.VirtAddr=%x, CLR.Size=%x\n", + der.inh64.CLR_DIRECTORY.VirtualAddress, + der.inh64.CLR_DIRECTORY.Size)); + + der.pclr = ((PBYTE)hModule) + der.inh64.CLR_DIRECTORY.VirtualAddress; + } + } + + if (der.pclr != 0) { + der.cbclr = sizeof(der.clr); + if (!ReadProcessMemory(hProcess, der.pclr, &der.clr, der.cbclr, NULL)) { + DETOUR_TRACE(("ReadProcessMemory(clr@%p..%p) failed: %d\n", + der.pclr, der.pclr + der.cbclr, GetLastError())); + return FALSE; + } + DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr)); + } + + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// +// +#if DETOURS_32BIT +#define DWORD_XX DWORD32 +#define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS32 +#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC +#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32 +#define UPDATE_IMPORTS_XX UpdateImports32 +#define DETOURS_BITS_XX 32 +#include "uimports.cpp" +#undef DETOUR_EXE_RESTORE_FIELD_XX +#undef DWORD_XX +#undef IMAGE_NT_HEADERS_XX +#undef IMAGE_NT_OPTIONAL_HDR_MAGIC_XX +#undef IMAGE_ORDINAL_FLAG_XX +#undef UPDATE_IMPORTS_XX +#endif // DETOURS_32BIT + +#if DETOURS_64BIT +#define DWORD_XX DWORD64 +#define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS64 +#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC +#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64 +#define UPDATE_IMPORTS_XX UpdateImports64 +#define DETOURS_BITS_XX 64 +#include "uimports.cpp" +#undef DETOUR_EXE_RESTORE_FIELD_XX +#undef DWORD_XX +#undef IMAGE_NT_HEADERS_XX +#undef IMAGE_NT_OPTIONAL_HDR_MAGIC_XX +#undef IMAGE_ORDINAL_FLAG_XX +#undef UPDATE_IMPORTS_XX +#endif // DETOURS_64BIT + +////////////////////////////////////////////////////////////////////////////// +// +#if DETOURS_64BIT + +C_ASSERT(sizeof(IMAGE_NT_HEADERS64) == sizeof(IMAGE_NT_HEADERS32) + 16); + +static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, + DETOUR_EXE_RESTORE& der) +{ + IMAGE_DOS_HEADER idh; + IMAGE_NT_HEADERS32 inh32; + IMAGE_NT_HEADERS64 inh64; + IMAGE_SECTION_HEADER sects[32]; + PBYTE pbModule = (PBYTE)hModule; + DWORD n; + + ZeroMemory(&inh32, sizeof(inh32)); + ZeroMemory(&inh64, sizeof(inh64)); + ZeroMemory(sects, sizeof(sects)); + + DETOUR_TRACE(("UpdateFrom32To64(%04x)\n", machine)); + //////////////////////////////////////////////////////// Read old headers. + // + if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { + DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", + pbModule, pbModule + sizeof(idh), GetLastError())); + return FALSE; + } + DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p)\n", + pbModule, pbModule + sizeof(idh))); + + PBYTE pnh = pbModule + idh.e_lfanew; + if (!ReadProcessMemory(hProcess, pnh, &inh32, sizeof(inh32), NULL)) { + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", + pnh, pnh + sizeof(inh32), GetLastError())); + return FALSE; + } + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p)\n", pnh, pnh + sizeof(inh32))); + + if (inh32.FileHeader.NumberOfSections > (sizeof(sects)/sizeof(sects[0]))) { + return FALSE; + } + + PBYTE psects = pnh + + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + + inh32.FileHeader.SizeOfOptionalHeader; + ULONG cb = inh32.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); + if (!ReadProcessMemory(hProcess, psects, §s, cb, NULL)) { + DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %d\n", + psects, psects + cb, GetLastError())); + return FALSE; + } + DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p)\n", psects, psects + cb)); + + ////////////////////////////////////////////////////////// Convert header. + // + inh64.Signature = inh32.Signature; + inh64.FileHeader = inh32.FileHeader; + inh64.FileHeader.Machine = machine; + inh64.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64); + + inh64.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; + inh64.OptionalHeader.MajorLinkerVersion = inh32.OptionalHeader.MajorLinkerVersion; + inh64.OptionalHeader.MinorLinkerVersion = inh32.OptionalHeader.MinorLinkerVersion; + inh64.OptionalHeader.SizeOfCode = inh32.OptionalHeader.SizeOfCode; + inh64.OptionalHeader.SizeOfInitializedData = inh32.OptionalHeader.SizeOfInitializedData; + inh64.OptionalHeader.SizeOfUninitializedData = inh32.OptionalHeader.SizeOfUninitializedData; + inh64.OptionalHeader.AddressOfEntryPoint = inh32.OptionalHeader.AddressOfEntryPoint; + inh64.OptionalHeader.BaseOfCode = inh32.OptionalHeader.BaseOfCode; + inh64.OptionalHeader.ImageBase = inh32.OptionalHeader.ImageBase; + inh64.OptionalHeader.SectionAlignment = inh32.OptionalHeader.SectionAlignment; + inh64.OptionalHeader.FileAlignment = inh32.OptionalHeader.FileAlignment; + inh64.OptionalHeader.MajorOperatingSystemVersion + = inh32.OptionalHeader.MajorOperatingSystemVersion; + inh64.OptionalHeader.MinorOperatingSystemVersion + = inh32.OptionalHeader.MinorOperatingSystemVersion; + inh64.OptionalHeader.MajorImageVersion = inh32.OptionalHeader.MajorImageVersion; + inh64.OptionalHeader.MinorImageVersion = inh32.OptionalHeader.MinorImageVersion; + inh64.OptionalHeader.MajorSubsystemVersion = inh32.OptionalHeader.MajorSubsystemVersion; + inh64.OptionalHeader.MinorSubsystemVersion = inh32.OptionalHeader.MinorSubsystemVersion; + inh64.OptionalHeader.Win32VersionValue = inh32.OptionalHeader.Win32VersionValue; + inh64.OptionalHeader.SizeOfImage = inh32.OptionalHeader.SizeOfImage; + inh64.OptionalHeader.SizeOfHeaders = inh32.OptionalHeader.SizeOfHeaders; + inh64.OptionalHeader.CheckSum = inh32.OptionalHeader.CheckSum; + inh64.OptionalHeader.Subsystem = inh32.OptionalHeader.Subsystem; + inh64.OptionalHeader.DllCharacteristics = inh32.OptionalHeader.DllCharacteristics; + inh64.OptionalHeader.SizeOfStackReserve = inh32.OptionalHeader.SizeOfStackReserve; + inh64.OptionalHeader.SizeOfStackCommit = inh32.OptionalHeader.SizeOfStackCommit; + inh64.OptionalHeader.SizeOfHeapReserve = inh32.OptionalHeader.SizeOfHeapReserve; + inh64.OptionalHeader.SizeOfHeapCommit = inh32.OptionalHeader.SizeOfHeapCommit; + inh64.OptionalHeader.LoaderFlags = inh32.OptionalHeader.LoaderFlags; + inh64.OptionalHeader.NumberOfRvaAndSizes = inh32.OptionalHeader.NumberOfRvaAndSizes; + for (n = 0; n < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; n++) { + inh64.OptionalHeader.DataDirectory[n] = inh32.OptionalHeader.DataDirectory[n]; + } + + /////////////////////////////////////////////////////// Write new headers. + // + DWORD dwProtect = 0; + if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh64.OptionalHeader.SizeOfHeaders, + PAGE_EXECUTE_READWRITE, &dwProtect)) { + return FALSE; + } + + if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) { + DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %d\n", + pnh, pnh + sizeof(inh64), GetLastError())); + return FALSE; + } + DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p)\n", pnh, pnh + sizeof(inh64))); + + psects = pnh + + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + + inh64.FileHeader.SizeOfOptionalHeader; + cb = inh64.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); + if (!WriteProcessMemory(hProcess, psects, §s, cb, NULL)) { + DETOUR_TRACE(("WriteProcessMemory(ish@%p..%p) failed: %d\n", + psects, psects + cb, GetLastError())); + return FALSE; + } + DETOUR_TRACE(("WriteProcessMemory(ish@%p..%p)\n", psects, psects + cb)); + + // Record the updated headers. + if (!RecordExeRestore(hProcess, hModule, der)) { + return FALSE; + } + + // Remove the import table. + if (der.pclr != NULL && (der.clr.Flags & 1)) { + inh64.IMPORT_DIRECTORY.VirtualAddress = 0; + inh64.IMPORT_DIRECTORY.Size = 0; + + if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) { + DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %d\n", + pnh, pnh + sizeof(inh64), GetLastError())); + return FALSE; + } + } + + DWORD dwOld = 0; + if (!VirtualProtectEx(hProcess, pbModule, inh64.OptionalHeader.SizeOfHeaders, + dwProtect, &dwOld)) { + return FALSE; + } + + return TRUE; +} +#endif // DETOURS_64BIT + +////////////////////////////////////////////////////////////////////////////// +// +BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_ DWORD nDlls) +{ + // Find the next memory region that contains a mapped PE image. + // + BOOL bHas64BitDll = FALSE; + BOOL bHas32BitExe = FALSE; + BOOL bIs32BitProcess; + HMODULE hModule = NULL; + HMODULE hLast = NULL; + + DETOUR_TRACE(("DetourUpdateProcessWithDll(%p,dlls=%d)\n", hProcess, nDlls)); + + for (;;) { + IMAGE_NT_HEADERS32 inh; + + if ((hLast = EnumerateModulesInProcess(hProcess, hLast, &inh)) == NULL) { + break; + } + + DETOUR_TRACE(("%p machine=%04x magic=%04x\n", + hLast, inh.FileHeader.Machine, inh.OptionalHeader.Magic)); + + if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) { + hModule = hLast; + if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC + && inh.FileHeader.Machine != 0) { + + bHas32BitExe = TRUE; + } + DETOUR_TRACE(("%p Found EXE\n", hLast)); + } + else { + if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC + && inh.FileHeader.Machine != 0) { + + bHas64BitDll = TRUE; + } + } + } + + if (hModule == NULL) { + SetLastError(ERROR_INVALID_OPERATION); + return FALSE; + } + + if (!bHas32BitExe) { + bIs32BitProcess = FALSE; + } + else if (!bHas64BitDll) { + bIs32BitProcess = TRUE; + } + else { + if (!IsWow64Process(hProcess, &bIs32BitProcess)) { + return FALSE; + } + } + + DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bHas32BitExe, bIs32BitProcess)); + + return DetourUpdateProcessWithDllEx(hProcess, + hModule, + bIs32BitProcess, + rlpDlls, + nDlls); +} + +BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, + _In_ HMODULE hModule, + _In_ BOOL bIs32BitProcess, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_ DWORD nDlls) +{ + // Find the next memory region that contains a mapped PE image. + // + BOOL bIs32BitExe = FALSE; + + DETOUR_TRACE(("DetourUpdateProcessWithDllEx(%p,%p,dlls=%d)\n", hProcess, hModule, nDlls)); + + IMAGE_NT_HEADERS32 inh; + + if (hModule == NULL || LoadNtHeaderFromProcess(hProcess, hModule, &inh) == NULL) { + SetLastError(ERROR_INVALID_OPERATION); + return FALSE; + } + + if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC + && inh.FileHeader.Machine != 0) { + + bIs32BitExe = TRUE; + } + + DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bIs32BitExe, bIs32BitProcess)); + + if (hModule == NULL) { + SetLastError(ERROR_INVALID_OPERATION); + return FALSE; + } + + // Save the various headers for DetourRestoreAfterWith. + // + DETOUR_EXE_RESTORE der; + + if (!RecordExeRestore(hProcess, hModule, der)) { + return FALSE; + } + +#if defined(DETOURS_64BIT) + // Try to convert a neutral 32-bit managed binary to a 64-bit managed binary. + if (bIs32BitExe && !bIs32BitProcess) { + if (!der.pclr // Native binary + || (der.clr.Flags & 1) == 0 // Or mixed-mode MSIL + || (der.clr.Flags & 2) != 0) { // Or 32BIT Required MSIL + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (!UpdateFrom32To64(hProcess, hModule, +#if defined(DETOURS_X64) + IMAGE_FILE_MACHINE_AMD64, +#elif defined(DETOURS_IA64) + IMAGE_FILE_MACHINE_IA64, +#elif defined(DETOURS_ARM64) + IMAGE_FILE_MACHINE_ARM64, +#else +#error Must define one of DETOURS_X64 or DETOURS_IA64 or DETOURS_ARM64 on 64-bit. +#endif + der)) { + return FALSE; + } + bIs32BitExe = FALSE; + } +#endif // DETOURS_64BIT + + // Now decide if we can insert the detour. + +#if defined(DETOURS_32BIT) + if (bIs32BitProcess) { + // 32-bit native or 32-bit managed process on any platform. + if (!UpdateImports32(hProcess, hModule, rlpDlls, nDlls)) { + return FALSE; + } + } + else { + // 64-bit native or 64-bit managed process. + // + // Can't detour a 64-bit process with 32-bit code. + // Note: This happens for 32-bit PE binaries containing only + // manage code that have been marked as 64-bit ready. + // + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#elif defined(DETOURS_64BIT) + if (bIs32BitProcess || bIs32BitExe) { + // Can't detour a 32-bit process with 64-bit code. + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + else { + // 64-bit native or 64-bit managed process on any platform. + if (!UpdateImports64(hProcess, hModule, rlpDlls, nDlls)) { + return FALSE; + } + } +#else +#pragma Must define one of DETOURS_32BIT or DETOURS_64BIT. +#endif // DETOURS_64BIT + + /////////////////////////////////////////////////// Update the CLR header. + // + if (der.pclr != NULL) { + DETOUR_CLR_HEADER clr; + CopyMemory(&clr, &der.clr, sizeof(clr)); + clr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag. + + DWORD dwProtect; + if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &dwProtect)) { + DETOUR_TRACE(("VirtualProtectEx(clr) write failed: %d\n", GetLastError())); + return FALSE; + } + + if (!WriteProcessMemory(hProcess, der.pclr, &clr, sizeof(clr), NULL)) { + DETOUR_TRACE(("WriteProcessMemory(clr) failed: %d\n", GetLastError())); + return FALSE; + } + + if (!VirtualProtectEx(hProcess, der.pclr, sizeof(clr), dwProtect, &dwProtect)) { + DETOUR_TRACE(("VirtualProtectEx(clr) restore failed: %d\n", GetLastError())); + return FALSE; + } + DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr)); + +#if DETOURS_64BIT + if (der.clr.Flags & 0x2) { // Is the 32BIT Required Flag set? + // X64 never gets here because the process appears as a WOW64 process. + // However, on IA64, it doesn't appear to be a WOW process. + DETOUR_TRACE(("CLR Requires 32-bit\n", der.pclr, der.pclr + der.cbclr)); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif // DETOURS_64BIT + } + + //////////////////////////////// Save the undo data to the target process. + // + if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) { + DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError())); + return FALSE; + } + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// +// +BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, + _Inout_opt_ LPSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOA lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ LPCSTR lpDllName, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) +{ + DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED); + PROCESS_INFORMATION pi; + BOOL fResult = FALSE; + + if (pfCreateProcessA == NULL) { + pfCreateProcessA = CreateProcessA; + } + + fResult = pfCreateProcessA(lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwMyCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + &pi); + + if (lpProcessInformation != NULL) { + CopyMemory(lpProcessInformation, &pi, sizeof(pi)); + } + + if (!fResult) { + return FALSE; + } + + LPCSTR rlpDlls[2]; + DWORD nDlls = 0; + if (lpDllName != NULL) { + rlpDlls[nDlls++] = lpDllName; + } + + if (!DetourUpdateProcessWithDll(pi.hProcess, rlpDlls, nDlls)) { + TerminateProcess(pi.hProcess, ~0u); + return FALSE; + } + + if (!(dwCreationFlags & CREATE_SUSPENDED)) { + ResumeThread(pi.hThread); + } + return TRUE; +} + + +BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, + _Inout_opt_ LPWSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCWSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOW lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ LPCSTR lpDllName, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) +{ + DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED); + PROCESS_INFORMATION pi; + + if (pfCreateProcessW == NULL) { + pfCreateProcessW = CreateProcessW; + } + + BOOL fResult = pfCreateProcessW(lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwMyCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + &pi); + + if (lpProcessInformation) { + CopyMemory(lpProcessInformation, &pi, sizeof(pi)); + } + + if (!fResult) { + return FALSE; + } + + LPCSTR rlpDlls[2]; + DWORD nDlls = 0; + if (lpDllName != NULL) { + rlpDlls[nDlls++] = lpDllName; + } + + if (!DetourUpdateProcessWithDll(pi.hProcess, rlpDlls, nDlls)) { + TerminateProcess(pi.hProcess, ~0u); + return FALSE; + } + + if (!(dwCreationFlags & CREATE_SUSPENDED)) { + ResumeThread(pi.hThread); + } + return TRUE; +} + +BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, + _In_ REFGUID rguid, + _In_reads_bytes_(cbData) PVOID pvData, + _In_ DWORD cbData) +{ + DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) + + sizeof(IMAGE_NT_HEADERS) + + sizeof(IMAGE_SECTION_HEADER) + + sizeof(DETOUR_SECTION_HEADER) + + sizeof(DETOUR_SECTION_RECORD) + + cbData); + + PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal, + MEM_COMMIT, PAGE_READWRITE); + if (pbBase == NULL) { + DETOUR_TRACE(("VirtualAllocEx(%d) failed: %d\n", cbTotal, GetLastError())); + return FALSE; + } + + PBYTE pbTarget = pbBase; + IMAGE_DOS_HEADER idh; + IMAGE_NT_HEADERS inh; + IMAGE_SECTION_HEADER ish; + DETOUR_SECTION_HEADER dsh; + DETOUR_SECTION_RECORD dsr; + SIZE_T cbWrote = 0; + + ZeroMemory(&idh, sizeof(idh)); + idh.e_magic = IMAGE_DOS_SIGNATURE; + idh.e_lfanew = sizeof(idh); + if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) || + cbWrote != sizeof(idh)) { + DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); + return FALSE; + } + pbTarget += sizeof(idh); + + ZeroMemory(&inh, sizeof(inh)); + inh.Signature = IMAGE_NT_SIGNATURE; + inh.FileHeader.SizeOfOptionalHeader = sizeof(inh.OptionalHeader); + inh.FileHeader.Characteristics = IMAGE_FILE_DLL; + inh.FileHeader.NumberOfSections = 1; + inh.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; + if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) || + cbWrote != sizeof(inh)) { + return FALSE; + } + pbTarget += sizeof(inh); + + ZeroMemory(&ish, sizeof(ish)); + memcpy(ish.Name, ".detour", sizeof(ish.Name)); + ish.VirtualAddress = (DWORD)((pbTarget + sizeof(ish)) - pbBase); + ish.SizeOfRawData = (sizeof(DETOUR_SECTION_HEADER) + + sizeof(DETOUR_SECTION_RECORD) + + cbData); + if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) || + cbWrote != sizeof(ish)) { + return FALSE; + } + pbTarget += sizeof(ish); + + ZeroMemory(&dsh, sizeof(dsh)); + dsh.cbHeaderSize = sizeof(dsh); + dsh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE; + dsh.nDataOffset = sizeof(DETOUR_SECTION_HEADER); + dsh.cbDataSize = (sizeof(DETOUR_SECTION_HEADER) + + sizeof(DETOUR_SECTION_RECORD) + + cbData); + if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) || + cbWrote != sizeof(dsh)) { + return FALSE; + } + pbTarget += sizeof(dsh); + + ZeroMemory(&dsr, sizeof(dsr)); + dsr.cbBytes = cbData + sizeof(DETOUR_SECTION_RECORD); + dsr.nReserved = 0; + dsr.guid = rguid; + if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) || + cbWrote != sizeof(dsr)) { + return FALSE; + } + pbTarget += sizeof(dsr); + + if (!WriteProcessMemory(hProcess, pbTarget, pvData, cbData, &cbWrote) || + cbWrote != cbData) { + return FALSE; + } + pbTarget += cbData; + + DETOUR_TRACE(("Copied %d byte payload into target process at %p\n", + cbTotal, pbTarget - cbTotal)); + return TRUE; +} + +static BOOL s_fSearchedForHelper = FALSE; +static PDETOUR_EXE_HELPER s_pHelper = NULL; + +VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, + _In_ HINSTANCE, + _In_ LPSTR, + _In_ INT) +{ + LPCSTR * rlpDlls = NULL; + DWORD Result = 9900; + DWORD cOffset = 0; + DWORD cSize = 0; + HANDLE hProcess = NULL; + + if (s_pHelper == NULL) { + DETOUR_TRACE(("DetourFinishHelperProcess called with s_pHelper = NULL.\n")); + Result = 9905; + goto Cleanup; + } + + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, s_pHelper->pid); + if (hProcess == NULL) { + DETOUR_TRACE(("OpenProcess(pid=%d) failed: %d\n", + s_pHelper->pid, GetLastError())); + Result = 9901; + goto Cleanup; + } + + rlpDlls = new NOTHROW LPCSTR [s_pHelper->nDlls]; + cSize = s_pHelper->cb - sizeof(DETOUR_EXE_HELPER); + for (DWORD n = 0; n < s_pHelper->nDlls; n++) { + size_t cchDest = 0; + HRESULT hr = StringCchLengthA(&s_pHelper->rDlls[cOffset], cSize - cOffset, &cchDest); + if (!SUCCEEDED(hr)) { + Result = 9902; + goto Cleanup; + } + + rlpDlls[n] = &s_pHelper->rDlls[cOffset]; + cOffset += (DWORD)cchDest + 1; + } + + if (!DetourUpdateProcessWithDll(hProcess, rlpDlls, s_pHelper->nDlls)) { + DETOUR_TRACE(("DetourUpdateProcessWithDll(pid=%d) failed: %d\n", + s_pHelper->pid, GetLastError())); + Result = 9903; + goto Cleanup; + } + Result = 0; + + Cleanup: + if (rlpDlls != NULL) { + delete[] rlpDlls; + rlpDlls = NULL; + } + + ExitProcess(Result); +} + +BOOL WINAPI DetourIsHelperProcess(VOID) +{ + PVOID pvData; + DWORD cbData; + + if (s_fSearchedForHelper) { + return (s_pHelper != NULL); + } + + s_fSearchedForHelper = TRUE; + pvData = DetourFindPayloadEx(DETOUR_EXE_HELPER_GUID, &cbData); + + if (pvData == NULL || cbData < sizeof(DETOUR_EXE_HELPER)) { + return FALSE; + } + + s_pHelper = (PDETOUR_EXE_HELPER)pvData; + if (s_pHelper->cb < sizeof(*s_pHelper)) { + s_pHelper = NULL; + return FALSE; + } + + return TRUE; +} + +static +BOOL WINAPI AllocExeHelper(_Out_ PDETOUR_EXE_HELPER *pHelper, + _In_ DWORD dwTargetPid, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls) +{ + PDETOUR_EXE_HELPER Helper = NULL; + BOOL Result = FALSE; + _Field_range_(0, cSize - 4) DWORD cOffset = 0; + DWORD cSize = 4; + + if (pHelper == NULL) { + goto Cleanup; + } + *pHelper = NULL; + + if (nDlls < 1 || nDlls > 4096) { + SetLastError(ERROR_INVALID_PARAMETER); + goto Cleanup; + } + + for (DWORD n = 0; n < nDlls; n++) { + HRESULT hr; + size_t cchDest = 0; + + hr = StringCchLengthA(rlpDlls[n], 4096, &cchDest); + if (!SUCCEEDED(hr)) { + goto Cleanup; + } + + cSize += (DWORD)cchDest + 1; + } + + Helper = (PDETOUR_EXE_HELPER) new NOTHROW BYTE[sizeof(DETOUR_EXE_HELPER) + cSize]; + if (Helper == NULL) { + goto Cleanup; + } + + Helper->cb = sizeof(DETOUR_EXE_HELPER) + cSize; + Helper->pid = dwTargetPid; + Helper->nDlls = nDlls; + + for (DWORD n = 0; n < nDlls; n++) { + HRESULT hr; + size_t cchDest = 0; + + if (cOffset > 0x10000 || cSize > 0x10000 || cOffset + 2 >= cSize) { + goto Cleanup; + } + + if (cOffset + 2 >= cSize || cOffset + 65536 < cSize) { + goto Cleanup; + } + + _Analysis_assume_(cOffset + 1 < cSize); + _Analysis_assume_(cOffset < 0x10000); + _Analysis_assume_(cSize < 0x10000); + + PCHAR psz = &Helper->rDlls[cOffset]; + + hr = StringCchCopyA(psz, cSize - cOffset, rlpDlls[n]); + if (!SUCCEEDED(hr)) { + goto Cleanup; + } + +// REVIEW 28020 The expression '1<=_Param_(2)& &_Param_(2)<=2147483647' is not true at this call. +// REVIEW 28313 Analysis will not proceed past this point because of annotation evaluation. The annotation expression *_Param_(3)<_Param_(2)&&*_Param_(3)<=stringLength$(_Param_(1)) cannot be true under any assumptions at this point in the program. +#pragma warning(suppress:28020 28313) + hr = StringCchLengthA(psz, cSize - cOffset, &cchDest); + if (!SUCCEEDED(hr)) { + goto Cleanup; + } + + // Replace "32." with "64." or "64." with "32." + + for (DWORD c = (DWORD)cchDest + 1; c > 3; c--) { +#if DETOURS_32BIT + if (psz[c - 3] == '3' && psz[c - 2] == '2' && psz[c - 1] == '.') { + psz[c - 3] = '6'; psz[c - 2] = '4'; + break; + } +#else + if (psz[c - 3] == '6' && psz[c - 2] == '4' && psz[c - 1] == '.') { + psz[c - 3] = '3'; psz[c - 2] = '2'; + break; + } +#endif + } + + cOffset += (DWORD)cchDest + 1; + } + + *pHelper = Helper; + Helper = NULL; + Result = TRUE; + + Cleanup: + if (Helper != NULL) { + delete[] (PBYTE)Helper; + Helper = NULL; + } + return Result; +} + +static +VOID WINAPI FreeExeHelper(PDETOUR_EXE_HELPER *pHelper) +{ + if (*pHelper != NULL) { + delete[] (PBYTE)*pHelper; + *pHelper = NULL; + } +} + +BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, + _In_ LPCSTR lpDllName, + _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) +{ + return DetourProcessViaHelperDllsA(dwTargetPid, 1, &lpDllName, pfCreateProcessA); +} + + +BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) +{ + BOOL Result = FALSE; + PROCESS_INFORMATION pi; + STARTUPINFOA si; + CHAR szExe[MAX_PATH]; + CHAR szCommand[MAX_PATH]; + PDETOUR_EXE_HELPER helper = NULL; + HRESULT hr; + DWORD nLen = GetEnvironmentVariableA("WINDIR", szExe, ARRAYSIZE(szExe)); + + DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%d,dlls=%d)\n", dwTargetPid, nDlls)); + if (nDlls < 1 || nDlls > 4096) { + SetLastError(ERROR_INVALID_PARAMETER); + goto Cleanup; + } + if (!AllocExeHelper(&helper, dwTargetPid, nDlls, rlpDlls)) { + goto Cleanup; + } + + if (nLen == 0 || nLen >= ARRAYSIZE(szExe)) { + goto Cleanup; + } + +#if DETOURS_OPTION_BITS +#if DETOURS_32BIT + hr = StringCchCatA(szExe, ARRAYSIZE(szExe), "\\sysnative\\rundll32.exe"); +#else // !DETOURS_32BIT + hr = StringCchCatA(szExe, ARRAYSIZE(szExe), "\\syswow64\\rundll32.exe"); +#endif // !DETOURS_32BIT +#else // DETOURS_OPTIONS_BITS + hr = StringCchCatA(szExe, ARRAYSIZE(szExe), "\\system32\\rundll32.exe"); +#endif // DETOURS_OPTIONS_BITS + if (!SUCCEEDED(hr)) { + goto Cleanup; + } + + hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand), + "rundll32.exe \"%hs\",#1", &helper->rDlls[0]); + if (!SUCCEEDED(hr)) { + goto Cleanup; + } + + ZeroMemory(&pi, sizeof(pi)); + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + DETOUR_TRACE(("DetourProcessViaHelperDlls(\"%hs\", \"%hs\")\n", szExe, szCommand)); + if (pfCreateProcessA(szExe, szCommand, NULL, NULL, FALSE, CREATE_SUSPENDED, + NULL, NULL, &si, &pi)) { + + if (!DetourCopyPayloadToProcess(pi.hProcess, + DETOUR_EXE_HELPER_GUID, + helper, helper->cb)) { + DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError())); + TerminateProcess(pi.hProcess, ~0u); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + goto Cleanup; + } + + ResumeThread(pi.hThread); + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD dwResult = 500; + GetExitCodeProcess(pi.hProcess, &dwResult); + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + if (dwResult != 0) { + DETOUR_TRACE(("Rundll32.exe failed: result=%d\n", dwResult)); + goto Cleanup; + } + Result = TRUE; + } + else { + DETOUR_TRACE(("CreateProcess failed: %d\n", GetLastError())); + goto Cleanup; + } + + Cleanup: + FreeExeHelper(&helper); + return Result; +} + +BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, + _In_ LPCSTR lpDllName, + _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) +{ + return DetourProcessViaHelperDllsW(dwTargetPid, 1, &lpDllName, pfCreateProcessW); +} + +BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) +{ + BOOL Result = FALSE; + PROCESS_INFORMATION pi; + STARTUPINFOW si; + WCHAR szExe[MAX_PATH]; + WCHAR szCommand[MAX_PATH]; + PDETOUR_EXE_HELPER helper = NULL; + HRESULT hr; + DWORD nLen = GetEnvironmentVariableW(L"WINDIR", szExe, ARRAYSIZE(szExe)); + + DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%d,dlls=%d)\n", dwTargetPid, nDlls)); + if (nDlls < 1 || nDlls > 4096) { + SetLastError(ERROR_INVALID_PARAMETER); + goto Cleanup; + } + if (!AllocExeHelper(&helper, dwTargetPid, nDlls, rlpDlls)) { + goto Cleanup; + } + + if (nLen == 0 || nLen >= ARRAYSIZE(szExe)) { + goto Cleanup; + } + +#if DETOURS_OPTION_BITS +#if DETOURS_32BIT + hr = StringCchCatW(szExe, ARRAYSIZE(szExe), L"\\sysnative\\rundll32.exe"); +#else // !DETOURS_32BIT + hr = StringCchCatW(szExe, ARRAYSIZE(szExe), L"\\syswow64\\rundll32.exe"); +#endif // !DETOURS_32BIT +#else // DETOURS_OPTIONS_BITS + hr = StringCchCatW(szExe, ARRAYSIZE(szExe), L"\\system32\\rundll32.exe"); +#endif // DETOURS_OPTIONS_BITS + if (!SUCCEEDED(hr)) { + goto Cleanup; + } + + hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand), + L"rundll32.exe \"%hs\",#1", &helper->rDlls[0]); + if (!SUCCEEDED(hr)) { + goto Cleanup; + } + + ZeroMemory(&pi, sizeof(pi)); + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + DETOUR_TRACE(("DetourProcessViaHelperDlls(\"%ls\", \"%ls\")\n", szExe, szCommand)); + if (pfCreateProcessW(szExe, szCommand, NULL, NULL, FALSE, CREATE_SUSPENDED, + NULL, NULL, &si, &pi)) { + + if (!DetourCopyPayloadToProcess(pi.hProcess, + DETOUR_EXE_HELPER_GUID, + helper, helper->cb)) { + DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError())); + TerminateProcess(pi.hProcess, ~0u); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + goto Cleanup; + } + + ResumeThread(pi.hThread); + + ResumeThread(pi.hThread); + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD dwResult = 500; + GetExitCodeProcess(pi.hProcess, &dwResult); + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + if (dwResult != 0) { + DETOUR_TRACE(("Rundll32.exe failed: result=%d\n", dwResult)); + goto Cleanup; + } + Result = TRUE; + } + else { + DETOUR_TRACE(("CreateProcess failed: %d\n", GetLastError())); + goto Cleanup; + } + + Cleanup: + FreeExeHelper(&helper); + return Result; +} + +BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, + _Inout_opt_ LPSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOA lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ LPCSTR lpDllName, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) +{ + if (pfCreateProcessA == NULL) { + pfCreateProcessA = CreateProcessA; + } + + PROCESS_INFORMATION backup; + if (lpProcessInformation == NULL) { + lpProcessInformation = &backup; + ZeroMemory(&backup, sizeof(backup)); + } + + if (!pfCreateProcessA(lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags | CREATE_SUSPENDED, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation)) { + return FALSE; + } + + LPCSTR szDll = lpDllName; + + if (!DetourUpdateProcessWithDll(lpProcessInformation->hProcess, &szDll, 1) && + !DetourProcessViaHelperA(lpProcessInformation->dwProcessId, + lpDllName, + pfCreateProcessA)) { + + TerminateProcess(lpProcessInformation->hProcess, ~0u); + CloseHandle(lpProcessInformation->hProcess); + CloseHandle(lpProcessInformation->hThread); + return FALSE; + } + + if (!(dwCreationFlags & CREATE_SUSPENDED)) { + ResumeThread(lpProcessInformation->hThread); + } + + if (lpProcessInformation == &backup) { + CloseHandle(lpProcessInformation->hProcess); + CloseHandle(lpProcessInformation->hThread); + } + + return TRUE; +} + +BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, + _Inout_opt_ LPWSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCWSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOW lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ LPCSTR lpDllName, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) +{ + if (pfCreateProcessW == NULL) { + pfCreateProcessW = CreateProcessW; + } + + PROCESS_INFORMATION backup; + if (lpProcessInformation == NULL) { + lpProcessInformation = &backup; + ZeroMemory(&backup, sizeof(backup)); + } + + if (!pfCreateProcessW(lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags | CREATE_SUSPENDED, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation)) { + return FALSE; + } + + + LPCSTR sz = lpDllName; + + if (!DetourUpdateProcessWithDll(lpProcessInformation->hProcess, &sz, 1) && + !DetourProcessViaHelperW(lpProcessInformation->dwProcessId, + lpDllName, + pfCreateProcessW)) { + + TerminateProcess(lpProcessInformation->hProcess, ~0u); + CloseHandle(lpProcessInformation->hProcess); + CloseHandle(lpProcessInformation->hThread); + return FALSE; + } + + if (!(dwCreationFlags & CREATE_SUSPENDED)) { + ResumeThread(lpProcessInformation->hThread); + } + + if (lpProcessInformation == &backup) { + CloseHandle(lpProcessInformation->hProcess); + CloseHandle(lpProcessInformation->hThread); + } + return TRUE; +} + +BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, + _Inout_opt_ LPSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOA lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) +{ + if (pfCreateProcessA == NULL) { + pfCreateProcessA = CreateProcessA; + } + + PROCESS_INFORMATION backup; + if (lpProcessInformation == NULL) { + lpProcessInformation = &backup; + ZeroMemory(&backup, sizeof(backup)); + } + + if (!pfCreateProcessA(lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags | CREATE_SUSPENDED, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation)) { + return FALSE; + } + + if (!DetourUpdateProcessWithDll(lpProcessInformation->hProcess, rlpDlls, nDlls) && + !DetourProcessViaHelperDllsA(lpProcessInformation->dwProcessId, + nDlls, + rlpDlls, + pfCreateProcessA)) { + + TerminateProcess(lpProcessInformation->hProcess, ~0u); + CloseHandle(lpProcessInformation->hProcess); + CloseHandle(lpProcessInformation->hThread); + return FALSE; + } + + if (!(dwCreationFlags & CREATE_SUSPENDED)) { + ResumeThread(lpProcessInformation->hThread); + } + + if (lpProcessInformation == &backup) { + CloseHandle(lpProcessInformation->hProcess); + CloseHandle(lpProcessInformation->hThread); + } + + return TRUE; +} + +BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, + _Inout_opt_ LPWSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCWSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOW lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) +{ + if (pfCreateProcessW == NULL) { + pfCreateProcessW = CreateProcessW; + } + + PROCESS_INFORMATION backup; + if (lpProcessInformation == NULL) { + lpProcessInformation = &backup; + ZeroMemory(&backup, sizeof(backup)); + } + + if (!pfCreateProcessW(lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags | CREATE_SUSPENDED, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation)) { + return FALSE; + } + + + if (!DetourUpdateProcessWithDll(lpProcessInformation->hProcess, rlpDlls, nDlls) && + !DetourProcessViaHelperDllsW(lpProcessInformation->dwProcessId, + nDlls, + rlpDlls, + pfCreateProcessW)) { + + TerminateProcess(lpProcessInformation->hProcess, ~0u); + CloseHandle(lpProcessInformation->hProcess); + CloseHandle(lpProcessInformation->hThread); + return FALSE; + } + + if (!(dwCreationFlags & CREATE_SUSPENDED)) { + ResumeThread(lpProcessInformation->hThread); + } + + if (lpProcessInformation == &backup) { + CloseHandle(lpProcessInformation->hProcess); + CloseHandle(lpProcessInformation->hThread); + } + return TRUE; +} + +// +///////////////////////////////////////////////////////////////// End of File. diff --git a/dev/Detours/detours.cpp b/dev/Detours/detours.cpp new file mode 100644 index 000000000..34f2458f1 --- /dev/null +++ b/dev/Detours/detours.cpp @@ -0,0 +1,2554 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Core Detours Functionality (detours.cpp of detours.lib) +// +// Microsoft Research Detours Package, Version 4.0.1 +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// + + +//#define DETOUR_DEBUG 1 +#define DETOURS_INTERNAL +#include "detours.h" + +#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH +#error detours.h version mismatch +#endif + +#define NOTHROW + +////////////////////////////////////////////////////////////////////////////// +// +struct _DETOUR_ALIGN +{ + BYTE obTarget : 3; + BYTE obTrampoline : 5; +}; + +C_ASSERT(sizeof(_DETOUR_ALIGN) == 1); + +////////////////////////////////////////////////////////////////////////////// +// +// Region reserved for system DLLs, which cannot be used for trampolines. +// +static PVOID s_pSystemRegionLowerBound = (PVOID)(ULONG_PTR)0x70000000; +static PVOID s_pSystemRegionUpperBound = (PVOID)(ULONG_PTR)0x80000000; + +////////////////////////////////////////////////////////////////////////////// +// +static bool detour_is_imported(PBYTE pbCode, PBYTE pbAddress) +{ + MEMORY_BASIC_INFORMATION mbi; + VirtualQuery((PVOID)pbCode, &mbi, sizeof(mbi)); + __try { + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase; + if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + return false; + } + + PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + + pDosHeader->e_lfanew); + if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { + return false; + } + + if (pbAddress >= ((PBYTE)pDosHeader + + pNtHeader->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && + pbAddress < ((PBYTE)pDosHeader + + pNtHeader->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress + + pNtHeader->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size)) { + return true; + } + } +#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.") + __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? + EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { + return false; + } + return false; +} + +inline ULONG_PTR detour_2gb_below(ULONG_PTR address) +{ + return (address > (ULONG_PTR)0x7ff80000) ? address - 0x7ff80000 : 0x80000; +} + +inline ULONG_PTR detour_2gb_above(ULONG_PTR address) +{ +#if defined(DETOURS_64BIT) + return (address < (ULONG_PTR)0xffffffff80000000) ? address + 0x7ff80000 : (ULONG_PTR)0xfffffffffff80000; +#else + return (address < (ULONG_PTR)0x80000000) ? address + 0x7ff80000 : (ULONG_PTR)0xfff80000; +#endif +} + +///////////////////////////////////////////////////////////////////////// X86. +// +#ifdef DETOURS_X86 + +struct _DETOUR_TRAMPOLINE +{ + BYTE rbCode[30]; // target code + jmp to pbRemain + BYTE cbCode; // size of moved target code. + BYTE cbCodeBreak; // padding to make debugging easier. + BYTE rbRestore[22]; // original target code. + BYTE cbRestore; // size of original target code. + BYTE cbRestoreBreak; // padding to make debugging easier. + _DETOUR_ALIGN rAlign[8]; // instruction alignment array. + PBYTE pbRemain; // first instruction after moved code. [free list] + PBYTE pbDetour; // first instruction of detour function. +}; + +C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 72); + +enum { + SIZE_OF_JMP = 5 +}; + +inline PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE pbJmpVal) +{ + PBYTE pbJmpSrc = pbCode + 5; + *pbCode++ = 0xE9; // jmp +imm32 + *((INT32*&)pbCode)++ = (INT32)(pbJmpVal - pbJmpSrc); + return pbCode; +} + +inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal) +{ + *pbCode++ = 0xff; // jmp [+imm32] + *pbCode++ = 0x25; + *((INT32*&)pbCode)++ = (INT32)((PBYTE)ppbJmpVal); + return pbCode; +} + +inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) +{ + while (pbCode < pbLimit) { + *pbCode++ = 0xcc; // brk; + } + return pbCode; +} + +inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) +{ + if (pbCode == NULL) { + return NULL; + } + if (ppGlobals != NULL) { + *ppGlobals = NULL; + } + + // First, skip over the import vector if there is one. + if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] + // Looks like an import alias jump, then get the code it points to. + PBYTE pbTarget = *(UNALIGNED PBYTE *)&pbCode[2]; + if (detour_is_imported(pbCode, pbTarget)) { + PBYTE pbNew = *(UNALIGNED PBYTE *)pbTarget; + DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); + pbCode = pbNew; + } + } + + // Then, skip over a patch jump + if (pbCode[0] == 0xeb) { // jmp +imm8 + PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; + DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); + pbCode = pbNew; + + // First, skip over the import vector if there is one. + if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] + // Looks like an import alias jump, then get the code it points to. + PBYTE pbTarget = *(UNALIGNED PBYTE *)&pbCode[2]; + if (detour_is_imported(pbCode, pbTarget)) { + pbNew = *(UNALIGNED PBYTE *)pbTarget; + DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); + pbCode = pbNew; + } + } + // Finally, skip over a long jump if it is the target of the patch jump. + else if (pbCode[0] == 0xe9) { // jmp +imm32 + pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; + DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); + pbCode = pbNew; + } + } + return pbCode; +} + +inline void detour_find_jmp_bounds(PBYTE pbCode, + PDETOUR_TRAMPOLINE *ppLower, + PDETOUR_TRAMPOLINE *ppUpper) +{ + // We have to place trampolines within +/- 2GB of code. + ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); + ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); + DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); + + // And, within +/- 2GB of relative jmp targets. + if (pbCode[0] == 0xe9) { // jmp +imm32 + PBYTE pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; + + if (pbNew < pbCode) { + hi = detour_2gb_above((ULONG_PTR)pbNew); + } + else { + lo = detour_2gb_below((ULONG_PTR)pbNew); + } + DETOUR_TRACE(("[%p..%p..%p] +imm32\n", lo, pbCode, hi)); + } + + *ppLower = (PDETOUR_TRAMPOLINE)lo; + *ppUpper = (PDETOUR_TRAMPOLINE)hi; +} + +inline BOOL detour_does_code_end_function(PBYTE pbCode) +{ + if (pbCode[0] == 0xeb || // jmp +imm8 + pbCode[0] == 0xe9 || // jmp +imm32 + pbCode[0] == 0xe0 || // jmp eax + pbCode[0] == 0xc2 || // ret +imm8 + pbCode[0] == 0xc3 || // ret + pbCode[0] == 0xcc) { // brk + return TRUE; + } + else if (pbCode[0] == 0xf3 && pbCode[1] == 0xc3) { // rep ret + return TRUE; + } + else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] + return TRUE; + } + else if ((pbCode[0] == 0x26 || // jmp es: + pbCode[0] == 0x2e || // jmp cs: + pbCode[0] == 0x36 || // jmp ss: + pbCode[0] == 0x3e || // jmp ds: + pbCode[0] == 0x64 || // jmp fs: + pbCode[0] == 0x65) && // jmp gs: + pbCode[1] == 0xff && // jmp [+imm32] + pbCode[2] == 0x25) { + return TRUE; + } + return FALSE; +} + +inline ULONG detour_is_code_filler(PBYTE pbCode) +{ + // 1-byte through 11-byte NOPs. + if (pbCode[0] == 0x90) { + return 1; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x90) { + return 2; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x00) { + return 3; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x40 && + pbCode[3] == 0x00) { + return 4; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x44 && + pbCode[3] == 0x00 && pbCode[4] == 0x00) { + return 5; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && + pbCode[3] == 0x44 && pbCode[4] == 0x00 && pbCode[5] == 0x00) { + return 6; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x80 && + pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && + pbCode[6] == 0x00) { + return 7; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x84 && + pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && + pbCode[6] == 0x00 && pbCode[7] == 0x00) { + return 8; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && + pbCode[3] == 0x84 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && + pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00) { + return 9; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x0F && + pbCode[3] == 0x1F && pbCode[4] == 0x84 && pbCode[5] == 0x00 && + pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && + pbCode[9] == 0x00) { + return 10; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x66 && + pbCode[3] == 0x0F && pbCode[4] == 0x1F && pbCode[5] == 0x84 && + pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && + pbCode[9] == 0x00 && pbCode[10] == 0x00) { + return 11; + } + + // int 3. + if (pbCode[0] == 0xcc) { + return 1; + } + return 0; +} + +#endif // DETOURS_X86 + +///////////////////////////////////////////////////////////////////////// X64. +// +#ifdef DETOURS_X64 + +struct _DETOUR_TRAMPOLINE +{ + // An X64 instuction can be 15 bytes long. + // In practice 11 seems to be the limit. + BYTE rbCode[30]; // target code + jmp to pbRemain. + BYTE cbCode; // size of moved target code. + BYTE cbCodeBreak; // padding to make debugging easier. + BYTE rbRestore[30]; // original target code. + BYTE cbRestore; // size of original target code. + BYTE cbRestoreBreak; // padding to make debugging easier. + _DETOUR_ALIGN rAlign[8]; // instruction alignment array. + PBYTE pbRemain; // first instruction after moved code. [free list] + PBYTE pbDetour; // first instruction of detour function. + BYTE rbCodeIn[8]; // jmp [pbDetour] +}; + +C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 96); + +enum { + SIZE_OF_JMP = 5 +}; + +inline PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE pbJmpVal) +{ + PBYTE pbJmpSrc = pbCode + 5; + *pbCode++ = 0xE9; // jmp +imm32 + *((INT32*&)pbCode)++ = (INT32)(pbJmpVal - pbJmpSrc); + return pbCode; +} + +inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal) +{ + PBYTE pbJmpSrc = pbCode + 6; + *pbCode++ = 0xff; // jmp [+imm32] + *pbCode++ = 0x25; + *((INT32*&)pbCode)++ = (INT32)((PBYTE)ppbJmpVal - pbJmpSrc); + return pbCode; +} + +inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) +{ + while (pbCode < pbLimit) { + *pbCode++ = 0xcc; // brk; + } + return pbCode; +} + +inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) +{ + if (pbCode == NULL) { + return NULL; + } + if (ppGlobals != NULL) { + *ppGlobals = NULL; + } + + // First, skip over the import vector if there is one. + if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] + // Looks like an import alias jump, then get the code it points to. + PBYTE pbTarget = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; + if (detour_is_imported(pbCode, pbTarget)) { + PBYTE pbNew = *(UNALIGNED PBYTE *)pbTarget; + DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); + pbCode = pbNew; + } + } + + // Then, skip over a patch jump + if (pbCode[0] == 0xeb) { // jmp +imm8 + PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; + DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); + pbCode = pbNew; + + // First, skip over the import vector if there is one. + if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] + // Looks like an import alias jump, then get the code it points to. + PBYTE pbTarget = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; + if (detour_is_imported(pbCode, pbTarget)) { + pbNew = *(UNALIGNED PBYTE *)pbTarget; + DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); + pbCode = pbNew; + } + } + // Finally, skip over a long jump if it is the target of the patch jump. + else if (pbCode[0] == 0xe9) { // jmp +imm32 + pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; + DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); + pbCode = pbNew; + } + } + return pbCode; +} + +inline void detour_find_jmp_bounds(PBYTE pbCode, + PDETOUR_TRAMPOLINE *ppLower, + PDETOUR_TRAMPOLINE *ppUpper) +{ + // We have to place trampolines within +/- 2GB of code. + ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); + ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); + DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); + + // And, within +/- 2GB of relative jmp vectors. + if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] + PBYTE pbNew = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; + + if (pbNew < pbCode) { + hi = detour_2gb_above((ULONG_PTR)pbNew); + } + else { + lo = detour_2gb_below((ULONG_PTR)pbNew); + } + DETOUR_TRACE(("[%p..%p..%p] [+imm32]\n", lo, pbCode, hi)); + } + // And, within +/- 2GB of relative jmp targets. + else if (pbCode[0] == 0xe9) { // jmp +imm32 + PBYTE pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; + + if (pbNew < pbCode) { + hi = detour_2gb_above((ULONG_PTR)pbNew); + } + else { + lo = detour_2gb_below((ULONG_PTR)pbNew); + } + DETOUR_TRACE(("[%p..%p..%p] +imm32\n", lo, pbCode, hi)); + } + + *ppLower = (PDETOUR_TRAMPOLINE)lo; + *ppUpper = (PDETOUR_TRAMPOLINE)hi; +} + +inline BOOL detour_does_code_end_function(PBYTE pbCode) +{ + if (pbCode[0] == 0xeb || // jmp +imm8 + pbCode[0] == 0xe9 || // jmp +imm32 + pbCode[0] == 0xe0 || // jmp eax + pbCode[0] == 0xc2 || // ret +imm8 + pbCode[0] == 0xc3 || // ret + pbCode[0] == 0xcc) { // brk + return TRUE; + } + else if (pbCode[0] == 0xf3 && pbCode[1] == 0xc3) { // rep ret + return TRUE; + } + else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] + return TRUE; + } + else if ((pbCode[0] == 0x26 || // jmp es: + pbCode[0] == 0x2e || // jmp cs: + pbCode[0] == 0x36 || // jmp ss: + pbCode[0] == 0x3e || // jmp ds: + pbCode[0] == 0x64 || // jmp fs: + pbCode[0] == 0x65) && // jmp gs: + pbCode[1] == 0xff && // jmp [+imm32] + pbCode[2] == 0x25) { + return TRUE; + } + return FALSE; +} + +inline ULONG detour_is_code_filler(PBYTE pbCode) +{ + // 1-byte through 11-byte NOPs. + if (pbCode[0] == 0x90) { + return 1; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x90) { + return 2; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x00) { + return 3; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x40 && + pbCode[3] == 0x00) { + return 4; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x44 && + pbCode[3] == 0x00 && pbCode[4] == 0x00) { + return 5; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && + pbCode[3] == 0x44 && pbCode[4] == 0x00 && pbCode[5] == 0x00) { + return 6; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x80 && + pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && + pbCode[6] == 0x00) { + return 7; + } + if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x84 && + pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && + pbCode[6] == 0x00 && pbCode[7] == 0x00) { + return 8; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && + pbCode[3] == 0x84 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && + pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00) { + return 9; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x0F && + pbCode[3] == 0x1F && pbCode[4] == 0x84 && pbCode[5] == 0x00 && + pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && + pbCode[9] == 0x00) { + return 10; + } + if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x66 && + pbCode[3] == 0x0F && pbCode[4] == 0x1F && pbCode[5] == 0x84 && + pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && + pbCode[9] == 0x00 && pbCode[10] == 0x00) { + return 11; + } + + // int 3. + if (pbCode[0] == 0xcc) { + return 1; + } + return 0; +} + +#endif // DETOURS_X64 + +//////////////////////////////////////////////////////////////////////// IA64. +// +#ifdef DETOURS_IA64 + +struct _DETOUR_TRAMPOLINE +{ + // On the IA64, a trampoline is used for both incoming and outgoing calls. + // + // The trampoline contains the following bundles for the outgoing call: + // movl gp=target_gp; + // + // brl target_code; + // + // The trampoline contains the following bundles for the incoming call: + // alloc r41=ar.pfs, b, 0, 8, 0 + // mov r40=rp + // + // adds r50=0, r39 + // adds r49=0, r38 + // adds r48=0, r37 ;; + // + // adds r47=0, r36 + // adds r46=0, r35 + // adds r45=0, r34 + // + // adds r44=0, r33 + // adds r43=0, r32 + // adds r42=0, gp ;; + // + // movl gp=ffffffff`ffffffff ;; + // + // brl.call.sptk.few rp=disas!TestCodes+20e0 (00000000`00404ea0) ;; + // + // adds gp=0, r42 + // mov rp=r40, +0 ;; + // mov.i ar.pfs=r41 + // + // br.ret.sptk.many rp ;; + // + // This way, we only have to relocate a single bundle. + // + // The complicated incoming trampoline is required because we have to + // create an additional stack frame so that we save and restore the gp. + // We must do this because gp is a caller-saved register, but not saved + // if the caller thinks the target is in the same DLL, which changes + // when we insert a detour. + // + DETOUR_IA64_BUNDLE bMovlTargetGp; // Bundle which sets target GP + BYTE rbCode[sizeof(DETOUR_IA64_BUNDLE)]; // moved bundle. + DETOUR_IA64_BUNDLE bBrlRemainEip; // Brl to pbRemain + // This must be adjacent to bBranchIslands. + + // Each instruction in the moved bundle could be a IP-relative chk or branch or call. + // Any such instructions are changed to point to a brl in bBranchIslands. + // This must be adjacent to bBrlRemainEip -- see "pbPool". + DETOUR_IA64_BUNDLE bBranchIslands[DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE]; + + // Target of brl inserted in target function + DETOUR_IA64_BUNDLE bAllocFrame; // alloc frame + DETOUR_IA64_BUNDLE bSave37to39; // save r37, r38, r39. + DETOUR_IA64_BUNDLE bSave34to36; // save r34, r35, r36. + DETOUR_IA64_BUNDLE bSaveGPto33; // save gp, r32, r33. + DETOUR_IA64_BUNDLE bMovlDetourGp; // set detour GP. + DETOUR_IA64_BUNDLE bCallDetour; // call detour. + DETOUR_IA64_BUNDLE bPopFrameGp; // pop frame and restore gp. + DETOUR_IA64_BUNDLE bReturn; // return to caller. + + PLABEL_DESCRIPTOR pldTrampoline; + + BYTE rbRestore[sizeof(DETOUR_IA64_BUNDLE)]; // original target bundle. + BYTE cbRestore; // size of original target code. + BYTE cbCode; // size of moved target code. + _DETOUR_ALIGN rAlign[14]; // instruction alignment array. + PBYTE pbRemain; // first instruction after moved code. [free list] + PBYTE pbDetour; // first instruction of detour function. + PPLABEL_DESCRIPTOR ppldDetour; // [pbDetour,gpDetour] + PPLABEL_DESCRIPTOR ppldTarget; // [pbTarget,gpDetour] +}; + +C_ASSERT(sizeof(DETOUR_IA64_BUNDLE) == 16); +C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 256 + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * 16); + +enum { + SIZE_OF_JMP = sizeof(DETOUR_IA64_BUNDLE) +}; + +inline PBYTE detour_skip_jmp(PBYTE pPointer, PVOID *ppGlobals) +{ + PBYTE pGlobals = NULL; + PBYTE pbCode = NULL; + + if (pPointer != NULL) { + PPLABEL_DESCRIPTOR ppld = (PPLABEL_DESCRIPTOR)pPointer; + pbCode = (PBYTE)ppld->EntryPoint; + pGlobals = (PBYTE)ppld->GlobalPointer; + } + if (ppGlobals != NULL) { + *ppGlobals = pGlobals; + } + if (pbCode == NULL) { + return NULL; + } + + DETOUR_IA64_BUNDLE *pb = (DETOUR_IA64_BUNDLE *)pbCode; + + // IA64 Local Import Jumps look like: + // addl r2=ffffffff`ffe021c0, gp ;; + // ld8 r2=[r2] + // nop.i 0 ;; + // + // ld8 r3=[r2], 8 ;; + // ld8 gp=[r2] + // mov b6=r3, +0 + // + // nop.m 0 + // nop.i 0 + // br.cond.sptk.few b6 + // + + // 002024000200100b + if ((pb[0].wide[0] & 0xfffffc000603ffff) == 0x002024000200100b && + pb[0].wide[1] == 0x0004000000203008 && + pb[1].wide[0] == 0x001014180420180a && + pb[1].wide[1] == 0x07000830c0203008 && + pb[2].wide[0] == 0x0000000100000010 && + pb[2].wide[1] == 0x0080006000000200) { + + ULONG64 offset = + ((pb[0].wide[0] & 0x0000000001fc0000) >> 18) | // imm7b + ((pb[0].wide[0] & 0x000001ff00000000) >> 25) | // imm9d + ((pb[0].wide[0] & 0x00000000f8000000) >> 11); // imm5c + if (pb[0].wide[0] & 0x0000020000000000) { // sign + offset |= 0xffffffffffe00000; + } + PBYTE pbTarget = pGlobals + offset; + DETOUR_TRACE(("%p: potential import jump, target=%p\n", pb, pbTarget)); + + if (detour_is_imported(pbCode, pbTarget) && *(PBYTE*)pbTarget != NULL) { + DETOUR_TRACE(("%p: is import jump, label=%p\n", pb, *(PBYTE *)pbTarget)); + + PPLABEL_DESCRIPTOR ppld = (PPLABEL_DESCRIPTOR)*(PBYTE *)pbTarget; + pbCode = (PBYTE)ppld->EntryPoint; + pGlobals = (PBYTE)ppld->GlobalPointer; + if (ppGlobals != NULL) { + *ppGlobals = pGlobals; + } + } + } + return pbCode; +} + + +inline void detour_find_jmp_bounds(PBYTE pbCode, + PDETOUR_TRAMPOLINE *ppLower, + PDETOUR_TRAMPOLINE *ppUpper) +{ + (void)pbCode; + *ppLower = (PDETOUR_TRAMPOLINE)(ULONG_PTR)0x0000000000080000; + *ppUpper = (PDETOUR_TRAMPOLINE)(ULONG_PTR)0xfffffffffff80000; +} + +inline BOOL detour_does_code_end_function(PBYTE pbCode) +{ + // Routine not needed on IA64. + (void)pbCode; + return FALSE; +} + +inline ULONG detour_is_code_filler(PBYTE pbCode) +{ + // Routine not needed on IA64. + (void)pbCode; + return 0; +} + +#endif // DETOURS_IA64 + +#ifdef DETOURS_ARM + +struct _DETOUR_TRAMPOLINE +{ + // A Thumb-2 instruction can be 2 or 4 bytes long. + BYTE rbCode[62]; // target code + jmp to pbRemain + BYTE cbCode; // size of moved target code. + BYTE cbCodeBreak; // padding to make debugging easier. + BYTE rbRestore[22]; // original target code. + BYTE cbRestore; // size of original target code. + BYTE cbRestoreBreak; // padding to make debugging easier. + _DETOUR_ALIGN rAlign[8]; // instruction alignment array. + PBYTE pbRemain; // first instruction after moved code. [free list] + PBYTE pbDetour; // first instruction of detour function. +}; + +C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 104); + +enum { + SIZE_OF_JMP = 8 +}; + +inline PBYTE align4(PBYTE pValue) +{ + return (PBYTE)(((ULONG)pValue) & ~(ULONG)3u); +} + +inline ULONG fetch_thumb_opcode(PBYTE pbCode) +{ + ULONG Opcode = *(UINT16 *)&pbCode[0]; + if (Opcode >= 0xe800) { + Opcode = (Opcode << 16) | *(UINT16 *)&pbCode[2]; + } + return Opcode; +} + +inline void write_thumb_opcode(PBYTE &pbCode, ULONG Opcode) +{ + if (Opcode >= 0x10000) { + *((UINT16*&)pbCode)++ = Opcode >> 16; + } + *((UINT16*&)pbCode)++ = (UINT16)Opcode; +} + +PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE *ppPool, PBYTE pbJmpVal) +{ + PBYTE pbLiteral; + if (ppPool != NULL) { + *ppPool = *ppPool - 4; + pbLiteral = *ppPool; + } + else { + pbLiteral = align4(pbCode + 6); + } + + *((PBYTE*&)pbLiteral) = DETOURS_PBYTE_TO_PFUNC(pbJmpVal); + LONG delta = pbLiteral - align4(pbCode + 4); + + write_thumb_opcode(pbCode, 0xf8dff000 | delta); // LDR PC,[PC+n] + + if (ppPool == NULL) { + if (((ULONG)pbCode & 2) != 0) { + write_thumb_opcode(pbCode, 0xdefe); // BREAK + } + pbCode += 4; + } + return pbCode; +} + +inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) +{ + while (pbCode < pbLimit) { + write_thumb_opcode(pbCode, 0xdefe); + } + return pbCode; +} + +inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) +{ + if (pbCode == NULL) { + return NULL; + } + if (ppGlobals != NULL) { + *ppGlobals = NULL; + } + + // Skip over the import jump if there is one. + pbCode = (PBYTE)DETOURS_PFUNC_TO_PBYTE(pbCode); + ULONG Opcode = fetch_thumb_opcode(pbCode); + + if ((Opcode & 0xfbf08f00) == 0xf2400c00) { // movw r12,#xxxx + ULONG Opcode2 = fetch_thumb_opcode(pbCode+4); + + if ((Opcode2 & 0xfbf08f00) == 0xf2c00c00) { // movt r12,#xxxx + ULONG Opcode3 = fetch_thumb_opcode(pbCode+8); + if (Opcode3 == 0xf8dcf000) { // ldr pc,[r12] + PBYTE pbTarget = (PBYTE)(((Opcode2 << 12) & 0xf7000000) | + ((Opcode2 << 1) & 0x08000000) | + ((Opcode2 << 16) & 0x00ff0000) | + ((Opcode >> 4) & 0x0000f700) | + ((Opcode >> 15) & 0x00000800) | + ((Opcode >> 0) & 0x000000ff)); + if (detour_is_imported(pbCode, pbTarget)) { + PBYTE pbNew = *(PBYTE *)pbTarget; + pbNew = DETOURS_PFUNC_TO_PBYTE(pbNew); + DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); + return pbNew; + } + } + } + } + return pbCode; +} + +inline void detour_find_jmp_bounds(PBYTE pbCode, + PDETOUR_TRAMPOLINE *ppLower, + PDETOUR_TRAMPOLINE *ppUpper) +{ + // We have to place trampolines within +/- 2GB of code. + ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); + ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); + DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); + + *ppLower = (PDETOUR_TRAMPOLINE)lo; + *ppUpper = (PDETOUR_TRAMPOLINE)hi; +} + + +inline BOOL detour_does_code_end_function(PBYTE pbCode) +{ + ULONG Opcode = fetch_thumb_opcode(pbCode); + if ((Opcode & 0xffffff87) == 0x4700 || // bx + (Opcode & 0xf800d000) == 0xf0009000) { // b + return TRUE; + } + if ((Opcode & 0xffff8000) == 0xe8bd8000) { // pop {...,pc} + __debugbreak(); + return TRUE; + } + if ((Opcode & 0xffffff00) == 0x0000bd00) { // pop {...,pc} + __debugbreak(); + return TRUE; + } + return FALSE; +} + +inline ULONG detour_is_code_filler(PBYTE pbCode) +{ + if (pbCode[0] == 0x00 && pbCode[1] == 0xbf) { // nop. + return 2; + } + if (pbCode[0] == 0x00 && pbCode[1] == 0x00) { // zero-filled padding. + return 2; + } + return 0; +} + +#endif // DETOURS_ARM + +#ifdef DETOURS_ARM64 + +struct _DETOUR_TRAMPOLINE +{ + // An ARM64 instruction is 4 bytes long. + // + // The overwrite is always composed of 3 instructions (12 bytes) which perform an indirect jump + // using _DETOUR_TRAMPOLINE::pbDetour as the address holding the target location. + // + // Copied instructions can expand. + // + // The scheme using MovImmediate can cause an instruction + // to grow as much as 6 times. + // That would be Bcc or Tbz with a large address space: + // 4 instructions to form immediate + // inverted tbz/bcc + // br + // + // An expansion of 4 is not uncommon -- bl/blr and small address space: + // 3 instructions to form immediate + // br or brl + // + // A theoretical maximum for rbCode is thefore 4*4*6 + 16 = 112 (another 16 for jmp to pbRemain). + // + // With literals, the maximum expansion is 5, including the literals: 4*4*5 + 16 = 96. + // + // The number is rounded up to 128. m_rbScratchDst should match this. + // + BYTE rbCode[128]; // target code + jmp to pbRemain + BYTE cbCode; // size of moved target code. + BYTE cbCodeBreak[3]; // padding to make debugging easier. + BYTE rbRestore[24]; // original target code. + BYTE cbRestore; // size of original target code. + BYTE cbRestoreBreak[3]; // padding to make debugging easier. + _DETOUR_ALIGN rAlign[8]; // instruction alignment array. + PBYTE pbRemain; // first instruction after moved code. [free list] + PBYTE pbDetour; // first instruction of detour function. +}; + +C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 184); + +enum { + SIZE_OF_JMP = 12 +}; + +inline ULONG fetch_opcode(PBYTE pbCode) +{ + return *(ULONG *)pbCode; +} + +inline void write_opcode(PBYTE &pbCode, ULONG Opcode) +{ + *(ULONG *)pbCode = Opcode; + pbCode += 4; +} + +struct ARM64_INDIRECT_JMP { + struct { + ULONG Rd : 5; + ULONG immhi : 19; + ULONG iop : 5; + ULONG immlo : 2; + ULONG op : 1; + } ardp; + + struct { + ULONG Rt : 5; + ULONG Rn : 5; + ULONG imm : 12; + ULONG opc : 2; + ULONG iop1 : 2; + ULONG V : 1; + ULONG iop2 : 3; + ULONG size : 2; + } ldr; + + ULONG br; +}; + +#pragma warning(push) +#pragma warning(disable:4201) + +union ARM64_INDIRECT_IMM { + struct { + ULONG64 pad : 12; + ULONG64 adrp_immlo : 2; + ULONG64 adrp_immhi : 19; + }; + + LONG64 value; +}; + +#pragma warning(pop) + +PBYTE detour_gen_jmp_indirect(BYTE *pbCode, ULONG64 *pbJmpVal) +{ + // adrp x17, [jmpval] + // ldr x17, [x17, jmpval] + // br x17 + + struct ARM64_INDIRECT_JMP *pIndJmp; + union ARM64_INDIRECT_IMM jmpIndAddr; + + jmpIndAddr.value = (((LONG64)pbJmpVal) & 0xFFFFFFFFFFFFF000) - + (((LONG64)pbCode) & 0xFFFFFFFFFFFFF000); + + pIndJmp = (struct ARM64_INDIRECT_JMP *)pbCode; + pbCode = (BYTE *)(pIndJmp + 1); + + pIndJmp->ardp.Rd = 17; + pIndJmp->ardp.immhi = jmpIndAddr.adrp_immhi; + pIndJmp->ardp.iop = 0x10; + pIndJmp->ardp.immlo = jmpIndAddr.adrp_immlo; + pIndJmp->ardp.op = 1; + + pIndJmp->ldr.Rt = 17; + pIndJmp->ldr.Rn = 17; + pIndJmp->ldr.imm = (((ULONG64)pbJmpVal) & 0xFFF) / 8; + pIndJmp->ldr.opc = 1; + pIndJmp->ldr.iop1 = 1; + pIndJmp->ldr.V = 0; + pIndJmp->ldr.iop2 = 7; + pIndJmp->ldr.size = 3; + + pIndJmp->br = 0xD61F0220; + + return pbCode; +} + +PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE *ppPool, PBYTE pbJmpVal) +{ + PBYTE pbLiteral; + if (ppPool != NULL) { + *ppPool = *ppPool - 8; + pbLiteral = *ppPool; + } + else { + pbLiteral = pbCode + 8; + } + + *((PBYTE*&)pbLiteral) = pbJmpVal; + LONG delta = (LONG)(pbLiteral - pbCode); + + write_opcode(pbCode, 0x58000011 | ((delta / 4) << 5)); // LDR X17,[PC+n] + write_opcode(pbCode, 0xd61f0000 | (17 << 5)); // BR X17 + + if (ppPool == NULL) { + pbCode += 8; + } + return pbCode; +} + +inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) +{ + while (pbCode < pbLimit) { + write_opcode(pbCode, 0xd4100000 | (0xf000 << 5)); + } + return pbCode; +} + +inline INT64 detour_sign_extend(UINT64 value, UINT bits) +{ + const UINT left = 64 - bits; + const INT64 m1 = -1; + const INT64 wide = (INT64)(value << left); + const INT64 sign = (wide < 0) ? (m1 << left) : 0; + return value | sign; +} + +inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) +{ + if (pbCode == NULL) { + return NULL; + } + if (ppGlobals != NULL) { + *ppGlobals = NULL; + } + + // Skip over the import jump if there is one. + pbCode = (PBYTE)pbCode; + ULONG Opcode = fetch_opcode(pbCode); + + if ((Opcode & 0x9f00001f) == 0x90000010) { // adrp x16, IAT + ULONG Opcode2 = fetch_opcode(pbCode + 4); + + if ((Opcode2 & 0xffe003ff) == 0xf9400210) { // ldr x16, [x16, IAT] + ULONG Opcode3 = fetch_opcode(pbCode + 8); + + if (Opcode3 == 0xd61f0200) { // br x16 + +/* https://static.docs.arm.com/ddi0487/bb/DDI0487B_b_armv8_arm.pdf + The ADRP instruction shifts a signed, 21-bit immediate left by 12 bits, adds it to the value of the program counter with + the bottom 12 bits cleared to zero, and then writes the result to a general-purpose register. This permits the + calculation of the address at a 4KB aligned memory region. In conjunction with an ADD (immediate) instruction, or + a Load/Store instruction with a 12-bit immediate offset, this allows for the calculation of, or access to, any address + within +/- 4GB of the current PC. + +PC-rel. addressing + This section describes the encoding of the PC-rel. addressing instruction class. The encodings in this section are + decoded from Data Processing -- Immediate on page C4-226. + Add/subtract (immediate) + This section describes the encoding of the Add/subtract (immediate) instruction class. The encodings in this section + are decoded from Data Processing -- Immediate on page C4-226. + Decode fields + Instruction page + op + 0 ADR + 1 ADRP + +C6.2.10 ADRP + Form PC-relative address to 4KB page adds an immediate value that is shifted left by 12 bits, to the PC value to + form a PC-relative address, with the bottom 12 bits masked out, and writes the result to the destination register. + ADRP ,