RDPAddins.NET/RDPAddins/Channel.cs

319 lines
9.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using Win32.WtsApi32;
using System.Threading;
using System.ComponentModel;
using RDPAddins.Common;
namespace RDPAddins
{
internal class Channel: IChannel, IUI
{
uint openChannel = 0;
ChannelOpenEventDelegate channelOpenEventDelegate;
ManualResetEvent write = new ManualResetEvent(true);
internal object tooltipconext = null;
Queue<MemoryChunk> buffers = new Queue<MemoryChunk>();
object readlock = new object();
public event EventHandler Connected;
public event EventHandler Disconnected;
public event EventHandler Terminated;
public event DataArrivedHandler DataArrived;
public event BalloonTipClickedHandler BalloonTipClicked;
public Lazy<IAddin, IAddinMetadata> Addin;
public Channel(RDPClient client, Lazy<IAddin, IAddinMetadata> addin)
{
Client = client;
Addin = addin;
Addin.Value.Initialize(this);
ChannelDef = new ChannelDef(){name = Metadata.ChannelName, options = Metadata.ChannelOptions };
channelOpenEventDelegate = new ChannelOpenEventDelegate(VirtualChannelOpenEvent);
}
internal ChannelDef ChannelDef;
public IChannel Parent { get { return this; } }
public bool Visible
{
get
{
if (Page != null)
return TabCtrl.TabPages.Contains(Page);
return false;
}
set
{
if (Page != null)
{
if (value)
{
if (!TabCtrl.TabPages.Contains(Page))
TabCtrl.TabPages.Add(Page);
}
else
{
if (TabCtrl.TabPages.Contains(Page))
TabCtrl.TabPages.Remove(Page);
}
}
}
}
private void VirtualChannelOpenEvent(uint openHandle, ChannelEvents openEvent, byte[] data, uint dataLength, uint totalLength, ChannelFlags dataFlags)
{
switch (openEvent)
{
case ChannelEvents.DataRecived:
int flag = (int)(dataFlags & ChannelFlags.Only);
WriteCore(data, dataLength);
OnDataArrived(dataLength, totalLength, (DataParts)flag);
break;
case ChannelEvents.WriteComplete:
write.Set();
break;
}
}
void WriteCore(byte[] data, uint count)
{
var mem = AllocateMemoryChunk(count);
Buffer.BlockCopy(data, 0, mem.Buffer, 0, (int)count);
lock (readlock)
{
buffers.Enqueue(mem);
AvailableDataLength += count;
}
}
public void Write(byte[] data, int offset, int count)
{
byte[] buff = data;
if (offset != 0)
{
buff = new byte[count];
Buffer.BlockCopy(data, offset, buff, 0, count);
}
write.Reset();
ChannelReturnCodes ret = Client.EntryPoint.VirtualChannelWrite(openChannel, buff, (uint)count, IntPtr.Zero);
write.WaitOne();
}
public int Read(byte[] buffer, int offset, int count)
{
if (AvailableDataLength > 0)
{
int toread = 0;
lock (readlock)
{
if (buffers.Count != 0)
{
var buf = buffers.Peek();
toread = buf.Buffer.Length - buf.Offset;
int off = buf.Offset;
if (count >= toread)
buffers.Dequeue();
else
{
toread = count;
buf.Offset += toread;
}
Buffer.BlockCopy(buf.Buffer, off, buffer, offset, toread);
AvailableDataLength -= (uint)toread;
}
return toread;
}
}
return 0;
}
TabPage Page = null;
TabControl TabCtrl = null;
RDPClient Client = null;
public uint AvailableDataLength { get; private set; }
internal ChannelReturnCodes ConnectedInternal(IntPtr Handle)
{
ChannelReturnCodes ret = Client.EntryPoint.VirtualChannelOpen(Handle, ref openChannel, Addin.Metadata.ChannelName, channelOpenEventDelegate);
if (ret == ChannelReturnCodes.Ok)
OnConnected(this, new EventArgs());
return ret;
}
internal void DisconnectedInternal()
{
openChannel = 0;
OnDisconnected(this, new EventArgs());
if (Stream != null)
{
Stream.Dispose();
Stream = null;
}
}
protected virtual void OnConnected(object sender, EventArgs e)
{
if (Connected != null)
DoOnUIThread(() => Connected(sender, e));
}
protected virtual void OnDisconnected(object sender, EventArgs e)
{
if (Disconnected != null)
DoOnUIThread(() => Disconnected(sender, e));
}
protected virtual void OnTerminated(object sender, EventArgs e)
{
if (Terminated != null)
DoOnUIThread(() => Terminated(sender, e));
}
internal void TerminatedInternal()
{
OnTerminated(this, new EventArgs());
}
protected virtual void OnInitialized(object sender, EventArgs e)
{
if (Initialized != null)
DoOnUIThread(() => Initialized(sender, e));
}
internal void InitializedInternal()
{
OnInitialized(this, new EventArgs());
}
public void ShowControl()
{
if (Page != null)
{
Client.MainForm.Visible = true;
Client.MainForm.Tab.SelectTab(Page);
}
}
public void DoOnUIThread(Action action)
{
if (Client.MainForm.InvokeRequired)
Client.MainForm.Invoke(action);
else
action();
}
public void ShowBalloonTip(int timeout, string tipTitle, string tipText, ToolTipIcon tipIcon, object context)
{
tooltipconext = context;
Client.MainForm.ShowToolTip(timeout, tipTitle, tipText, tipIcon, this);
}
protected virtual void OnDataArrived(uint dataLength, uint totalLength, DataParts dataFlags)
{
if (DataArrived != null)
DoOnUIThread(() => DataArrived(dataLength, totalLength, dataFlags));
}
internal protected virtual void OnBalloonTipClicked(object sender, EventArgs e)
{
if (BalloonTipClicked != null)
DoOnUIThread(() => BalloonTipClicked(this, tooltipconext));
}
private MemoryChunk AllocateMemoryChunk(uint newSize)
{
MemoryChunk chunk = new MemoryChunk(newSize);
return chunk;
}
ChannelStream Stream = null;
private class MemoryChunk
{
internal byte[] Buffer;
internal int Offset = 0;
internal MemoryChunk(uint bufferSize)
{
Buffer = new byte[bufferSize];
Offset = 0;
}
}
public event EventHandler Initialized;
public Stream GetStream()
{
Stream = Stream ?? new ChannelStream(this);
return Stream;
}
public IAddinMetadata Metadata { get { return Addin.Metadata; } }
public IUI UI { get { return this; } }
public event ControlCreatingHandler ControlCreating;
public event MenuCreatingHandler MenuCreating;
public event MenuCreatingHandler TrayMenuCreating;
public event IconCreatingHandler IconCreating;
internal void CreateUI()
{
if (ControlCreating != null)
{
var control = ControlCreating(this);
if (control != null)
{
Page = new TabPage(Metadata.AddinName);
TabCtrl = Page.Parent as TabControl;
control.Dock = DockStyle.Fill;
Page.Controls.Add(control);
Client.MainForm.Tab.TabPages.Add(Page);
Image icon = null;
if (IconCreating != null)
icon = IconCreating(this);
Page.ImageIndex = Client.MainForm.AddImage(icon);
}
}
if (MenuCreating != null)
{
var menu = MenuCreating(this);
if (menu != null)
{
var parentmenu = new MenuItem(Metadata.AddinName);
parentmenu.MenuItems.AddRange(menu.MenuItems.Cast<MenuItem>().ToArray());
Client.MainForm.MenuAddins.MenuItems.Add(parentmenu);
}
}
if (TrayMenuCreating != null)
{
var menu = TrayMenuCreating(this);
if (menu != null)
{
var parentmenu = new MenuItem(Metadata.AddinName);
parentmenu.MenuItems.AddRange(menu.MenuItems.Cast<MenuItem>().ToArray());
Client.MainForm.mnuAddinsContext.MenuItems.Add(parentmenu);
}
}
}
}
}