Dumping Useful Data to Console on Caught Exception - c++

I have a CExceptionHandler class that is invoked whenever my application detects a run-time exception. For example:
if ( val == NULL )
{
TRACE(_T("Unexpected NULL in sequence."));
AfxThrowException( ERROR_INVALID_DATA );
}
AfxThrowException is very simple:
void AfxThrowException( DWORD error )
{
CExceptionHandler * pException = NULL;
if ( error == 0 )
{
error = ::GetLastError();
}
pException = new CExceptionHandler( error );
TRACE(_T("Warning: throwing CSerialException for error %d\n"), error);
THROW(pException);
}
This is the member Dump function of CExceptionHandler:
void CExceptionHandler::Dump( CDumpContext & dc ) const
{
CObject::Dump(dc);
dc << "m_dwError = " << m_dwError;
}
Higher up in my code I have the try/catch statements:
try
{
/* My app does stuff where the exception is thrown. */
}
catch( CExceptionHandler * ex )
{
afxDump << _T("Dumping exceptional data: ") << _T("\r\n");
ex->Dump( afxDump );
afxDump << _T("\r\n");
}
I would like the collected debug information to be dumped to the console. However, when the PC gets into the catch statement (verified with breakpoint), nothing happens on the console. I am using Visual Studio 2008 in Debug mode. Thoughts are appreciated. Thanks.

CDumpContext sends output to the debugger, not to the console (see OutputDebugString for more information), and if you run under the Visual Studio debugger, the output will appear in the Output window.
If you want to also send output to the console, you can configure CDumpContext to write to a CFile by passing a pointer to a CFile object in the CDumpContext constructor.
If your application is built with the 'Use Multi-Byte Character Set' configuration option, you can use CStdioFile to write to either stdout or stderr:
CStdioFile file(stdout);
CDumpContext dumpContext(&file);
ex->Dump(dumpContext);
Or, if you want to use afxDump, you can set its m_pFile member variable directly (it's declared public). For example you could put this code inside your main function:
CStdioFile file(stdout);
afxDump.m_pFile = &file;
But, this won't work if your app is built as Unicode because strings need to be converted to multi-byte to be written to stdout. To do the conversion, write a class that inherits CFile:
class CDumpFile : public CFile
{
public:
virtual void Write(const void* lpBuf, UINT nCount);
};
void CDumpFile::Write(const void* lpBuf, UINT nCount)
{
// Construct string from array of wide chars
const wchar_t* p = static_cast<const wchar_t*>(lpBuf);
UINT len = nCount / sizeof(wchar_t);
CStringW str(p, len);
CStringA astr(str); // Convert wide char to multibyte
fputs((LPCSTR)astr, stdout); // Write multibyte string to stdout
}
and use it like this:
CDumpFile file;
afxDump.m_pFile = &file;
A couple of other points about your code:
You should ensure that the exception object is deleted in the catch block. If your CExceptionHandler class inherits MFC's CException then you should call ex->Delete(). If it doesn't, you need to delete ex.
I'd advise against using the Afx prefix for own functions - you should consider this reserved for use by the MFC library, in my opinion.
I hope this helps!

Related

Read the file version of a dll in C: The system cannot find the file specified

I am new in the forum but I have already found a lot of help for my other projects.
I am using Visual Studio 2019 and I have created a .rc file which contains the file version and a few other things. These information are displayed in the Properties window of the my dll correctly.
I have created a function
void PrintVersion(TCHAR* pszFilePath, void (*printFunc)(const char*, ...));
which receives the file path and a pointer to my logger function. Inside that function I want to read the file version and print it to the logger. But my logger returns Error in GetFileVersionInfoSize: The system cannot find the file specified.
My function call does look like this:
TCHAR* filename = L"mydll.dll";
PrintVersion(filename, gPrintFunc);
And the function is implemented as follows:
// Read the version of the dll and write it to the logger
void PrintVersion(TCHAR* pszFilePath, void (*printFunc)(const char*, ...))
{
DWORD dwSize = 0;
DWORD verHandle = 0;
BYTE* pbVersionInfo = NULL;
VS_FIXEDFILEINFO* pFileInfo = NULL;
UINT puLenFileInfo = 0;
// Get the size of the version information. This is done to check if the file is avaialbe
// If the size is zero then a error occured
dwSize = GetFileVersionInfoSize(pszFilePath, &verHandle);
if (dwSize == 0)
{
gPrintFunc("Error in GetFileVersionInfoSize: ");
PrintLastErrorString(gPrintFunc);
return;
}
// Create some memory for the file version info
pbVersionInfo = malloc(dwSize);
// Store the information into pbVersionInfo
#pragma warning(suppress : 6387)
if (!GetFileVersionInfo(pszFilePath, verHandle, dwSize, pbVersionInfo))
{
gPrintFunc("Error in GetFileVersionInfo: ");
PrintLastErrorString(gPrintFunc);
free(pbVersionInfo);
return;
}
// Make the information easier accessable in pFileInfo
#pragma warning(suppress : 6387)
if (!VerQueryValue(pbVersionInfo, TEXT("\\"), (LPVOID*)&pFileInfo, &puLenFileInfo))
{
gPrintFunc("Error in VerQueryValue: ");
PrintLastErrorString(gPrintFunc);
free(pbVersionInfo);
return;
}
// pFileInfo->dwFileVersionMS and pFileInfo->dwFileVersionLS contain the software version
// Major2B.Minor2B.Revision2B.Build2B
gPrintFunc("File Version of %s: %d.%d.%d.%d\n",
pszFilePath,
(pFileInfo->dwFileVersionMS >> 16) & 0xffff,
(pFileInfo->dwFileVersionMS >> 0) & 0xffff,
(pFileInfo->dwFileVersionLS >> 16) & 0xffff,
(pFileInfo->dwFileVersionLS >> 0) & 0xffff
);
// Free up the reserved memory
free(pbVersionInfo);
}
// Used for receiving the last WIN32 error and write it to the logger
void PrintLastErrorString(void (*printFunc)(const char*, ...))
{
// Get the error id of the last error
DWORD iLastError;
iLastError = GetLastError();
//Ask Win32 to give us the string version of that message ID.
//The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
LPSTR messageBuffer = NULL;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, iLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
gPrintFunc("%s\n", messageBuffer);
return;
}
I created that function by combining a few different C++ and C# examples from this forum. I am not familiar with the TCHAR* datatype. I assume that the problem has maybe something to do with the filename string. Further I am not able to print the filename to the logger with the %s format placeholder. In this case only the first letter of the filename is displayed.
One further info. Before I copied that code to the dll. I created a small console application. And in this case it was possible to read the file version of the exe. I also tried to specify the complete path of the dll. The dll and the exe, which uses the dll are in the same directory.
Maybe someone can help me :)
BR
Thank you for your answers.
I changed now the character set to: Use Unicode Character Set and now it works as expected.

