C++ TextOut writes random data. Is there a buffer overflow? - c++

I'm writing some example programs for a programming class using WinAPI. I'm familiar with GUI programming, but not in C++. As part of a test I ran into an anomaly. I'm hoping someone will know what I'm doing wrong and be able to explain the fix. Below is the callback function. Most of the code was copied directly from an example on basic paint.
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
PAINTSTRUCT ps;
HDC hdc;
std::string txt = "Hello\0";
switch(msg)
{
hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 0, 60, txt.c_str(), 45);
EndPain, h, &ps);
}
}
So, the function is supposed to simply print "Hello" on the GUI, but instead I was seeting "Hello xc". I expanded the length of the string to 45 and saw a lot more. It prints random bits of text. I've seen class names and string values which were going to cout.
I have no idea why this is happening, but it appears that txt is being read far past the end of the buffer. I added a \0. No difference. The value is different every time.
Any idea what is going on?

TextOut uses the final parameter cchString to determine how many characters to print. You must tell it the correct number.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd145133.aspx
lpString [in]
A pointer to the string to be drawn. The string does not need to be zero-terminated, because cchString specifies the length of the string.
cchString [in]
The length of the string pointed to by lpString, in characters.

TextOut() does not stop writing text at the null terminator, it will just keep going for as long as you specified. The last parameter tells the function how many characters to write. Instead of giving it 45, give it something like strlen(txt.c_str()).

Related

How can I get a list of installed fonts on Windows including font style using c++

I have been trying to get a list of installed fonts on Windows including font style.
After investigation, I found out that I need to use: EnumFontFamiliesEx.
I use it BUT I get only the font name and not all the styles of this font.
for example: for font: "Verdana"
There are four different styles, But I get only one - the regular.
My question is: how can I get the fonts list including all the styles?
My code:
void getFonts()
{
LOGFONT lf;
memset(&lf, 0, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET;
HDC hDC = GetDC(NULL);
EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)(EnumFontFamExProc), NULL, 0);
}
int CALLBACK EnumFontFamExProc(
ENUMLOGFONTEX *lpelfe,
NEWTEXTMETRICEX *lpntme,
DWORD FontType,
LPARAM lParam
)
{
UTF8String fontName = (lpelfe->elfFullName);
return 1;
}
ENUMLOGFONTEX *lpelfe - contains the font. but I don't get all the different styles
after more investigation, I found out that if I change the lfFaceName to a specific font the method returns all styles.
// To enumerate all styles of all fonts for the ANSI character set
lf.lfFaceName[0] = '\0';
lf.lfCharSet = ANSI_CHARSET;
// To enumerate all styles of Arial font that cover the ANSI charset
hr = StringCchCopy( (LPSTR)lf.lfFaceName, LF_FACESIZE, "Arial" );
So I'm not sure what I should do, I need to get all the styles for all the installed fonts.
Thank you in advance
See the details for EnumFontFamiliesEx, specifically for the lfFaceName parameter:
If set to an empty string, the function enumerates one font in each available typeface name. If set to a valid typeface name, the function enumerates all fonts with the specified name.
The most common scenario is to get a list of families to display in a font-selection UI (e.g., dropdown), not all of the individual faces. For that reason, if you call with lfFacename set to "", that's what you'll get: the list of families. If you really want to get all of the individual faces—with multiple faces per family—then you need to call recursively within the EnumFontFamiliesExProc call back, passing the family name as lfFaceName on the inner loop — you can just use the LOGFONT passed to the call back as the argument into the inner-loop call to EnumFontFamiliesEx:
int CALLBACK GdiFontEnumeration::EnumFontFamiliesExCallback(
_In_ const ENUMLOGFONTEX *lpelfe,
_In_ const NEWTEXTMETRICEX *lpntme,
_In_ DWORD dwFontType,
_In_ LPARAM lParam
)
{
// If no facename parameter was passed in the command line, then
// lParam will be 0 the first time the callback is called for a
// given family. We'll call EnumFontFamiliesEx again passing the
// LOGFONT, and that way we'll get callbacks for the variations
// within the given family. When making the inner-loop call, set
// lParam = 1 so that we don't keep recursing.
if (lParam == 0)
{
LOGFONT lf = lpelfe->elfLogFont;
HDC hdc = CreateDC(L"DISPLAY", NULL, NULL, NULL);
int result = EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)EnumFontFamiliesExCallback, 1, 0);
}
else
...
This little program will list all the fonts installed on your system. You can separate them by the style just looking for the suffix. It uses C++17 features so remember to compile it with the correct standard.
i = Italic
b = Bold
bi = Bold and Italic
...
#include <string>
#include <iostream>
#include <filesystem>
int main()
{
std::string path = "C:\\Windows\\Fonts";
for (const auto& entry : std::filesystem::directory_iterator(path))
std::cout << entry.path() << std::endl;
}

