changeset 0:e1ec7bf71313

Initial commit
author Ivo Smits
date Wed, 04 May 2011 00:59:43 +0200
parents
children 55ca098c88d0
files InteropCodeGen/InteropCodeGen.csproj InteropCodeGen/Properties/AssemblyInfo.cs InteropCodeGen/gendotnet.cs VBoxDotNet.sln VBoxFrontend/Display.Designer.cs VBoxFrontend/Display.cs VBoxFrontend/Display.resx VBoxFrontend/Framebuffer.cs VBoxFrontend/Program.cs VBoxFrontend/ProgramLoader.cs VBoxFrontend/Properties/AssemblyInfo.cs VBoxFrontend/Properties/Resources.Designer.cs VBoxFrontend/Properties/Resources.resx VBoxFrontend/VBoxEventListener.cs VBoxFrontend/VBoxFrontend.csproj VBoxFrontend/VBoxKeyboardHelper.cs VBoxFrontend/VBoxXPCOM.cs
diffstat 17 files changed, 1947 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InteropCodeGen/InteropCodeGen.csproj	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{9C96A3C0-1673-457A-BF8D-CB97B44533A3}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>VBoxSDK</RootNamespace>
+    <AssemblyName>VBoxSDK</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="gendotnet.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InteropCodeGen/Properties/AssemblyInfo.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("VBoxSDK")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("VBoxSDK")]
+[assembly: AssemblyCopyright("Copyright ©  2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fd486bf3-6c0d-457c-aeee-69f138d6eef9")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InteropCodeGen/gendotnet.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,407 @@
+//+reference System.dll
+//+reference System.Xml.dll
+using System;
+using System.Xml.XPath;
+using System.IO;
+using System.Collections.Generic;
+class Program {
+	enum ParameterType {
+		In,
+		Out,
+		Reference,
+		Return,
+		Param,
+	}
+	class TypeInfo {
+		public String Name { get; private set; }
+		public String[] Attributes { get; private set; }
+		//public Boolean InputOnly { get; private set; }
+		public String Members { get; set; }
+
+		public TypeInfo(String name, params String[] attributes) {
+			this.Name = name;
+			this.Attributes = attributes;
+		}
+		/*public TypeInfo(String name, bool inputOnly, params String[] attributes)
+			: this(name, attributes) {
+			this.InputOnly = inputOnly;
+		}*/
+		/*public static TypeInfo CreateInterfaceWithMembers(String name, String members) {
+			TypeInfo ret = new TypeInfo(name, "MarshalAs(UnmanagedType.Interface)");
+			ret.Members = members;
+			return ret;
+		}*/
+		//Todo: if attribute mod="string"/"ptr" ...
+		public void WriteDeclaration(TextWriter o, ParameterType vartype) {
+			WriteAttributes(o, vartype);
+			o.Write(Name);
+		}
+		public void WriteAttributes(TextWriter o, ParameterType vartype) {
+			//if (InputOnly && vartype != ParameterType.In) {
+			foreach (String attribute in Attributes) {
+				o.Write("[");
+				if (vartype == ParameterType.Return) o.Write("return: ");
+				else if (vartype == ParameterType.Param) o.Write("param: ");
+				o.Write(attribute);
+				o.Write("] ");
+			}
+			if (vartype == ParameterType.Out) o.Write("out ");
+			else if (vartype == ParameterType.Reference) o.Write("ref ");
+		}
+	}
+	static Dictionary<String, TypeInfo> Types = new Dictionary<string, TypeInfo>();
+	static void InitTypes() {
+		Types.Add("short", new TypeInfo("Int16"));
+		Types.Add("unsigned short", new TypeInfo("UInt16"));
+		Types.Add("unsigned long", new TypeInfo("UInt32"));
+		Types.Add("long long", new TypeInfo("Int64"));
+		Types.Add("long", new TypeInfo("Int32"));
+		Types.Add("octet", new TypeInfo("Byte"));
+		Types.Add("unsigned long long", new TypeInfo("UInt32"));
+		//Types.Add("boolean", new TypeInfo("Boolean", "MarshalAs(UnmanagedType.Bool)"));
+		Types.Add("boolean", new TypeInfo("Int32"));
+		Types.Add("wstring", new TypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)"));
+		//Types.Add("uuid", new TypeInfo("Guid", true, "MarshalAs(UnmanagedType.LPStruct)"));
+		Types.Add("uuid", new TypeInfo("Guid", "MarshalAs(UnmanagedType.LPStruct)"));
+
+		Types.Add("IMachine", new TypeInfo("IMachine", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("ISession", new TypeInfo("ISession", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IVirtualBox", new TypeInfo("IVirtualBox", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IHost", new TypeInfo("IHost", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IConsole", new TypeInfo("IConsole", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("ISystemProperties", new TypeInfo("ISystemProperties", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IProgress", new TypeInfo("IProgress", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IDisplay", new TypeInfo("IDisplay", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IMouse", new TypeInfo("IMouse", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IKeyboard", new TypeInfo("IKeyboard", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IFramebuffer", new TypeInfo("IFramebuffer", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IFramebufferOverlay", new TypeInfo("IFramebufferOverlay", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IMachineDebugger", new TypeInfo("IMachineDebugger", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IVirtualBoxErrorInfo", new TypeInfo("IVirtualBoxErrorInfo", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IEventSource", new TypeInfo("IEventSource", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IEventListener", new TypeInfo("IEventListener", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IEventContext", new TypeInfo("IEventContext", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IConsoleCallback", new TypeInfo("IConsoleCallback", "MarshalAs(UnmanagedType.Interface)"));
+		Types.Add("IEvent", new TypeInfo("IEvent", "MarshalAs(UnmanagedType.Interface)"));
+
+		Types.Add("LockType", new TypeInfo("LockType"));
+		Types.Add("MediumVariant", new TypeInfo("MediumVariant"));
+		Types.Add("AccessMode", new TypeInfo("AccessMode"));
+		Types.Add("NATProtocol", new TypeInfo("NATProtocol"));
+		Types.Add("FirmwareType", new TypeInfo("FirmwareType"));
+		Types.Add("StorageControllerType", new TypeInfo("StorageControllerType"));
+		Types.Add("StorageBus", new TypeInfo("StorageBus"));
+		Types.Add("SessionType", new TypeInfo("SessionType"));
+		Types.Add("SessionState", new TypeInfo("SessionState"));
+		Types.Add("USBDeviceState", new TypeInfo("USBDeviceState"));
+		Types.Add("USBDeviceFilterAction", new TypeInfo("USBDeviceFilterAction"));
+		Types.Add("AudioControllerType", new TypeInfo("AudioControllerType"));
+		Types.Add("AudioDriverType", new TypeInfo("AudioDriverType"));
+		Types.Add("VRDPAuthType", new TypeInfo("VRDPAuthType"));
+		Types.Add("MachineState", new TypeInfo("MachineState"));
+		Types.Add("NetworkAdapterType", new TypeInfo("NetworkAdapterType"));
+		Types.Add("NetworkAttachmentType", new TypeInfo("NetworkAttachmentType"));
+		Types.Add("PortMode", new TypeInfo("PortMode"));
+		Types.Add("DeviceType", new TypeInfo("DeviceType"));
+		Types.Add("MediumState", new TypeInfo("MediumState"));
+		Types.Add("MediumType", new TypeInfo("MediumType"));
+		Types.Add("HostNetworkInterfaceType", new TypeInfo("HostNetworkInterfaceType"));
+		Types.Add("DeviceActivity", new TypeInfo("DeviceActivity"));
+		Types.Add("HostNetworkInterfaceMediumType", new TypeInfo("HostNetworkInterfaceMediumType"));
+		Types.Add("HostNetworkInterfaceStatus", new TypeInfo("HostNetworkInterfaceStatus"));
+		Types.Add("ProcessorFeature", new TypeInfo("ProcessorFeature"));
+		Types.Add("VFSType", new TypeInfo("VFSType"));
+		Types.Add("BIOSBootMenuMode", new TypeInfo("BIOSBootMenuMode"));
+		Types.Add("VirtualSystemDescriptionType", new TypeInfo("VirtualSystemDescriptionType"));
+		Types.Add("VirtualSystemDescriptionValueType", new TypeInfo("VirtualSystemDescriptionValueType"));
+		Types.Add("KeyboardHidType", new TypeInfo("KeyboardHidType"));
+		Types.Add("ClipboardMode", new TypeInfo("ClipboardMode"));
+		Types.Add("PointingHidType", new TypeInfo("PointingHidType"));
+		Types.Add("CPUPropertyType", new TypeInfo("CPUPropertyType"));
+		Types.Add("HWVirtExPropertyType", new TypeInfo("HWVirtExPropertyType"));
+		Types.Add("Scope", new TypeInfo("Scope"));
+		Types.Add("ChipsetType", new TypeInfo("ChipsetType"));
+		Types.Add("FaultToleranceState", new TypeInfo("FaultToleranceState"));
+		Types.Add("BandwidthGroupType", new TypeInfo("BandwidthGroupType"));
+		Types.Add("VBoxEventType", new TypeInfo("VBoxEventType"));
+		Types.Add("GuestMonitorChangedEventType", new TypeInfo("GuestMonitorChangedEventType"));
+		Types.Add("AuthType", new TypeInfo("AuthType"));
+		Types.Add("NetworkAdapterPromiscModePolicy", new TypeInfo("NetworkAdapterPromiscModePolicy"));
+		Types.Add("ExecuteProcessStatus", new TypeInfo("ExecuteProcessStatus"));
+		Types.Add("AdditionsRunLevelType", new TypeInfo("AdditionsRunLevelType"));
+		Types.Add("AdditionsFacilityStatus", new TypeInfo("AdditionsFacilityStatus"));
+		Types.Add("AdditionsFacilityType", new TypeInfo("AdditionsFacilityType"));
+		Types.Add("AdditionsFacilityClass", new TypeInfo("AdditionsFacilityClass"));
+		Types.Add("CleanupMode", new TypeInfo("CleanupMode"));
+		Types.Add("DataType", new TypeInfo("DataType"));
+
+		Types.Add("IBandwidthControl", new TypeInfo("IntPtr"));
+		Types.Add("IVRDEServerInfo", new TypeInfo("IntPtr"));
+		Types.Add("IAdditionsFacility", new TypeInfo("IntPtr"));
+		Types.Add("IExtPackPlugIn", new TypeInfo("IntPtr"));
+		Types.Add("IExtPackFile", new TypeInfo("IntPtr"));
+		Types.Add("IExtPack", new TypeInfo("IntPtr"));
+		Types.Add("IBIOSSettings", new TypeInfo("IntPtr"));
+		Types.Add("IVFSExplorer", new TypeInfo("IntPtr"));
+		Types.Add("IUSBController", new TypeInfo("IntPtr"));
+		Types.Add("IStorageController", new TypeInfo("IntPtr"));
+		Types.Add("IVRDPServer", new TypeInfo("IntPtr"));
+		Types.Add("ISnapshot", new TypeInfo("IntPtr"));
+		Types.Add("INATEngine", new TypeInfo("IntPtr"));
+		Types.Add("IUSBDeviceFilter", new TypeInfo("IntPtr"));
+		Types.Add("IMediumAttachment", new TypeInfo("IntPtr"));
+		Types.Add("IUSBDevice", new TypeInfo("IntPtr"));
+		Types.Add("IParallelPort", new TypeInfo("IntPtr"));
+		Types.Add("ISerialPort", new TypeInfo("IntPtr"));
+		Types.Add("INetworkAdapter", new TypeInfo("IntPtr"));
+		Types.Add("IMedium", new TypeInfo("IntPtr"));
+		Types.Add("IGuestOSType", new TypeInfo("IntPtr"));
+		Types.Add("ISharedFolder", new TypeInfo("IntPtr"));
+		Types.Add("IPerformanceCollector", new TypeInfo("IntPtr"));
+		Types.Add("IDHCPServer", new TypeInfo("IntPtr"));
+		Types.Add("IAppliance", new TypeInfo("IntPtr"));
+		Types.Add("IVirtualBoxCallback", new TypeInfo("IntPtr"));
+		Types.Add("IPerformanceMetric", new TypeInfo("IntPtr"));
+		Types.Add("IMediumFormat", new TypeInfo("IntPtr"));
+		Types.Add("IHostUSBDevice", new TypeInfo("IntPtr"));
+		Types.Add("IHostNetworkInterface", new TypeInfo("IntPtr"));
+		Types.Add("IHostUSBDeviceFilter", new TypeInfo("IntPtr"));
+		Types.Add("IRemoteDisplayInfo", new TypeInfo("IntPtr"));
+		Types.Add("IGuest", new TypeInfo("IntPtr"));
+		Types.Add("IVirtualSystemDescription", new TypeInfo("IntPtr"));
+		Types.Add("IAudioAdapter", new TypeInfo("IntPtr"));
+		Types.Add("IExtPackManager", new TypeInfo("IntPtr"));
+		Types.Add("IVRDEServer", new TypeInfo("IntPtr"));
+		Types.Add("IPciDeviceAttachment", new TypeInfo("IntPtr"));
+		Types.Add("IBandwidthGroup", new TypeInfo("IntPtr"));
+
+		Types.Add("$unknown", new TypeInfo("IntPtr"));
+	}
+	static void Main(string[] args) {
+		InitTypes();
+
+		XPathDocument doc = new XPathDocument("VirtualBox.xidl");
+		XPathNavigator nav = doc.CreateNavigator();
+		nav = nav.SelectSingleNode("/idl/library[@name='VirtualBox']");
+		TextWriter o = Console.Out;
+		o.WriteLine("using System;");
+		o.WriteLine("using System.Runtime.CompilerServices;");
+		o.WriteLine("using System.Runtime.InteropServices;");
+		o.WriteLine("namespace VirtualBox {");
+		foreach (XPathNavigator intf in nav.Select("interface")) {
+			ProcessInterface(intf, o, nav);
+		}
+		foreach (XPathNavigator intf in nav.Select("enum")) {
+			ProcessEnum(intf, o);
+		}
+		o.WriteLine("}");
+	}
+	static void ProcessEnum(XPathNavigator nav, TextWriter o) {
+		String typeName = nav.SelectSingleNode("@name").Value;
+		if (!Types.ContainsKey(typeName)) Types.Add(typeName, new TypeInfo(typeName));
+		o.WriteLine("[Guid(\"{0}\")]", nav.SelectSingleNode("@uuid").Value);
+		o.WriteLine("enum " + typeName + " {");
+		foreach (XPathNavigator member in nav.SelectChildren(XPathNodeType.Element)) {
+			switch (member.Name) {
+				case "desc":
+					break;
+				case "const":
+					o.WriteLine("\t{0} = {1},", member.SelectSingleNode("@name").Value, member.SelectSingleNode("@value").Value);
+					break;
+				default:
+					Console.Error.WriteLine("Unknown member type {0}", member.Name);
+					break;
+			}
+		}
+		o.WriteLine("}");
+	}
+	static void ProcessInterface(XPathNavigator nav, TextWriter o, XPathNavigator parentNav) {
+		String typeName = nav.SelectSingleNode("@name").Value;
+		if (!Types.ContainsKey(typeName)) Types.Add(typeName, new TypeInfo(typeName, "MarshalAs(UnmanagedType.Interface)"));
+		o.WriteLine("[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]");
+		o.WriteLine("[Guid(\"{0}\")]", nav.SelectSingleNode("@uuid").Value);
+		o.WriteLine("[ComImport()]");
+		o.Write("interface " + typeName);
+		o.WriteLine(" {");
+		ProcessInterfaceMembersAndInherited(nav, o, parentNav);
+		o.WriteLine("}");
+	}
+	static void ProcessInterfaceMembersAndInherited(XPathNavigator nav, TextWriter o, XPathNavigator parentNav) {
+		XPathItem item = nav.SelectSingleNode("@extends");
+		if (item != null && item.Value[0] != '$') {
+			XPathNavigator inav = parentNav.SelectSingleNode("interface[@name='" + item.Value + "']");
+			ProcessInterfaceMembersAndInherited(inav, o, parentNav);
+		}
+		ProcessInterfaceMembers(nav.SelectChildren(XPathNodeType.Element), o);
+	}
+	static void ProcessInterfaceMembers(XPathNodeIterator members, TextWriter oattribute) {
+		XPathItem item;
+		StringWriter omethod = new StringWriter();
+		foreach (XPathNavigator member in members) {
+			switch (member.Name) {
+				case "desc":
+					break;
+				case "attribute": {
+						String mName = member.SelectSingleNode("@name").Value;
+						//String mType = member.SelectSingleNode("@type").Value;
+						item = member.SelectSingleNode("@readonly");
+						Boolean mReadOnly = item == null ? false : item.Value == "yes";
+						//item = member.SelectSingleNode("@mod");
+						//String mMod = item == null ? null : item.Value;
+						mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1);
+						oattribute.Write("\t");
+						/*TypeInfo t;
+						if (mMod == "ptr") {
+							t = new TypeInfo("IntPtr");
+						} else if (mMod == "string") {
+							t = new TypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)");
+						} else if (mMod == null) {
+							if (!Types.TryGetValue(mType, out t)) {
+								Console.Error.WriteLine("Type {0} is not supported", mType);
+								t = new TypeInfo("void");
+							}
+						} else {
+							Console.Error.WriteLine("Type modifier {0} is not supported", mMod);
+							t = new TypeInfo("void");
+						}*/
+						TypeInfo t = GetTypeDeclaration(member);
+						oattribute.Write(t.Name);
+						oattribute.Write(" ");
+						oattribute.Write(mName);
+						oattribute.WriteLine(" {");
+						oattribute.Write("\t\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] ");
+						t.WriteAttributes(oattribute, ParameterType.Return);
+						oattribute.WriteLine("get;");
+						if (!mReadOnly) {
+							oattribute.Write("\t\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] ");
+							t.WriteAttributes(oattribute, ParameterType.Param);
+							oattribute.WriteLine("set;");
+						}
+						oattribute.WriteLine("\t}");
+					} break;
+				case "method": {
+						String mName = member.SelectSingleNode("@name").Value;
+						XPathNodeIterator mParamReturn = member.Select("param[@dir='return']");
+						omethod.WriteLine("\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]");
+						omethod.Write("\t");
+						bool mReturn = false;
+						if (mParamReturn == null || mParamReturn.Count != 1) {
+							omethod.Write("void");
+						} else {
+							mParamReturn.MoveNext();
+							mReturn = true;
+							TypeInfo t = GetTypeDeclaration(mParamReturn.Current);
+							/*String mType = mParamReturn.Current.SelectSingleNode("@type").Value;
+							TypeInfo t;
+							if (!Types.TryGetValue(mType, out t)) {
+								Console.Error.WriteLine("Type {0} is not supported", mType);
+								t = new TypeInfo("void");
+								mReturn = false;
+							}*/
+							t.WriteDeclaration(omethod, ParameterType.Return);
+						}
+						mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1);
+						omethod.Write(" ");
+						omethod.Write(mName);
+						omethod.Write("(");
+						XPathNodeIterator mParams = member.Select("param");
+						bool first = true;
+						if (mParams.MoveNext()) {
+							while (true) {
+								XPathNavigator mParam = mParams.Current;
+								String pDir = mParam.SelectSingleNode("@dir").Value;
+								//item = mParam.SelectSingleNode("@safearray");
+								//Boolean pArray = item == null ? false : item.Value == "yes";
+								//item = mParam.SelectSingleNode("@mod");
+								//String pMod = item == null ? null : item.Value;
+								if (pDir == "return" && mReturn) {
+									if (mParams.MoveNext()) {
+										continue;
+									} else {
+										break;
+									}
+								} else if (pDir == "in") {
+								} else if (pDir == "out") {
+								} else {
+									Console.Error.WriteLine("Unsupported parameter direction {0}", pDir);
+								}
+								if (first) {
+									first = false;
+								} else {
+									omethod.Write(", ");
+								}
+								ParameterType pt = ParameterType.In;
+								if (pDir == "out") pt = ParameterType.Out;
+								TypeInfo t = GetTypeDeclaration(mParam, ref pt);
+								t.WriteDeclaration(omethod, pt);
+								/*if (pArray) {
+									omethod.Write("[MarshalAs(UnmanagedType.SafeArray)] ");
+									if (pDir == "out") omethod.Write("out ");
+									else omethod.Write("ref ");
+									omethod.Write("System.Array");
+								} else {
+									String pType = mParam.SelectSingleNode("@type").Value;
+									TypeInfo t;
+									if (!Types.TryGetValue(pType, out t)) {
+										Console.Error.WriteLine("Type {0} is not supported", pType);
+										t = new TypeInfo("IntPtr");
+										mReturn = false;
+									}
+									if (pMod == "ptr") {
+										t.WriteDeclaration(omethod, ParameterType.Reference);
+									} else if (pDir == "out") {
+										t.WriteDeclaration(omethod, ParameterType.Out);
+									} else {
+										t.WriteDeclaration(omethod, ParameterType.In);
+									}
+								}*/
+								omethod.Write(" p");
+								omethod.Write(mParam.SelectSingleNode("@name").Value);
+								if (!mParams.MoveNext()) break;
+							}
+						}
+						omethod.WriteLine(");");
+					} break;
+				default:
+					Console.Error.WriteLine("Unknown member type {0}", member.Name);
+					break;
+			}
+		}
+		oattribute.Write((omethod as StringWriter).ToString());
+	}
+	private static TypeInfo GetTypeDeclaration(XPathNavigator nav) {
+		ParameterType pt = ParameterType.Param;
+		return GetTypeDeclaration(nav, ref pt);
+	}
+	private static TypeInfo GetTypeDeclaration(XPathNavigator nav, ref ParameterType paramType) {
+		String mType = nav.SelectSingleNode("@type").Value;
+		XPathItem item;
+		item = nav.SelectSingleNode("@mod");
+		String mMod = item == null ? null : item.Value;
+		item = nav.SelectSingleNode("@safearray");
+		Boolean pArray = item == null ? false : item.Value == "yes";
+
+		TypeInfo t;
+		if (!Types.TryGetValue(mType, out t)) {
+			Console.Error.WriteLine("Type {0} is not supported", mType);
+			t = new TypeInfo("void");
+		}
+		if (mMod == "ptr") {
+			if (paramType == ParameterType.In) {
+				paramType = ParameterType.Reference;
+			} else {
+				t = new TypeInfo("IntPtr");
+			}
+		} else if (mMod == "string") {
+			t = new TypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)");
+		} else if (mMod != null) {
+			Console.Error.WriteLine("Type modifier {0} is not supported", mMod);
+			t = new TypeInfo("void");
+		}
+		if (pArray) {
+			t = new TypeInfo("Array", "MarshalAs(UnmanagedType.SafeArray)");
+			if (paramType == ParameterType.In || paramType == ParameterType.Out) paramType = ParameterType.Reference;
+		}
+		return t;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxDotNet.sln	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VBoxFrontend", "VBoxFrontend\VBoxFrontend.csproj", "{B1236187-8BCB-4DD7-A4C2-F2C3BBC555A1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InteropCodeGen", "InteropCodeGen\InteropCodeGen.csproj", "{9C96A3C0-1673-457A-BF8D-CB97B44533A3}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B1236187-8BCB-4DD7-A4C2-F2C3BBC555A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B1236187-8BCB-4DD7-A4C2-F2C3BBC555A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B1236187-8BCB-4DD7-A4C2-F2C3BBC555A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B1236187-8BCB-4DD7-A4C2-F2C3BBC555A1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9C96A3C0-1673-457A-BF8D-CB97B44533A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9C96A3C0-1673-457A-BF8D-CB97B44533A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9C96A3C0-1673-457A-BF8D-CB97B44533A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9C96A3C0-1673-457A-BF8D-CB97B44533A3}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Display.Designer.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,187 @@
+namespace ConsoleApplication1 {
+	partial class Display {
+		/// <summary>
+		/// Required designer variable.
+		/// </summary>
+		private System.ComponentModel.IContainer components = null;
+
+		/// <summary>
+		/// Clean up any resources being used.
+		/// </summary>
+		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+		protected override void Dispose(bool disposing) {
+			if (disposing && (components != null)) {
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Windows Form Designer generated code
+
+		/// <summary>
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// </summary>
+		private void InitializeComponent() {
+			this.components = new System.ComponentModel.Container();
+			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Display));
+			this.DisplayBox = new System.Windows.Forms.PictureBox();
+			this.COMEventTimer = new System.Windows.Forms.Timer(this.components);
+			this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+			this.toolStripDropDownButton1 = new System.Windows.Forms.ToolStripDropDownButton();
+			this.testToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+			this.resumeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+			this.saveStateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+			this.aCPIPowerDownToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+			this.shutdownToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+			this.resetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+			this.statusLabel = new System.Windows.Forms.ToolStripLabel();
+			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+			this.ProgressWatcher = new System.Windows.Forms.Timer(this.components);
+			((System.ComponentModel.ISupportInitialize)(this.DisplayBox)).BeginInit();
+			this.toolStrip1.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// DisplayBox
+			// 
+			this.DisplayBox.BackColor = System.Drawing.Color.Black;
+			this.DisplayBox.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.DisplayBox.Location = new System.Drawing.Point(0, 20);
+			this.DisplayBox.Name = "DisplayBox";
+			this.DisplayBox.Size = new System.Drawing.Size(292, 246);
+			this.DisplayBox.TabIndex = 0;
+			this.DisplayBox.TabStop = false;
+			this.DisplayBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Display_MouseEvent);
+			this.DisplayBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Display_MouseEvent);
+			this.DisplayBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Display_MouseEvent);
+			// 
+			// COMEventTimer
+			// 
+			this.COMEventTimer.Tick += new System.EventHandler(this.COMEventTimer_Tick);
+			// 
+			// toolStrip1
+			// 
+			this.toolStrip1.AutoSize = false;
+			this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.toolStripDropDownButton1,
+            this.toolStripSeparator1,
+            this.statusLabel});
+			this.toolStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
+			this.toolStrip1.Location = new System.Drawing.Point(0, 0);
+			this.toolStrip1.Name = "toolStrip1";
+			this.toolStrip1.Size = new System.Drawing.Size(292, 20);
+			this.toolStrip1.TabIndex = 2;
+			this.toolStrip1.Text = "toolStrip1";
+			// 
+			// toolStripDropDownButton1
+			// 
+			this.toolStripDropDownButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+			this.toolStripDropDownButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.testToolStripMenuItem,
+            this.resumeToolStripMenuItem,
+            this.saveStateToolStripMenuItem,
+            this.aCPIPowerDownToolStripMenuItem,
+            this.resetToolStripMenuItem,
+            this.shutdownToolStripMenuItem});
+			this.toolStripDropDownButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripDropDownButton1.Image")));
+			this.toolStripDropDownButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
+			this.toolStripDropDownButton1.Name = "toolStripDropDownButton1";
+			this.toolStripDropDownButton1.Size = new System.Drawing.Size(59, 17);
+			this.toolStripDropDownButton1.Text = "Machine";
+			// 
+			// testToolStripMenuItem
+			// 
+			this.testToolStripMenuItem.Name = "testToolStripMenuItem";
+			this.testToolStripMenuItem.Size = new System.Drawing.Size(171, 22);
+			this.testToolStripMenuItem.Text = "Pause";
+			this.testToolStripMenuItem.Click += new System.EventHandler(this.pauseToolStripMenuItem_Click);
+			// 
+			// resumeToolStripMenuItem
+			// 
+			this.resumeToolStripMenuItem.Name = "resumeToolStripMenuItem";
+			this.resumeToolStripMenuItem.Size = new System.Drawing.Size(171, 22);
+			this.resumeToolStripMenuItem.Text = "Resume";
+			this.resumeToolStripMenuItem.Click += new System.EventHandler(this.resumeToolStripMenuItem_Click);
+			// 
+			// saveStateToolStripMenuItem
+			// 
+			this.saveStateToolStripMenuItem.Name = "saveStateToolStripMenuItem";
+			this.saveStateToolStripMenuItem.Size = new System.Drawing.Size(171, 22);
+			this.saveStateToolStripMenuItem.Text = "Save state";
+			this.saveStateToolStripMenuItem.Click += new System.EventHandler(this.savestateToolStripMenuItem_Click);
+			// 
+			// aCPIPowerDownToolStripMenuItem
+			// 
+			this.aCPIPowerDownToolStripMenuItem.Name = "aCPIPowerDownToolStripMenuItem";
+			this.aCPIPowerDownToolStripMenuItem.Size = new System.Drawing.Size(171, 22);
+			this.aCPIPowerDownToolStripMenuItem.Text = "ACPI power down";
+			this.aCPIPowerDownToolStripMenuItem.Click += new System.EventHandler(this.aCPIPowerButtonToolStripMenuItem_Click);
+			// 
+			// shutdownToolStripMenuItem
+			// 
+			this.shutdownToolStripMenuItem.Name = "shutdownToolStripMenuItem";
+			this.shutdownToolStripMenuItem.Size = new System.Drawing.Size(171, 22);
+			this.shutdownToolStripMenuItem.Text = "Shutdown";
+			this.shutdownToolStripMenuItem.Click += new System.EventHandler(this.powerdownToolStripMenuItem_Click);
+			// 
+			// resetToolStripMenuItem
+			// 
+			this.resetToolStripMenuItem.Name = "resetToolStripMenuItem";
+			this.resetToolStripMenuItem.Size = new System.Drawing.Size(171, 22);
+			this.resetToolStripMenuItem.Text = "Reset";
+			this.resetToolStripMenuItem.Click += new System.EventHandler(this.resetToolStripMenuItem_Click);
+			// 
+			// statusLabel
+			// 
+			this.statusLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+			this.statusLabel.Name = "statusLabel";
+			this.statusLabel.Size = new System.Drawing.Size(38, 13);
+			this.statusLabel.Text = "Busy..";
+			this.statusLabel.Visible = false;
+			// 
+			// toolStripSeparator1
+			// 
+			this.toolStripSeparator1.Name = "toolStripSeparator1";
+			this.toolStripSeparator1.Size = new System.Drawing.Size(6, 23);
+			// 
+			// ProgressWatcher
+			// 
+			this.ProgressWatcher.Tick += new System.EventHandler(this.ProgressWatcher_Tick);
+			// 
+			// Display
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.ClientSize = new System.Drawing.Size(292, 266);
+			this.Controls.Add(this.DisplayBox);
+			this.Controls.Add(this.toolStrip1);
+			this.Name = "Display";
+			this.Text = "VirtualBox Virtual Machine Display";
+			this.Load += new System.EventHandler(this.Display_Load);
+			this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Display_KeyUp);
+			this.Resize += new System.EventHandler(this.Display_Resize);
+			this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Display_KeyDown);
+			((System.ComponentModel.ISupportInitialize)(this.DisplayBox)).EndInit();
+			this.toolStrip1.ResumeLayout(false);
+			this.toolStrip1.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.PictureBox DisplayBox;
+		private System.Windows.Forms.Timer COMEventTimer;
+		private System.Windows.Forms.ToolStrip toolStrip1;
+		private System.Windows.Forms.ToolStripDropDownButton toolStripDropDownButton1;
+		private System.Windows.Forms.ToolStripMenuItem testToolStripMenuItem;
+		private System.Windows.Forms.ToolStripMenuItem resumeToolStripMenuItem;
+		private System.Windows.Forms.ToolStripMenuItem saveStateToolStripMenuItem;
+		private System.Windows.Forms.ToolStripMenuItem aCPIPowerDownToolStripMenuItem;
+		private System.Windows.Forms.ToolStripMenuItem shutdownToolStripMenuItem;
+		private System.Windows.Forms.ToolStripMenuItem resetToolStripMenuItem;
+		private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+		private System.Windows.Forms.ToolStripLabel statusLabel;
+		private System.Windows.Forms.Timer ProgressWatcher;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Display.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,243 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Threading;
+using VirtualBox;
+
+namespace ConsoleApplication1 {
+	public partial class Display : Form {
+		public Framebuffer Framebuffer { get; private set; }
+		public IConsole VMConsole { get; private set; }
+		private Point MouseLocation = new Point(0, 0);
+		private VBoxEventListener EventListener = new VBoxEventListener();
+		private VBoxKeyboardHelper Keyboard;
+		private Size RequestedClientSize = new Size(0, 0);
+		private IProgress WaitingForProgress = null;
+		private Boolean InitialPaused = true;
+
+		public Display(IConsole console, Framebuffer fb) {
+			VMConsole = console;
+			Framebuffer = fb;
+			Keyboard = new VBoxKeyboardHelper(VMConsole.Keyboard);
+			InitializeComponent();
+			Framebuffer.BufferChanged += Framebuffer_BufferChanged;
+			Framebuffer.Update += Framebuffer_Update;
+			DisplayBox.Image = Framebuffer.Bitmap;
+			EventListener.HandleEvent += EventListener_HandleEvent;
+			EventListener.RegisterSource(VMConsole.EventSource, VBoxEventType.VBoxEventType_Any);
+			this.MouseWheel += Display_MouseEvent;
+		}
+
+		private void Display_Load(object sender, EventArgs e) {
+			ClientSize = RequestedClientSize = new Size(800, 600);
+			if (ProgramRun.VBoxXPCOM != null) COMEventTimer.Enabled = true;
+			Framebuffer.WinId = Handle.ToInt64();
+		}
+
+		private void EventListener_HandleEvent(Object sender, VBoxEventArgs ea) {
+			IEvent aEvent = ea.Event;
+			switch (aEvent.Type) {
+				case VBoxEventType.VBoxEventType_OnCanShowWindow: {
+						ICanShowWindowEvent e = (ICanShowWindowEvent)aEvent;
+					} break;
+				case VBoxEventType.VBoxEventType_OnEventSourceChanged:
+					break;
+				case VBoxEventType.VBoxEventType_OnStateChanged: {
+						IStateChangedEvent e = (IStateChangedEvent)aEvent;
+						Console.WriteLine("New state: {0}", e.State);
+						switch (e.State) {
+							case MachineState.MachineState_Paused:
+								if (InitialPaused) {
+									InitialPaused = false;
+									ThreadPool.QueueUserWorkItem(delegate(Object state) {
+										VMConsole.Resume();
+									});
+								}
+								break;
+							case MachineState.MachineState_Running:
+								ThreadPool.QueueUserWorkItem(delegate(Object state) {
+									try {
+										if (VMConsole.Mouse.AbsoluteSupported == 0 && VMConsole.Mouse.RelativeSupported != 0) {
+											Console.WriteLine("Reset mouse position to {0}", MouseLocation);
+											//MouseLocation = new Point(0, 0);
+											VMConsole.Mouse.PutMouseEvent(-(int)Framebuffer.Width, -(int)Framebuffer.Height, 0, 0, 0);
+											VMConsole.Mouse.PutMouseEvent(MouseLocation.X, MouseLocation.Y, 0, 0, 0);
+										}
+									} catch (Exception ex) {
+										Console.WriteLine(ex.ToString());
+									}
+									try {
+										VMConsole.Display.InvalidateAndUpdate();
+									} catch (Exception ex) {
+										Console.WriteLine(ex.ToString());
+									}
+								});
+								break;
+							case MachineState.MachineState_Aborted:
+							case MachineState.MachineState_PoweredOff:
+							case MachineState.MachineState_Saved:
+								if (IsHandleCreated) Invoke((MethodInvoker)delegate() { Close(); });
+								break;
+						}
+					} break;
+				case VBoxEventType.VBoxEventType_OnShowWindow: {
+						IShowWindowEvent e = (IShowWindowEvent)aEvent;
+						e.WinId = Handle.ToInt64();
+					} break;
+				case VBoxEventType.VBoxEventType_OnKeyboardLedsChanged: {
+						IKeyboardLedsChangedEvent e = (IKeyboardLedsChangedEvent)aEvent;
+						Console.WriteLine("Keyboard leds: Numlock={0} Capslock={1} Scrolllock={2}", e.NumLock, e.CapsLock, e.ScrollLock);
+					} break;
+				case VBoxEventType.VBoxEventType_OnMouseCapabilityChanged: {
+						IMouseCapabilityChangedEvent e = (IMouseCapabilityChangedEvent)aEvent;
+						Console.WriteLine("MouseCapabilityChanged NeedsHostCursor={0} SupportsAbsolute={1} SupportsRelative={2}", e.NeedsHostCursor, e.SupportsAbsolute, e.SupportsRelative);
+					} break;
+				case VBoxEventType.VBoxEventType_OnMousePointerShapeChanged: {
+						IMousePointerShapeChangedEvent e = (IMousePointerShapeChangedEvent)aEvent;
+					} break;
+				case VBoxEventType.VBoxEventType_OnAdditionsStateChanged: {
+						IAdditionsStateChangedEvent e = (IAdditionsStateChangedEvent)aEvent;
+					} break;
+			}
+		}
+
+		private void COMEventTimer_Tick(object sender, EventArgs e) {
+			ProgramRun.VBoxXPCOM.EventQueue.ProcessPendingEvents();
+		}
+
+		private void Display_Resize(object sender, EventArgs e) {
+			if (RequestedClientSize.Equals(ClientSize)) return;
+			if (VMConsole.State != MachineState.MachineState_Running) return;
+			VMConsole.Display.SetVideoModeHint((uint)DisplayBox.Width, (uint)DisplayBox.Height, 0, 0);
+		}
+
+		private void Framebuffer_BufferChanged(Object sender, EventArgs e) {
+			DisplayBox.Invoke((MethodInvoker)delegate() {
+				Framebuffer fb = (Framebuffer)sender;
+				DisplayBox.Image = fb.Bitmap;
+				if (fb.Width > Screen.FromControl(this).WorkingArea.Width || fb.Height > Screen.FromControl(this).WorkingArea.Height) return;
+				ClientSize = RequestedClientSize = new Size((int)fb.Width + ClientSize.Width - DisplayBox.Width, (int)fb.Height + ClientSize.Height - DisplayBox.Height);
+			});
+		}
+
+		private void Framebuffer_Update(Object sender, FramebufferUpdateEventArgs e) {
+			DisplayBox.Invoke((MethodInvoker)delegate() {
+				DisplayBox.Invalidate(e.Rectangle);
+			});
+		}
+
+		private void Display_MouseEvent(object sender, MouseEventArgs e) {
+			IMouse mouse = VMConsole.Mouse;
+			MouseButtonState mbs = (MouseButtonState)0;
+			if ((e.Button & MouseButtons.Left) == MouseButtons.Left) mbs |= MouseButtonState.MouseButtonState_LeftButton;
+			if ((e.Button & MouseButtons.Right) == MouseButtons.Right) mbs |= MouseButtonState.MouseButtonState_RightButton;
+			if ((e.Button & MouseButtons.Middle) == MouseButtons.Middle) mbs |= MouseButtonState.MouseButtonState_MiddleButton;
+			if ((e.Button & MouseButtons.XButton1) == MouseButtons.XButton1) mbs |= MouseButtonState.MouseButtonState_XButton1;
+			if ((e.Button & MouseButtons.XButton2) == MouseButtons.XButton2) mbs |= MouseButtonState.MouseButtonState_XButton2;
+			try {
+				//Console.WriteLine("Mouse {0} Scroll {1} Buttons {2}", e.Location, e.Delta, mbs);
+				if (mouse.AbsoluteSupported != 0) {
+					mouse.PutMouseEventAbsolute(e.X + 1, e.Y + 1, -e.Delta / 120, 0, (int)mbs);
+				} else if (mouse.RelativeSupported != 0) {
+					mouse.PutMouseEvent(e.X - MouseLocation.X, e.Y - MouseLocation.Y, -e.Delta / 120, 0, (int)mbs);
+				}
+				MouseLocation = e.Location;
+			} catch (Exception ex) {
+				Console.WriteLine("MouseEventHandler Exception: {0}", ex.ToString());
+			}
+		}
+
+		private void Display_KeyDown(object sender, KeyEventArgs e) {
+			Keyboard.SendKeyCode(e.KeyCode, true);
+		}
+
+		private void Display_KeyUp(object sender, KeyEventArgs e) {
+			Keyboard.SendKeyCode(e.KeyCode, false);
+		}
+
+		private void pauseToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				VMConsole.Pause();
+				statusLabel.Text = "Paused";
+				statusLabel.Visible = true;
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void resumeToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				VMConsole.Resume();
+				if (statusLabel.Text == "Paused") statusLabel.Visible = false;
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void savestateToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				MonitorUntilCompleted(VMConsole.SaveState());
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void aCPIPowerButtonToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				VMConsole.PowerButton();
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void powerdownToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				MonitorUntilCompleted(VMConsole.PowerDown());
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void resetToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				VMConsole.Reset();
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		public void MonitorUntilCompleted(IProgress p) {
+			WaitingForProgress = p;
+			statusLabel.Visible = true;
+			statusLabel.Text = "Busy...";
+			ProgressWatcher.Enabled = true;
+		}
+
+		private void ProgressWatcher_Tick(object sender, EventArgs e) {
+			IProgress p = WaitingForProgress;
+			if (p == null) {
+				ProgressWatcher.Enabled = false;
+				statusLabel.Visible = false;
+			} else {
+				if (p.Canceled == 0 && p.Completed == 0) {
+					statusLabel.Text = "Busy " + p.Percent + "%...";
+				} else if (p.Canceled != 0) {
+					WaitingForProgress = null;
+					statusLabel.Text = "Operation aborted";
+				} else if (p.Completed != 0) {
+					WaitingForProgress = null;
+					if (p.ErrorInfo == null || p.ErrorInfo.ResultCode == 0) {
+						statusLabel.Text = "Operation completed";
+					} else {
+						statusLabel.Text = "Operation failed";
+						MessageBox.Show(p.ErrorInfo.Text, "Operation failed");
+						if (p.Cancelable != 0) p.Cancel();
+					}
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Display.resx	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="COMEventTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>133, 17</value>
+  </metadata>
+  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>374, 17</value>
+  </metadata>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="toolStripDropDownButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgxJREFUOE+lkvtL
+        U2EYx+0PEbtpFwnBKPGKiJImGP0gYhIYs1E5GF5gIxkpA00JRSmMEF0ohMh+GaRWYlqabMVcNdS2QpaI
+        VqiDIYhk397vA6fXhCjyhYdzeM/5fp7vczkAdeL2cwho7v/wWzT1zcN+Pwhr51uY2/y41PQaF+wzKKiZ
+        QvaN58g0jyLd5KEUcQbg+84P/Cm2tncQjW3j68YWIqubCC3FcOJc478BAuGoZM6zvoRnakXEruEIjhc4
+        /g5gZop9c+voGAyLbQIfeBZxLL9BA1jzXvuGbWamuKh+GmmVbswE19A59FEBbmoAG7YbsLtm2mZmiml9
+        cvabNDwpz6YB7LYBoMXCumkJr7LOmnnHzBQ/9X2Bo2cOibm1GsBREbAQiYmw/8lnuCeWkVzcgnZlnw1j
+        3HV/wuNXK6i/9x5Hc6wawDlTXHbLJ+LZUBQPRyKwdQdxutwl1h+NLXHh5Ht1ewBHsiwawCW57HyDAfWR
+        dvl0uhZQ1eqX8aVc7EKLqrum651ATLf9OJx5XQM4KmY0xPzZ0hFAiQJnXB0WwME0E3IsL5B17ZlADqWb
+        NYDrOepdlcysmTWWOrxqbceRWtaLk0VO1XW72D5Vckd2gMBfq8zdpmUG62NJvKM4+XyziDk24xmfWoGE
+        s1c0gHPmbrPTpHNJKOCo2G1mZs20zcwUJ5yp1AB5+8/zEwgF5GMVDxh4AAAAAElFTkSuQmCC
+</value>
+  </data>
+  <metadata name="ProgressWatcher.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>473, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Framebuffer.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,101 @@
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using VirtualBox;
+
+namespace ConsoleApplication1 {
+	public class FramebufferUpdateEventArgs : EventArgs {
+		public Rectangle Rectangle { get; private set; }
+		public FramebufferUpdateEventArgs(Rectangle rect) {
+			Rectangle = rect;
+		}
+	}
+	[ClassInterface((Int16)0)]
+	[TypeLibType(2)]
+	[ComVisible(true)]
+	public class Framebuffer : IFramebuffer {
+		Mutex mutex = new Mutex();
+
+		public Framebuffer() {
+			byte b = 0;
+			RequestResize(0, (int)FramebufferPixelFormat.FramebufferPixelFormat_FOURCC_RGB, ref b, 32, 0, 640, 480);
+		}
+
+		public void Lock() {
+			//Console.WriteLine("Lock");
+			mutex.WaitOne();
+		}
+		public void Unlock() {
+			//Console.WriteLine("Unlock");
+			mutex.ReleaseMutex();
+		}
+
+		public Bitmap Bitmap { get; private set; }
+		public event EventHandler BufferChanged;
+		public event EventHandler<FramebufferUpdateEventArgs> Update;
+
+		public IntPtr Address { get; private set; }
+		public uint BitsPerPixel { get; private set; }
+		public uint BytesPerLine { get; private set; }
+		public uint Height { get; private set; }
+		public uint HeightReduction { get { return 0; } }
+		public IFramebufferOverlay Overlay { get { return null; } }
+		public uint PixelFormat { get; private set; }
+		public int UsesGuestVRAM { get { return 0; } }
+		public uint Width { get; private set; }
+		public long WinId { get; internal set; }
+
+		public unsafe void NotifyUpdate(uint aX, uint aY, uint aWidth, uint aHeight) {
+			//Console.WriteLine("NotifyUpdate X={0} Y={1} Width={2} Height={3}", aX, aY, aWidth, aHeight);
+			if (Update != null) Update(this, new FramebufferUpdateEventArgs(new Rectangle((int)aX, (int)aY, (int)aWidth, (int)aHeight)));
+		}
+		public void ProcessVHWACommand(ref byte aCommand) {
+			Console.WriteLine("ProcessVHWACommand");
+		}
+		public unsafe int RequestResize(uint aScreenId, uint aPixelFormat, ref byte aVRAM, uint aBitsPerPixel, uint aBytesPerLine, uint aWidth, uint aHeight) {
+			//Note that aVRAM is a pointer, which may be NULL!
+			//fixed (Byte* vrp = &aVRAM) Console.WriteLine("RequestResize Current={0} ScreenId={1} PixelFormat={2} VRAM={3} BitsPerPixel={4} BytesPerLine={5} Width={6} Height={7}", Address, aScreenId, aPixelFormat, (IntPtr)vrp, aBitsPerPixel, aBytesPerLine, aWidth, aHeight);
+			Console.WriteLine("RequestResize Current={0} ScreenId={1} PixelFormat={2} VRAM={3} BitsPerPixel={4} BytesPerLine={5} Width={6} Height={7}", Address, aScreenId, aPixelFormat, 0, aBitsPerPixel, aBytesPerLine, aWidth, aHeight);
+			Lock();
+			try {
+				IntPtr oldAddress = Address;
+
+				Width = aWidth;
+				Height = aHeight;
+
+				BitsPerPixel = 32;
+				PixelFormat = (int)FramebufferPixelFormat.FramebufferPixelFormat_FOURCC_RGB;
+				BytesPerLine = BitsPerPixel * Width / 8; //aBytesPerLine;
+				Address = Marshal.AllocHGlobal((int)(BytesPerLine * Height));
+				if (Bitmap != null) Bitmap.Dispose();
+				Bitmap = new Bitmap((int)Width, (int)Height, (int)BytesPerLine, System.Drawing.Imaging.PixelFormat.Format32bppRgb, Address);
+				if (BufferChanged != null) BufferChanged(this, new EventArgs());
+				if (oldAddress != IntPtr.Zero) Marshal.FreeHGlobal(oldAddress);
+				//Console.WriteLine("RequestResizeDone Current={0} ScreenId={1} PixelFormat={2} VRAM={3} BitsPerPixel={4} BytesPerLine={5} Width={6} Height={7}", Address, aScreenId, PixelFormat, 0, BitsPerPixel, BytesPerLine, Width, Height);
+			} finally {
+				Unlock();
+			}
+			return 1; //Finished
+		}
+
+		~Framebuffer() {
+			if (Bitmap != null) Bitmap.Dispose();
+			if (Address != IntPtr.Zero) Marshal.FreeHGlobal(Address);
+		}
+
+		public void SetVisibleRegion(ref byte aRectangles, uint aCount) {
+			Console.WriteLine("SetVisibleRegion");
+		}
+		public uint GetVisibleRegion(ref byte aRectangles, uint aCount) {
+			Console.WriteLine("GetVisibleRegion");
+			return 0;
+		}
+		public int VideoModeSupported(uint aWidth, uint aHeight, uint aBpp) {
+			Console.WriteLine("VideoModeSupported Width={0} Height={1} Bpp={2}", aWidth, aHeight, aBpp);
+			return 1; //Supported
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Program.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,134 @@
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using System.Threading;
+using VirtualBox;
+
+namespace ConsoleApplication1 {
+	class ProgramRun {
+		public static VBoxXPCOM VBoxXPCOM { get; private set; }
+		Object WaitingForProgress = null;
+
+		public int Run(string[] args) {
+			IVirtualBox vb;
+			ISession sess;
+			if (Environment.OSVersion.Platform == PlatformID.Unix) {
+				VBoxXPCOM = new VBoxXPCOM();
+				vb = VBoxXPCOM.VirtualBox;
+				sess = VBoxXPCOM.Session;
+			} else {
+				VBoxCOMInit(out vb, out sess);
+			}
+
+			Console.WriteLine("VirtualBox version={0} revision={1}", vb.Version, vb.Revision);
+			Console.WriteLine("VirtualBox HomeFolder={0}", vb.HomeFolder);
+
+			if (args.Length < 1) {
+				Console.Error.WriteLine("Usage: {0} machine-name-or-id", Assembly.GetExecutingAssembly().Location);
+				return 1;
+			}
+			IMachine m;
+			m = vb.FindMachine(args[0]);
+
+			Console.WriteLine("Lock machine");
+			m.LockMachine((Session)sess, LockType.LockType_Write);
+			try {
+				Framebuffer fb = new Framebuffer();
+				sess.Console.Display.SetFramebuffer(0, fb);
+
+				Console.WriteLine("Start GUI thread");
+				Display disp = new Display(sess.Console, fb);
+
+				Console.WriteLine("Power up...");
+				//MonitorAndProcessEventsUntilCompleted(sess.Console.PowerUpPaused());
+
+				try {
+					disp.MonitorUntilCompleted(sess.Console.PowerUpPaused());
+
+					//Console.WriteLine("Resume");
+					//sess.Console.Resume();
+
+					Application.Run(disp);
+				} finally {
+					if (VBoxXPCOM != null) VBoxXPCOM.EventQueue.ProcessPendingEvents();
+					switch (sess.Console.State) {
+						case MachineState.MachineState_PoweredOff:
+						case MachineState.MachineState_Saved:
+						case MachineState.MachineState_Aborted:
+							break;
+						default:
+							Console.WriteLine("Power down");
+							WaitingForProgress = null;
+							ThreadPool.QueueUserWorkItem(delegate(Object state) {
+								Console.WriteLine("Requesting SaveState");
+								IProgress p = sess.Console.SaveState();
+								Console.WriteLine("Waiting for SaveState completion");
+								WaitingForProgress = p;
+								VBoxWaitComplete(p);
+							});
+							ProcessEventsUntilCompleted();
+							break;
+					}
+				}
+			} finally {
+				Console.WriteLine("Unlock machine");
+				sess.UnlockMachine();
+				if (VBoxXPCOM != null) VBoxXPCOM.EventQueue.ProcessPendingEvents();
+			}
+			return 0;
+		}
+
+		void VBoxCOMInit(out IVirtualBox vb, out ISession sess) {
+			//vb = (IVirtualBox)Activator.CreateInstance(Type.GetTypeFromProgID("VirtualBox.VirtualBox"));
+			//vb = (IVirtualBox)Activator.CreateInstance(typeof(VirtualBoxClass));
+			//vb = (IVirtualBox)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("B1A7A4F2-47B9-4A1E-82B2-07CCD5323C3F")));
+			vb = new VirtualBox.VirtualBoxClass();
+			sess = new VirtualBox.SessionClass();
+		}
+
+		public void VBoxWaitComplete(IProgress p) {
+			uint prev = 0;
+			while (p.Completed == 0) {
+				if (p.Percent != prev) Console.Write("{0}% ", p.Percent);
+				prev = p.Percent;
+				p.WaitForCompletion(100);
+			}
+			if (p.ResultCode == 0) {
+				Console.WriteLine("done");
+			} else {
+				Console.WriteLine("Error {0} {1}", p.ErrorInfo.ResultCode, p.ErrorInfo.Text);
+				throw new COMException(p.ErrorInfo.Text, p.ErrorInfo.ResultCode);
+			}
+		}
+
+		public void MonitorAndProcessEventsUntilCompleted(IProgress p) {
+			MonitorProgressAsync(p);
+			ProcessEventsUntilCompleted(p);
+		}
+		public void MonitorProgressAsync(IProgress p) {
+			ThreadPool.QueueUserWorkItem(delegate(Object state) {
+				try {
+					VBoxWaitComplete(p);
+				} catch (Exception ex) {
+					Console.WriteLine(ex.ToString());
+				}
+			});
+		}
+		public void ProcessEventsUntilCompleted(IProgress p) {
+			do {
+				if (VBoxXPCOM != null) VBoxXPCOM.EventQueue.ProcessPendingEvents();
+				Thread.Sleep(100);
+			} while (p.Canceled == 0 && p.Completed == 0);
+			Console.WriteLine("Event processing completed");
+		}
+		public void ProcessEventsUntilCompleted() {
+			Console.WriteLine("Processing COM events...");
+			do {
+				if (VBoxXPCOM != null) VBoxXPCOM.EventQueue.ProcessPendingEvents();
+				Thread.Sleep(100);
+			} while (WaitingForProgress == null || ((WaitingForProgress as IProgress).Canceled == 0 && (WaitingForProgress as IProgress).Completed == 0));
+			Console.WriteLine("COM Event processing completed");
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/ProgramLoader.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,36 @@
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace ConsoleApplication1 {
+	class ProgramLoader {
+		[DllImport("/usr/lib/virtualbox/VBoxXPCOMC.so")]
+		private static extern Int32 RTR3InitAndSUPLib();
+
+		static unsafe int Main(string[] args) {
+			if (Environment.OSVersion.Platform == PlatformID.Unix) {
+				Console.WriteLine("UNIX based OS detected, doing some magic...");
+				int init = RTR3InitAndSUPLib();
+				if (init != 0) throw new COMException("Failed to initialize VirtualBox driver", init);
+				Unix_setuid();
+				Assembly.LoadFile("Interop.VirtualBox.XPCOM.dll");
+			}
+			return Main2(args);
+		}
+
+		static int Main2(String[] args) {
+			ProgramRun p = new ProgramRun();
+			return p.Run(args);
+		}
+
+		private static void Unix_setuid() {
+			uint uid = Mono.Unix.Native.Syscall.getuid();
+			uint euid = Mono.Unix.Native.Syscall.geteuid();
+			Console.WriteLine("Running as user {0} effective {1}", uid, euid);
+			if (uid != euid) {
+				Console.WriteLine("Set user ID: {0}", uid);
+				Mono.Unix.Native.Syscall.setreuid(uid, uid);
+			}
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Properties/AssemblyInfo.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ConsoleApplication1")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ConsoleApplication1")]
+[assembly: AssemblyCopyright("Copyright ©  2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("961036de-7f79-4cab-8f29-b6fc4c427a71")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Properties/Resources.Designer.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.3620
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace ConsoleApplication1.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ConsoleApplication1.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Properties/Resources.resx	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/VBoxEventListener.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,66 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using VirtualBox;
+
+namespace ConsoleApplication1 {
+	public class VBoxEventArgs : EventArgs {
+		public IEvent Event { get; private set; }
+		public VBoxEventArgs(IEvent e) {
+			Event = e;
+		}
+	}
+
+	[ClassInterface(ClassInterfaceType.None)]
+	[TypeLibType(TypeLibTypeFlags.FCanCreate)]
+	[ComVisible(true)]
+	public class VBoxEventListener : IEventListener {
+		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+		[Guid("9b6e1aee-35f3-4f4d-b5bb-ed0ecefd8538")]
+		[ComImport()]
+		interface IEventSourceXPCOM {
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			[return: MarshalAs(UnmanagedType.Interface)]
+			IEventListener CreateListener();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			[return: MarshalAs(UnmanagedType.Interface)]
+			IEventSource CreateAggregator([MarshalAs(UnmanagedType.SafeArray)] ref System.Array psubordinates);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void RegisterListener([MarshalAs(UnmanagedType.Interface)] IEventListener plistener, UInt32 pinterestinglen, IntPtr pinteresting, Int32 pactive);
+			//void RegisterListener([MarshalAs(UnmanagedType.Interface)] IEventListener plistener, UInt32 pinterestinglen, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] VBoxEventType[] pinteresting, Int32 pactive);
+
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void UnregisterListener([MarshalAs(UnmanagedType.Interface)] IEventListener plistener);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			Int32 FireEvent([MarshalAs(UnmanagedType.Interface)] IEvent pevent, Int32 ptimeout);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			[return: MarshalAs(UnmanagedType.Interface)]
+			IEvent GetEvent([MarshalAs(UnmanagedType.Interface)] IEventListener plistener, Int32 ptimeout);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void EventProcessed([MarshalAs(UnmanagedType.Interface)] IEventListener plistener, [MarshalAs(UnmanagedType.Interface)] IEvent pevent);
+		}
+
+		public EventHandler<VBoxEventArgs> HandleEvent;
+		void IEventListener.HandleEvent(IEvent aEvent) {
+			Console.WriteLine("Event: {0}", aEvent.Type);
+			if (HandleEvent != null) HandleEvent(this, new VBoxEventArgs(aEvent));
+		}
+
+		public void RegisterSource(IEventSource src, params VBoxEventType[] events) {
+			if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.WinCE) {
+				Array eventTypesArray = (Array)events;
+				src.RegisterListener(this, ref eventTypesArray, 1);
+			} else {
+				unsafe {
+					fixed (VBoxEventType* ptr = events) {
+						((IEventSourceXPCOM)src).RegisterListener(this, (uint)events.Length, (IntPtr)ptr, 1);
+					}
+				}
+			}
+		}
+
+		public void UnregisterSource(IEventSource src) {
+			src.UnregisterListener(this);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/VBoxFrontend.csproj	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{B1236187-8BCB-4DD7-A4C2-F2C3BBC555A1}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>ConsoleApplication1</RootNamespace>
+    <AssemblyName>VBoxTest</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <StartupObject>
+    </StartupObject>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>C:\Program Files\Mono-2.8\lib\mono\2.0\Mono.Posix.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Display.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Display.Designer.cs">
+      <DependentUpon>Display.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Framebuffer.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="ProgramLoader.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="VBoxEventListener.cs" />
+    <Compile Include="VBoxKeyboardHelper.cs" />
+    <Compile Include="VBoxXPCOM.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <COMReference Include="VirtualBox">
+      <Guid>{46137EEC-703B-4FE5-AFD4-7C9BBBBA0259}</Guid>
+      <VersionMajor>1</VersionMajor>
+      <VersionMinor>3</VersionMinor>
+      <Lcid>0</Lcid>
+      <WrapperTool>tlbimp</WrapperTool>
+      <Isolated>False</Isolated>
+    </COMReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Display.resx">
+      <DependentUpon>Display.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/VBoxKeyboardHelper.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,80 @@
+using System;
+using VirtualBox;
+using System.Windows.Forms;
+
+namespace ConsoleApplication1 {
+	public class VBoxKeyboardHelper {
+		public IKeyboard Keyboard { get; private set; }
+
+		public VBoxKeyboardHelper(IKeyboard kb) {
+			Keyboard = kb;
+		}
+
+		public void SendKeyCode(Keys keycode, bool down) {
+			int code;
+			//Console.WriteLine("VBoxKeyboardHelper.SendKeyCode({1}={2},{0})", down, keycode, (int)keycode);
+			int[] codes_az = { 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c }; //a-z
+			int[] codes_num = {0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a}; //0123456789
+			int[] codes_Fkeys = { 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x57, 0x58 }; //F123456789,10,11,12
+			if (keycode >= Keys.A && keycode <= Keys.Z) {
+				code = codes_az[keycode - Keys.A];
+			} else if (keycode >= Keys.D0 && keycode <= Keys.D9) {
+				code = codes_num[keycode - Keys.D0];
+			} else if (keycode >= Keys.F1 && keycode <= Keys.F12) {
+				code = codes_Fkeys[keycode - Keys.F1];
+			} else {
+				switch (keycode) {
+					case Keys.Space: code = 0x0239; break;
+					case Keys.Left: code = 0xe04b; break;
+					case Keys.Up: code = 0xe048; break;
+					case Keys.Right: code = 0xe04d; break;
+					case Keys.Down: code = 0xe050; break;
+					case Keys.Enter: code = 0x1c; break;
+					case Keys.LShiftKey:
+					case Keys.RShiftKey:
+					case Keys.ShiftKey: code = 0x2a; break;
+					case Keys.Tab: code = 0x0f; break;
+					case Keys.Back: code = 0x0e; break;
+					case Keys.Escape: code = 0x01; break;
+					case Keys.Home: code = 0xe047; break;
+					case Keys.PageUp: code = 0xe049; break;
+					case Keys.PageDown: code = 0xe051; break;
+					case Keys.End: code = 0xe04f; break;
+					case Keys.Insert: code = 0xe052; break;
+					case Keys.ControlKey:
+					case Keys.LControlKey: code = 0x1d; break;
+					case Keys.RControlKey: code = 0xe01d; break;
+					case Keys.Menu:
+					case Keys.LMenu: code = 0x38; break; //Left Alt
+					case Keys.RMenu: code = 0xe038; break; //Right Alt
+					case Keys.LWin: code = 0xe05b; break; //Left windows key
+					case Keys.RWin: code = 0xe05c; break; //Right windows key
+					case Keys.Delete: code = 0xe053; break;
+					case Keys.OemQuotes: code = 0x28; break;
+					case Keys.OemQuestion: code = 0x35; break;
+					case Keys.OemPeriod: code = 0x34; break;
+					case Keys.OemMinus: code = 0x0c; break;
+					case Keys.Oemplus: code = 0x0d; break;
+					case Keys.Oemcomma: code = 0x33; break;
+					case Keys.OemSemicolon: code = 0x27; break;
+					case Keys.Oemtilde: code = 0x29; break;
+					case Keys.OemCloseBrackets: code = 0x1b; break;
+					case Keys.OemBackslash: code = 0x2b; break;
+					case Keys.OemOpenBrackets: code = 0x1a; break;
+					default:
+						Console.Error.WriteLine("VBoxKeyboardHelper.SendKeyCode({1}={2},{0}) unknown key", down, keycode, (int)keycode);
+						return;
+				}
+			}
+			if ((code & 0xff00) != 0) kbdPutCode((code >> 8) & 0xff);
+			kbdPutCode((code & 0xff) | (down ? 0 : 0x80));
+		}
+		private void kbdPutCode(int code) {
+			try {
+				Keyboard.PutScancode(code);
+			} catch (Exception ex) {
+				Console.Error.WriteLine("VBoxKeyboardHelper.PutScancode Exception: {0}", ex.ToString());
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/VBoxXPCOM.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,124 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using VirtualBox;
+
+namespace ConsoleApplication1 {
+	public class VBoxXPCOM {
+		private delegate UInt32 pfnGetVersionDelegate();
+		private unsafe delegate void pfnComInitializeDelegate(
+			[MarshalAs(UnmanagedType.LPStr)] String pszVirtualBoxIID,
+			out IntPtr ppVirtualBox,
+			[MarshalAs(UnmanagedType.LPStr)] String pszSessionIID,
+			out IntPtr ppSession);
+		private delegate void pfnComUninitializeDelegate();
+		private delegate void pfnGetEventQueueDelegate(out IntPtr eventQueue); //void  (*pfnGetEventQueue)(nsIEventQueue **eventQueue);
+
+		private struct VBOXXPCOMC {
+			public UInt32 cb; //The size of the structure.
+			public UInt32 uVersion; //The structure version.
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			public pfnGetVersionDelegate pfnGetVersion;
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			public pfnComInitializeDelegate pfnComInitialize;
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			public pfnComUninitializeDelegate pfnComUninitialize;
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			private pfnComUninitializeDelegate pfnComUnallocMem; //void  (*pfnComUnallocMem)(void *pv);
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			private pfnComUninitializeDelegate pfnUtf16Free; //void  (*pfnUtf16Free)(PRUnichar *pwszString);
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			private pfnComUninitializeDelegate pfnUtf8Free; //void  (*pfnUtf8Free)(char *pszString);
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			private pfnComUninitializeDelegate pfnUtf16ToUtf8; //int   (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			private pfnComUninitializeDelegate pfnUtf8ToUtf16; //int   (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
+			[MarshalAs(UnmanagedType.FunctionPtr)]
+			public pfnGetEventQueueDelegate pfnGetEventQueue; //void  (*pfnGetEventQueue)(nsIEventQueue **eventQueue);
+			public UInt32 uEndVersion; //Tail version, same as uVersion.
+		}
+
+		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+		[Guid("176afb41-00a4-11d3-9f2a-00400553eef0")]
+		[ComImport()]
+		public interface nsIEventQueue {
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void PostEvent(IntPtr aEvent); //[noscript] void postEvent (in PLEventPtr aEvent);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			Int32 IsOnCurrentThread(); //boolean isOnCurrentThread ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void InitEvent(IntPtr aEvent, IntPtr owner, IntPtr handler, IntPtr destructor); //[noscript] void initEvent (in PLEventPtr aEvent, in voidPtr owner, in PLHandleEventProc handler, in PLDestroyEventProc destructor);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void PostSynchronousEvent(IntPtr aEvent, out IntPtr aResult); //[noscript] void postSynchronousEvent (in PLEventPtr aEvent, out voidPtr aResult);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			Int32 PendingEvents(); //boolean pendingEvents ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void ProcessPendingEvents(); //void processPendingEvents ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void EventLoop(); //void eventLoop ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void EventAvailable(ref Int32 aResult); //[noscript] void eventAvailable (in PRBoolRef aResult);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			IntPtr GetEvent(); //[noscript] PLEventPtr getEvent ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void HandleEvent(IntPtr aEvent); //[noscript] void handleEvent (in PLEventPtr aEvent);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			IntPtr WaitForEvent(); //[noscript] PLEventPtr waitForEvent ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			Int32 GetEventQueueSelectFD(); //[notxpcom] PRInt32 getEventQueueSelectFD ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void Init(Int32 aNative); //void init (in boolean aNative);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void InitFromPRThread(IntPtr thread, Int32 aNative); //[noscript] void initFromPRThread (in PRThreadPtr thread, in boolean aNative);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void InitFromPLQueue(IntPtr aQueue); //[noscript] void initFromPLQueue (in PLEventQueuePtr aQueue);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void EnterMonitor(); //void enterMonitor ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void ExitMonitor(); //void exitMonitor ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void RevokeEvents(IntPtr owner); //[noscript] void revokeEvents (in voidPtr owner);
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			IntPtr GetPLEventQueue(); //[noscript] PLEventQueuePtr getPLEventQueue ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			Int32 IsQueueNative(); //boolean isQueueNative ();
+			[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+			void StopAcceptingEvents(); //void stopAcceptingEvents ();
+		}
+
+		public const UInt32 VBOX_XPCOMC_VERSION = 0x00020000U;
+		[DllImport("/usr/lib/virtualbox/VBoxXPCOMC.so")]
+		public static extern IntPtr VBoxGetXPCOMCFunctions(UInt32 uVersion);
+
+		private VBOXXPCOMC FunctionTable;
+		public IVirtualBox VirtualBox { get; private set; }
+		public ISession Session { get; private set; }
+		public nsIEventQueue EventQueue { get; private set; }
+
+		//[STAThread]
+		public VBoxXPCOM() {
+			IntPtr ftptr = VBoxGetXPCOMCFunctions(VBOX_XPCOMC_VERSION);
+			//Console.WriteLine("Function table={0}", ftptr);
+
+			FunctionTable = (VBOXXPCOMC)Marshal.PtrToStructure(ftptr, typeof(VBOXXPCOMC));
+			//Console.WriteLine("Version {0}={1}={2}", VBOX_XPCOMC_VERSION, FunctionTable.uVersion, FunctionTable.uEndVersion);
+			//Console.WriteLine("Version {0}", FunctionTable.pfnGetVersion());
+
+			IntPtr vbptr, sessptr, eqptr;
+			FunctionTable.pfnComInitialize("D2DE270C-1D4B-4C9E-843F-BBB9B47269FF", out vbptr, "12F4DCDB-12B2-4EC1-B7CD-DDD9F6C5BF4D", out sessptr);
+			FunctionTable.pfnGetEventQueue(out eqptr);
+			//Console.WriteLine("VirtualBox={0} Session={1} EventQueue={2}", vbptr, sessptr, eqptr);
+
+			VirtualBox = (IVirtualBox)Marshal.GetObjectForIUnknown(vbptr);
+			Session = (ISession)Marshal.GetObjectForIUnknown(sessptr);
+			EventQueue = (nsIEventQueue)Marshal.GetObjectForIUnknown(eqptr);
+		}
+		~VBoxXPCOM() {
+			VirtualBox = null;
+			Session = null;
+			EventQueue = null;
+			GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
+			FunctionTable.pfnComUninitialize();
+		}
+	}
+}
\ No newline at end of file