Creating a Remote Desktop Plugin Using Delphi - Part 4

Now that we have the client side ready to receive data from the server we need to look at programming the server side.  This actually seems to be quite a bit simpler that the client side.  There are just four functions; WTSVirtualChannelOpen, WTSVirtualChannelClose, WTSVirtualChannelRead and WTSVirtualWrite.  Actually, there are a few more, but these are the ones that you need to get by.

Once I added the new functions to my virtual channel type definitions it simply became a matter of knocking together a simple VCL forms application with a few buttons to initiate opening, closing, reading and writing the virtual channel.

To open the virtual channel, just call WTSVirtualChannelOpen passing the name of the virtual channel that we passed to VirtualChannelInit on the client side.


var
  err: Integer;
begin
  FChannelHandle := WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE,
              WTS_CURRENT_SESSION,
               'AurScan');
  if (FChannelHandle = 0) then
  begin
    err := GetLastError;
    raise Exception.CreateFmt('Open failed! Error = %d.', [err]);
  end;
end;

To close the channel, just call WTSVirtualChannelClose passing the channel handle returned by WTSVirtualChannelOpen.


var
  err: Integer;
begin
  if (not WTSVirtualChannelClose(FChannelHandle)) then
  begin
    err := GetLastError;
    raise Exception.CreateFmt('Close failed! Error = %d.', [err]);
  end;
end;

To write to the virtual channel, call WTSVirtualChannelWrite passing the channel handle, a buffer pointer and the length of the buffer.


var
  len: Integer;
  i: Integer;
  bfr: PAnsiChar;
  bytesWritten: Cardinal;
  err: Integer;
begin
  if (not TryStrToInt(BfrSize.Text, len)) then
  begin
    BfrSize.SetFocus;
    raise Exception.Create('Buffer size invalid');
  end;
  if (len = 0) then
  begin
    BfrSize.SetFocus;
    raise Exception.Create('Please enter the buffer size');
  end;
  GetMem(bfr, len);
  try
    for i := 0 to len - 1 do
      (bfr + i)^ := AnsiChar((i mod 10) + Byte(AnsiChar('0')));
    if (not WTSVirtualChannelWrite(FChannelHandle,
              PByte(bfr),
              len,
              bytesWritten)) then
    begin
      err := GetLastError;
      raise Exception.CreateFmt('Write failed! Error = %d.', [err]);
    end;
  finally
    FreeMem(bfr);
  end;
end;

The source code for the plugin as it stands so far is available here.

The first article of the series is here.

Leave a Reply