master
cs 102 lines 3.6 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 using System;
4 using System.Runtime.CompilerServices;
5 using System.Runtime.InteropServices;
6 using WinRT;
7
8 namespace Microsoft.WSL.Containers;
9
10 internal static class WinRTActivation
11 {
12 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
13 private delegate int DllGetActivationFactoryFn(IntPtr classId, out IntPtr factory);
14
15 private static DllGetActivationFactoryFn s_getDllFactory;
16
17 // Overrides the WinRT activation to route activation of our types through our native DLL.
18 #pragma warning disable CA2255
19 // CA2255 warns against using ModuleInitializer to discourage using it without thinking through some possible issues.
20 // For example, unintuitive timing (it runs the first time a type is used, not when the module is loaded or inspected),
21 // and limiting possible optimizations (if the module is loaded, but nothing that depended on the initializer is ever used).
22 // In this case, we only need it to run before using any of our types, and everything in the assembly needs this
23 // initialization, so it's fine.
24 [ModuleInitializer]
25 #pragma warning restore CA2255
26 internal static void Initialize()
27 {
28 // Get a pointer to the function in the DLL that creates activation factories.
29 s_getDllFactory = Marshal.GetDelegateForFunctionPointer<DllGetActivationFactoryFn>(
30 NativeLibrary.GetExport(
31 NativeLibrary.Load("wslcsdk.dll", typeof(WinRTActivation).Assembly, DllImportSearchPath.AssemblyDirectory),
32 "DllGetActivationFactory"));
33
34 // Custom WinRT activation handler:
35 // If it is one of our types, we resolve it with our native DLL. Otherwise, we defer to the previous handler if one exists.
36 var previousHandler = ActivationFactory.ActivationHandler;
37 ActivationFactory.ActivationHandler = (typeName, iid) =>
38 {
39 if (typeName.StartsWith("Microsoft.WSL.Containers.", StringComparison.Ordinal))
40 {
41 return GetActivationFactory(typeName, iid);
42 }
43
44 if (previousHandler != null)
45 {
46 return previousHandler(typeName, iid);
47 }
48
49 return IntPtr.Zero;
50 };
51
52 }
53
54 private static IntPtr GetActivationFactory(string typeName, Guid iid)
55 {
56 // Convert the type name to HSTRING
57 if (WindowsCreateString(typeName, (uint)typeName.Length, out var hstring) < 0)
58 {
59 return IntPtr.Zero;
60 }
61 try
62 {
63 if (s_getDllFactory(hstring, out var factory) < 0)
64 {
65 return IntPtr.Zero;
66 }
67
68 if (iid == IID_IActivationFactory)
69 {
70 return factory;
71 }
72
73 try
74 {
75 if (Marshal.QueryInterface(factory, ref iid, out var queried) >= 0)
76 {
77 return queried;
78 }
79 else
80 {
81 return IntPtr.Zero;
82 }
83 }
84 finally
85 {
86 Marshal.Release(factory);
87 }
88 }
89 finally
90 {
91 WindowsDeleteString(hstring);
92 }
93 }
94
95 private static readonly Guid IID_IActivationFactory = new(0x00000035, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
96
97 [DllImport("combase.dll", CharSet = CharSet.Unicode)]
98 private static extern int WindowsCreateString(string sourceString, uint length, out IntPtr hstring);
99
100 [DllImport("combase.dll")]
101 private static extern int WindowsDeleteString(IntPtr hstring);
102 }