Click here to Skip to main content
Click here to Skip to main content

Remote Desktop Viewer Lite

, 11 Oct 2005
Rate this:
Please Sign up or sign in to vote.
The Remote Desktop Viewer Lite is a system to remotely monitor desktop activity. This system is designed to view a remote desktop's activity.

Introduction

The Remote Desktop Viewer Lite is 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

  1. Quick Compress - A compression COM object.

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

    RemoteDesktopService and RemoteDesktop both call on it to compress and uncompress the data.

  2. 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 sample code, I wouldn't have been able to have a rapid turn around 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 in Technical Articles. I used this program as the foundation for my service.

    A Windows registration file fine tunes the behavior of the service. It controls the socket connectivity parameters, the bit depth of the display, the port to allow connections, and an optional password required to make a successful connection. If no registration file is installed, the program uses intelligent defaults, except it will use true color because it looks the best.

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

    1. “MaxBlock” - The number of times to block for “MinWait” microseconds on a socket for data.
    2. “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.
    3. “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.
    4. “BitCount” - The bit depth of the captured display.

      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).
    5. The server port which listens for incoming connections and password.
      • 'ServerPort' – Should be in the range of 1025 to 65535. The default is 8370 in honor of my birth date.
      • 'Password' – The plain text password that allows clients a connection.

    This service runs using the following design:

    • The main thread of execution listens on the port for new connections.
    • New connections are then handled in a separate thread of execution.
      1. Each thread is a “desktop” entity composed of GDI components.
      2. When the thread's connection to the client (the accepted socket) detects a lost connection, it ends.
      3. In this way, multiple clients can simultaneously view the machine.
  3. 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 a project for this application did not come lightly. 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 the boiler plate 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 OK.

    To connect to the server, use the 'New Connection'. 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 the 'Close Connection'.

The Service

The service itself is its own installer and uninstaller.

  1. To install the service issue the following command:
    RemoteDesktopService -i
  2. To uninstall the service issue the following command:
    RemoteDesktopService -u

Data Flow

Data flows from the client to the server and back.

  1. Client initiates a connection to the server on the server IP or name. DNS or host entries are required for name resolution.
  2. Client sends the password, or 1 byte null character for no password.
  3. Server receives the connection and spawns a thread for handling the connection.
  4. Server sends the bit depth, the width, and the height of its desktop.
  5. Client receives the bit depth, the width, and the height.
  6. Server captures and sends the desktop to the client.
  7. Client receives the desktop and acknowledges receipt.
  8. Repeat steps 6-7 until the client closes the connection.
  9. Server ends the thread that handles the client's connection.

Data Compression

We will see how data compression is integrated into the data flow.

If the server simply sent the desktop every time it changed, that wouldn't be very optimal at all. A few techniques have been added to get the size down.

  1. The server starts with two empty DIB buffers.
    1. Buffer 1 is the current desktop.
    2. Buffer 2 is the last desktop.
  2. The current desktop is captured and XOR'ed with the last desktop.

    This step masks out all the common bits of each desktop.

  3. The XOR'ed desktop is run length encoded to take advantage of high encodeability of the masked out bits.
  4. The resultant desktop is then Huffman compressed to achieve minimum redundancy of the data.

    Please refer to my other article for a breakdown of the compression and encoding techniques.

  5. The desktop is sent to the client.
  6. The client Huffman decompresses.
  7. The client run length decodes.
  8. The client XOR's with the last desktop.

The key to keeping the data is the initial second buffer, or the “last desktop”. The code uses a DIB that is filled with the color black in both the client and the server applications.

For fun you can fool around with the raster codes of these original buffers. You may get some strange kaleidoscopic effects. Just put on your favorite classic rock and trance with it.

TCP/IP connectivity

The socket class: there is a custom, home grown socket class that handles all the communication from the client and server. Who doesn't like writing their own socket classes? It's a rite of passage as far as I am concerned. It is a robust enough class that is decently lightweight and does the trick. It has solid error detection and graceful behaviors when connectivity is lost or can't be established. It simply focuses on the Berkeley subset of socket functions available on Win32 API. I am going to leave it to the reader to break down this class.

Debug versus Release modes

Debug mode contains informative output for most of the system. Using the debug viewer from SysInternals is a good way to see what is going on. Another way is to run the program in the debugger and pay attention to the 'Output' tab. In the service you will have to attach to the process to get the same thing. Services can't be run like other programs but they can be debugged when you attach to them. Be prepared for Visual Studio to crash here from time to time. It sometimes has problems enumerating the processes. I've sent 20 error reports to Microsoft when I was deep in the development of this. Lucky for me that the program creates its own report and asked me if I wanted to send it on. I enjoyed spamming Microsoft with these reports.

Building and Running the System

  1. Extract the RDVL.zip file to a folder location that suits you best.

    The zip contains all the source code and projects.

  2. Load up RDVL.sln into your Visual C++ .NET 2003 Studio.
  3. Rebuild the entire solution.
    1. After building the solution for the first time, the service will have to be installed and manually started before it will serve up desktops.
      1. The Services Control Panel applet of the Administrative Tools can be used to do this.
      2. The 'net start' DOS command can also be used to do this.
    2. The ATL/COM object builds and registers itself to the machine.

      If you redistribute the application make sure to put the QuickCompress.dll in the application path.

      1. You won't have to register it on an enduser machine.
      2. The code does a smart register and unregister of this component when the client or service starts up. As long as the DLL is in the application path you will be OK.
  4. Run the client and connect to 'localhost', this resolves to 127.0.0.1, and if you see your desktop appearing in the client window then all is working as it should.