Why can't the entry point of a dll be found within my program? PE file

I'm trying to create a mod loader for an 18 year old game to help me get better at c++. Right now I'm just trying to inject a dll into the same process of the mod loader. The sample dll just prints some text to the command window but doesn't. I think that the code that I have loading the entry point of the dll is not working because everything works up until I call the entry point function of my sample dll within my ModLoader.exe, and Visual Studio just throws an Access Violation. I poked through the memory viewer in debug mode within visual studio to try and see where my ModLoader program thinks the dll entry point is located within the dll but the address just points to a bunch of zeros. I recently learned the PE file format and tried to understand all the code that I wrote when I was following a tutorial on Youtube on how to do this, so forgive me for my inexperience I'm just trying to learn. The other code that I do not show is me locating and finding the target process, reading the dll binary, getting the headers from the dll, me allocating space on the target process for the dll, and finally me writing all of the section header data into the target process. I can provide any other code that y'all would like to see!
Injector.h
using ModLoader_LoadLibrary = HINSTANCE(WINAPI*)(const char* filename);
using ModLoader_GetProcAddress = UINT_PTR(WINAPI*)(HINSTANCE module, const char* procName);
using ModLoader_DllEntry = BOOL(WINAPI*)(HINSTANCE dll, DWORD reason, LPVOID reserved);
struct ModLoader_ManualMapping_Data
{
ModLoader_LoadLibrary ML_LoadLibrary; //Function pointer to the windows load library function
ModLoader_GetProcAddress ML_ProcAddress; //Function pointer to a function to be called
HINSTANCE ML_Module; //dll instance
};
Injector.cpp : Shellcode function that'll run alongside the target executable
void __stdcall Shellcode(ModLoader_ManualMapping_Data* data)
{
if (!data)
return;
BYTE* pData = reinterpret_cast<BYTE*>(data);
IMAGE_OPTIONAL_HEADER& optHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(pData + reinterpret_cast<IMAGE_DOS_HEADER*>(pData)->e_lfanew)->OptionalHeader;
auto loadLibrary = data->ML_LoadLibrary;
auto procAddress = data->ML_ProcAddress;
auto dllLoad = reinterpret_cast<ModLoader_DllEntry>(pData + optHeader.AddressOfEntryPoint); //Loads entry point func from dll
BYTE* locationDelta = pData - optHeader.ImageBase; //pData = the new address | ImageBase = preferred address -> Get the difference between the two to add to every address in the relocation table
if (locationDelta) //THIS DOES NOT GET RAN
{
//Adds the delta value to all addresses within the base relocation table
}
//Import table
if (optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
{
IMAGE_IMPORT_DESCRIPTOR* imgImport = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>(pData
+ optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (imgImport->Name) //THIS DOES NOT GET RAN B\C imgImport is all zeros.
{
//Loops through import table
}
}
if (optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) //THIS DOES NOT GET RAN
{
//Calls the callback functions within dll
}
dllLoad(reinterpret_cast<HINSTANCE>(pData), DLL_PROCESS_ATTACH, nullptr); //PROBLEM: ACCESS VIOLATION
}
Injector.cpp : bool ManualMapping(HANDLE process, const char* dllFilepath)
-- This function is called in main.cpp.
The srcData variable is just the binary contents of the dll
ModLoader_ManualMapping_Data loadData = { 0 };
loadData.ML_LoadLibrary = LoadLibraryA;
loadData.ML_ProcAddress = reinterpret_cast<ModLoader_GetProcAddress>(GetProcAddress);
memcpy(srcData, &loadData, sizeof(loadData));
WriteProcessMemory(process, locOfDll, srcData, 0x1000, nullptr);
void* shellCodeBase = VirtualAllocEx(process, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //Allocates 0x1000 bytes in the process memory for the shellcode
WriteProcessMemory(process, shellCodeBase, Shellcode, 0x1000, nullptr); //Injects the Shellcode function into the process
HANDLE thread = nullptr;
thread = CreateRemoteThread(process, nullptr, 0, reinterpret_cast<PTHREAD_START_ROUTINE>(shellCodeBase), locOfDll, 0, nullptr); //Runs
Finally the sample dll code
#include <Windows.h>
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD reason_for_call, LPVOID lpReserved)
{
switch (reason_for_call)
{
case DLL_PROCESS_ATTACH:
OutputDebugStringA("Injected!");
break;
}
return TRUE;
}
EDIT
After rewriting all the code and looking at it all day I finally figured it out. I just had to make sure that the parameters were right when I called dllLoad!

Memory Access error using STK and the FMVoices class

I'm trying to use the STK from Stanford to do some realtime wavetable synthesis. I'm using the FMVoices instrument class https://ccrma.stanford.edu/software/stk/classstk_1_1FMVoices.html
and trying to use it in a callback routine defined below.
int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *dataPointer )
{
FMVoices *FM = (FMVoices *) dataPointer;
register StkFloat *samples = (StkFloat *) outputBuffer;
for ( unsigned int i=0; i<nBufferFrames; i++ )
*samples++ = FM->tick();
return 0;
}
The issue, I think, is with the type of that last parameter. I'm getting a runtime error : "0xC0000005: Access violation executing location 0x000000001." Now, this is the way that the callback is supposed to be written for other STK instruments like Clarinet or even the FileLoop class, but there's something funky about FMVoices. The object is passed to openStream (which handles platform specific realtime output) as a pointer to void. The callback is called automatically when the system's audio buffer is full. A code snippet that implements this and DOES work for other instruments is shown below:
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
RtAudio dac;
Instrmnt * instrument_FM;
int nFrames = 10000;
try {
instrument_FM = new FMVoices;
}
catch ( StkError & ) {
goto cleanup;
}
instrument_FM->setFrequency(440.0);
// Figure out how many bytes in an StkFloat and setup the RtAudio stream.
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 1;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
unsigned int bufferFrames = RT_BUFFER_SIZE;
try {
dac.openStream( &parameters, NULL, format, (unsigned int)Stk::sampleRate(), &bufferFrames, &tick, (void *)&instrument_FM);
}
catch ( RtError &error ) {
error.printMessage();
Sleep(1000);
goto cleanup;
}
The size of nFrames does not seem to have an effect. It just seemed to me that these types of errors usually come from referencing a pointer to void.
The problem is you are taking the address of a pointer, and passing it into openStream.
// pointer to instrument
Instrmnt * instrument_FM;
// snip ...
// &instrument_FM is a pointer to a pointer! i.e. Instrmnt **
dac.openStream( &parameters, /* other params */, (void *)&instrument_FM)
The quickest solution is to just get rid of the & in that line.
Now some comments on C++, and some more fixes to your code. The code looks like a mixture of C and Java, and opens up a lot of pitfalls to fall into, one of which led to your problem.
There is no need for dynamically allocating FMVoices . Use the stack just like you did for RtAudio dac.
No need to worry about pointers, and deleteing the memory you allocated
Therefore no memory leaks.
Just write FMVoices instrument_FM;
There is no need to do try/catch in most cases for cleanup since C++ has destructors that trigger at the end of scope, and propagate the error.
If you only use the stack, there is no need to worry about delete and having cleanup operations
Don't ever use goto in C++, it's really not needed. (unlike in C, where it could be used for cleanup).
There are destructors and RAII for that.
Use C++ casts which are more fine-grained, such as static_cast<> and reinterpret_cast<>, instead of C-style casts
See this article for an explanation.
Here's the revised code:
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
RtAudio dac;
FMVoices instrument_FM;
instrument_FM.setFrequency(440.0);
// Figure out how many bytes in an StkFloat and setup the RtAudio stream.
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 1;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
unsigned int bufferFrames = RT_BUFFER_SIZE;
// didn't get rid of this try since you want to print the error message.
try {
// note here i need the ampersand &, because instrument_FM is on the stack
dac.openStream( &parameters, NULL, format, static_cast<unsigned int>(Stk::sampleRate()), &bufferFrames, &tick, reinterpret_cast<void*>(&instrument_FM));
}
catch ( RtError& error ) {
error.printMessage();
}
}

