diff options
Diffstat (limited to 'src/tools/heat/DllHarvester.cs')
-rw-r--r-- | src/tools/heat/DllHarvester.cs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/tools/heat/DllHarvester.cs b/src/tools/heat/DllHarvester.cs new file mode 100644 index 00000000..e8c5ae40 --- /dev/null +++ b/src/tools/heat/DllHarvester.cs | |||
@@ -0,0 +1,106 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Harvesters | ||
4 | { | ||
5 | using System; | ||
6 | using System.Reflection; | ||
7 | using System.Reflection.Emit; | ||
8 | using System.Runtime.InteropServices; | ||
9 | using Wix = WixToolset.Harvesters.Serialize; | ||
10 | |||
11 | /// <summary> | ||
12 | /// Harvest WiX authoring from a native DLL file. | ||
13 | /// </summary> | ||
14 | public sealed class DllHarvester | ||
15 | { | ||
16 | /// <summary> | ||
17 | /// Harvest the registry values written by calling DllRegisterServer on the specified file. | ||
18 | /// </summary> | ||
19 | /// <param name="file">The file to harvest registry values from.</param> | ||
20 | /// <returns>The harvested registry values.</returns> | ||
21 | public Wix.RegistryValue[] HarvestRegistryValues(string file) | ||
22 | { | ||
23 | // load the DLL | ||
24 | NativeMethods.LoadLibrary(file); | ||
25 | |||
26 | using (RegistryHarvester registryHarvester = new RegistryHarvester(true)) | ||
27 | { | ||
28 | try | ||
29 | { | ||
30 | DynamicPInvoke(file, "DllRegisterServer", typeof(int), null, null); | ||
31 | |||
32 | return registryHarvester.HarvestRegistry(); | ||
33 | } | ||
34 | catch (TargetInvocationException e) | ||
35 | { | ||
36 | e.Data["file"] = file; | ||
37 | throw; | ||
38 | } | ||
39 | } | ||
40 | } | ||
41 | |||
42 | /// <summary> | ||
43 | /// Dynamically PInvokes into a DLL. | ||
44 | /// </summary> | ||
45 | /// <param name="dll">Dynamic link library containing the entry point.</param> | ||
46 | /// <param name="entryPoint">Entry point into dynamic link library.</param> | ||
47 | /// <param name="returnType">Return type of entry point.</param> | ||
48 | /// <param name="parameterTypes">Type of parameters to entry point.</param> | ||
49 | /// <param name="parameterValues">Value of parameters to entry point.</param> | ||
50 | /// <returns>Value from invoked code.</returns> | ||
51 | private static object DynamicPInvoke(string dll, string entryPoint, Type returnType, Type[] parameterTypes, object[] parameterValues) | ||
52 | { | ||
53 | #if NETCOREAPP | ||
54 | throw new PlatformNotSupportedException(); | ||
55 | #else | ||
56 | AssemblyName assemblyName = new AssemblyName(); | ||
57 | assemblyName.Name = "wixTempAssembly"; | ||
58 | |||
59 | AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); | ||
60 | ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("wixTempModule"); | ||
61 | |||
62 | MethodBuilder dynamicMethod = dynamicModule.DefinePInvokeMethod(entryPoint, dll, MethodAttributes.Static | MethodAttributes.Public | MethodAttributes.PinvokeImpl, CallingConventions.Standard, returnType, parameterTypes, CallingConvention.Winapi, CharSet.Ansi); | ||
63 | dynamicModule.CreateGlobalFunctions(); | ||
64 | |||
65 | MethodInfo methodInfo = dynamicModule.GetMethod(entryPoint); | ||
66 | return methodInfo.Invoke(null, parameterValues); | ||
67 | #endif | ||
68 | } | ||
69 | |||
70 | /// <summary> | ||
71 | /// Native methods for loading libraries. | ||
72 | /// </summary> | ||
73 | private sealed class NativeMethods | ||
74 | { | ||
75 | private const UInt32 LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008; | ||
76 | |||
77 | /// <summary> | ||
78 | /// Load a DLL library. | ||
79 | /// </summary> | ||
80 | /// <param name="file">The file name of the executable module.</param> | ||
81 | /// <returns>If the function succeeds, the return value is a handle to the mapped executable module.</returns> | ||
82 | internal static IntPtr LoadLibrary(string file) | ||
83 | { | ||
84 | IntPtr dllHandle = LoadLibraryEx(file, IntPtr.Zero, NativeMethods.LOAD_WITH_ALTERED_SEARCH_PATH); | ||
85 | |||
86 | if (IntPtr.Zero == dllHandle) | ||
87 | { | ||
88 | int lastError = Marshal.GetLastWin32Error(); | ||
89 | throw new Exception(String.Format("Unable to load file: {0}, error: {1}", file, lastError)); | ||
90 | } | ||
91 | |||
92 | return dllHandle; | ||
93 | } | ||
94 | |||
95 | /// <summary> | ||
96 | /// Maps the specified executable module into the address space of the calling process. | ||
97 | /// </summary> | ||
98 | /// <param name="file">The file name of the executable module.</param> | ||
99 | /// <param name="fileHandle">This parameter is reserved for future use. It must be NULL.</param> | ||
100 | /// <param name="flags">Action to take when loading the module.</param> | ||
101 | /// <returns>If the function succeeds, the return value is a handle to the mapped executable module.</returns> | ||
102 | [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)] | ||
103 | private static extern IntPtr LoadLibraryEx(string file, IntPtr fileHandle, UInt32 flags); | ||
104 | } | ||
105 | } | ||
106 | } | ||