5 // Sebastien Pouliot <sebastien@ximian.com>
6 // Kornél Pál <http://www.kornelpal.hu/>
7 // Jonathan Chambers <joncham@gmail.com>
9 // Copyright (C) 2004 Novell (http://www.novell.com)
10 // Copyright (C) 2005 Kornél Pál
11 // Copyright (C) 2006 Jonathan Chambers
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.Runtime.InteropServices;
38 using System.Runtime.CompilerServices;
42 // This is a private class that is used as a generic wrapper class
43 // for COM objects that have no specific wrapper class.
45 // It has no public methods, it's functionality is exposed trough
46 // System.Runtime.InteropServices.Marshal class and can be casted to
47 // any interface that is implemented by the wrapped COM object.
49 // This class is referenced in .NET Framework SDK Documentation so
50 // many times that obj.GetType().FullName == "System.__ComObject" and
51 // Type.GetType("System.__ComObject") may be used.
53 internal class __ComObject : MarshalByRefObject
55 #region Sync with object-internals.h
59 // this is used internally and for the the methods
60 // Marshal.GetComObjectData and Marshal.SetComObjectData
64 static bool coinitialized;
66 [MethodImplAttribute (MethodImplOptions.InternalCall)]
67 internal extern void Finalizer ();
71 ComInteropProxy.ReleaseComObject (this);
77 // call CoInitialize once per thread
79 CoInitialize (IntPtr.Zero);
83 hashtable = new Hashtable ();
87 int hr = CoCreateInstance (GetCLSID (t), IntPtr.Zero, 0x1 | 0x4 | 0x10, IID_IUnknown, out ppv);
88 Marshal.ThrowExceptionForHR (hr);
93 internal __ComObject (Type t)
95 // call CoInitialize once per thread
97 CoInitialize (IntPtr.Zero);
101 hashtable = new Hashtable ();
104 int hr = CoCreateInstance (GetCLSID (t), IntPtr.Zero, 0x1 | 0x4 | 0x10, IID_IUnknown, out ppv);
105 Marshal.ThrowExceptionForHR (hr);
110 private Guid GetCLSID (Type t)
115 // look at supertypes
116 Type super = t.BaseType;
117 while (super != typeof (object)) {
120 super = super.BaseType;
122 throw new COMException ("Could not find base COM type for type " + t.ToString());
125 internal __ComObject (IntPtr pItf)
127 hashtable = new Hashtable ();
129 Guid iid = IID_IUnknown;
130 int hr = Marshal.QueryInterface (pItf, ref iid, out ppv);
131 Marshal.ThrowExceptionForHR (hr);
135 public Hashtable Hashtable
143 [MethodImplAttribute (MethodImplOptions.InternalCall)]
144 internal static extern __ComObject CreateRCW (Type t);
146 [MethodImplAttribute (MethodImplOptions.InternalCall)]
147 extern void SetIUnknown (IntPtr t);
149 [MethodImplAttribute (MethodImplOptions.InternalCall)]
150 extern IntPtr GetIUnknown ();
152 [MethodImplAttribute (MethodImplOptions.InternalCall)]
153 extern IntPtr FindInterface (Type t);
155 [MethodImplAttribute (MethodImplOptions.InternalCall)]
156 extern void CacheInterface (Type t, IntPtr pItf);
158 internal IntPtr GetInterface(Type t)
160 // this is needed later and checks to see if we are
162 IntPtr pUnk = IUnknown;
163 IntPtr pItf = FindInterface (t);
164 if (pItf != IntPtr.Zero) {
170 int hr = Marshal.QueryInterface (pUnk, ref iid, out ppv);
171 Marshal.ThrowExceptionForHR (hr);
172 CacheInterface (t, ppv);
176 internal IntPtr IUnknown
180 IntPtr pUnk = GetIUnknown();
181 if (pUnk == IntPtr.Zero)
182 throw new InvalidComObjectException ("COM object that has been separated from its underlying RCW cannot be used.");
187 internal IntPtr IDispatch
191 IntPtr pUnk = GetInterface (typeof (IDispatch));
192 if (pUnk == IntPtr.Zero)
193 throw new InvalidComObjectException ("COM object that has been separated from its underlying RCW cannot be used.");
198 internal static Guid IID_IUnknown
202 return new Guid("00000000-0000-0000-C000-000000000046");
206 internal static Guid IID_IDispatch
210 return new Guid ("00020400-0000-0000-C000-000000000046");
214 public override bool Equals (object obj)
219 __ComObject co = obj as __ComObject;
220 if ((object)co == null)
223 return (IUnknown == co.IUnknown);
226 public override int GetHashCode ()
228 // not what MS seems to do,
229 // but IUnknown is identity in COM
230 return IUnknown.ToInt32 ();
233 [DllImport ("ole32.dll", CallingConvention = CallingConvention.StdCall)]
234 static extern int CoInitialize (IntPtr pvReserved);
236 [DllImport ("ole32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, PreserveSig = true)]
237 static extern int CoCreateInstance (
238 [In, MarshalAs (UnmanagedType.LPStruct)] Guid rclsid,
241 [In, MarshalAs (UnmanagedType.LPStruct)] Guid riid,