creating/opening file on disk returns EAGAIN

As title says I'm getting this error while trying to open file for binary writing(mode doesnt seem matter).
My app uses libev to handle sockets(non blocking/epoll backend) and while parsing client packets i want at some point where i receive fileupload message to start writing down to disk data i get from server.
I couldn't google anything about EAGAIN(Resource temporarily unavailable) message and file opening..
These are methods I've tried:
fopen( ... ) returns EAGAIN
using ofstream/fstream's open(...) by creating them on heap(new) returns EAGAIN
using ofstream/fstream's open(...) staticly as class member (ofstream m_ofFile;) works, but strangly compiler generates code which calls ofstream destructor and closes file before exiting class method im calling .open from. Now that contradicts with my C++ knowledge where for class members which are class types, destructors are called right before class owner's..
edit:
#Joachim
You're right, I'm not acually getting this error..(method #1. gonna test method #2 again soon). File opens regulary and i get regular FILE*. That happens in Init(...) function of my class, but then when I call OnFileChunk later on m_hFile is 0 and therefor i cant write to it. Here is complete class code:
class CFileTransferCS
{
wstring m_wszfile;
wstring m_wszLocalUserFolderPath;
int m_nChunkIndex;
int m_nWrittenBytes;
int m_nFileSize;
FILE* m_hFile;
CFileTransferCS( const CFileTransferCS& c ){}
CFileTransferCS& operator=( const CFileTransferCS& c ){}
public:
CFileTransferCS( );
CFileTransferCS( wstring file, uint32_t size );
void OnFileChunk( char* FileChunk, int size );
void Init( wstring file, uint32_t size );
void SetLocalUserLocalPath( wstring path );
};
CFileTransferCS::CFileTransferCS( )
{
m_hFile = NULL;
m_wszLocalUserFolderPath = L"";
m_nChunkIndex = 0;
m_nWrittenBytes = 0;
}
CFileTransferCS::CFileTransferCS( wstring file, uint32_t size )
{
m_nChunkIndex = 0;
m_nWrittenBytes = 0;
m_wszfile = file;
m_nFileSize = size;
wstring wszFullFilePath = m_wszLocalUserFolderPath + m_wszfile.substr( m_wszfile.find_last_of(L"\\") + 1 );
// string fp = string( file.begin(),file.end() );
string fp ="test.bin"; //for testing purposes
this->m_hFile = fopen(fp.c_str(),"wb");
printf("fp: %s hFile %d\n",fp.c_str(),this->m_hFile); //everything's fine here...
if(!this->m_hFile)
{
perror ("cant open file ");
}
}
void CFileTransferCS::SetLocalUserLocalPath( wstring path )
{
m_wszLocalUserFolderPath = path;
}
void CFileTransferCS::Init( wstring file, uint32_t size )
{
// If previous transfer session got interrupted for whatever reason
// close and delete old file and open new one
if( this->m_hFile )
{
printf("init CS transfer: deleting old file///\n");
fclose( this->m_hFile );
string fp = string( file.begin(),file.end() );
if( remove( fp.c_str() ))
{
//cant delete file...
}
}
CFileTransferCS( file, size );
}
void CFileTransferCS::OnFileChunk( char* FileChunk, int size )
{
for (;;)
{
printf("ofc: hFile %d\n",this->m_hFile); //m_hFile is 0 here...
if( !this->m_hFile )
{
// m_pofFile->open("kurac.txt",fstream::out);
printf("file not opened!\n");
break;
}
int nBytesWritten = fwrite( FileChunk, 1, size, this->m_hFile );
if( !nBytesWritten )
{
perror("file write!!\n");
break;
}
m_nWrittenBytes+=size;
if( m_nWrittenBytes == m_nFileSize )
{
fclose( m_hFile );
printf("file uplaod transfer finished!!!\n");
}
break;
}
printf("CFileTransferCS::OnFileChunk size: %d m_nWrittenBytes: %d m_nFileSize: %d\n",size,m_nWrittenBytes,m_nFileSize);
}
final edit:
I got it.. Calling explicitly CFileTransferCS( wstring file, uint32_t size ) constructor made problems.. Calling constructor like this explicitly caused that this pointer in it wasnt original one(that Init function was using) so when i was opening file from it and saving handle to m_hFile, i was doing it in some other object(now im not sure if CFileTransferCS(..) call allocated memory for CFileTransferCS object or it corrupted some other part of memory randomly.. will check it out with IDA later on )
Thanks to everyone and my apologies.
Regards, Mike –
#MikeJacksons answer:
Calling explicitly CFileTransferCS( wstring file, uint32_t size ) constructor made problems. Calling constructor like this explicitly caused that this pointer in it wasnt original one(that Init function was using) so when i was opening file from it and saving handle to m_hFile, i was doing it in some other object(now im not sure if CFileTransferCS(..) call allocated memory for CFileTransferCS object or it corrupted some other part of memory randomly.. will check it out with IDA later on ) Thanks everyone and my apologies.
Removed: CFileTransferCS( file, size );
(No need to appologize Mike, looks like you did a great job hunting down the bug).

"Access violation writing location" with file.getline? (Only in release build)

getting this error in an application written in C++ (VS 2010):
Unhandled exception at 0x77648da9 in divt.exe: 0xC0000005: Access
violation writing location 0x00000014.
it points to this function in free.c:
void __cdecl _free_base (void * pBlock)
{
int retval = 0;
if (pBlock == NULL)
return;
RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
retval = HeapFree(_crtheap, 0, pBlock);
if (retval == 0) //<-----------------------right here
{
errno = _get_errno_from_oserr(GetLastError());
}
}
Via debugging I was able to determine where its actually crashing:
void MenuState::LoadContentFromFile(char* File,std::string &Content)
{
std::string strbuf;
char buffer[1028];
std::fstream file;
file.open(File,std::ios_base::in);
if(file.fail())
{
Content = ErrorTable->GetString("W0001");
return;
}
if(file.is_open())
{
while(!file.eof())
{
file.getline(buffer,128,'\n'); // <----here
strbuf = buffer;
Content += strbuf + "\n";
}
}
file.close();
strbuf.clear();
}
It crashes on file.getline(buffer,128,'\n');
I don't understand why but it's only doing it in release build (Optimizations turned off), on debug build its working fine.
Any Ideas?
I know this is an old question, but when you encounter these sorts of issues buried deep in files such as, free.c or xmemory, you may also want to double check your project configuration. Especially when the issue pertains to only certain build configurations.
For example, in MSVC check your Project Properties > Configuration Properties > C/C++ > Code Generation > Runtime Library. Make sure it consistent for all dependencies and that it is set to a Debug/Release variant depending on the current build.
I would bet that the read prior to the read crashing the application actually failed (although I'm not quite sure why it would crash). The important thing to note is that eof() is only good for determining what caused a read failure (and typically suppressing an error message). In addition, you always want to check after the read whether it was successful. Finally, I can't see any reason why you don't read an std::string directly. In summary, try to use this loop instead:
for (std::string strbuf; std::getline(file, strbuf); ) {
Content += strbuf;
}
Asked a friend for help, we came up with this Solution:
std::string strbuf;
char buffer[256] = "\0";
FILE* f = fopen(File, "rt");
while(fgets(buffer,sizeof(buffer),f) != NULL)
{
Content += buffer;
}
fclose(f);
strbuf.clear();
Works fine, still thanks for your efforts.