Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ComWrappers.cs
Go to the documentation of this file.
6
8
9[UnsupportedOSPlatform("android")]
10[UnsupportedOSPlatform("browser")]
11[UnsupportedOSPlatform("ios")]
12[UnsupportedOSPlatform("tvos")]
13[CLSCompliant(false)]
14public abstract class ComWrappers
15{
17 {
18 private struct ComInterfaceInstance
19 {
21 }
22
23 public IntPtr Vtable;
24
25 public unsafe static T GetInstance<T>(ComInterfaceDispatch* dispatchPtr) where T : class
26 {
27 ComInterfaceInstance* ptr = *(ComInterfaceInstance**)((ulong)dispatchPtr & 0xFFFFFFFFFFFFFFF0uL);
28 return Unsafe.As<T>(GCHandle.InternalGet(ptr->GcHandle));
29 }
30 }
31
32 public struct ComInterfaceEntry
33 {
34 public Guid IID;
35
36 public IntPtr Vtable;
37 }
38
40
42
43 private static long s_instanceCounter;
44
45 private readonly long id = Interlocked.Increment(ref s_instanceCounter);
46
48 {
49 if (!TryGetOrCreateComInterfaceForObjectInternal(this, instance, flags, out var retValue))
50 {
51 throw new ArgumentException(null, "instance");
52 }
53 return retValue;
54 }
55
56 private static bool TryGetOrCreateComInterfaceForObjectInternal(ComWrappers impl, object instance, CreateComInterfaceFlags flags, out IntPtr retValue)
57 {
58 if (instance == null)
59 {
60 throw new ArgumentNullException("instance");
61 }
62 return TryGetOrCreateComInterfaceForObjectInternal(ObjectHandleOnStack.Create(ref impl), impl.id, ObjectHandleOnStack.Create(ref instance), flags, out retValue);
63 }
64
65 [DllImport("QCall")]
66 private static extern bool TryGetOrCreateComInterfaceForObjectInternal(ObjectHandleOnStack comWrappersImpl, long wrapperId, ObjectHandleOnStack instance, CreateComInterfaceFlags flags, out IntPtr retValue);
67
68 internal unsafe static void* CallComputeVtables(ComWrappersScenario scenario, ComWrappers comWrappersImpl, object obj, CreateComInterfaceFlags flags, out int count)
69 {
70 ComWrappers comWrappers = null;
71 switch (scenario)
72 {
73 case ComWrappersScenario.Instance:
74 comWrappers = comWrappersImpl;
75 break;
76 case ComWrappersScenario.TrackerSupportGlobalInstance:
78 break;
79 case ComWrappersScenario.MarshallingGlobalInstance:
81 break;
82 }
83 if (comWrappers == null)
84 {
85 count = -1;
86 return null;
87 }
88 return comWrappers.ComputeVtables(obj, flags, out count);
89 }
90
91 public object GetOrCreateObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags)
92 {
93 if (!TryGetOrCreateObjectForComInstanceInternal(this, externalComObject, IntPtr.Zero, flags, null, out var retValue))
94 {
95 throw new ArgumentNullException("externalComObject");
96 }
97 return retValue;
98 }
99
100 internal static object CallCreateObject(ComWrappersScenario scenario, ComWrappers comWrappersImpl, IntPtr externalComObject, CreateObjectFlags flags)
101 {
102 ComWrappers comWrappers = null;
103 switch (scenario)
104 {
105 case ComWrappersScenario.Instance:
106 comWrappers = comWrappersImpl;
107 break;
108 case ComWrappersScenario.TrackerSupportGlobalInstance:
110 break;
111 case ComWrappersScenario.MarshallingGlobalInstance:
112 comWrappers = s_globalInstanceForMarshalling;
113 break;
114 }
115 return comWrappers?.CreateObject(externalComObject, flags);
116 }
117
118 public object GetOrRegisterObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags, object wrapper)
119 {
120 return GetOrRegisterObjectForComInstance(externalComObject, flags, wrapper, IntPtr.Zero);
121 }
122
123 public object GetOrRegisterObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags, object wrapper, IntPtr inner)
124 {
125 if (wrapper == null)
126 {
127 throw new ArgumentNullException("wrapper");
128 }
129 if (!TryGetOrCreateObjectForComInstanceInternal(this, externalComObject, inner, flags, wrapper, out var retValue))
130 {
131 throw new ArgumentNullException("externalComObject");
132 }
133 return retValue;
134 }
135
136 private static bool TryGetOrCreateObjectForComInstanceInternal(ComWrappers impl, IntPtr externalComObject, IntPtr innerMaybe, CreateObjectFlags flags, object wrapperMaybe, out object retValue)
137 {
138 if (externalComObject == IntPtr.Zero)
139 {
140 throw new ArgumentNullException("externalComObject");
141 }
142 if (innerMaybe != IntPtr.Zero && !flags.HasFlag(CreateObjectFlags.Aggregation))
143 {
145 }
146 object o = wrapperMaybe;
147 retValue = null;
148 return TryGetOrCreateObjectForComInstanceInternal(ObjectHandleOnStack.Create(ref impl), impl.id, externalComObject, innerMaybe, flags, ObjectHandleOnStack.Create(ref o), ObjectHandleOnStack.Create(ref retValue));
149 }
150
151 [DllImport("QCall")]
152 private static extern bool TryGetOrCreateObjectForComInstanceInternal(ObjectHandleOnStack comWrappersImpl, long wrapperId, IntPtr externalComObject, IntPtr innerMaybe, CreateObjectFlags flags, ObjectHandleOnStack wrapper, ObjectHandleOnStack retValue);
153
154 internal static void CallReleaseObjects(ComWrappers comWrappersImpl, IEnumerable objects)
155 {
156 (comWrappersImpl ?? s_globalInstanceForTrackerSupport).ReleaseObjects(objects);
157 }
158
159 public static void RegisterForTrackerSupport(ComWrappers instance)
160 {
161 if (instance == null)
162 {
163 throw new ArgumentNullException("instance");
164 }
165 if (Interlocked.CompareExchange(ref s_globalInstanceForTrackerSupport, instance, null) != null)
166 {
168 }
170 }
171
172 [DllImport("QCall")]
173 [SuppressGCTransition]
174 private static extern void SetGlobalInstanceRegisteredForTrackerSupport(long id);
175
176 [SupportedOSPlatform("windows")]
177 public static void RegisterForMarshalling(ComWrappers instance)
178 {
179 if (instance == null)
180 {
181 throw new ArgumentNullException("instance");
182 }
183 if (Interlocked.CompareExchange(ref s_globalInstanceForMarshalling, instance, null) != null)
184 {
186 }
188 }
189
190 [DllImport("QCall")]
191 [SuppressGCTransition]
192 private static extern void SetGlobalInstanceRegisteredForMarshalling(long id);
193
194 protected static void GetIUnknownImpl(out IntPtr fpQueryInterface, out IntPtr fpAddRef, out IntPtr fpRelease)
195 {
196 GetIUnknownImplInternal(out fpQueryInterface, out fpAddRef, out fpRelease);
197 }
198
199 [DllImport("QCall")]
200 private static extern void GetIUnknownImplInternal(out IntPtr fpQueryInterface, out IntPtr fpAddRef, out IntPtr fpRelease);
201
202 internal static int CallICustomQueryInterface(object customQueryInterfaceMaybe, ref Guid iid, out IntPtr ppObject)
203 {
204 if (!(customQueryInterfaceMaybe is ICustomQueryInterface customQueryInterface))
205 {
206 ppObject = IntPtr.Zero;
207 return -1;
208 }
209 return (int)customQueryInterface.GetInterface(ref iid, out ppObject);
210 }
211
212 protected unsafe abstract ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count);
213
214 protected abstract object? CreateObject(IntPtr externalComObject, CreateObjectFlags flags);
215
216 protected abstract void ReleaseObjects(IEnumerable objects);
217}
static void GetIUnknownImpl(out IntPtr fpQueryInterface, out IntPtr fpAddRef, out IntPtr fpRelease)
object GetOrCreateObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags)
IntPtr GetOrCreateComInterfaceForObject(object instance, CreateComInterfaceFlags flags)
static void SetGlobalInstanceRegisteredForTrackerSupport(long id)
static object CallCreateObject(ComWrappersScenario scenario, ComWrappers comWrappersImpl, IntPtr externalComObject, CreateObjectFlags flags)
object GetOrRegisterObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags, object wrapper, IntPtr inner)
static void CallReleaseObjects(ComWrappers comWrappersImpl, IEnumerable objects)
static int CallICustomQueryInterface(object customQueryInterfaceMaybe, ref Guid iid, out IntPtr ppObject)
static unsafe void * CallComputeVtables(ComWrappersScenario scenario, ComWrappers comWrappersImpl, object obj, CreateComInterfaceFlags flags, out int count)
void ReleaseObjects(IEnumerable objects)
static bool TryGetOrCreateComInterfaceForObjectInternal(ObjectHandleOnStack comWrappersImpl, long wrapperId, ObjectHandleOnStack instance, CreateComInterfaceFlags flags, out IntPtr retValue)
object GetOrRegisterObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags, object wrapper)
static ComWrappers s_globalInstanceForMarshalling
object? CreateObject(IntPtr externalComObject, CreateObjectFlags flags)
static void RegisterForTrackerSupport(ComWrappers instance)
static void GetIUnknownImplInternal(out IntPtr fpQueryInterface, out IntPtr fpAddRef, out IntPtr fpRelease)
static ComWrappers s_globalInstanceForTrackerSupport
unsafe ComInterfaceEntry * ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count)
static void RegisterForMarshalling(ComWrappers instance)
static bool TryGetOrCreateComInterfaceForObjectInternal(ComWrappers impl, object instance, CreateComInterfaceFlags flags, out IntPtr retValue)
static bool TryGetOrCreateObjectForComInstanceInternal(ObjectHandleOnStack comWrappersImpl, long wrapperId, IntPtr externalComObject, IntPtr innerMaybe, CreateObjectFlags flags, ObjectHandleOnStack wrapper, ObjectHandleOnStack retValue)
static void SetGlobalInstanceRegisteredForMarshalling(long id)
static bool TryGetOrCreateObjectForComInstanceInternal(ComWrappers impl, IntPtr externalComObject, IntPtr innerMaybe, CreateObjectFlags flags, object wrapperMaybe, out object retValue)
static string InvalidOperation_SuppliedInnerMustBeMarkedAggregation
Definition SR.cs:2132
static string InvalidOperation_ResetGlobalComWrappersInstance
Definition SR.cs:2130
Definition SR.cs:7
static int CompareExchange(ref int location1, int value, int comparand)
static int Increment(ref int location)
static readonly IntPtr Zero
Definition IntPtr.cs:18
static unsafe T GetInstance< T >(ComInterfaceDispatch *dispatchPtr)
static unsafe object InternalGet(IntPtr handle)
Definition GCHandle.cs:40