-
Notifications
You must be signed in to change notification settings - Fork 107
/
Copy pathOOPObject.cs
115 lines (95 loc) · 3.5 KB
/
OOPObject.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Windows.Foundation;
using Windows.Win32;
using Windows.Win32.System.Com;
namespace UnitTest
{
// https://docs.microsoft.com/windows/win32/api/unknwn/nn-unknwn-iclassfactory
[ComImport]
[ComVisible(false)]
[Guid("00000001-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IClassFactory
{
void CreateInstance(
[MarshalAs(UnmanagedType.Interface)] object pUnkOuter,
ref Guid riid,
out IntPtr ppvObject);
void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock);
}
[ComVisible(true)]
internal class WinRTClassFactory<T> : IClassFactory
{
private static readonly Guid IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
public static void RegisterClass<T>(IClassFactory classFactory)
{
RegisterClassObject(typeof(T).GUID, classFactory);
}
private static void RegisterClassObject(Guid clsid, object factory)
{
int hr = PInvoke.CoRegisterClassObject(in clsid, factory, CLSCTX.CLSCTX_LOCAL_SERVER, (int)REGCLS.REGCLS_MULTIPLEUSE, out uint _);
if (hr < 0)
{
Marshal.ThrowExceptionForHR(hr);
}
}
private readonly Func<T> createFunction;
private readonly Dictionary<Guid, Func<object, IntPtr>> marshalFuncByGuid;
public WinRTClassFactory(Func<T> createFunction, Dictionary<Guid, Func<object, IntPtr>> marshalFuncByGuid)
{
this.createFunction = createFunction ?? throw new ArgumentNullException(nameof(createFunction));
this.marshalFuncByGuid = marshalFuncByGuid ?? throw new ArgumentNullException(nameof(marshalFuncByGuid));
}
public void CreateInstance(
[MarshalAs(UnmanagedType.Interface)] object pUnkOuter,
ref Guid riid,
out IntPtr ppvObject)
{
if (pUnkOuter != null)
{
throw new COMException();
}
object obj = this.createFunction();
if (riid == IUnknown)
{
ppvObject = WinRT.MarshalInspectable<object>.FromManaged(obj);
}
else
{
if (!this.marshalFuncByGuid.TryGetValue(riid, out Func<object, IntPtr> marshalFunc))
{
throw new InvalidCastException();
}
ppvObject = marshalFunc(obj);
}
}
public void LockServer(bool fLock)
{
// No-op
}
}
[ComVisible(true)]
[Guid("15F1005B-E23A-4154-9417-CCD083D452BB")]
[ComDefaultInterface(typeof(IAsyncAction))]
internal class OOPAsyncAction : IAsyncAction
{
public bool delegateCalled;
public AsyncActionCompletedHandler Completed { get; set; }
public Exception ErrorCode => throw new NotImplementedException();
public uint Id => throw new NotImplementedException();
public AsyncStatus Status => throw new NotImplementedException();
public void Cancel()
{
}
public void Close()
{
Completed(this, AsyncStatus.Completed);
}
public void GetResults()
{
delegateCalled = true;
}
}
}