Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Remote Control PCs

0.00/5 (No votes)
20 Sep 2013 47  
Two projects that work together to remote control PCs across a LAN.

Introduction 

Here are two projects that work together to remote control PCs. This software only works for XP and above, and is very stable. The server can handle multiple clients, and each client can handle multiple connections to the same or different servers.

The projects are a server and client pair. The server is RDS, Remote Desktop Server, and the client is RDV, Remote Desktop Viewer. The executables are packaged up with the source code, and there are projects for Visual Studio 2005 and 2008. I built a custom project out of the zlib library and compiled it as a Windows library with the /MT settings. Both 32 and 64 bit library files, in Release and Debug mode, are included. The ZLIB.H and ZCONF.H files are also included. For examples of single-threaded usage, see the CZLib class. For examples of multi-threaded usage, see the classes CDriveMultiThreadedCompression, CMultiThreadedCompression, and CZLib.

The system can be broken into four main components:

  1. Network layer
  2. Compression layer
  3. Graphics layer
  4. Input layer

The network layer, CTCPSocket, relies on SOCKET events as provided by the O/S, and it then forwards them onto the message pump of the window that is expecting those messages. It has operator overloading, using << and >>, for sending and receiving data. The data is described by its own class in CPacket, and each type of packet has a constructor. The socket class is derived from CAsyncSocket. This class relies on network events, as relayed through the message pump, to notify the program when something interesting happens. Of note, the send function is the TransmitPackets function. The TransmitPackets function transmits in-memory data or file data over a connected socket. The TransmitPackets function uses the Operating System cache manager to retrieve file data, locking memory for the minimum time required to transmit, and resulting in efficient, high-performance transmission.

The compression layer can be compartmentalized in two parts with two categories in each part. The outer part is the threading model. The compression can either be done in single or multiple threads. For each kind of threading, there are available the zlib compressor and my own homegrown arithmetic encoder compressor. Compression occurs in the data packet that represents the bitmap data. My compressor was based on the knowledge of Jean-Loup Gailley and Mark Nelson in their book "The Data Compression Book - Second Edition" ISBN 1-55851-434-1.

The graphics layer is another area that is multi-threaded. This portion of the code has undergone significant improvements since the last version of the code. The system is over twice as fast now with this reworking of this section of code. The main body of the code creates a thread for each rectangular region of the screen which will be polled for changes. When a thread detects a change in its area, it posts a notification back to the main thread. The main thread then sends this packet onto all the connected clients. Each thread has an activity timer. The less frequent a change occurs, the less frequent that area is checked. When a change does occur in an area, the activity timer is reset to the shortest pause.

The input layer is in the client code. The client captures the mouse and keyboard events and sends them to the server. The server uses the SendInput function to act out these events.

TODO

There are two areas of the code which still need attention. The first area is adding the capability to interact with terminal server sessions and capture those desktops. Currently, the code can't see those desktops. I am researching this problem diligently because it irritates me. The second area is to add support for the DFMirage mirror driver. This is the mirror driver that Tight VNC uses. I'm not reusing the VNC code, but I will learn how to instantiate a mirrored device context to help my code know better about screen updates.

