using System; using System.IO; using System.Windows.Forms; using System.IO.Compression; using System.Collections.Generic; using System.Threading.Tasks; using System.Threading; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; namespace FileTransfer { public partial class frmMain : Form { public frmMain() { InitializeComponent(); } IntPtr handle = IntPtr.Zero; FileStream fileStream = null; private void btLoadAndSend_Click(object sender, EventArgs e) { if (openFileDialog.ShowDialog() == DialogResult.OK) { try { var fileOpenPath = openFileDialog.FileName; btLoadAndSend.Enabled = false; Task.Factory.StartNew(() => { byte[] filename = System.Text.Encoding.UTF8.GetBytes(Path.GetFileName(fileOpenPath)); using (FileStream fs = File.OpenRead(fileOpenPath)) { fileStream.Write(BitConverter.GetBytes(fs.Length), 0, 8); fileStream.Write(BitConverter.GetBytes(filename.Length), 0, 4); fileStream.Write(filename, 0, filename.Length); fs.CopyTo(fileStream); fileStream.Flush(); } }).ContinueWith(task => { btLoadAndSend.Enabled = true; }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current); } catch (Exception ex) { btLoadAndSend.Enabled = true; MessageBox.Show("Somethings gone wrong:\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } static void StartFile(string filename) { Task.Factory.StartNew(() => { try { System.Diagnostics.Process.Start(filename); } catch { } }); } private void frmMain_Load(object sender, EventArgs e) { handle = WtsApi32.WTSVirtualChannelOpen(IntPtr.Zero, -1, "FTFTA1"); Task.Factory.StartNew(() => { IntPtr tempPointer = IntPtr.Zero; uint pointerLen = 0; if (WtsApi32.WTSVirtualChannelQuery(handle, WtsApi32.VirtualClass.FileHandle, out tempPointer, ref pointerLen)) { IntPtr realPointer = Marshal.ReadIntPtr(tempPointer); WtsApi32.WTSFreeMemory(tempPointer); var fileHandle = new SafeFileHandle(realPointer, false); fileStream = new FileStream(fileHandle, FileAccess.ReadWrite, 0x640, true); var os = new ObjectState(); os.RDPStream = fileStream; var iar = fileStream.BeginRead(os.Buffer, 0, 8, CallBack, os); } else Close(); }); } private void frmMain_FormClosed(object sender, FormClosedEventArgs e) { fileStream.Dispose(); bool ret = WtsApi32.WTSVirtualChannelClose(handle); } enum FileDownloadStatus { Length, NameLength, Name, Body, } class ObjectState { public int NameLength = 0; public string Name = string.Empty; public long Length = 0; public FileDownloadStatus State = FileDownloadStatus.Length; public byte[] Buffer = new byte[0x640]; public FileStream File = null; public FileStream RDPStream = null; } static void CallBack(IAsyncResult iar) { if (iar.IsCompleted || iar.CompletedSynchronously) { var os = iar.AsyncState as ObjectState; int readed = 0; try { readed = os.RDPStream.EndRead(iar); } catch (IOException ex) { MessageBox.Show(ex.Message); } if (readed != 0) { switch (os.State) { case FileDownloadStatus.Length: os.Length = BitConverter.ToInt64(os.Buffer, 0); os.State = FileDownloadStatus.NameLength; os.RDPStream.BeginRead(os.Buffer, 0, 4, CallBack, os); break; case FileDownloadStatus.NameLength: os.NameLength = BitConverter.ToInt32(os.Buffer, 0); os.State = FileDownloadStatus.Name; os.RDPStream.BeginRead(os.Buffer, 0, os.NameLength, CallBack, os); break; case FileDownloadStatus.Name: os.Name = Path.Combine(Path.GetTempPath(), System.Text.Encoding.UTF8.GetString(os.Buffer, 0, readed)); os.File = File.OpenWrite(os.Name); os.State = FileDownloadStatus.Body; os.RDPStream.BeginRead(os.Buffer, 0, Math.Min(os.Buffer.Length, (int)os.Length), CallBack, os); break; case FileDownloadStatus.Body: os.Length -= readed; os.File.Write(os.Buffer, 0, readed); if (os.Length == 0) { os.File.Dispose(); StartFile(os.Name); var newos = new ObjectState(); newos.RDPStream = os.RDPStream; os.RDPStream.BeginRead(newos.Buffer, 0, 8, CallBack, newos); } else { if (!os.RDPStream.SafeFileHandle.IsInvalid) os.RDPStream.BeginRead(os.Buffer, 0, Math.Min(os.Buffer.Length, (int)os.Length), CallBack, os); } break; } } } } } }