Write an RDP client that dumps the pixels of the screen

1.9k Views Asked by At

I would like to implement a RDP client in C++ that is able to get the color value of all pixels of the screen and dump them to a file. I know this is conceptually different from how RDP works but I need it for my application. I am trying to make use of freerdp but I am not sure how can I efficiently write a client that simply dumps all pixels in a file.

So far my best attempt is making use of the function gdi_GetPixel_32bpp but of course calling this function for each pixel in turn is far from efficient.

A solution that makes use of another library will also be greatly appreciated.

4

There are 4 best solutions below

5
On

Well you could try to this (disclaimer untested pseudo code):

HGDI_DC memDC = gdi_CreateCompatibleDC ( hDC );
HGDI_BITMAP memBM = gdi_CreateCompatibleBitmap ( hDC, screenWidth, screenHeight );
gdi_SelectObject ( memDC, memBM );
gdi_BitBlt(memDC, 0, 0, screenWidth, screenHeight, hDC, 0, 0, GDI_SRCCOPY);

Now you should have in memBM->data the complete array of pixel data. memBM->data has the following size: memBM->width * memBM->height * memBM->bytesPerPixel

Hope that this helps you at least somewhat.

2
On

If you run a VNC X server and start the RDP client fullscreen inside it (with no window manager etc.), the drawing sequence should be something like:

  1. RDP client receives an update from the remote session
  2. RDP client translates update into X11 messages, most likely sent over the shared memory transport
  3. VNC server receives X11 requests and uses them to render a bitmap

so the overhead should just be the X11 protocol, which is admittedly clunky but should at least be sent through a shared memory segment.

Honestly, I'd try this zero coding approach first, and see if performance is really a problem.

2
On

WebRTC may have some code you can look at to help, like the screen capturer or window capturer.

The desktop capturer is more complicated because it does (1) diffing to capture minimal contents, and (2) captures the mouse as well. Since the desktop is just a special "window", as retrieved with ::GetDesktopWindow(), and its DC can be retrieved with that window or just GetDC(NULL), you can use the window capturer and ignore the more complicated bits. Check the window capturer's Capture function for the details, as well as some helpful hints around handling Aero and other compositing/offscreen issues.

0
On

This should be fairly easy to do in a very efficient way using libfreerdp-gdi. FreeRDP can render everything to a software buffer which you can then dump to a file, and you can do this entirely in memory, without an X11 environment, if you wish. Since Linux is mentioned, one quick way to get started would be to use xfreerdp with the /gdi:sw option to make use of libfreerdp-gdi (the default is to use an X11-based implementation) and to then dump the pixels as updates come in. You can hook yourself in xf_sw_end_paint, which is called at the end of an array of updates. You have access to the invalid region and the pixel buffer (all under the rdpGdi* gdi structure). Important fields are gdi->primary_buffer, gdi->dstBpp, gdi->bytesPerPixel, gdi->width and gdi->height. In most cases you will get an XRGB32 buffer, which is easy to deal with. In doubt, take a look at gdi_init() for the initialization of the internal buffer.