Compression Ratios

The following chart shows some typical compression ratios using a 1280 x 960 resolution display. In debug mode the actual amount of data that is sent for each desktop is sent to the debugger output.

  • 32 bpp
    • First frame is about 4 MB, compression brings it down to 1 MB.
    • Second frame, with no visible change, will drop down to about 8 KB.
  • 8 bpp
    • First frame is about 100 KB after compression.
    • Second frame, with no visible change, will drop down to about 1 KB.

What is next?

(You wondered why I called it the lite version.)

Good question.

  1. Integrate the controlling component into the application.
  2. Not send duplicate screens is a nice and easy optimization.
  3. Multiple socket connections to the clients.

    Each socket represents a grid of the screen and is responsible for sending only its data. This concept helps leverage the power of your networking to handle more than one data stream at a time.

    I've contemplated on a screen divided into 4 areas ought to deliver the best performance and compression.

  4. Mirror Driver

    Ahh.. the real deal here. This is where I am ultimately headed. I have the Windows DDK which describes how to build a graphics mirror driver.

    1. A mirror driver simply echoes all graphical operations to the mirror display.
    2. Integrating with a mirror driver, the key behind VNC, is what really delivers performance.

      Balancing this type of graphical refresh with my method ought to really deliver a punch and make this program a real contender to VNC.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Andy Bantly
Founder
United States United States
Working as a software developer since 1989. Started out with Basic, FORTRAN and JCL, moved into Visual Basic 1.0, C, then C++, and now I work mainly in C++ using MFC, Win32, and ATL/COM. I use Microsoft Products only because that is what gives me gainful employment. Through work, I have a lot of experience with HTML, JavaScript, XSL transformations, the XMLHTTP object, PHP 4.x, and simple COM object integrations.
 
I've worked for the University of Oklahoma in the school of meteorology (Go SOONERS!), consulting, and now as a Senior Software Engineer. These things keep my lights on and electricity going. My dream job is to own a bowling alley and rub elbows with pro-bowlers! I'm also an avid pedicab driver and have my own cab. I like the hustle of picking up people in downtown and biking them to their destination.
Follow on   Google+   LinkedIn

Comments and Discussions

 
Questionip address parsing PinmemberC++learner20-Nov-13 7:48 
AnswerRe: ip address parsing PinmemberAndy Bantly20-Nov-13 9:15 
QuestionThis code is deprecated PinmemberAndy Bantly8-Nov-13 5:48 
Questiongood project [modified] PinmemberMember 103869438-Nov-13 5:24 
AnswerRe: RDP is failing not taking more than 3 connections PinmemberAndy Bantly8-Nov-13 5:47 
GeneralRe: RDP is failing not taking more than 3 connections PinmemberMember 103869438-Nov-13 7:25 
GeneralRe: RDP is failing not taking more than 3 connections PinmemberAndy Bantly8-Nov-13 11:21 
QuestionUpdating RDVL(v2).net 2003 To VS 2010 PinmemberMember 98809563-Mar-13 22:31 
Hello. Bantly!
Your project(revl) is so Excellent!
 
And...Thank you for your sample!
 
I am downloading your sample rdvl ver2 and studying it
 
it works well on vs.net2003 ,
but it doesn.t work 2010..
so I debugger and fix it
 
Finally! I managed to Fixed...
But click ok in remotedesktopview and connect to remotedesktopview
it works well but image is crahsed..
 
Please share your update version (vs 2008 or vs2010)
 
I am thirty for your help!
 
My e-mail Address is khd1017@empas.com
 
thanks so much!
AnswerRe: Updating RDVL(v2).net 2003 To VS 2010 PinmemberAndy Bantly7-Mar-13 5:54 
GeneralMy vote of 5 Pinmemberblpandya31-Jul-12 0:04 
GeneralRe: My vote of 5 PinmemberAndy Bantly7-Mar-13 5:55 
Generalhello Pinmembersmart_kh2-Dec-11 0:40 
QuestionNothing displayed PinmemberSaaf 787994424-Oct-11 19:03 
GeneralA little Slow PinmemberAddwhy11-Feb-10 23:26 
GeneralRe: A little Slow PinmemberAndy Bantly12-Feb-10 3:11 
GeneralUpdate to the article PinmemberAndy Bantly5-Oct-09 10:49 
GeneralRe: Update to the article - What happened to the update? PinmemberJon68z23-Oct-09 4:50 
GeneralRe: Update to the article - What happened to the update? PinmemberAndy Bantly23-Oct-09 12:47 
Generaldoesnt work 2008 + vista 64 Pinmembermikejobu2310-Sep-09 0:50 
QuestionCan implement same concept in PHP PinmemberHarold_audi21-Jul-09 9:25 
Generalslow! Pinmemberaihuazhiren30-Jun-09 16:43 
GeneralUnable to connect to remote Desktop Pinmembermbcvamsidhar7-May-09 19:23 
Questionexecutables Pinmemberjqt3-Apr-07 11:25 
GeneralLooks like we could use some help... PinmemberWhiteSpy21-Mar-07 4:27 
Generalhelp! Pinmemberbrac29020-Feb-07 6:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 11 Oct 2005
Article Copyright 2005 by Andy Bantly
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid