Remote Desktop View Lite

Remote Desktop Viewer Lite: A System to Remotely Monitor Desktop Activity

This system is designed to view a remote desktop’s activity. It is composed of three Visual C++ .NET 2003 projects.

Quick Compress: A Compression COM Object

Quick Compress is a previous project that I have uploaded. I will briefly sum it up here. It is a ATL/COM component that performs Huffman compression and run length encoding. Both methods are written directly in assembler for optimized performance.

  • Huffman compression deals with minimum data redundancy by using a Huffman encoding tree.
  • Run length encoding deals with packing up like data into a packet containing the byte and the run length.
  • RemoteDesktopService and RemoteDesktop both call on it to compress and uncompress the data.
  • RemoteDesktopService first run length encodes the data; then it passes over the data multiple times with the Huffman encoding scheme to achieve the maximum minimum redundancy.
  • RemoteDesktop reverses the steps of RemoteDesktopService.

RemoteDesktopService: A Win32 Console Application that Creates an Installable Service

The service, when running, accepts TCP/IP connections and then streams the desktop out to the connection. If it weren’t for MSDN and its sample code, I wouldn’t have been able to have a rapid turnaround on the development of the service. Please refer to the article “Creating a Simple Win32 Service in C++” by Nigel Thompson. It is located in the section DLLs, Processes, and Threads Technical Articles. I used this program as my foundation for my service.

A Windows registration file fine tunes the service’s behavior. It controls the socket connectivity parameters, the bit depth of the display, the port to allow connections, an optional password required to make a successful connection, the number of threads dedicated to updating the display, and the delay between capturing the display and sending. If no registration file is installed, the program uses intelligent defaults.

The socket connectivity parameters should not be adjusted unless you really know what you are doing. Here is a breakdown of their behavior:

    • MaxBlock: The number of times to block for “MinWait” microseconds on a socket for data. Default is “10”
    • MinWait: The number of microseconds to block for data on a socket. Blocking implies a slice of time where the socket is queried for its status. The status can indicate many states including lost connectivity and data present on the port for reading. These last two are uses I make of blocking in the code. Default is “100000”
    • MaxPacket: The maximum attempted send size of a data packet. In most cases, the real amount of data sent will be less, but the attempted send size will always be transmitted. The default setting is 65 Kbytes. Default is “65536”

The bit depth of the captured display. Default is “16”. “BitCount” can only be the following values; changing it to another value is undefined behavior and usually causes a failure in the GDI system.

      • 4: a 16-color gray scale palette
      • 8: a 256-color gray scale palette (best economical setting)
      • 16: 2^16 colors
      • 24: 2^24 colors
      • 32: 2^32 colors (true color)
    • The server port that listens for incoming connections and password.
      • ServerPort: Should be in the range of 1025 to 65535. The default is “8370”, which is the day when Mr. Gravy entered this world.
      • Password: The plain text password that allows clients a connection. Default is “pass”
      • Delay: The amount of time in milliseconds to sleep after a screen has been sent to the client. Default is “250”
      • DisplayBands: The number of threads dedicated to monitoring the screen for changes and sending these onto the client. This parameter must be divisible by the number of Y pixels of the display. Default is “32”

If ‘DisplayBands’ are set to ‘4’ and the height of the display is 1024, the breakdown on each thread is as follows. The more threads, the less data that each connection must send to the client.

      1. Thread 1 monitors Y from 0-255
      2. Thread 2 monitors Y from 256-511
      3. Thread 3 monitors Y from 512-767
      4. Thread 4 monitors Y from 768-1023

This service runs using the following design:

    1. The main thread of execution listens on the port for new connections.

Upon a new connection, a packet of data is sent to the client that describes the following in the list below. The client uses this data to construct empty DIBs that will accept the servers DIB data. It also allows for maximized performance in the number of ports for the client to make successive connections. This reduces the load on any one connection for sending back DIB data to the client.

    • Initial port
    • Number of ports to connect with
    • The screen width, height, and bit depth
  1. The main thread then listens for connections starting on the initial port and numbering the number of ports. This connection is then handled in a seperate thread. The thread is created suspended until all connections are made. This keeps the early connections from overloading the pipe with DIB data that will prevent connectivity timeouts. If any of the connections fail, all client connections are terminated.
  2. All new connections are then handled in a seperate thread of execution.
    • Each thread is a “desktop” entity composed of GDI components.
    • When the threads connection to the client (the accepted socket) detects a lost connection, it ends.
    • In this way, multiple clients can simultaneously view the machine. A new client will connect with the server and the server will negotiate different ports for it to connect.

RemoteDesktop: A Win32 MFC SDI Application that Displays the Remote Desktop in the SDI Document and Allows Scrolling Around the Document

Choosing this type of project for this application did not come litely. When I was a brand-new Windows 95 programmer using C and the Win32 API solely, I would have balked at such a monstrosity. Back then, I wanted to write boilerplate code because learning Windows programming requires getting your hands dirty. Well, many years have passed since then and my zeal is about sharing the important part of my code with you.

This is a pretty simple SDI application. It derives from CScrollView because of the wonder that class provides for scrolling around the document. So much for handling WM_HSCROLL and WM_VSCROLL. Oh well, in the name of progress, I suppose this is all right.

To connect to the server, use the ‘New Connection’ toolbar button. The new connection dialog is displayed.

  1. Enter the server name or IP.
  2. Enter the server’s negotiation port.
  3. Enter the password (sent plain text).

In case of an error in connection, no real message is displayed. However, if you are in debug mode, you will see an error message in the debug output.

To disconnect from the server, use ‘Close Connection’.

The RemoteDesktop uses the Registry to save some common settings. The Registry is not required because intelligent defaults are used. All Registry keys are stored in HKEY_CURRENT_USERSoftwareGravyLabsRemoteDesktop.

The socket connectivity parameters should not be adjusted unless you really know what you are doing. Here is a breakdown of their behavior:

  • MaxBlock: The number of times to block for “MinWait” microseconds on a socket for data. Default is “10”
  • MinWait: The number of microseconds to block for data on a socket. Blocking implies a slice of time where the socket is queried for its status. The status can indicate many states, including lost connectivity and data present on the port for reading. These last two are uses I make of blocking in the code. Default is “100000”
  • MaxPacket: The maximum attempted send size of a data packet. In most cases, the real amount of data sent will be less, but the attempted send size will always be transmitted. The default setting is 65 Kbytes. Default is “65536”
  • Host: The server name or IP address to make a connection. The default is “localhost”
  • Port: The server negotiation port. The default is “8370”
  • Password: The password to make a connection. The default is “pass”

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read