changeset 7:a7650e26195f tip

Added support for generating Com Callable Wrappers
author Ivo Smits
date Fri, 06 May 2011 08:12:43 +0200
parents e640ca67b819
children
files InteropCodeGen/ComInteropProxyGenerator.cs InteropCodeGen/Program.cs
diffstat 2 files changed, 328 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- a/InteropCodeGen/ComInteropProxyGenerator.cs	Fri May 06 04:02:43 2011 +0200
+++ b/InteropCodeGen/ComInteropProxyGenerator.cs	Fri May 06 08:12:43 2011 +0200
@@ -8,15 +8,67 @@
 		public TextWriter Output { get; private set; }
 		public Boolean IncludeInheritedMembers { get; set; }
 		public String TypeModifiers { get; set; }
+		public Boolean GenerateDelegates { get; set; }
+		public Boolean GenerateVTables { get; set; }
+		public Boolean GenerateProxies { get; set; }
+		public Boolean GenerateCCWs { get; set; }
 
 		public ComInteropProxyGenerator(TextWriter output) {
 			Output = output;
+			GenerateDelegates = true;
+			GenerateVTables = true;
+			GenerateProxies = true;
+			GenerateCCWs = true;
 		}
 		public void WriteLibrary(LibraryInfo lib) {
-			Output.WriteLine("interface IComProxy {");
-			Output.WriteLine("IntPtr ComPointer { get; }");
-			Output.WriteLine("void AddRef();");
-			Output.WriteLine("}");
+			if (GenerateProxies) {
+				Output.WriteLine("interface IComProxy {");
+				Output.WriteLine("IntPtr ComPointer { get; }");
+				Output.WriteLine("void AddRef();");
+				Output.WriteLine("}");
+			}
+
+			if (GenerateCCWs) {
+				Output.WriteLine("public interface IComCallableWrapper {");
+				Output.WriteLine("Guid IID { get; }");
+				Output.WriteLine("Int32 ReferenceCount { get; set; }");
+				Output.WriteLine("Object Object { get; }");
+				Output.WriteLine("IntPtr Pointer { get; }");
+				Output.WriteLine("}");
+				Output.WriteLine("public unsafe class IUnknown_CCW {");
+				Output.WriteLine("public static Dictionary<IntPtr, IComCallableWrapper> Instances = new Dictionary<IntPtr, IComCallableWrapper>();");
+				Output.WriteLine("public static IUnknown_vtable GetFunctionTable() {");
+				Output.WriteLine("IUnknown_vtable functions;");
+				Output.WriteLine("functions.AddRef = AddRef;");
+				Output.WriteLine("functions.QueryInterface = QueryInterface;");
+				Output.WriteLine("functions.Release = Release;");
+				Output.WriteLine("return functions;");
+				Output.WriteLine("}");
+				Output.WriteLine("public static HRESULT QueryInterface(IntPtr pthis, ref Guid priid, out IntPtr p) {");
+				Output.WriteLine("p = pthis;");
+				Output.WriteLine("if (Instances[pthis].IID != priid) return 1;");
+				Output.WriteLine("Instances[pthis].ReferenceCount++;");
+				Output.WriteLine("return 0;");
+				Output.WriteLine("}");
+				Output.WriteLine("public static HRESULT AddRef(IntPtr pthis) {");
+				Output.WriteLine("Instances[pthis].ReferenceCount++;");
+				Output.WriteLine("return Instances[pthis].ReferenceCount;");
+				Output.WriteLine("}");
+				Output.WriteLine("public static HRESULT Release(IntPtr pthis) {");
+				Output.WriteLine("IComCallableWrapper cw = Instances[pthis];");
+				Output.WriteLine("cw.ReferenceCount--;");
+				Output.WriteLine("if (cw.ReferenceCount == 0) {");
+				Output.WriteLine("Instances.Remove(pthis);");
+				Output.WriteLine("if (cw is IDisposable) (cw as IDisposable).Dispose();");
+				Output.WriteLine("Marshal.FreeCoTaskMem(*(IntPtr*)pthis);");
+				Output.WriteLine("Marshal.FreeCoTaskMem(pthis);");
+				Output.WriteLine("return 0;");
+				Output.WriteLine("} else {");
+				Output.WriteLine("return cw.ReferenceCount;");
+				Output.WriteLine("}");
+				Output.WriteLine("}");
+				Output.WriteLine("}");
+			}
 			foreach (KeyValuePair<String, InterfaceInfo> intf in lib.Interfaces) {
 				WriteInterface(intf.Value);
 			}
@@ -29,11 +81,17 @@
 				intfp = intfp.Extends;
 			}*/
 
