using System; using System.Collections.Generic; using System.Linq; using Win32.WtsApi32; using System.Windows.Forms; using System.ComponentModel.Composition.Hosting; using System.ComponentModel.Composition; using System.IO; using System.Runtime.InteropServices; using System.Drawing; using RDPAddins.Common; namespace RDPAddins { class RDPClient { IntPtr initHandle = IntPtr.Zero; ChannelInitEventDelegate channelInitEventDelegate; [ImportMany(typeof(IAddin))] IEnumerable> Addins { get; set; } List Channels; public ChannelEntryPoints EntryPoint { get; private set; } internal SlaveMode MainForm { get; set; } RDPClient Client; public ChannelReturnCodes Initialize(string Path, IntPtr entry) { Client = this; var pluginspath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Path), "Plugins"); try { if (Directory.Exists(pluginspath)) { EntryPoint = (ChannelEntryPoints)Marshal.PtrToStructure(entry, typeof(ChannelEntryPoints)); channelInitEventDelegate = new ChannelInitEventDelegate(VirtualChannelInitEventProc); var batch = new CompositionBatch(); batch.AddPart(this); var catalog = new DirectoryCatalog(pluginspath); var container = new CompositionContainer(catalog); container.Compose(batch); Channels = Addins.Select(addin => { return new Channel(this, addin); }).ToList(); Channels.ForEach(channel => { MainForm.Invoke(new Action(() => { channel.CreateUI(); })); }); var cds = Channels.Select(channel => channel.ChannelDef).ToArray(); return EntryPoint.VirtualChannelInit(ref initHandle, cds, cds.Length, 1, channelInitEventDelegate); } } catch (Exception ex) { MessageBox.Show(ex.Message, "RDPAddins", MessageBoxButtons.OK, MessageBoxIcon.Error); } return ChannelReturnCodes.NullData; } void ChannelsInitialized() { MainForm.Invoke(new Action(() => { if (MainForm.Opacity == 0) { MainForm.Hide(); MainForm.Opacity = 100; } })); } void VirtualChannelInitEventProc(IntPtr initHandle, ChannelEvents initEvent, byte[] data, uint dataLength) { switch (initEvent) { case ChannelEvents.Initialized: ChannelsInitialized(); Client.Channels.ForEach(channel => channel.InitializedInternal()); break; case ChannelEvents.Connected: string server = System.Text.Encoding.Unicode.GetString(data); server = server.Substring(0, server.IndexOf('\0')); Client.Channels.ForEach(channel => { ChannelReturnCodes ret = channel.ConnectedInternal(initHandle); if (ret != ChannelReturnCodes.Ok) { MessageBox.Show(string.Format("{0}: VirtualChannelOpen error: {1}", channel.Metadata.ChannelName, ret), "RDPAddins", MessageBoxButtons.OK, MessageBoxIcon.Error); } }); MainForm.Invoke(new Action(() => { MainForm.Text = "RDPAddnins: " + server; })); break; case ChannelEvents.V1Connected: MessageBox.Show("Bad RDP server version.", "RDPAddins", MessageBoxButtons.OK, MessageBoxIcon.Error); break; case ChannelEvents.Disconnected: MainForm.Invoke(new Action(() => MainForm.Text = "RDPAddnins")); Channels.ForEach(channel => channel.DisconnectedInternal()); GC.Collect(); GC.WaitForPendingFinalizers(); break; case ChannelEvents.Terminated: Channels.ForEach(channel => channel.TerminatedInternal()); MainForm.RealClosing = true; MainForm.Invoke(new Action(() => MainForm.Close())); break; } } } }