0

I am trying to build a keylogger in C++. Part of my keylogger is to capture the screen.
After a lot of searching, I decided to try to understand how it works instantly by trying to build one.

This is my screen capture code:

    HDC hdc = GetDC(NULL); // get the desktop device context
    HDC hDest = CreateCompatibleDC(hdc); // create a device context to use yourself

    // get the height and width of the screen
    int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
    int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);

    // create a bitmap
    HBITMAP hbDesktop = CreateCompatibleBitmap(hdc, width, height);

    // use the previously created device context with the bitmap
    SelectObject(hDest, hbDesktop);

    // copy from the desktop device context to the bitmap device context
    // call this once per 'frame'
    BitBlt(hDest, 0, 0, width, height, hdc, 0, 0, SRCCOPY);

    /*CImage image; // from this code i tried to understand how to save the bitmap
    image.Attach(hbDesktop); 
    image.Save(pathname, Gdiplus::ImageFormatBMP);*/

    CImage image;//this code is what I came up with eventually
    image.Attach(hbDesktop);
    CHAR buffer[100] = _T("this is a literal string");  // THIS IS WHERE MY PROBLEM STARTS 
    sprintf(buffer,_T("this is a literal string"), 1);
    image.Save(_T(buffer), Gdiplus::ImageFormatBMP);

I tried to make the program save the bitmap file each time with a different name. The problem is that the last line doesn't work unless I use _T sign, and when I do put the _T, it won't take the buffer and says "identifier "Lbuffer" is undefined". What does this mean? Where do I need to put this L sign and why? Also, is there a better way to save bitmap to a file without using this _T sign?

I've tried to look this up, and on https://msdn.microsoft.com/en-us/library/dybsewaf.aspx they say this is about Unicode. Why do I need Unicode for this function?

IMSoP
  • 89,526
  • 13
  • 117
  • 169
Mendy Shif
  • 69
  • 1
  • 1
  • 5
  • Sorry, even after reading the link still I did not understand the subject I'd be happy if someone could explain to me with an example of the code I brought Thank you very much to assistants – Mendy Shif Mar 07 '15 at 17:25

1 Answers1

16

_T(), and its Win32 equivilent TEXT(), are preprocessor macros that prepend the input value with L if _UNICODE or UNICODE are defined, respectively.

These macros are meant to be used with character/string literals only. You cannot use them with variables. So _T(buffer) is not valid code. That is why you are getting an identifer "Lbuffer" not defined error (_UNICODE is obviously defined in your project).

If _UNICODE/UNICODE are defined, _T("literal") and TEXT("literal") are evaluated by the compiler as L"literal" - a wide string literal of type wchar_t[].

If _UNICODE/UNICODE are not defined, _T("literal") and TEXT("literal") are evaluated by the compiler as "literal" - a narrow string literal of type char[].

CHAR is not a macro, it is a typedef for char, and is unconditional (there is an equivalent WCHAR typedef for wchar_t).

Thus, this line:

CHAR buffer[100] = _T("this is a literal string");

Is evaluated as this:

// when _UNICODE is defined
char buffer[100] = L"this is a literal string"; // DOES NOT COMPILE!
// You cannot assign/fill a char[] array with wchar_t data!

// when _UNICODE is not defined
char buffer[100] = "this is a literal string"; // OK

If you want to use _T()/TEXT(), you must use _TCHAR/TCHAR instead of CHAR so they match:

_TCHAR buffer[100] = _T("this is a literal string");

_TCHAR/TCHAR are _UNICODE/UNICODE-sensitive preprocessor #defines. When _UNICODE/UNICODE are defined, they resolve to wchar_t, otherwise they resolve to char instead:

// when _UNICODE is defined
wchar_t buffer[100] = L"this is a literal string"; // OK

// when _UNICODE is not defined
char buffer[100] = "this is a literal string"; // OK

sprint() only works with char data. The wchar_t version is swprintf(), and the _TCHAR/TCHAR version is _stprintf():

char buffer[100];
sprintf(buffer, "this is a literal string", 1); // OK

wchar_t buffer[100];
swprintf(buffer, L"this is a literal string", 1); // OK

_TCHAR buffer[100];
_stprintf(buffer, _T("this is a literal string"), 1); // OK

CImage::Save() accepts a LPCTSTR as input. LPCTSTR is a typedef for const TCHAR*, thus resolves to const wchar_t* when UNICODE is defined, otherwise resolves to const char*. As it is UNICODE-sensitive, but your buffer is always a char[], you will not be able to pass buffer to Save() if UNICODE is defined. You need to use TCHAR instead:

// In this case, you should use the Win32 macros instead of the C macros.
// It is not good practice to mix C's _T()/_TCHAR macros with Win32 APIs,
// and Win32's TEXT()/TCHAR macros with C APIs, though technically it will
// work fine.  Best to keep the two APIs separate...

TCHAR buffer[100];
_stprintf(buffer, TEXT("filename_%d.bmp"), 1);
image.Save(buffer, Gdiplus::ImageFormatBMP);    
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770