C++ program crashes after exit - c++

I'm using the following function to open a dialog box, using the OPENFILENAME. Problem is, after opening the dialog box, and closing it, everything works fine, but when I exit my application then Windows says it crashed.
bool openDialog()
{
OPENFILENAME ofn; // common dialog box structure
char szFile[260]; // buffer for file name
HWND hwnd = NULL; // owner window
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
//
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
//
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrTitle = "Open File";
ofn.lpstrFilter = "Custom File\0*.Cus\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn) == true)
{
path = ofn.lpstrFile;
return true;
}
else
{
return false;
}
}
I noticed it was the dialog box because the crash only happens if I use it at runtime, meaning that when I close the application without opening the dialog box at some point, it exits successfully.
Anyways, as far as I researched, it is probably caused my a 'heap corruption' or something similar that I don't have much knowledge of, so when my application tries to close, it doesn't release memory as it should (?). If anyone could figure out a solution it'd be greatly appreciated.

Most likely the problem is to do with path if this is simply a const char * or char * declared outside the function.
When the openDialog function returns, both the ofn structure of type OPENFILENAME and character array szFile go out of scope (along with all the other local, stack-allocated variables) and are no longer valid. As a result, the character array that ofn.lpstrFile and consequently path point to is no longer valid.
You should allocate space for the file name outside the function and perform a copy with strcpy, strncpy or equivalent before returning from it. Another approach would be to move the szFile character array out of the function and into the containing class as a member variable. Either way, the scope of the character array containing the file name returned needs to extend beyond the lifetime of the execution of the openDialog function.

Related

How can I read and write text files using the windows api

There are many similar questions, but mine is a bit different. Mine involves a Windows GUI. I am using an open file dialog or an "OPENFILENAME". I want to get the dialog result as OK when the user clicks the OK button and then open a text encoded file. I have done it in Java, but the UI looks weird. So I am not sure whether or not people would like it. I want to learn C++ as well, so I need some help. I have a text box called "hWndEdit" in the WM_COMMAND message inside my program. After opening, the text in the file is supposed to be displayed in the textBox I have specified. I have defined the function in a header file with the following code:
#include <iostream>
#include <fstream>
#include <windows.h>
using namespace std;
void OpenFile()
{
OPENFILENAME ofn; // common dialog box structure
HWND hwnd = nullptr; // owner window
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"NoteRecorder Notes\0(*.recnote)\0Text\0(*.txt)\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn) == TRUE)
{
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL);
}
}
Then I call it from my WM_COMMAND message:
case WM_COMMAND:
switch (wParam)
{
case 12:
OpenFile();
break;
}
But when the user presses the OK button in the OPENFILENAME, it doesn't read any text from the file. How can I accomplish this?
And I want to write files with a save file dialog. Tell me how to do that as well.
The main purpose of the functions GetOpenFileName and GetSaveFileName is to provide you with the filename that the user selected. However, doing the actual File Input and Output is a different issue. You can use the standard C/C++ library for that or you can use the Windows API functions, such as CreateFile, ReadFile and WriteFile.
Since you seem to already be using the function CreateFile, it would make sense to call ReadFile after verifying that the function call to CreateFile succeeded (i.e. that it did not return INVALID_HANDLE_VALUE). After reading the data, you can add a terminating null character to the data (you should make sure that the memory buffer is large enough) and then pass it to the SetDlgItemText function (if the text box is in a dialog box) or SetWindowText function.

Problems with common dialog functions in a binary dll

I did a simple test of using common dialog in a console application and everything worked properly. Then I tried to use the same code putting it in a binary dll. I called my function from Vb 6 and strange things have begun to happen.
I have already tried to call other functions from vb 6 contained in this dll without problems.
With the common dialog, on the first call, the dialog appears correctly. The next calls vb says it cannot find the dll (error 53) and I have to close and reopen the IDE of vb 6. It only happens using the common dialog functions. For every other type of code this problem does not occur.
Here is the code:
C++:
bool _stdcall FsDialog(HWND hwnd){
OPENFILENAME openFile;
wchar_t szFileName[MAX_PATH];
wchar_t szFileTitle[MAX_PATH];
int index = 0;
ZeroMemory( &openFile, sizeof(OPENFILENAME) );
openFile.lStructSize = sizeof(OPENFILENAME);
szFileTitle[0] = '\0';
szFileName[0] = '\0';
openFile.hwndOwner = hwnd;
openFile.lpstrFilter = L"Logs (*.log)\0*.log\0";
openFile.lpstrFile = szFileName;
openFile.nMaxFile = MAX_PATH;
openFile.lpstrFileTitle = szFileTitle;
openFile.nMaxFileTitle = sizeof(szFileTitle)/sizeof(*szFileTitle);
openFile.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
openFile.lpstrDefExt = L"log";
if (GetOpenFileName(&openFile)){
return(1);
}
}
VB6:
Private Declare Function FsDialog Lib "mydll.dll" (ByVal hWnd As Long) As Integer
Private Sub Form_Load()
Debug.Print FsDialog(Me.hWnd)
End Sub

GetOpenFileName with SDL2