-			foreach (InterfaceMemberInfo member in intf.Members) {
+			if (GenerateDelegates) WriteInterfaceDelegates(intf.Name, intf.Members);
+			if (GenerateVTables) WriteInterfaceVTableStructure(intf.Name, intf.Extends, intf.Members);
+			if (GenerateProxies) WriteInterfaceProxyClasses(intf);
+			if (GenerateCCWs) WriteInterfaceCCWClass(intf);
+		}
+		private void WriteInterfaceDelegates(String Name, IEnumerable<InterfaceMemberInfo> Members) {
+			foreach (InterfaceMemberInfo member in Members) {
 				if (member is PropertyInfo) {
 					PropertyInfo memberi = (PropertyInfo)member;
 					if (memberi.Gettable) {
-						Output.Write("{2} delegate HRESULT {0}_{1}_get_Delegate(IntPtr pThis, ", intf.Name, memberi.Name, TypeModifiers);
+						Output.Write("{2} delegate HRESULT {0}_{1}_get_Delegate(IntPtr pThis, ", Name, memberi.Name, TypeModifiers);
 						if (memberi.Type is InterfaceTypeInfo) {
 							Output.WriteLine("out IntPtr value);");
 						} else {
@@ -42,7 +100,7 @@
 						}
 					}
 					if (memberi.Settable) {
-						Output.Write("{2} delegate HRESULT {0}_{1}_set_Delegate(IntPtr pThis, ", intf.Name, memberi.Name, TypeModifiers);
+						Output.Write("{2} delegate HRESULT {0}_{1}_set_Delegate(IntPtr pThis, ", Name, memberi.Name, TypeModifiers);
 						if (memberi.Type is InterfaceTypeInfo) {
 							Output.WriteLine("IntPtr value);");
 						} else {
@@ -54,7 +112,7 @@
 					MethodInfo memberi = (MethodInfo)member;
 					Output.Write("{0} delegate ", TypeModifiers);
 					Output.Write("HRESULT ");
-					Output.Write("{0}_{1}_Delegate(IntPtr mThis", intf.Name, memberi.Name);
+					Output.Write("{0}_{1}_Delegate(IntPtr mThis", Name, memberi.Name);
 					foreach (MethodParameterInfo param in memberi.Parameters) {
 						Output.Write(", ");
 						if (param.Type is InterfaceTypeInfo) {
@@ -80,57 +138,29 @@
 					Output.WriteLine(");");
 				}
 			}
-
-			Output.WriteLine("{1} struct {0}_vtable {{", intf.Name, TypeModifiers);
-			if (intf.Extends != null) {
-				Output.WriteLine("public {0}_vtable {0};", intf.Extends.Name);
+		}
+		private void WriteInterfaceVTableStructure(String Name, InterfaceInfo Extends, IEnumerable<InterfaceMemberInfo> Members) {
+			Output.WriteLine("{1} struct {0}_vtable {{", Name, TypeModifiers);
+			if (Extends != null) {
+				Output.WriteLine("public {0}_vtable {0};", Extends.Name);
 			}
-			foreach (InterfaceMemberInfo member in intf.Members) {
+			foreach (InterfaceMemberInfo member in Members) {
 				if (member is PropertyInfo) {
 					PropertyInfo memberi = (PropertyInfo)member;
 					if (memberi.Gettable) {
-						Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_get_Delegate get_{1};", intf.Name, memberi.Name);
+						Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_get_Delegate get_{1};", Name, memberi.Name);
 					}
 					if (memberi.Settable) {
-						Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_set_Delegate set_{1};", intf.Name, memberi.Name);
+						Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_set_Delegate set_{1};", Name, memberi.Name);
 					}
 				} else if (member is MethodInfo) {
 					MethodInfo memberi = (MethodInfo)member;
-					Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_Delegate {1};", intf.Name, memberi.Name);
+					Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_Delegate {1};", Name, memberi.Name);
 				}
 			}
 			Output.WriteLine("}");
-
-			Output.WriteLine("{1} unsafe class {0}_Proxy : IComProxy, {0} {{", intf.Name, TypeModifiers);
-			Output.WriteLine("public static Guid IID = new Guid(\"{0}\");", intf.IID);
-			Output.WriteLine("private IntPtr pointer;");
-			Output.WriteLine("private {0}_vtable functions;", intf.Name);
-			Output.WriteLine("public {0}_Proxy(IntPtr p) {{", intf.Name);
-			Output.WriteLine("IUnknown_vtable ft = (IUnknown_vtable)Marshal.PtrToStructure(*(IntPtr*)p, typeof(IUnknown_vtable));");
-			Output.WriteLine("Guid IIDCopy = IID;");
-			Output.WriteLine("HRESULT hr = ft.QueryInterface(p, ref IIDCopy, out pointer);");
-			Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
-			//Output.WriteLine("ft.AddRef(p);");
-			Output.WriteLine("functions = ({0}_vtable)Marshal.PtrToStructure(*(IntPtr*)pointer, typeof({0}_vtable));", intf.Name);
-			Output.WriteLine("}");
-			Output.WriteLine("IntPtr IComProxy.ComPointer { get { return pointer; } }");
-			Output.Write("~{0}_Proxy() {{ functions", intf.Name);
-			{
-				InterfaceInfo intfp = intf;
-				while (intfp.Extends != null && intfp.Name != "IUnknown") {
-					intfp = intfp.Extends;
-					Output.Write(".{0}", intfp.Name);
-				}
-			}
-			Output.WriteLine(".Release(pointer); }");
-			WriteInterfaceMembers(intf, "");
-			Output.WriteLine("}");
 		}
-		private void WriteInterfaceMembers(InterfaceInfo intf, String ftprefix) {
-			if (intf.Extends != null) WriteInterfaceMembers(intf.Extends, ftprefix + "." + intf.Extends.Name);
-			WriteInterfaceMembers(intf.Members, ftprefix);
-		}
-		private void WriteInterfaceMembers(ICollection<InterfaceMemberInfo> members, String ftprefix) {
+		private void WriteInterfaceMembers(ICollection<InterfaceMemberInfo> members) {
 			foreach (InterfaceMemberInfo member in members) {
 				if (member is PropertyInfo) {
 					PropertyInfo memberi = (PropertyInfo)member;
@@ -138,37 +168,12 @@
 					Output.WriteLine("public {0} {1} {{", memberi.Type.Name, memberi.Name);
 					if (memberi.Gettable) {
 						Output.WriteLine("get {");
-						if (memberi.Type is InterfaceTypeInfo) {
-							Output.WriteLine("IntPtr value;");
-						} else {
-							Output.WriteLine("{0} value;", memberi.Type.Name);
-						}
-						Output.WriteLine("HRESULT hr = functions{1}.get_{0}(pointer, out value);", memberi.Name, ftprefix);
-						Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
-						if (memberi.Type is InterfaceTypeInfo) {
-							Output.WriteLine("return value == IntPtr.Zero ? null : new {0}_Proxy(value);", memberi.Type.Name);
-						} else {
-							Output.WriteLine("return value;");
-						}
+						WriteMethodComCall("get_" + memberi.Name, null, memberi.Type);
 						Output.WriteLine("}");
 					}
 					if (memberi.Settable) {
 						Output.WriteLine("set {");
-						if (memberi.Type is InterfaceTypeInfo) {
-							Output.WriteLine("IntPtr pvalue;");
-							Output.WriteLine("if (pvalue == null) {");
-							Output.WriteLine("pvalue = IntPtr.Zero;");
-							Output.WriteLine("} else if (pvalue is IComProxy) {");
-							Output.WriteLine("((IComProxy)value).AddRef();");
-							Output.WriteLine("pvalue = ((IComProxy)value).ComPointer;");
-							Output.WriteLine("} else {");
-							Output.WriteLine("pvalue = Marshal.GetIUnknownForObject(value);");
-							Output.WriteLine("}");
-							Output.WriteLine("HRESULT hr = functions{1}.set_{0}(pointer, pvalue);", memberi.Name, ftprefix);
-						} else {
-							Output.WriteLine("HRESULT hr = functions{1}.set_{0}(pointer, value);", memberi.Name, ftprefix);
-						}
-						Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
+						WriteMethodComCall("set_" + memberi.Name, new MethodParameterInfo(null, memberi.Type, true, false, false));
 						Output.WriteLine("}");
 					}
 					Output.WriteLine("}");
@@ -196,30 +201,205 @@
 						Output.Write("{0} p{1}", parameter.Type.Name, parameter.Name);
 					}
 					Output.WriteLine(") {");
-					if (memberi.ReturnType != null) {
-						if (memberi.ReturnType is InterfaceTypeInfo) {
-							Output.WriteLine("IntPtr retval;");
+
+					WriteMethodComCall(memberi.Name, memberi.Parameters, memberi.ReturnType);
+
+					Output.WriteLine("}");
+				}
+			}
+		}
+		private void WriteMethodComCall(String fname, params MethodParameterInfo[] parameters) {
+			WriteMethodComCall(fname, (IEnumerable<MethodParameterInfo>)parameters, null);
+		}
+		private void WriteMethodComCall(String fname, IEnumerable<MethodParameterInfo> parameters, TypeInfo returnType) {
+			if (returnType == null) {
+			} else if (returnType is InterfaceTypeInfo) {
+				Output.WriteLine("IntPtr retval;");
+			} else {
+				Output.WriteLine("{0} retval;", returnType.Name);
+			}
+
+			if (parameters != null) foreach (MethodParameterInfo parameter in parameters) {
+					if (parameter.Type is InterfaceTypeInfo) {
+						String pname = parameter.Name;
+						if (pname == null) {
+							pname = "value";
 						} else {
-							Output.WriteLine("{0} retval;", memberi.ReturnType.Name);
+							pname = "p" + pname;
+						}
+						Output.WriteLine("IntPtr l{0};", pname);
+						if (parameter.Input) {
+							Output.WriteLine("if ({0} == null) {{", pname);
+							Output.WriteLine("l{0} = IntPtr.Zero;", pname);
+							Output.WriteLine("}} else if ({0} is IComProxy) {{", pname);
+							Output.WriteLine("((IComProxy){0}).AddRef();", pname);
+							Output.WriteLine("l{0} = ((IComProxy){0}).ComPointer;", pname);
+							Output.WriteLine("} else {");
+							if (parameter.Type.Name == "IFramebuffer") {
+								Output.WriteLine("l{0} = (new {1}_CCW({0})).Pointer;", pname, parameter.Type.Name);
+							} else {
+								Output.WriteLine("l{0} = Marshal.GetIUnknownForObject({0});", pname);
+							}
+							Output.WriteLine("}");
 						}
 					}
-					foreach (MethodParameterInfo parameter in memberi.Parameters) {
-						if (parameter.Type is InterfaceTypeInfo) {
-							Output.WriteLine("IntPtr lp{0};", parameter.Name);
-							if (parameter.Input) {
-								Output.WriteLine("if (p{0} == null) {{", parameter.Name);
-								Output.WriteLine("lp{0} = IntPtr.Zero;", parameter.Name);
-								Output.WriteLine("}} else if (p{0} is IComProxy) {{", parameter.Name);
-								Output.WriteLine("((IComProxy)p{0}).AddRef();", parameter.Name);
-								Output.WriteLine("lp{0} = ((IComProxy)p{0}).ComPointer;", parameter.Name);
-								Output.WriteLine("} else {");
-								Output.WriteLine("lp{0} = Marshal.GetIUnknownForObject(p{0});", parameter.Name);
-								Output.WriteLine("}");
-							}
+				}
+
+			Output.Write("HRESULT hr = functions.{0}(Pointer", fname);
+			if (parameters != null) foreach (MethodParameterInfo parameter in parameters) {
+					Output.Write(", ");
+					if (parameter.Output && !parameter.Input) {
+						Output.Write("out ");
+					} else if (parameter.Reference) {
+						Output.Write("ref ");
+					}
+					String pname = parameter.Name;
+					if (pname == null) {
+						pname = "value";
+					} else {
+						pname = "p" + pname;
+					}
+					if (parameter.Type is InterfaceTypeInfo) {
+						pname = "l" + pname;
+					}
+					Output.Write(pname);
+				}
+			if (returnType != null) {
+				Output.Write(", out retval");
+			}
+			Output.WriteLine(");");
+			Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
+
+			if (parameters != null) foreach (MethodParameterInfo parameter in parameters) {
+					if (parameter.Type is InterfaceTypeInfo) {
+						if (parameter.Output) {
+							Output.WriteLine("p{0} = lp{0} == IntPtr.Zero ? null : new {1}_Proxy(lp{0});", parameter.Name, parameter.Type.Name);
 						}
 					}
+				}
 
-					Output.Write("HRESULT hr = functions{1}.{0}(pointer", memberi.Name, ftprefix);
+			if (returnType == null) {
+			} else if (returnType is InterfaceTypeInfo) {
+				Output.WriteLine("return retval == IntPtr.Zero ? null : new {0}_Proxy(retval);", returnType.Name);
+			} else {
+				Output.WriteLine("return retval;");
+			}
+		}
+		private void WriteInterfaceProxyClasses(InterfaceInfo intf) {
+			if (intf.Extends != null) {
+				Output.WriteLine("{1} unsafe class {0}_Proxy : {2}_Proxy, {0} {{", intf.Name, TypeModifiers, intf.Extends.Name);
+				Output.WriteLine("public new static Guid IID = new Guid(\"{0}\");", intf.IID);
+			} else {
+				Output.WriteLine("{1} unsafe class {0}_Proxy : IComProxy, {0} {{", intf.Name, TypeModifiers);
+				Output.WriteLine("public IntPtr Pointer { get; protected set; }");
+				Output.WriteLine("IntPtr IComProxy.ComPointer { get { return Pointer; } }");
+				Output.WriteLine("public static Guid IID = new Guid(\"{0}\");", intf.IID);
+			}
+			Output.WriteLine("private {0}_vtable functions;", intf.Name);
+
+			Output.WriteLine("public {0}_Proxy(IntPtr p) : this(p, IID) {{ }}", intf.Name);
+
+			if (intf.Extends != null) {
+				Output.WriteLine("public {0}_Proxy(IntPtr p, Guid iid) : base(p, iid) {{", intf.Name, intf.Extends.Name);
+				Output.WriteLine("functions = ({0}_vtable)Marshal.PtrToStructure(*(IntPtr*)Pointer, typeof({0}_vtable));", intf.Name);
+				Output.WriteLine("}");
+			} else {
+				Output.WriteLine("public {0}_Proxy(IntPtr p, Guid iid) {{", intf.Name);
+				Output.WriteLine("IUnknown_vtable ft = (IUnknown_vtable)Marshal.PtrToStructure(*(IntPtr*)p, typeof(IUnknown_vtable));");
+				Output.WriteLine("HRESULT hr = ft.QueryInterface(p, ref iid, out p);");
+				Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
+				Output.WriteLine("ft.AddRef(p);");
+				Output.WriteLine("Pointer = p;");
+				Output.WriteLine("functions = ({0}_vtable)Marshal.PtrToStructure(*(IntPtr*)Pointer, typeof({0}_vtable));", intf.Name);
+				Output.WriteLine("}");
+			}
+
+			if (intf.Name == "IUnknown") {
+				Output.Write("~{0}_Proxy() {{ functions.Release(Pointer); }}", intf.Name);
+			}
+
+			WriteInterfaceMembers(intf.Members);
+			Output.WriteLine("}");
+		}
+		private void WriteInterfaceCCWClass(InterfaceInfo intf) {
+			if (intf.Extends == null) return;
+			Boolean writeMembers = true;
+			if (intf.Name == "IDispatch" || intf.Name == "IErrorInfo") writeMembers = false;
+			Output.WriteLine("public unsafe class {0}_CCW : IComCallableWrapper {{", intf.Name);
+			Output.WriteLine("public IntPtr Pointer { get; protected set; }");
+			Output.WriteLine("public Object Object { get; private set; }");
+			Output.WriteLine("public Int32 ReferenceCount { get; set; }");
+			Output.WriteLine("Guid IComCallableWrapper.IID {{ get {{ return {0}_Proxy.IID; }} }}", intf.Name);
+
+			Output.WriteLine("public static {0}_vtable GetFunctionTable() {{", intf.Name);
+			Output.WriteLine("{0}_vtable functions = new {0}_vtable();", intf.Name);
+			if (writeMembers) foreach (InterfaceMemberInfo member in intf.Members) {
+				if (member is PropertyInfo) {
+					PropertyInfo memberi = (PropertyInfo)member;
+					if (memberi.Gettable) Output.WriteLine("functions.get_{0} = get_{0};", memberi.Name);
+					if (memberi.Settable) Output.WriteLine("functions.set_{0} = set_{0};", memberi.Name);
+				} else if (member is MethodInfo) {
+					MethodInfo memberi = (MethodInfo)member;
+					Output.WriteLine("functions.{0} = {0};", memberi.Name);
+				}
+			}
+			if (intf.Extends != null) Output.WriteLine("functions.{0} = {0}_CCW.GetFunctionTable();", intf.Extends.Name);
+			Output.WriteLine("return functions;");
+			Output.WriteLine("}");
+
+			Output.WriteLine("public {0}_CCW({0} p) {{", intf.Name);
+			Output.WriteLine("Object = p;");
+			Output.WriteLine("Pointer = Marshal.AllocCoTaskMem(IntPtr.Size);");
+			Output.WriteLine("*(IntPtr*)Pointer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof({0}_vtable)));", intf.Name);
+			Output.WriteLine("Marshal.StructureToPtr(GetFunctionTable(), *(IntPtr*)Pointer, false);");
+			Output.WriteLine("IUnknown_CCW.Instances[Pointer] = this;");
+			Output.WriteLine("}");
+			Output.WriteLine("private static {0} GetInstance(IntPtr pthis) {{", intf.Name);
+			Output.WriteLine("return ({0})IUnknown_CCW.Instances[pthis].Object;", intf.Name);
+			Output.WriteLine("}");
+
+			if (writeMembers) foreach (InterfaceMemberInfo member in intf.Members) {
+				if (member is PropertyInfo) {
+					PropertyInfo memberi = (PropertyInfo)member;
+					if (memberi.Gettable) {
+						Output.Write("private static HRESULT get_{0}(IntPtr pthis, out ", memberi.Name);
+						if (memberi.Type is InterfaceTypeInfo) {
+							Output.Write("IntPtr");
+						} else {
+							Output.Write(memberi.Type.Name);
+						}
+						Output.WriteLine(" ret) {");
+						if (memberi.Type is InterfaceTypeInfo) {
+							Output.WriteLine("{1} iret = GetInstance(pthis).{0};", memberi.Name, memberi.Type.Name);
+							Output.WriteLine("if (iret == null) { ret = IntPtr.Zero; } else if (iret is IComProxy) { ret = ((IComProxy)iret).ComPointer; } else {");
+							Output.WriteLine("ret = (new {0}_CCW(iret)).Pointer; }}", memberi.Type.Name);
+						} else {
+							Output.WriteLine("ret = GetInstance(pthis).{0};", memberi.Name);
+						}
+						Output.WriteLine("return 0;");
+						Output.WriteLine("}");
+					}
+					if (memberi.Settable) {
+						Output.Write("private static HRESULT set_{0}(IntPtr pthis, ", memberi.Name);
+						if (memberi.Type is InterfaceTypeInfo) {
+							Output.Write("IntPtr");
+						} else {
+							Output.Write(memberi.Type.Name);
+						}
+						Output.WriteLine(" value) {");
+						if (memberi.Type is InterfaceTypeInfo) {
+							Output.WriteLine("{0} ivalue;", memberi.Type.Name);
+							Output.WriteLine("if (value == IntPtr.Zero) { ivalue = null; } else if (IUnknown_CCW.Instances.ContainsKey(value)) { ivalue = ({0})(IUnknown_CCW.Instances[value].Object) } else { ivalue = new {0}_CCW(value); }", memberi.Type.Name);
+							Output.WriteLine("GetInstance(pthis).{0} = ivalue;", memberi.Name);
+						} else {
+							Output.WriteLine("GetInstance(pthis).{0} = value;", memberi.Name);
+						}
+						Output.WriteLine("return 0;");
+						Output.WriteLine("}");
+					}
+				} else if (member is MethodInfo) {
+					MethodInfo memberi = (MethodInfo)member;
+					Output.Write("private static HRESULT {0}(IntPtr pthis", memberi.Name);
 					foreach (MethodParameterInfo parameter in memberi.Parameters) {
 						Output.Write(", ");
 						if (parameter.Output && !parameter.Input) {
@@ -228,34 +408,80 @@
 							Output.Write("ref ");
 						}
 						if (parameter.Type is InterfaceTypeInfo) {
-							Output.Write("lp{0}", parameter.Name);
+							Output.Write("IntPtr");
 						} else {
-							Output.Write("p{0}", parameter.Name);
+							Output.Write(parameter.Type.Name);
 						}
+						Output.Write(" p{0}", parameter.Name);
 					}
-					if (memberi.ReturnType != null) Output.Write(", out retval");
-					Output.WriteLine(");");
-					Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
+					if (memberi.ReturnType != null) {
+						Output.Write(", out ");
+						if (memberi.ReturnType is InterfaceTypeInfo) {
+							Output.Write("IntPtr");
+						} else {
+							Output.Write(memberi.ReturnType.Name);
+						}
+						Output.Write(" retval");
+					}
+					Output.WriteLine(") {");
 
 					foreach (MethodParameterInfo parameter in memberi.Parameters) {
 						if (parameter.Type is InterfaceTypeInfo) {
-							if (parameter.Output) {
-								Output.WriteLine("p{0} = lp{0} == IntPtr.Zero ? null : new {1}_Proxy(lp{0});", parameter.Name, parameter.Type.Name);
+							Output.WriteLine("{0} i{1};", parameter.Type.Name, parameter.Name);
+							if (parameter.Input) {
+								Output.WriteLine("if (p{0} == IntPtr.Zero) {{ i{0} = null; }} else if (IUnknown_CCW.Instances.ContainsKey(p{0})) {{ i{0} = ({1})(IUnknown_CCW.Instances[p{0}].Object); }} else {{ i{0} = new {1}_Proxy(p{0}); }}", parameter.Name, parameter.Type.Name);
 							}
 						}
 					}
 
 					if (memberi.ReturnType != null) {
 						if (memberi.ReturnType is InterfaceTypeInfo) {
-							Output.WriteLine("return retval == IntPtr.Zero ? null : new {0}_Proxy(retval);", memberi.ReturnType.Name);
+							Output.Write("{0} iretval = ", memberi.ReturnType.Name);
 						} else {
-							Output.WriteLine("return retval;");
+							Output.Write("retval = ");
 						}
 					}
+					Output.Write("GetInstance(pthis).{0}(", memberi.Name);
+					bool first = true;
+					foreach (MethodParameterInfo parameter in memberi.Parameters) {
+						if (first) {
+							first = false;
+						} else {
+							Output.Write(", ");
+						}
+						if (parameter.Output && !parameter.Input) {
+							Output.Write("out ");
+						} else if (parameter.Reference) {
+							Output.Write("ref ");
+						}
+						if (parameter.Type is InterfaceTypeInfo) {
+							Output.Write("i{0}", parameter.Name);
+						} else {
+							Output.Write("p{0}", parameter.Name);
+						}
+					}
+					Output.WriteLine(");");
+
+					foreach (MethodParameterInfo parameter in memberi.Parameters) {
+						if (parameter.Type is InterfaceTypeInfo) {
+							if (parameter.Output || parameter.Reference) {
+								Output.WriteLine("if (i{0} == null) {{ p{0} = IntPtr.Zero; }} else if (i{0} is IComProxy) {{ p{0} = ((IComProxy)i{0}).ComPointer; }} else {{", parameter.Name);
+								Output.WriteLine("p{1} = (new {0}_CCW(i{1})).Pointer; }}", parameter.Type.Name, parameter.Name);
+							}
+						}
+					}
+					if (memberi.ReturnType is InterfaceTypeInfo) {
+						Output.WriteLine("if (iretval == null) { retval = IntPtr.Zero; } else if (iretval is IComProxy) { retval = ((IComProxy)iretval).ComPointer; } else {");
+						Output.WriteLine("retval = (new {0}_CCW(iretval)).Pointer; }}", memberi.ReturnType.Name);
+					}
+
+					Output.WriteLine("return 0;");
 					Output.WriteLine("}");
 				}
 			}
+			Output.WriteLine("}");
 		}
+
 		public void WriteTypeComMarshalAttributes(TypeInfo type, String paramType) {
 			if (type == null) return;
 			String MarshalAs = null;
@@ -271,4 +497,4 @@
 			}
 		}
 	}
-}
+}
\ No newline at end of file
--- a/InteropCodeGen/Program.cs	Fri May 06 04:02:43 2011 +0200
+++ b/InteropCodeGen/Program.cs	Fri May 06 08:12:43 2011 +0200
@@ -65,6 +65,7 @@
 			using (TextWriter outfile = File.CreateText("Proxy.cs")) {
 				outfile.WriteLine("using System;");
 				outfile.WriteLine("using System.Runtime.InteropServices;");
+				outfile.WriteLine("using System.Collections.Generic;");
 				outfile.WriteLine("using HRESULT = System.Int32;");
 				outfile.WriteLine("namespace VirtualBox {");
 				ComInteropProxyGenerator igen = new ComInteropProxyGenerator(outfile);