WinAPI GetWindowText as string

I was wondering if it were possible to take text input from a text box (CreateWindowEx "EDIT") and store it as a string or even better a vector
I need to have a textbox that the user can enter or paste text and when I click a button it will alphabetize the words and count unique words etc...
so far I have it reading it in as characters (i dont know how to make it a string) and alphabetizes the characters
so if I type in: how now brown cow
it will output: bchnnoooorwwww
instead of: brown cow how now
my code under the WM_COMMAND case is
int length;
length = GetWindowTextLength(textbox) + 1;
vector<wchar_t> list(length);
GetWindowText(textbox, &list[0], length);
wstring stxt = &list[0];
wstring str(stxt);
sort(str.begin(), str.end());
SetWindowText(sortedOutput, &str[0]);
This answer may be of use to you in devising a solution. I don't really know of one that is not hacky, but it can be done casting of the constness of c_string() from std::string.
https://stackoverflow.com/a/1986974/128581
A std::string's allocation is not guaranteed to be contiguous under the C++98/03 standard, but C++11 forces it to be. In practice, neither I nor Herb Sutter know of an implementation that does not use contiguous storage.
Notice that the &s[0] thing is always guaranteed to work by the C++11 standard, even in the 0-length string case. It would not be guaranteed if you did str.begin() or &*str.begin(), but for &s[0] the standard defines operator[] as:
Returns: *(begin() + pos) if pos < size(), otherwise a reference to an object of type T with value charT(); the referenced value shall not be modified
Continuing on, data() is defined as:
Returns: A pointer p such that p + i == &operator for each i in [0,size()].
(notice the square brackets at both ends of the range)
Thus it follows you can do something like this:
int len = GetWindowTextLength(hwnd) + 1;
std::string s;
s.reserve(len);
GetWindowText(hwnd, const_cast<char*>(s.c_str()), len - 1);
Which is pretty ugly. Welcome any more "correct" answers, though.
Regarding when unicode is enabled on your build, you have to use a wstring or equivalent. Testing that out just a moment ago, this works:
std::wstring title;
title.reserve(GetWindowTextLength(m_window_handle) + 1);
GetWindowText(m_window_handle, const_cast<WCHAR *>(title.c_str()), title.capacity());
In general, regarding the windows api its useful to google their all caps typedefs and figure out what they really are.
Regarding splitting strings, std::string isn't particular good at this kind of manipulation. This is where std::stringstream (or wstringstream for unicode) comes in handy. I am fairly certain stringstream is not guaranteed to be contiguous in memory, so you can't really go around writing directly into its buffer.
// Initialize a stringstream so we can extract input using >> operator
std::wstringstream ss;
ss.str(title);
// Make a vector, so we can store our words as we're extracting them
// and so we can use sort later, which works on many stl containers
std::vector<std::wstring> words;
std::wstring word;
// This will evaluate to false and thus end the loop when its done
// reading the string word by word
while(ss >> word)
{
words.push_back(word);
}
Then proceed with your sorting, but on the new vector words.
Your problem is not a winapi problem. While not the only way, you found a solution to transfer a string back and forth to your edit box.
How to turn that string into a list/vector of strings, with words being the elements of that list/vector is in fact an STL problem.
Basically, you are looking for the C++ equivalent of the C# function String.Split().
And there is already a good question and answer for that, here:
Most elegant way to split a string?
So, all you have to do is a sort of round trip:
Get string from TextBox
Convert string to a std::vector<string>, using your split function (see the other question for how to do that).
Sort the vector in the usual way.
Convert the vector back to a string, which is the inverse of your split function (Hint: std::ostringstream).
Set the resulting string as the text of your TextBox.
Depending on your preferences regarding multi character strings and globalization, you might decide to stick to the ASCII versions at first. On windows, you can compile to MBCS or ASCII. The respective string types are then respectively (TCHAR and LPCTSTR or WCHAR and LPCWSTR or CHAR and LPCSTR). All win32 functions come in two flavors, distinguished by a trailing A or W at the end of the function name, respectively.
AFAIK, while there is std::string and std::wstring, there is no standard implementation for std::basic_string<TCHAR>, which would work along with your compile options.
As for the window handling, here some code example (snippets):
In InitInstance(), I created the dialog (IDD_FORMVIEW) with my input edit box, my button and my static output area as a child window of the main application window:
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
HWND hWndChild = CreateDialogW(hInstance, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, dlgProc);
if (NULL == hWndChild)
{
DWORD lastError = GetLastError();
wchar_t msg[100];
swprintf_s(msg, _countof(msg), L"error code: 0x%0X\n", lastError);
OutputDebugString(msg);
}
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
ShowWindow(hWndChild, SW_SHOW);
UpdateWindow(hWnd);
return TRUE;
}
CreateDialogW() takes as the last parameter a pointer to the dialog handler function, which is called dlgProc() in this example.
This is how that dlgProc() function looks like:
// Message handler for our menu which is a child window of the main window, here.
static INT_PTR CALLBACK dlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
BOOL processed = false;
switch (uMsg)
{
case WM_INITDIALOG:
break;
case WM_NOTIFY:
break;
case WM_COMMAND:
{
auto sourceId = LOWORD(wParam);
auto code = HIWORD(wParam);
if (IDC_BUTTON1 == sourceId)
{
if (BN_CLICKED == code)
{
wchar_t text[1024];
GetDlgItemText(hwndDlg, IDC_EDIT1, text, _countof(text));
// TODO: do your string processing here (string -> string)
SetDlgItemText(hwndDlg, IDC_STATIC, text);
processed = TRUE;
}
}
}
break;
default:
break;
}
return processed;
}
I have just mixed a few lines of code to convert wchar_t to wstring to std::string. Here you go!
string GetWindowStringText(HWND hwnd)
{
int len = GetWindowTextLength(hwnd) + 1;
vector<wchar_t> buf(len);
GetWindowText(hwnd, &buf[0], len);
wstring wide = &buf[0];
string s(wide.begin(), wide.end());
return s;
}
This has a vector so you'll need to include it.