I wrote a c++ app using SDL2 to simulate an editBox. It worked ok untill i added a function to open and select a file on Windows explorer.
Precisely after i click "Open" on the file browser, i can not use TTF_OpenFont() anymore...
I am still able to use TextSprites i have declared at the initialisation but i can't change the string associate to them no more. And that's really annoying because my editBox have to display a string var in my main loop.
I've already checked my font path with debug break points and it didn't change (still the same absolute path) nor the font size.
I've tryed many things to solve this : use another .ttf, use another TTF_Font *var, ect
Also tryed to put my openfiledialog function in a separate thread, that didn't change anything, so i tryed to control the new thread with windows Events and then with Sdl_Event but had no luck.
I obviously spent hours and hours of testing searching the web for similar issues and found nothing but unsolved posts.
Here is the funtion that allows me to get the name of the file opened :
void CMain::changeDirectoryPath()
{
OPENFILENAME ofn;
TCHAR szFile[MAX_PATH];
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.hwndOwner = NULL;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = TEXT("Text Files\0*.txt\0Any File\0*.*\0");
ofn.nFilterIndex = 1;
ofn.lpstrTitle = TEXT("Select dictionary");
ofn.lpstrInitialDir = L"data\\dictionary";
ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
if(GetOpenFileName(&ofn))
{
OutputDebugString(ofn.lpstrFile);
int cSize = WideCharToMultiByte (CP_ACP, 0, ofn.lpstrFile, wcslen(ofn.lpstrFile), NULL, 0, NULL, NULL);
string output(static_cast<size_t>(cSize), '\0');
WideCharToMultiByte (CP_ACP, 0, ofn.lpstrFile, wcslen(ofn.lpstrFile), reinterpret_cast<char*>(&output[0]), cSize, NULL, NULL);
cout<<output<<endl;
}
cdpOn = false;
}
And the one that used to change the text displayed on my TextSprite :
bool CDictionary::loadFromRenderedText(std::string textureText)
{
if(Message!=NULL)
{
SDL_DestroyTexture(Message);
Message = NULL;
TTF_CloseFont(font);
}
font = TTF_OpenFont(filePath.c_str(), policeSize);
if(!font)
{
cout<<"TTF_OpenFont: "<<TTF_GetError()<<endl;
return 0;
}
textSurface = TTF_RenderText_Solid(font, textureText.c_str(), textColor);
if(textSurface != NULL)
{
Message = SDL_CreateTextureFromSurface(renderer, textSurface);
if(Message==NULL)
{
printf("Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError());
}
else
{
position.x=50;
position.y=50;
position.w=textSurface->w;
position.h=textSurface->h;
}
SDL_FreeSurface(textSurface);
}
else
{
printf("Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
}
return Message != NULL;
}
At last i thought to add WxWidget in my project and use wxFileDialog to see if it solve the problem but i'm affraid mixing SDL2 and wxWidget will resort in a savage mess :-(
Does anybody knows why i can not reopen a tt_font after i select and open a file with GetOpenFileName()?
Or have suggestion to possibly solve this?
Thanks in advance
Comment under this functions MSDN page says "Current Working Directory is altered when a file is opened", which is exactly what you're describing. Revert it back with SetCurrentDirectory (query at launch with GetCurrentDirectory, once).
Another way would be not closing the font since you're using it quite often.

Local html (RoboHelp) index online help file under MFC is not opened

I followed all the instructions that is referred here :
http://help.adobe.com/en_US/robohelp/robohtml/WS5b3ccc516d4fbf351e63e3d11aff59c571-7f43.html
My CMainFrame::HtmlHelp overiden handler looks like this :
void CMainFrame::HtmlHelp(DWORD_PTR dwData, UINT nCmd)
{
// TODO: Add your specialized code here and/or call the base class
CWaitCursor wait;
// Get the path to the Help system
CWinApp* pApp = AfxGetApp();
ASSERT_VALID(pApp);
// Set the path to server-based help
CString csOnlineHelpPath = _T("C:\\Help\\Final\\index.htm");
PrepareForHelp();
// must use top level parent (for the case where m_hWnd is in DLL)
CWnd* pWnd = GetTopLevelParent();
// finally, run the RoboHelp Help engine
if (!RH_ShowHelp(pWnd->m_hWnd, csOnlineHelpPath, nCmd, dwData))
AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
}
The problem is that the help is never opened. I tried to debug the RoboHelp_CSH.cpp file and I found out that at the line #3267 with the code
MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, szTempFile, (int)uLen, bstr, uLen+1);
the bstr buffer have an extra char at the end that makes the following code
hr=s_pstBrowser->Navigate(bstr, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
HWND hWnd;
hr=s_pstBrowser->get_HWND((long*)&hWnd);
if (SUCCEEDED(hr))
{
::SetForegroundWindow(hWnd);
}
::SysFreeString(bstr);
}
to fail. The original szTempFile has the data below
C:\Users\sdancer\AppData\Local\Temp\robohelp_csh.htm
and the bstr the the following (the DC2 is the symbol I show inside notepad++, unside VS2008 I see an up and down arrow).
C:\Users\sdancer\AppData\Local\Temp\robohelp_csh.htmDC2
What am I doing wrong here ?

How can I get the current window's title with char * format in C++ on Windows?

I want the write the current window title in console and/or file, and I have trouble with LPWSTR to char * or const char *. My code is:
LPWSTR title = new WCHAR();
HWND handle = GetForegroundWindow();
GetWindowText(handle, title, GetWindowTextLength( handle )+1);
/*Problem is here */
char * CSTitle ???<??? title
std::cout << CSTitle;
FILE *file;
file=fopen("file.txt","a+");
fputs(CSTitle,file);
fclose(file);
You are only allocating enough memory for one character, not the entire string. When GetWindowText is called it copies more characters than there is memory for causing undefined behavior. You can use std::string to make sure there is enough memory available and avoid managing memory yourself.
#include <string>
HWND handle = GetForegroundWindow();
int bufsize = GetWindowTextLength(handle);
std::basic_string<TCHAR> title(bufsize, 0);
GetWindowText(handle, &title[0], bufsize + 1);
You need to allocate enough memory for storing title:
HWND handle = GetForegroundWindow();
int bufsize = GetWindowTextLength(handle) + 1;
LPWSTR title = new WCHAR[bufsize];
GetWindowText(handle, title, bufsize);