summaryrefslogtreecommitdiff
path: root/src/tools/heat/DllHarvester.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/heat/DllHarvester.cs')
-rw-r--r--src/tools/heat/DllHarvester.cs106
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
3namespace 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}