Displaying Int Variable in LPCSTR CreateWindowEx function

So i am making a basic tic tac toe game as my first program in win32 (just for fun to learn more, no school assignment or anything). I have most of the UI done and the basic gameplay such as clicking squares and placing x's or o's appropriately. I have written it so that it recognizes who is the winner when the game is over and can display a little text window saying "PLAYER 1 WINS!" etc....
No my question is concerning how to display the score. My idea is to have a int variable called scoreplayer1, and when the player wins, i will increase it by 1 (scoreplayer1++). I then want to have the window that has the previous score change to the new score. This is what i have so far (I am going to take out all of the code that is not relevant to this question but if you need more let me know):
My Global Variables:
//Global Variables
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5, hwnd6, hwnd7, hwnd8;
HWND hwnd9, hwndscore1, hwndscore2, hWnd;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int determinewinner();
int showscore(int win_value);
int scoreplayer1,scoreplayer2;
The CreateWindow function that originally creates the score windows (they start out blank):
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
case WM_CREATE:
hwndscore1 = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("STATIC"),TEXT(""), WS_CHILD|WS_VISIBLE|SS_CENTER, 20,285,100,20,hWnd,HMENU(NULL),GetModuleHandle(NULL),NULL);
hwndscore2 = CreateWindowEx(WS_EX_CLIENTEDGE,TEXT("STATIC"),TEXT(""), WS_CHILD|WS_VISIBLE|SS_CENTER, 130,285,100,20,hWnd,HMENU(NULL),GetModuleHandle(NULL),NULL);
Then the function that is trying to handle changing the score window:
int showscore(int win_value)
{
if(win_value==1)
{ scoreplayer1++;
DestroyWindow(hwndscore1);
hwndscore1 = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("STATIC"),TEXT(scoreplayer1), WS_CHILD|WS_VISIBLE|SS_CENTER, 20,285,100,20,hWnd,HMENU(NULL),GetModuleHandle(NULL),NULL);
return (scoreplayer1);} // This return part is just temporary because it wants
// the function to return a value, it doesn't come into play
}
The idea was to destroy the old window and simply recreate a new window with the new score (that seemed to be the easiest way to go about doing it). I know where the problem is, it says i can't put the int scoreplayer1 variable in that TEXT("scoreplayer1") part in the last CreateWindowEx function. The error is: argument of typ int is incompatible with parameter of type LPCSTR.
So how can change the creation of that last window so that it will display a int variable (such as scoreplayer1) that will be increasing as the game goes on? Thanks!
*EDIT***
In response to a comment i attempted to use itoa() to fix the problem, i did the following:
int showscore(int win_value)
{ if(win_value==1)
{ scoreplayer1++;
char score1[1];
itoa(scoreplayer1, score1, 1);
DestroyWindow(hwndscore1);
hwndscore1 = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("STATIC"),TEXT(score1), WS_CHILD|WS_VISIBLE|SS_CENTER, 20,285,100,20,hWnd,HMENU(NULL),GetModuleHandle(NULL),NULL);
return (scoreplayer1);}
Which forces the program to break as soon as i get to that point in the game... Any ideas on what i did wrong?
Converting an integer to a string can be made MANY different ways in C and C++.
Your edited code fails because the string is 1 character long, and ALL numbers are guaranteed to NOT fit in one character, since all numbers take one character for the string itself, and a further character for the zero byte marking the end of the string. If the number is greater than 9, it will take up three characters, greater than 99 will take 4, and so on.
In C++, I would suggest that, although a bit longer, usign a stringstream to output the number to is an easier/safer method that avoids the problems if figuring out how much space you need for the string (and allows output of more complex things than just one integer, since you can simply combine any output, just like you would for console output using cout).
Something like this:
std::stringstream ss;
ss << scoreplayer1;
hwndscore1 = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("STATIC"),ss.str().c_str(), WS_CHILD|WS_VISIBLE|SS_CENTER, 20,285,100,20,hWnd,HMENU(NULL),GetModuleHandle(NULL),NULL);

