From 222874b6fe882ea674e49f01ee60be56f3dfeade Mon Sep 17 00:00:00 2001 From: Rob LaDuca Date: Wed, 29 May 2019 12:07:56 -0700 Subject: [PATCH] Inject Module Constructor into PCore (#741) PresentationCore used to have a module constructor that called SetProcessDpiAware. Now that DirectWriteForwarder has been split off from the C# piece of PresentationCore, this module constructor lives in DirectWriteForwarder. Due to this, the call is happening too late. To fix this, add a module constructor back into PresentationCore via IL Injection. * Adding InjectModuleInitializer initial targets. Initial targets copy over ILDAsm, ILAsm, and CoreCLR bits needed to form an ILTools directory. * Adding initial ILDAsm and ILAsm tasks and DLL assembly/disassembly targets. * Fixing call to ILAsm to ensure it builds a DLL. * Fixing up temp location for ILTools * Updating packages to be RID specific and to use the latest CoreCLR packages from the COreCLR feed. * Enabling debug in ILAsm so as to add back the Debuggable attribute. * Switch on or off the Debuggable attribute based on the build configuration. * Lifting inline tasks into their own code files and replacing the MSBuild based IL manipulation with C# code. * Removing test project changes * Fixing module constructor task to append to file. * Removing setting of RID property as it was affecting obj/bin layout. Fixing InjectModuleInitializer targets to use a local RID. * Fixing module constructor creation and adding an option to use .NET Framework or .NET Core ILAsm. This is because IL tools in .NET Core do not support debug info. * Adding basic comments. * Enabling module constructor injection for PresentationCore * Fixing missing semi-colon from merge * Creation of satellite assemblies uses PresentationCore.dll as a template to grab assembly attributes from. Reconstructing the DLL (and injecting the module initializer) is affecting this, so we move the injection to after construction of satellites. * Always instruct ILAsm to generate debug information, otherwise release won't have PDBs. * Adding GitHub issue links for IL Tools modifications. Adding exception handling for FindDotNetFrameworkILToolsTask Fixing architecture identification (using semantics from Wpf.Cpp.Props) * Replacing escaping with verbatim literals Adding returns for error conditions * Adding DARC dependencies. * Add coherent parents for IL(D)Asm * Coherency updates --- .gitignore | 1 + NuGet.config | 1 + eng/Version.Details.xml | 98 ++-- eng/Versions.props | 47 +- eng/WpfArcadeSdk/Sdk/Sdk.targets | 1 + .../tools/InjectModuleInitializer.targets | 428 ++++++++++++++++++ .../AddModuleConstructorTask.cs | 80 ++++ .../InjectModuleInitializer/ILAsmTask.cs | 301 ++++++++++++ .../InjectModuleInitializer/ILDasmTask.cs | 212 +++++++++ .../ModuleInitializer.il | 59 +++ .../MsCorLibAssemblySection.il | 5 + eng/WpfArcadeSdk/tools/Packaging.props | 4 +- .../src/PresentationCore/ModuleInitializer.cs | 21 + .../PresentationCore/PresentationCore.csproj | 2 + 14 files changed, 1196 insertions(+), 64 deletions(-) create mode 100644 eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets create mode 100644 eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs create mode 100644 eng/WpfArcadeSdk/tools/InjectModuleInitializer/ILAsmTask.cs create mode 100644 eng/WpfArcadeSdk/tools/InjectModuleInitializer/ILDasmTask.cs create mode 100644 eng/WpfArcadeSdk/tools/InjectModuleInitializer/ModuleInitializer.il create mode 100644 eng/WpfArcadeSdk/tools/InjectModuleInitializer/MsCorLibAssemblySection.il create mode 100644 src/Microsoft.DotNet.Wpf/src/PresentationCore/ModuleInitializer.cs diff --git a/.gitignore b/.gitignore index 48f24dfd9..314e6954e 100644 --- a/.gitignore +++ b/.gitignore @@ -332,6 +332,7 @@ ASALocalRun/ /.dotnet /.packages /.tools/vswhere/2.5.2 +/.tools/native/iltools ### OSX ### diff --git a/NuGet.config b/NuGet.config index 54c43172e..7ccc2a1b4 100644 --- a/NuGet.config +++ b/NuGet.config @@ -6,6 +6,7 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 3a0af3bcc..237fbff97 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,85 +1,99 @@ + + + https://github.com/dotnet/winforms + bbde30e7f09411d9c045015e8f3b6517bec2828a + + - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://github.com/dotnet/core-setup - 20426e8c486d8715337cb6438ec70bc3619a514d + b2f8fc281df93b0ecb148224369b938d753d1616 - + https://github.com/dotnet/arcade - 11f90a2a260422201895de58e57170131ab4efe7 + 3b0760f8789d5d4bd146b36bd9051696d7a56bfa - + https://github.com/dotnet/arcade - 11f90a2a260422201895de58e57170131ab4efe7 + 3b0760f8789d5d4bd146b36bd9051696d7a56bfa - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 - - - https://github.com/dotnet/winforms - ee51a187ba1d2174233dacb6e2056e5403f9d36e + ac24849e0404b9a7caba56fd398dbe6c5dbede0a - + https://dev.azure.com/dnceng/internal/_git/dotnet-wpf-int - 15c3713f381b6208032e951e577be263152c310e + db55c197391f1185a493b036b030a6b46c796f74 - + https://github.com/dotnet/corefx - 41489a93acf3f36abcaaaea2003a8fdbb577cf35 + ac24849e0404b9a7caba56fd398dbe6c5dbede0a + + + https://github.com/dotnet/coreclr + 7631331183266734342de351b25519a07743e13e + + + https://github.com/dotnet/coreclr + 7631331183266734342de351b25519a07743e13e + + + https://github.com/dotnet/coreclr + 7631331183266734342de351b25519a07743e13e diff --git a/eng/Versions.props b/eng/Versions.props index 13df4da68..f98a9cc4e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -4,37 +4,43 @@ 4.8.0 preview6 4.0.0.0 - 4.6.0-preview6.19273.5 + 4.6.0-preview6.19278.5 - 4.8.0-preview6.19258.6 + 4.8.0-preview6.19279.2 + + + + 3.0.0-preview6.19278.71 + 3.0.0-preview6.19278.71 + 3.0.0-preview6.19278.71 - 3.0.0-preview6-27723-08 - 3.0.0-preview6.19273.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 + 3.0.0-preview6-27728-04 + 3.0.0-preview6.19278.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 4.6.0-preview4.19176.11 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 - 4.6.0-preview6.19273.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 + 4.6.0-preview6.19278.5 - 1.0.0-beta.19278.1 + 1.0.0-beta.19270.2 @@ -57,8 +63,9 @@ $(RestoreSources); https://dotnet.myget.org/F/dotnet-corefxlab/api/v3/index.json; + https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json; + https://dotnetfeed.blob.core.windows.net/dotnet-coreclr/index.json; https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; - https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json @@ -91,6 +98,6 @@ It is worth reiterating that this package *should not* be consumed to build the product. --> - 4.8.0-preview6.19278.10 + 4.8.0-preview6.19279.6 diff --git a/eng/WpfArcadeSdk/Sdk/Sdk.targets b/eng/WpfArcadeSdk/Sdk/Sdk.targets index 122821d91..88a2a498f 100644 --- a/eng/WpfArcadeSdk/Sdk/Sdk.targets +++ b/eng/WpfArcadeSdk/Sdk/Sdk.targets @@ -20,6 +20,7 @@ + diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets b/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets new file mode 100644 index 000000000..e1e3ef4a5 --- /dev/null +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets @@ -0,0 +1,428 @@ + + + + + win-$(Platform) + win-x86 + win-x64 + + + + + + + + + + + + + + $(Pkgruntime_win-x86_Microsoft_NETCore_ILDAsm)\runtimes\$(LocalRuntimeIdentifier)\native\ + $(Pkgruntime_win-x86_Microsoft_NETCore_ILAsm)\runtimes\$(LocalRuntimeIdentifier)\native\ + $(Pkgruntime_win-x86_Microsoft_NETCore_Runtime_CoreCLR)\runtimes\$(LocalRuntimeIdentifier)\native\ + + + + $(Pkgruntime_win-x64_Microsoft_NETCore_ILDAsm)\runtimes\$(LocalRuntimeIdentifier)\native\ + $(Pkgruntime_win-x64_Microsoft_NETCore_ILAsm)\runtimes\$(LocalRuntimeIdentifier)\native\ + $(Pkgruntime_win-x64_Microsoft_NETCore_Runtime_CoreCLR)\runtimes\$(LocalRuntimeIdentifier)\native\ + + + + + $(ArtifactsTmpDir)\iltools\$(PackageRuntimeIdentifierPrefix)\ + $(ILToolsPath)ildasm.exe + $(ILToolsPath)ilasm.exe + + + + + + + RoslynCodeTaskFactory + $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bitness64 + Bitness32 + + + + + + + + + + + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName)$(TargetExt)')) + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) + + + + + + + + + + + + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) + $(WpfArcadeSdkToolsDir)InjectModuleInitializer\ModuleInitializer.il + $(WpfArcadeSdkToolsDir)InjectModuleInitializer\MsCorLibAssemblySection.il + + + + + + + + + + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName)$(TargetExt)')) + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) + + + + + + + + + + diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs new file mode 100644 index 000000000..2e0739b8c --- /dev/null +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs @@ -0,0 +1,80 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text.RegularExpressions; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace WpfArcadeSdk.Build.Tasks +{ + /// + /// Append the supplied module constructor to the supplied IL file. + /// Using this requires that the DLL has implemented a static class named + /// ModuleInitializer with a static void Initialize function. This class + /// is called from the module initializer. + /// + public class AddModuleConstructorTask : Task + { + /// + /// The original IL file to manipulate + /// + [Required] + public string ILFile { get; set; } + + /// + /// Contains the IL section referencing mscorlib. + /// This is inserted if not already present. + /// + [Required] + public string MsCorLibAssemblySectionIL { get; set; } + + /// + /// Contains the IL of the module constructor + /// + [Required] + public string ModuleConstructorIL { get; set; } + + public override bool Execute() + { + try + { + var moduleConstructorIL = File.ReadAllText(ModuleConstructorIL); + var msCorLibAssemblySectionIL = File.ReadAllText(MsCorLibAssemblySectionIL); + var sourceIL = File.ReadAllText(ILFile); + + using (var outputIL = new StreamWriter(File.Open(ILFile, FileMode.Truncate))) + { + if (Regex.Match(sourceIL, @"\.class.+?ModuleInitializer.+?\.method.+?static.+?Initialize\(\).+?end of class ModuleInitializer", RegexOptions.Singleline) == Match.Empty) + { + Log.LogError("Inserting a module initializer requires the assembly to implement a class named ModuleInitializer with a static parameterless method named Initialize."); + return false; + } + + if (Regex.Match(sourceIL, @"\.assembly extern mscorlib", RegexOptions.Singleline) == Match.Empty) + { + outputIL.WriteLine(msCorLibAssemblySectionIL); + } + + if (Regex.Match(sourceIL, @"\.class private auto ansi '\'.+?\.method private hidebysig specialname rtspecialname static void \.cctor \(\) cil managed ", RegexOptions.Singleline) == Match.Empty) + { + outputIL.WriteLine(moduleConstructorIL); + } + else + { + Log.LogError("Cannot insert a module initializer into an assembly that already contains one."); + return false; + } + + outputIL.WriteLine(sourceIL); + } + + return true; + } + catch (Exception e) + { + Log.LogError(e.ToString() + Environment.NewLine + e.StackTrace); + return false; + } + } + } +} diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ILAsmTask.cs b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ILAsmTask.cs new file mode 100644 index 000000000..dc52629d2 --- /dev/null +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ILAsmTask.cs @@ -0,0 +1,301 @@ +using System; +using System.Diagnostics; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace WpfArcadeSdk.Build.Tasks +{ + /// + /// Runs ILAsm from the path supplied on the assembly supplied. + /// + public class ILAsmTask : Task + { + /// + /// The full path to ILAsm.exe + /// + [Required] + public string ILAsm { get; set; } + + /// + /// The source file to assemble + /// + [Required] + public string SourceFile { get; set; } + + /// + /// The output path + /// + [Required] + public string Out { get; set; } + + /// + /// /NOLOGO Don't type the logo + /// + public bool NoLogo { get; set; } + + /// + /// /QUIET Don't report assembly progress + /// + public bool Quiet { get; set; } + + /// + /// /NOAUTOINHERIT Disable inheriting from System.Object by default + /// + public bool NoAutoInherit { get; set; } + + /// + /// /DLL Compile to.dll + /// + public bool Dll { get; set; } + + /// + /// /EXE Compile to.exe(default) + /// + public bool Exe { get; set; } + + /// + /// /PDB Create the PDB file without enabling debug info tracking + /// + public bool Pdb { get; set; } + + /// + /// /APPCONTAINER Create an AppContainer exe or dll + /// + public bool AppContainer { get; set; } + + /// + /// /DEBUG Disable JIT optimization, create PDB file, use sequence points from PDB + /// + public bool Debug { get; set; } + + /// + /// /DEBUG=IMPL Disable JIT optimization, create PDB file, use implicit sequence points + /// + public bool DebugDisableJitOptimization { get; set; } + + + /// + /// / DEBUG = OPT Enable JIT optimization, create PDB file, use implicit sequence points + /// + public bool DebugEnableJitOptimization { get; set; } + + + /// + /// / OPTIMIZE Optimize long instructions to short + /// + public bool Optimize { get; set; } + + + /// + /// / FOLD Fold the identical method bodies into one + /// + public bool Fold { get; set; } + + + /// + /// / CLOCK Measure and report compilation times + /// + public bool Clock { get; set; } + + + /// + /// / RESOURCE =< res_file > Link the specified resource file(*.res) into resulting.exe or.dll + /// + public string Resource { get; set; } + + + /// + /// / CVRES =< path_to_file > Set path to cvtres tool: /CVR= cvtres.exe / CVR = tool\cvtres.cmd /CVR= D:\tool\ + /// + public string CvRes { get; set; } + + /// + /// /KEY =< keyfile > Compile with strong signature + /// ( contains private key) + /// + public string KeyFile { get; set; } + + /// + /// /KEY=@ Compile with strong signature + /// ( is the private key source name) + /// + public string KeySource { get; set; } + + /// + /// /INCLUDE= Set path to search for #include'd files + /// + public string Include { get; set; } + + /// + /// /SUBSYSTEM= Set Subsystem value in the NT Optional header + /// + public string SubSystem { get; set; } + + /// + /// /SSVER=. Set Subsystem version number in the NT Optional header + /// + public string SubSystemVersion { get; set; } + + /// + /// /FLAGS= Set CLR ImageFlags value in the CLR header + /// + public string Flags { get; set; } + + /// + /// /ALIGNMENT= Set FileAlignment value in the NT Optional header + /// + public string Alignment { get; set; } + + /// + /// /BASE= Set ImageBase value in the NT Optional header(max 2GB for 32-bit images) + /// + public string Base { get; set; } + + /// + /// /STACK= Set SizeOfStackReserve value in the NT Optional header + /// + public string Stack { get; set; } + + /// + /// /MDV= Set Metadata version string + /// + public string MetadataVersion { get; set; } + + /// + /// /MSV=. Set Metadata stream version(.) + /// + public string MetadataStreamVersion { get; set; } + + /// + /// /PE64 Create a 64bit image(PE32+) + /// + public string PE64 { get; set; } + + /// + /// /HIGHENTROPYVA Set High Entropy Virtual Address capable PE32+ images(default for /APPCONTAINER) + /// + public string HighEntropyVirtualAddress { get; set; } + + /// + /// /NOCORSTUB Suppress generation of CORExeMain stub + /// + public string NoCorStub { get; set; } + + /// + /// /STRIPRELOC Indicate that no base relocations are needed + /// + public string StripReLoc { get; set; } + + /// + /// /ITANIUM Target processor: Intel Itanium + /// + public string Itanium { get; set; } + + /// + /// /X64 Target processor: 64bit AMD processor + /// + public string X64 { get; set; } + + /// + /// /ARM Target processor: ARM processor + /// + public string Arm { get; set; } + + /// + /// /32BITPREFERRED Create a 32BitPreferred image(PE32) + /// + public string Prefer32Bit { get; set; } + + /// + /// /ENC= Create Edit-and-Continue deltas from specified source file + /// + public string ENC { get; set; } + + public override bool Execute() + { + try + { + string commandLine = "/OUT=" + Out; + if (NoLogo) commandLine += " /NOLOGO"; + if (Quiet) commandLine += " /QUIET"; + if (NoAutoInherit) commandLine += " /NOAUTOINHERIT"; + if (Dll) commandLine += " /DLL"; + if (Exe) commandLine += " /EXE"; + if (Pdb) commandLine += " /PDB"; + if (AppContainer) commandLine += " /APPCONTAINER"; + if (Debug) commandLine += " /DEBUG"; + if (DebugDisableJitOptimization) commandLine += " /DEBUG=IMPL"; + if (DebugEnableJitOptimization) commandLine += " /DEBUG=OPT"; + if (Optimize) commandLine += " /OPTIMIZE"; + if (Fold) commandLine += " /FOLD"; + if (Clock) commandLine += " /CLOCK"; + if (!string.IsNullOrEmpty(Resource)) commandLine += " /RESOURCE=" + Resource; + if (!string.IsNullOrEmpty(CvRes)) commandLine += " /CVRES=" + CvRes; + if (!string.IsNullOrEmpty(KeyFile)) commandLine += " /KeyFile=" + KeyFile; + if (!string.IsNullOrEmpty(KeySource)) commandLine += " /CVRES=@" + KeySource; + if (!string.IsNullOrEmpty(Include)) commandLine += " /INCLUDE=" + Include; + + int subSystem = -1; + if (!string.IsNullOrEmpty(SubSystem) && Int32.TryParse(SubSystem, out subSystem)) commandLine += " /SUBSYSTEM=" + subSystem; + if (!string.IsNullOrEmpty(SubSystemVersion)) commandLine += " /SUBSYSTEMVERSION=" + SubSystemVersion; + + int flags = -1; + if (!string.IsNullOrEmpty(Flags) && Int32.TryParse(Flags, out flags)) commandLine += " /FLAGS=" + flags; + + int alignment = -1; + if (!string.IsNullOrEmpty(Alignment) && Int32.TryParse(Alignment, out alignment)) commandLine += " /ALIGNMENT=" + alignment; + + int @base = -1; + if (!string.IsNullOrEmpty(Base) && Int32.TryParse(Base, out @base)) commandLine += " /BASE=" + @base; + + int stack = -1; + if (!string.IsNullOrEmpty(Stack) && Int32.TryParse(Stack, out stack)) commandLine += " /STACK=" + stack; + + if (!string.IsNullOrEmpty(MetadataVersion)) commandLine += " /MDV=" + MetadataVersion; + if (!string.IsNullOrEmpty(MetadataStreamVersion)) commandLine += " /MSV=" + MetadataStreamVersion; + + bool pe64 = false; + if (!string.IsNullOrEmpty(PE64) && bool.TryParse(PE64, out pe64)) commandLine += " /PE64=" + pe64; + + bool highEntropyVA = false; + if (!string.IsNullOrEmpty(HighEntropyVirtualAddress) && bool.TryParse(HighEntropyVirtualAddress, out highEntropyVA)) commandLine += " /HIGHENTROPYVA=" + highEntropyVA; + + bool noCorStub = false; + if (!string.IsNullOrEmpty(NoCorStub) && bool.TryParse(NoCorStub, out noCorStub)) commandLine += " /NOCORSTUB=" + noCorStub; + + bool stripreloc = false; + if (!string.IsNullOrEmpty(StripReLoc) && bool.TryParse(StripReLoc, out stripreloc)) commandLine += " /STRIPRELOC=" + stripreloc; + + bool itanium = false; + if (!string.IsNullOrEmpty(Itanium) && bool.TryParse(Itanium, out itanium)) commandLine += " /ITANIUM=" + itanium; + + bool x64 = false; + if (!string.IsNullOrEmpty(X64) && bool.TryParse(X64, out x64)) commandLine += " /X64=" + x64; + + bool arm = false; + if (!string.IsNullOrEmpty(Arm) && bool.TryParse(Arm, out arm)) commandLine += " /ARM=" + arm; + + bool prefer32bit = false; + if (!string.IsNullOrEmpty(Prefer32Bit) && bool.TryParse(Prefer32Bit, out prefer32bit)) commandLine += " /32BITPREFERRED=" + prefer32bit; + + if (!string.IsNullOrEmpty(ENC)) commandLine += " /ENC=" + ENC; + + + ProcessStartInfo startInfo = new ProcessStartInfo(ILAsm); + startInfo.CreateNoWindow = true; + startInfo.UseShellExecute = false; + startInfo.Arguments = SourceFile + " " + commandLine; + + Log.LogMessage("Starting process: " + startInfo.FileName + " " + startInfo.Arguments); + + Process.Start(startInfo).WaitForExit(); + return true; + } + catch (Exception e) + { + Log.LogError(e.ToString() + e.StackTrace); + return false; + } + } + } +} diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ILDasmTask.cs b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ILDasmTask.cs new file mode 100644 index 000000000..b31903647 --- /dev/null +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ILDasmTask.cs @@ -0,0 +1,212 @@ +using System; +using System.Diagnostics; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace WpfArcadeSdk.Build.Tasks +{ + /// + /// Runs ILDAsm from the path supplied on the assembly supplied. + /// + public class ILDAsmTask : Task + { + [Required] + public string ILDAsm { get; set; } + + [Required] + public string Assembly { get; set; } + + [Required] + public string Out { get; set; } + + /// + /// Output in HTML format + /// + public bool Html { get; set; } + + /// + /// Output in rich text format + /// + public bool Rtf { get; set; } + + /// + /// Show actual bytes(in hex) as instruction comments + /// + public bool Bytes { get; set; } + + /// + /// Show exception handling clauses in raw form + /// + public bool RawEH { get; set; } + + /// + /// Show metadata tokens of classes and members + /// + public bool Tokens { get; set; } + + /// + /// Show original source lines as comments + /// + public bool Source { get; set; } + + /// + /// Include references to original source lines + /// + public bool LineNum { get; set; } + + /// + /// =[+...] Only disassemble the items with specified + /// visibility. ( = PUB | PRI | FAM | ASM | FAA | FOA | PSC) + /// + public string Visibility { get; set; } + + /// + /// Only disassemble the public items(same as /VIS= PUB) + /// + public bool PubOnly { get; set; } + + /// + /// Include all names into single quotes + /// + public bool QuoteAllNames { get; set; } + + /// + /// Suppress output of custom attributes + /// + public bool NoCA { get; set; } + + /// + /// Output CA blobs in verbal form(default - in binary form) + /// + public bool CAVerbal { get; set; } + + /// + /// Suppress disassembly progress bar window pop-up + /// + public bool NoBar { get; set; } + + /// + /// Use UTF-8 encoding for output(default - ANSI) + /// + public bool Utf8 { get; set; } + + /// + /// Use UNICODE encoding for output + /// + public bool Unicode { get; set; } + + /// + /// Suppress IL assembler code output + /// + public bool NoIL { get; set; } + + /// + /// Use forward class declaration + /// + public bool Forward { get; set; } + + /// + /// Output full list of types(to preserve type ordering in round-trip) + /// + public bool TypeList { get; set; } + + /// + /// Display.NET projection view if input is a.winmd file + /// + public bool Project { get; set; } + + /// + /// Include file headers information in the output + /// + public bool Headers { get; set; } + + /// + /// =[::[(< sig >)] Disassemble the specified item only + /// + public string Item { get; set; } + + /// + /// Include statistics on the image + /// + public bool Stats { get; set; } + + /// + /// Include list of classes defined in the module + /// + public bool ClassList { get; set; } + + /// + /// Combination of /HEADER,/BYTES,/STATS,/CLASSLIST,/TOKENS + /// + public bool All { get; set; } + + /// + /// Options for EXE,DLL,OBJ and LIB files: + /// /METADATA[=< specifier >] Show MetaData, where is: + /// /MDHEADER Show MetaData header information and sizes. + /// /HEX Show more things in hex as well as words. + /// /CSV Show the record counts and heap sizes. + /// /UNREX Show unresolved externals. + /// /SCHEMA Show the MetaData header and schema information. + /// /RAW Show the raw MetaData tables. + /// /HEAPS Show the raw heaps. + /// /VALIDATE Validate the consistency of the metadata. + /// + public string Metadata { get; set; } + + /// + /// Options for LIB files only: + /// /OBJECTFILE=< obj_file_name > Show MetaData of a single object file in library + /// + public string ObjectFile { get; set; } + + public override bool Execute() + { + try + { + string commandLine = "/OUT=" + Out; + if (Html) commandLine += " /HTML"; + if (Rtf) commandLine += " /RTF"; + if (Bytes) commandLine += " /BYTES"; + if (RawEH) commandLine += " /RAWEH"; + if (Tokens) commandLine += " /TOKENS"; + if (Source) commandLine += " /SOURCE"; + if (LineNum) commandLine += " /LINENUM"; + if (Visibility != null && Visibility.Trim() != string.Empty) commandLine += " /VISIBILITY=" + Visibility; + if (PubOnly) commandLine += " /PUBONLY"; + if (QuoteAllNames) commandLine += " /QUOTEALLNAMES"; + if (NoCA) commandLine += " /NOCA"; + if (CAVerbal) commandLine += " /CAVERBAL"; + if (NoBar) commandLine += " /NOBAR"; + if (Utf8) commandLine += " /UTF8"; + if (Unicode) commandLine += " /UNICODE"; + if (NoIL) commandLine += " /NOIL"; + if (Forward) commandLine += " /FORWARD"; + if (TypeList) commandLine += " /TYPELIST"; + if (Headers) commandLine += " /HEADERS"; + if (Item != null && Item.Trim() != string.Empty) commandLine += " /ITEM=" + Item; + if (Stats) commandLine += " /STATS"; + if (ClassList) commandLine += " /CLASSLIST"; + if (All) commandLine += " /ALL"; + if (Metadata != null && Metadata.Trim() != string.Empty) commandLine += " /METADATA=" + Metadata; + if (ObjectFile != null && ObjectFile.Trim() != string.Empty) commandLine += " /OBJECTFILE=" + ObjectFile; + + ProcessStartInfo startInfo = new ProcessStartInfo(ILDAsm); + startInfo.CreateNoWindow = true; + startInfo.UseShellExecute = false; + startInfo.Arguments = Assembly + " " + commandLine; + + + Log.LogMessage("Starting process: " + startInfo.FileName + " " + startInfo.Arguments); + + Process.Start(startInfo).WaitForExit(); + return true; + } + catch (Exception e) + { + Log.LogError(e.ToString() + e.StackTrace); + return false; + } + } + } +} diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ModuleInitializer.il b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ModuleInitializer.il new file mode 100644 index 000000000..3c49d33d2 --- /dev/null +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/ModuleInitializer.il @@ -0,0 +1,59 @@ +.class private auto ansi '' +{ + .method private hidebysig specialname rtspecialname static void .cctor () cil managed + { + // Code size 76 (0x4c) + .maxstack 3 + + .locals init (class [mscorlib]System.Type V_0, bool V_1, class [mscorlib]System.Reflection.MethodInfo V_2, bool V_3) + IL_0000: nop + IL_0001: call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::GetExecutingAssembly() + IL_0006: ldstr "ModuleInitializer" + IL_000b: callvirt instance class [mscorlib]System.Type [mscorlib]System.Reflection.Assembly::GetType(string) + IL_0010: stloc.0 + IL_0011: ldloc.0 + IL_0012: ldnull + IL_0013: call bool [mscorlib]System.Type::op_Inequality(class [mscorlib]System.Type, class [mscorlib]System.Type) + IL_0018: stloc.1 + IL_0019: ldloc.1 + IL_001a: brfalse.s IL_004b + + IL_001c: nop + IL_001d: ldloc.0 + IL_001e: ldstr "Initialize" + IL_0023: ldc.i4.s 24 + IL_0025: callvirt instance class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string, valuetype [mscorlib]System.Reflection.BindingFlags) + IL_002a: stloc.2 + IL_002b: ldloc.2 + IL_002c: ldnull + IL_002d: call bool [mscorlib]System.Reflection.MethodInfo::op_Inequality(class [mscorlib]System.Reflection.MethodInfo, class [mscorlib]System.Reflection.MethodInfo) + IL_0032: stloc.3 + IL_0033: ldloc.3 + IL_0034: brfalse.s IL_004a + + IL_0036: nop + .try + { + IL_0037: nop + IL_0038: ldloc.2 + IL_0039: ldnull + IL_003a: ldnull + IL_003b: callvirt instance object [mscorlib]System.Reflection.MethodBase::Invoke(object, object[]) + IL_0040: pop + IL_0041: nop + IL_0042: leave.s IL_0049 + + } // end .try + catch [mscorlib]System.Exception + { + IL_0044: pop + IL_0045: nop + IL_0046: nop + IL_0047: leave.s IL_0049 + + } // end handler + IL_0049: nop + IL_004a: nop + IL_004b: ret + } +} diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/MsCorLibAssemblySection.il b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/MsCorLibAssemblySection.il new file mode 100644 index 000000000..b159214ce --- /dev/null +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/MsCorLibAssemblySection.il @@ -0,0 +1,5 @@ +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) + .ver 4:0:0:0 +}; diff --git a/eng/WpfArcadeSdk/tools/Packaging.props b/eng/WpfArcadeSdk/tools/Packaging.props index 844837f52..f533fc603 100644 --- a/eng/WpfArcadeSdk/tools/Packaging.props +++ b/eng/WpfArcadeSdk/tools/Packaging.props @@ -15,7 +15,7 @@ false - + MIT $(CopyrightNetFoundation) @@ -25,7 +25,7 @@ Microsoft.DotNet.Wpf.GitHub Microsoft.DotNet.Wpf.DncEng - + Microsoft.NET.Sdk.WindowsDesktop diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/ModuleInitializer.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/ModuleInitializer.cs new file mode 100644 index 000000000..aae7e0475 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/ModuleInitializer.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +internal static class ModuleInitializer +{ + /// + /// DirectWriteForwarder has a module constructor that implements + /// the setting of the default DPI awareness for the process. + /// We need to load DirectWriteForwarder the instant PresentationCore + /// loads in order to ensure that this is set before any DPI sensitive + /// operations are carried out. To do this, we simply call LoadDwrite + /// as the module constructor for DirectWriteForwarder would do this anyway. + /// + public static void Initialize() + { + MS.Internal.NativeWPFDLLLoader.LoadDwrite(); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/PresentationCore.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationCore/PresentationCore.csproj index b1081d923..2602b6dc6 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/PresentationCore.csproj +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/PresentationCore.csproj @@ -9,6 +9,7 @@ MS.Internal.PresentationCore None AnyCPU;x64 + true @@ -96,6 +97,7 @@ + -- GitLab