{
// called from unmanaged code after .ctor is invoked
// we need .ctor to create unmanaged object and thus IUnknown property value
- if (FindProxy(com_object.IUnknown) == null)
+ if (FindProxy (com_object.IUnknown) == null)
AddProxy (com_object.IUnknown, this);
else
System.Threading.Interlocked.Increment (ref ref_count);
internal ComInteropProxy (IntPtr pUnk, Type t)
: base (t)
{
- com_object = new __ComObject (pUnk);
+ com_object = new __ComObject (pUnk, this);
CacheProxy ();
}
// already known, a cached proxy will be returned.
internal static ComInteropProxy CreateProxy (Type t)
{
- ComInteropProxy proxy = new ComInteropProxy (t);
- proxy.com_object.Initialize (t);
-
- ComInteropProxy cachedProxy = FindProxy (proxy.com_object.IUnknown);
+ IntPtr iunknown = __ComObject.CreateIUnknown (t);
+ ComInteropProxy proxy;
+ ComInteropProxy cachedProxy = FindProxy (iunknown);
if (cachedProxy != null) {
// check that the COM type of the cached proxy matches
// the requested type. See 2nd part of bug #520437.
Type cachedType = cachedProxy.com_object.GetType ();
if (cachedType != t)
throw new InvalidCastException (String.Format ("Unable to cast object of type '{0}' to type '{1}'.", cachedType, t));
- return cachedProxy;
+ proxy = cachedProxy;
+ Marshal.Release (iunknown);
+ } else {
+ proxy = new ComInteropProxy (t);
+ proxy.com_object.Initialize (iunknown, proxy);
}
return proxy;
}
#endregion
#pragma warning restore 169
+ // keep a reference to the proxy so it doesn't get garbage collected before the RCW
+ ComInteropProxy proxy;
+
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal static extern __ComObject CreateRCW (Type t);
~__ComObject ()
{
- if (synchronization_context != null)
- synchronization_context.Post ((state) => ReleaseInterfaces (), this);
- else
- ReleaseInterfaces ();
+ if (hash_table != IntPtr.Zero) {
+ if (synchronization_context != null)
+ synchronization_context.Post ((state) => ReleaseInterfaces (), this);
+ else
+ ReleaseInterfaces ();
+ }
+ proxy = null;
}
public __ComObject ()
Initialize (t);
}
- internal __ComObject (IntPtr pItf)
+ internal __ComObject (IntPtr pItf, ComInteropProxy p)
{
+ proxy = p;
InitializeApartmentDetails ();
Guid iid = IID_IUnknown;
int hr = Marshal.QueryInterface (pItf, ref iid, out iunknown);
Marshal.ThrowExceptionForHR (hr);
}
+ internal void Initialize (IntPtr pUnk, ComInteropProxy p)
+ {
+ proxy = p;
+ InitializeApartmentDetails ();
+ iunknown = pUnk;
+ }
+
internal void Initialize (Type t)
{
InitializeApartmentDetails ();
if (iunknown != IntPtr.Zero)
return;
+ iunknown = CreateIUnknown (t);
+ }
+
+ internal static IntPtr CreateIUnknown(Type t)
+ {
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (t.TypeHandle);
-
+
+ IntPtr iunknown;
ObjectCreationDelegate ocd = ExtensibleClassFactory.GetObjectCreationCallback (t);
if (ocd != null) {
iunknown = ocd (IntPtr.Zero);
int hr = CoCreateInstance (GetCLSID (t), IntPtr.Zero, 0x1 | 0x4 | 0x10, IID_IUnknown, out iunknown);
Marshal.ThrowExceptionForHR (hr);
}
+
+ return iunknown;
}
private void InitializeApartmentDetails ()