How can I get a list of installed fonts on Windows, using unmanaged C++?

I've explored a bit, and so far I've found EnumFontFamiliesEx(...). However, it looks like this function is used to return all the charsets for a given font (e.g. "Arial").
I can't quite figure out how to get the list of installed fonts to begin with. Any help/suggestions would be appreciated.
Thank you in advance.
You can do it something like this:
LOGFONT lf;
lf.lfFaceName[0] = '\0';
lf.lfCharSet = DEFAULT_CHARSET;
HDC hDC = ::GetDC();
EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)&EnumFontFamExProc, 0, 0);
ReleaseDC(hDC);
Then define a callback function:
int CALLBACK EnumFontFamExProc(
ENUMLOGFONTEX *lpelfe,
NEWTEXTMETRICEX *lpntme,
DWORD FontType,
LPARAM lParam
)
{
AfxMessageBox(lpelfe->elfFullName);
//Return non--zero to continue enumeration
return 1;
}
You might want to take a look here, as the code there explains how to use the EnumFontFamiliesEx to get all the font names.

Switch statement use

Should i use this form of switch statement:
switch(msg)
{
case WM_LBUTTONDOWN:
{
char szFileName[MAX_PATH];
HINSTANCE hInstance = GetModuleHandle(NULL);
GetModuleFileName(hInstance, (LPWCH)szFileName, MAX_PATH);
MessageBox(hwnd, (LPCWSTR)szFileName, L"This program is:", MB_OK | MB_ICONINFORMATION);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
or make a function for the first case constant ?
There's nothing wrong with how you have it, but it's probably cleaner code to call a function so you can keep your functions a reasonable size.
Also, take a look at message crackers
What you going to do when will hadle 20 or 50 window messages?
Maybe it right time for create map - events on functions ( fuctors ) and call them?
Or start to use rule - one message = one function call.
char szFileName[MAX_PATH];
HINSTANCE hInstance = GetModuleHandle(NULL);
GetModuleFileName(hInstance, (LPWCH)szFileName, MAX_PATH);
MessageBox(hwnd, (LPCWSTR)szFileName, L"This program is:", MB_OK | MB_ICONINFORMATION);
Could you explain this strange trick with convetation (LPCWSTR)szFileName. Why you don't use array wchar_t instead casting? - you will have big problem with long paths ( path_length > MAX_PATH / sizeof( wchar_t ) )
One reccomendation - avoid to use casts in general and C-style casts in particulary.
If you are asking if you should turn the code in the first case into a function, then yes, definitely.
Well, it would depend on how many other cases you would have.
Something as small as that, I would say it is not worth it to make it a function, but if your switch statement contains more cases, it will just get ugly, especially if a lot of the cases has multiple lines like that. Putting it into a function would clean it up and make your code look nicer.
One of the most important things I'd say would be consistency. If you create a function for LBUTTONDOWN then create a function for everything. This way there is a predictable pattern for where to find stuff if it breaks.
Related to the topic at hand:
I personally find an if / else if pattern to work better, as it eliminates the problem of a forgotten break:
if (msg == WM_LBUTTONDOWN) {
// your code here
return 0;
} else if (msg == WM_DESTROY) {
PostQuitMessage(0);
return;
} else if (msg == WM_KEYDOWN) {
if (wp == VK_F1) {
DoSomething();
return;
}
}
return DefWindowProc(hWnd, msg, wp, lp);
It's really up to you, in the end.
I would probably declare a map and use functors for every message:
typedef std::map<UINT, boost::function<int (HWND, WPARAM, LPARAM) > > messageFuncs_t;
messageFuncs_t messageFuncs;
Then, when the window class is created, just add a new function for each message:
messageFuncs[WM_LBUTTONDOWN] = &onMouseDownEvent;
... And then implement the message loop thus:
messageFuncs_t::iterator fun = messageFuncs.find(msg);
if(fun != messageFuncs.end())
return (*fun)(hWnd, wparam, lparam);
else
return DefWindowProc(hWnd, msg, wp, lp);
... Or whatever works. Then it's easy to add new messages, and the work for each is delegated to a function. Clean, concise, and makes sense.
You are missing a break on the first case. Other than that, I would definitely put that code on a separate function.
It's fine, but I generally don't like mixing styles and indentations. If I needed to bracket one case I'd probably bracket them all and keep the indentation consistent.
Also bb is right, you should use wchar_t array instead of char in that case.
I'm writing fairly many Win32 message crackers such as these switches.
My rule of thumb is: Wiring up the behavior goes into the switch, behavior into a separate function. That usually means the switch contains the decision whether this command should be handled (e.g. testing for sender ID), and "prettyfying" the parameters.
So in that particular case, a separate function.
The original motivation is that I often end up triggering the behavior in other circumstances (e.g. "when no file name has been specified and the dialog is called with the moon parameter set to full, show the SaveAs dialog immediately").