Thread: Win32 Screenshot bits

  1. #1
    Rat with a C++ compiler Rodaxoleaux's Avatar
    Join Date
    Sep 2011
    Location
    ntdll.dll
    Posts
    203

    Win32 Screenshot bits

    I'm not sure if it's the transfer that's causing the problem but I am trying to take a screen capture and send the bits across a socket. I am... confident I have the bits correctly but... perhaps not since I'm still having a problem. Is there anything wrong that I may have missed here while getting the bits?

    Code:
    HDC hdc    = GetDC(NULL);
                            HDC dskt   = GetDC(GetDesktopWindow());
                            HDC hDest  = CreateCompatibleDC(dskt);
    
    
                            int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
                            int width  = GetSystemMetrics(SM_CXVIRTUALSCREEN);
    
    
                            cout << "Creating compatible bitmap" << endl;
                            HBITMAP hbDesktop = CreateCompatibleBitmap( hdc, width, height);
                            cout << "Done" << endl;
    
    
                            SelectObject(hDest, hbDesktop);
    
    
                            cout << "Blitting" << endl;
                            BitBlt(hDest, 0,0, width, height, hdc, 0, 0, SRCCOPY);
                            cout << "Done" << endl;
    
    
                            BITMAP bt;
    
    
                            GetObject(hbDesktop,sizeof(BITMAP),&bt);
    
    
                            BITMAPFILEHEADER bmfHeader;
                            BITMAPINFOHEADER bi;
    
    
                            bi.biSize = sizeof(BITMAPINFOHEADER);
                            bi.biWidth = width;
                            bi.biHeight = height;
                            bi.biPlanes = 1;
                            bi.biBitCount = 32;
                            bi.biCompression = BI_RGB;
                            bi.biSizeImage = 0;
                            bi.biXPelsPerMeter = 0;
                            bi.biYPelsPerMeter = 0;
                            bi.biClrUsed = 0;
                            bi.biClrImportant = 0;
    
    
                            DWORD bmpSize = ((width*bi.biBitCount+31)/32)*4*height;
    
    
                            cout << "Needed size: " << bmpSize << endl;
    
    
                            HANDLE hDIB = GlobalAlloc(GHND,bmpSize);
                            char* bits = (char*)GlobalLock(hDIB);
    
    
                            GetDIBits(dskt,hbDesktop,0,
                                      height,bits,
                                      (BITMAPINFO*)&bi,
                                      DIB_RGB_COLORS);
    
    
                            s.Send(RKL_WIDTH_SND);
                            if (s.Receive().compare(RKL_WIDTH_RECVD) != 0)
                            {
                                cout << "Failed to receive the width data confirmation" << endl;
                                continue;
                            }
                            char width_c[65]; //64 bit compatible
                            char height_c[65];
    
    
                            itoa(width,width_c,10);
                            s.Send(width_c);
                            s.Receive();
    
    
                            s.Send(RKL_HEIGHT_SND);
                            if (s.Receive().compare(RKL_HEIGHT_RECVD) != 0)
                            {
                                cout << "Failed to receive the height data confirmation" << endl;
                                continue;
                            }
                            itoa(height,height_c,10);
                            s.Send(height_c);
                            s.Receive();
    
    
                            cout << "Sending bits" << endl;
                            s.Send(bits);
                            cout << "Done" << endl;
                            s.Receive();
    
    
                            GlobalUnlock(hDIB);
                            GlobalFree(hDIB);
    
    
                            DeleteObject(hbDesktop);
                            DeleteObject(hDest);
                            ReleaseDC(NULL,hdc);
                            ReleaseDC(GetDesktopWindow(),dskt);
    s is an instance of a "home-made" socket class. Send and Receive are just as they are. Send() sends an std::string. When I try a reinterpret_cast to a char* from getting bits, the application crashes. I suppose that's why I'm a little sceptical.
    How to ask smart questions
    Code:
    DWORD dwBytesOverwritten;
    BYTE rgucOverWrite[] = {0xe9,0,0,0,0};
    WriteProcessMemory(hTaskManager,(LPVOID)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtQuerySystemInformation"),rgucOverWrite,5,&dwBytesOverwritten);

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Just how does your s.Send() actually figure out how much data to send?

    s.Send(RKL_HEIGHT_SND);
    s.Send(height_c);
    s.Send(bits);

    I've no idea what RKL_HEIGHT_SND is, perhaps it's a std::string as you say in your description.

    height_c would work OK, since it is a nul-terminated string. Conversion to a std::string would be easy enough.

    bits on the other hand is totally screwed, since there is no way to work out how much data there is, simply by examining the data it points to.

    Overload your send function as follows
    Code:
    Send(std::string s);
    Send(const char *s, size_t len = 0);
    In the last case, send 'len' chars if len is greater than 0, otherwise send up to the first nul character (it's a normal C string).

    Sending bits would be
    s.Send(bits,bmpSize);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Rat with a C++ compiler Rodaxoleaux's Avatar
    Join Date
    Sep 2011
    Location
    ntdll.dll
    Posts
    203
    That's true. Same for the Receive() function that adds all data received to an std::string. Thank you. I forgot about that. So that does mean that I am getting the bits right? Perhaps I'm setting them wrong then...

    Yes RKL_WIDTH_SEND is a basic little numeric string. Basically a packet ID so the server knows what it is receiving.
    Last edited by Rodaxoleaux; 05-23-2012 at 08:00 AM.
    How to ask smart questions
    Code:
    DWORD dwBytesOverwritten;
    BYTE rgucOverWrite[] = {0xe9,0,0,0,0};
    WriteProcessMemory(hTaskManager,(LPVOID)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtQuerySystemInformation"),rgucOverWrite,5,&dwBytesOverwritten);

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Are you really going to send an uncompressed bitmap across a socket? Wow. I would look into compressing it or at least run-length encoding it. If this is a 24-bit image RLE probably will not do much but it's better than nothing. Also it looks like your send is blocking which is also bad news since an uncompressed bitmap can be gigantic which means the rest of your program will just sit there while it waits for the send to complete.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screenshot OCR SDK
    By texasnomad in forum C++ Programming
    Replies: 0
    Last Post: 04-06-2011, 08:29 AM
  2. Extracting certain bits from sequence of bits
    By lucaspewkas in forum C Programming
    Replies: 5
    Last Post: 10-06-2007, 12:22 AM
  3. take screenshot
    By MeGaBiTe1 in forum Windows Programming
    Replies: 2
    Last Post: 09-02-2004, 10:33 PM
  4. New idea on conveting byte to bits/bits to byte
    By megablue in forum C Programming
    Replies: 10
    Last Post: 10-26-2003, 01:16 AM
  5. copy some bits into a 8 bits binary number
    By Unregistered in forum C Programming
    Replies: 6
    Last Post: 05-29-2002, 10:54 AM