History

  • 20th October, 2009
    • This update adds MDI support to the system. The client component can now make multiple connections to many servers.
  • 17th October, 2009: Source code updated
    • The server now supports multiple monitor configurations. It captures the entire "virtual desktop". Previously, it only captured the primary desktop.
  • 9th October, 2009: Source code update that addresses three issues:
    • Binaries are added to the ZIP, in the Target Directory, for people to try out the system immediately.
    • Receiving data is faster now.
    • Experimental support for Video for Windows ICImageCompress and ICImageDecompress has been added.
  • 14th September, 2009
    • Updated to use a multithreaded arithmetic encoder. It uses four threads to concurrently encode the DIB data. It previously was just single threaded. It improves compression by about 40%.
  • 12th March, 2010
    • The solutions are now available in VS 2005 and VS 2008 projects.
  • 16th March, 2010
    • Minor update that adds the ZLIB code to the project files.
  • 30th March, 2010
    • This update is performance related. Memory allocations and network performance were improved. With the memory, the system minimizes the frequency of memory being allocated and released. During compression, the buffers are allocated once and resized as needed. With network performance, it improves the way the worker threads interact with the main thread. The main thread has been modified to look for another update after the first update, instead of waiting for the next iteration of the 0 millisecond timer message. This improves the overall performance of the system.
  • 2nd November, 2010
    • This update is performance related. The main changes center around the network connections. The network connections are now multi-threaded. This allows the server to concurrently send updates to the connected clients. For the client, it means a performance improvement in the UI. The network connection to the server and the UI are no longer in the same thread sharing the same message pump. The client now caches keyboard and mouse commands, which minimizes the lag of pressing a key and seeing it appear.

    Given below is a screenshot demonstrating remotely operating two machines over a WAN:

  • 10th November, 2010
    • This update addresses two items. The first item is stability. The second item adds a feature to the client that prevents resizing the window larger than the server's desktop screen size.
  • 1st December, 2010

    This update adds more stability, updates an item and adds two new items:

    • The system improves the stability between the client and the server.
    • The system changes the handshaking mechanism between the client and the server when a new connection is established. This means that previous versions of the system will not be compatible with this version.
    • The server now transmits cursor information to the client. The client's CScrollView window will now echo the cursor that is active on the server. The server code captures the cursor and breaks it down into data representing the monochrome bitmap and color bitmap of the icon as well as the other icon information. This data is transmitted to the client in a CPacket data structure. The client builds a cursor from this data and uses it for the active cursor of the CScrollView.
      • A CCursor class was added to DIBFrame.h which builds an HCURSOR.
    • The client will not resize larger than the server's virtual desktop size, and a "shrink to fit" option was added. This option allows the client to shrink the server display into the client view window. This option is accessed via the toolbar as a magnifying glass icon and also from the view menu. The system starts in a "zoomed in" state. Clicking the new toolbar button will "zoom out" the view.
      • For developers familiar with CScrollView, this is the functionality that is embodied in the function call "SetScaleToFitSize".
      • For CView derived classes, like CScrollView in this project, window sizing is actually tricky. The trick to limiting the size of the window can be accomplished by the code in RDVView.cpp, implementing the methods "OnSize" and "OnUpdate". The key is to use the functions "RecalcLayout" and "ResizeParentToFit".
  • 1st March, 2011

    This update improves performance by choosing good starting values for threads and grids. It also adds PNG file support using GDI+. This format compresses better than the DIB format.

    • Compression was delegated to the main thread's code to prevent over subscription of the hardware.
    • The data of the PNG format comes by using the CImage class.
      • For reading, the data is serialized to a COleStreamFile whose contents are extracted by calls to GetHGlobalFromStream and GlobalLock.
      • For writing, the data is serialized from a COleStreamFile whose contents are loaded into the CImage.
    • The server displays its public IP address (in case you are supporting your parents remotely and they don't know how to tell you their public IP address).
    • This update removes displaying the server's cursor on the client until the issue with it can be resolved.
    • This update only supports the VS2008 workspace. It should be easy enough to migrate the source code to the VS2005 project if that is what you use.
  • 12th March, 2011
    • This update reworks the graphics layer and adds ZLIB compression to the compression layer. The compression layer supports both single and multi-threaded use of ZLIB and Arithmetic Encoding. Overall, the system was redesigned for a multi-threaded environment.
  • 18th April, 2011
    • Source code updated. This update brings the cursor from the server to the client.
  • 22nd August, 2011
    • This update fixes the memory leak from using COleStreamFile.
  • 22nd July, 2012
    • This update distills the system to its simplest form.
    • UAC prompts are displayed on the non-secure desktop.
    • Replace auto_ptr<> with vector<> via recomendation of Davide Zaccanti
    • Thread cleanup code not dependent on m_hThread anymore
  • 10th September, 2013
    • Binary only update.  The system has been redesigned with 3 components.  RDS and RDV still exist but now communicate through RDP.  This allows a server to be deployed on the internet and both clients and servers connect through this proxy.  This lets us bypass the security problems of trying to make a peer to peer connection directly with the client
  • 19th September, 2013
    • Binary only update.  The system is faster, transmits the cursor, and has a donate button.  PM me if you are interested in the source code. 

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