MFC file creation not working properly with pugixml - c++

I'm trying to create an xml file using pugixml. The code is;
//Open the save as diolog
TCHAR szFilters[]= _T("Files (*.abc)|*.abc|All Files (*.*)|*.*||");
// Create an SaveAs dialog; the default file name extension is ".abc".
CFileDialog fileDlg(FALSE, _T("abc"), NULL,
OFN_OVERWRITEPROMPT |OFN_CREATEPROMPT| OFN_PATHMUSTEXIST, szFilters);
// Display the file dialog.
CString pathName;
CString fileName;
if(fileDlg.DoModal() == IDOK)
{
pathName = fileDlg.GetPathName();
fileName = fileDlg.GetFileName();
::CreateFile(pathName,GENERIC_WRITE,0,NULL,CREATE_NEW, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
} //File is created in explorer
else
return;
//[code_modify_add
// add node with some name
pugi::xml_document xmlDoc;
pugi::xml_parse_result result = xmlDoc.load_file(fileName);
The problem is result always gives out a 'file_not_found' status, but I can see that the file is created in windows explorer. When I try to select the same file during the execution of the program it still returns 'file_not_found'.
However if I close the program and run again and then select the file, result returns true.
I noticed that while the program is executing I cannot open the newly created file, but when the program is closed I can open it.
What could be the matter with it?
Thanks.

You are creating a file and leaving it open write only with a share mode of zero (meaning it can not be shared) and throwing away its handle and then trying to reopen the file for reading with the xml parser.
You probably want to CloseHandle() on the return value for ::CreateFile()
HANDLE hFile = ::CreateFile(pathName,GENERIC_WRITE,0,NULL,CREATE_NEW, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if (hFile == INVALID_HANDLE_VALUE) {
// Call GetLastError() to figure out why the file creation failed.
}
else
{
CloseHandle(hFile);
}

Related

fopen / ofstream::open fail when creating a BMP file

Years ago I created a C++ function using FILE to create bitmap files. Recently (not sure when or why) this code is now failing when opening the file. The problem is with the open call ...
file_ptr = fopen("ScreenShots/Screenshot1.bmp", "wb");
Currently this results in an error 13, permission denied error. Change the filename extension to something else and the fopen works fine. For example,
file_ptr = fopen("ScreenShots/Screenshot1.bm2", "wb");
The file saves correctly and when changing the extension back to BMP I can display the file correctly in Paintshop.
Did a quick check using ofstream and same problem.
Any ideas why I get a permission denied error when trying to open BMP files to write data? For information I am using Visual Studio Community 2017 on Windows 10.
To give the complete section of code ...
BITMAPFILEHEADER bitmap_header;
BITMAPINFOHEADER bitmap_info;
FILE *file_ptr;
unsigned int count;
unsigned char tempRGB;
char filename[256];
bool finished;
// CREATE A UNIQUE FILENAME
count = 1;
finished = false;
do
{
// CREATE NAME
sprintf(filename, "ScreenShots/Screenshot%d.bmp", count);
// CHECK IF FILE EXISTS
errno = 0;
file_ptr = fopen(filename, "rb");
if (file_ptr)
{
// FILE EXISTS
fclose(file_ptr);
count = count + 1;
}
else
{
// UNIQUE FILENAME
file_ptr = fopen(filename, "wb");
if (file_ptr == NULL)
{
// UNABLE TO OPEN FOR WRITING - GIVE UP
// (USING OWN LOGGING CLASS)
jalog.log("\nERROR on Screenshot >");
jalog.log(filename);
jalog.log("< >");
jalog.log((short)errno);
return;
}
finished = true;
}
}
while (finished == false);
I've managed to find the issue ... Avast antivirus. I noticed that trying to do an open action for a BMP file took a few seconds while opening any other file type (successfully or unsuccessfully) was instantaneous. As something similar happens when running new programs I tried disabling all the Avast shields and I could successfully create a BMP file using the existing code.
For my own personal use I can whitelist my own programs, but annoying if I get to distributing the program to other people.
Thanks for the help ... and sorry for raising a C++ issue that in the end had nothing to do with C++!

How can I create a file when file path name is over 255 characters using MFC in Windows?

I am working in Windows,using vc++2010 and MFC.
Following is my code:
CFile File;
TCHAR lpCause[1024];
CFileException eException;
CString strErrorMessage;
// a very long file path name means a file name over 255 characters
if (!File.Open(_T("a very long file path name"), CFile::modeCreate, &eException))
{
eException.GetErrorMessage(lpCause, 1024);
strErrorMessage = lpCause;
}
else
File.Close();
When I run the code, I got error message:"a very long file path name contains an incorrect path".
My questions are:
How to modify my code to make it work?
I learn that CreateFile() function can add "\\\\?\" in the beginning of file path, then it will extend this limit to 32767 wide characters.How can I do the same thing in MFC?
Cause
In the source of CFile::Open(), there is an explicit check if the path length exceeds _MAX_PATH:
if (lpszFileName != NULL && SUCCEEDED(StringCchLength(lpszFileName, _MAX_PATH, NULL)) )
If _MAX_PATH is exceeded, the function sets pException->m_cause = CFileException::badPath and returns FALSE.
This is true even for the MFC version that comes with VS2017.
So the standard technique to circumvent the _MAX_PATH limit, that is prefixing the path with \\?\ won't work.
Possible Solutions
Call CreateFileW() directly to pass it a path with \\?\ prefix. Use the CFile constructor that accepts a HANDLE to manage the file through a CFile object. The CFile object will take ownership of the handle so you must not call CloseHandle() on the handle.
HANDLE hFile = CreateFileW( L"\\\\?\\a very long file path name", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
// Manage the handle using CFile
CFile file( hFile );
// Use the file...
// The CFile destructor closes the handle here.
}
else
{
DWORD err = GetLastError();
// TODO: do your error handling...
}
Another possibility is to derive a class from CFile that overrides CFile::Open() (which is virtual). For the implementation copy/paste the MFC source, but leave out the _MAX_PATH check. For a big project, this class could be a drop-in replacement for CFile to enable long paths. You could even go so far to prepend the \\?\ prefix if it isn't already there (but that is more involved as the prefix also disables the regular transformations from a Win32 path to a NT-style path, like converting / to \, resolving dots and so on).

Change text file on runtime in resource.rc winapi c++

I would like to read from file in resource file. That's ok like so:
char LineBuffer[255];
HRSRC hRes = FindResource(0, MAKEINTRESOURCE(ID_TEXT_FILE), "0");
if(hRes != NULL)
{
HGLOBAL hData = LoadResource(0, hRes);
if(hData != NULL)
{
sprintf(LineBuffer, "%s", LockResource(hData));
}
}
But I want to change the text in the txt file stored in resource. I have read something about it and everyone uses BeginUpdateResource(); UpdateResource(); EndUpdateResource(); but I don't get it. Any help would be appreciated :) A code snippet would be awesome. Thanks in advance ;-)
A running process cannot alter its own resources. You have to use a separate application to update the resources of the main application while it is not running. Only then can you use (Begin/End)UpdateResource().

Second use of CFileDialog in my program gets the run-time error Debug Assertion failed

I have developed a simple program with MFC. It's responsible for reading and writing geotiff files using GDAL library. For this purpose, I have derived two classes from CFileDialog class named ManageOpenGeoTiffFiles and ManageSaveGeoTiffFiles each have 3 functions to support reading and writing geotiffs.
this is the header of the constructor and destructor for one of them:
ManageOpenGeoTiffFiles::ManageOpenGeoTiffFiles(void):CFileDialog(true,0,0,OFN_ENABLESIZING | OFN_HIDEREADONLY,_T("Tiff Files (*.tif)|*.tif|"),0,0,true)
ManageOpenGeoTiffFiles::~ManageOpenGeoTiffFiles(void)
{
}
and this is how I use it in my code:
void CInitialJobProject2FinalDlg::OnBnClickedBtnopen()
{
// TODO: Add your control notification handler code here
m_oglWindow1.WantToPan = false;
m_oglWindow1.WantToUseZoomTool = false;
CString fullpath;
if ( m_openFiles.DoModal() == IDOK )
{
fullpath = m_openFiles.GetPathName();
try{
m_openFiles.OpenGeoTiffAsReadonly(fullpath);
}
catch(CFileException *e){
MessageBox(_T("the file could not be opened"),_T("error"),MB_OK);
this ->ExitMFCApp();
}
m_openFiles.ReadRasterData();
}
else
MessageBox(_T("you pressed cancel and can not proceed."),_T("error"),MB_ICONERROR);
}
everythings ok when I use the Open or Save button for the first time in my program but when it comes to second use I get the error:
and if I click ignore:
this error occurs in the line:
if ( m_openFiles.DoModal() == IDOK )
of each dialog and even if I click cancel the first time,the error occures in the second use of dialog.
Line 398 of dlgFile.cpp is as follows:
hr = (static_cast<IFileDialog*>(m_pIFileDialog))->SetFileTypes(nFilterCount, pFilter);
ENSURE(SUCCEEDED(hr));
Edited section:
Answering one of the comments and providing information for others too:
When I set a breakpoint there saw these results when the assertion fails:
pFilter 0x00fc3660 {pszName=0x00fc36a8 "Tiff Files (*.tif)" pszSpec=0x00fc3788 "*.tif" }
hr E_UNEXPECTED
and the results for the first time when the assertion does not fail is as follows:
pFilter 0x004cfca0 {pszName=0x004cfce8 "Tiff Files (*.tif)" pszSpec=0x004cfdc8 "*.tif" }
hr S_OK
You are passing a malformed filter string to CFileDialog::CFileDialog. The Remarks sections states the following condition:
The lpszFilter parameter [...] ends with two '|' characters.

How do I CloseHandle a handle that was converted to a FILE*?

I am trying to redirect the output of a child process and return a FILE* to the parent.
I am essentially following the code example at Creating a Child Process with Redirected Input and Output. The only modification is that i encapsulated the whole thing in a function and do
return _fdopen(_open_osfhandle((intptr_t)g_hChildStd_OUT_Rd, _O_RDONLY), "rb");
The problem is that I want to cleanup and fclose is throwing an error. Was I supposed to close handle after I did the _fdopen? How am I supposed to clean up here?
The correct way to close a file stream opened with _fdopen is to call fclose. If that's not working for you, then you have other problems.
Do not close the file descriptor after calling _fdopen. The documentation doesn't exactly say, but the FILE object owns that file descriptor and will close it when you call fclose. Likewise, the file descriptor owns the file handle, so you shouldn't call CloseHandle, either.
May be quite late to answer, but just adding for reference. I looked into call stack of fclose, and it is actually making a call to CloseHandle
auto NThdl = CreateFileW(L"D:\\s.txt", GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (NThdl != INVALID_HANDLE_VALUE)
{
int iohdl = _open_osfhandle((intptr_t) NThdl, O_RDWR | O_BINARY);
if (iohdl != 0xFFFFFFFF)
{
FILE *hLstFile = _wfdopen(iohdl, L"w+bc");
fwrite("Bogus", 5, 1, hLstFile);
fclose(hLstFile);
// Exception
CloseHandle(NThdl);
}
}
And attempt to call CloseHandle after fclose would cause an exception saying that Handle is invalid.