//MaxiDump_03.cpp
// MaxiDump.cpp
//
// Sample approach to collecting data with MiniDumpWriteDump
//
// Author: Oleg Starodumov (www.debuginfo.com)
//
//
///
// Include files
//
#include <windows.h>
#include <tchar.h>
#include <dbghelp.h>
#include <stdio.h>
#include <crtdbg.h>
///
// Directives
//
#pragma comment ( lib, "dbghelp.lib" )
///
// Function declarations
//
void CreateMiniDump( EXCEPTION_POINTERS* pep );
///
// Test data and code
//
struct A
{
int a;
A()
: a( 0 ) {}
void Print()
{
_tprintf( _T("a: %d\n"), a );
}
};
struct B
{
A* pA;
B()
: pA( 0 ) {}
void Print()
{
_tprintf( _T("pA: %x\n"), pA );
pA->Print();
}
};
void DoWork()
{
B* pB = new B(); // but forget to initialize B::pA
pB->Print(); // here it should crash
}
///
// main() function
//
int main( int argc, char* argv[] )
{
__try
{
DoWork();
}
__except( CreateMiniDump( GetExceptionInformation() ), EXCEPTION_EXECUTE_HANDLER )
{
}
return 0;
}
///
// Minidump creation function
//
void CreateMiniDump( EXCEPTION_POINTERS* pep )
{
// Open the file
HANDLE hFile = CreateFile( _T("MaxiDump.dmp"), GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
{
// Create the minidump
MINIDUMP_EXCEPTION_INFORMATION mdei;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = FALSE;
MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithFullMemory |
MiniDumpWithFullMemoryInfo |
MiniDumpWithHandleData |
MiniDumpWithThreadInfo |
MiniDumpWithUnloadedModules );
BOOL rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, 0, 0 );
if( !rv )
_tprintf( _T("MiniDumpWriteDump failed. Error: %u \n"), GetLastError() );
else
_tprintf( _T("Minidump created.\n") );
// Close the file
CloseHandle( hFile );
}
else
{
_tprintf( _T("CreateFile failed. Error: %u \n"), GetLastError() );
}
}
//MaxiDump_03.cpp
///
//MidiDump.cpp
// MidiDump.cpp
//
// Sample approach to collecting data with MiniDumpWriteDump and MiniDumpCallback
//
// Author: Oleg Starodumov (www.debuginfo.com)
//
//
///
// Include files
//
#include <windows.h>
#include <tchar.h>
#include <dbghelp.h>
#include <stdio.h>
#include <crtdbg.h>
///
// Directives
//
#pragma comment ( lib, "dbghelp.lib" )
///
// Function declarations
//
void CreateMiniDump( EXCEPTION_POINTERS* pep );
BOOL CALLBACK MyMiniDumpCallback(
PVOID pParam,
const PMINIDUMP_CALLBACK_INPUT pInput,
PMINIDUMP_CALLBACK_OUTPUT pOutput
);
bool IsDataSectionNeeded( const WCHAR* pModuleName );
///
// Test data and code
//
struct A
{
int a;
A()
: a( 0 ) {}
void Print()
{
_tprintf( _T("a: %d\n"), a );
}
};
struct B
{
A* pA;
B()
: pA( 0 ) {}
void Print()
{
_tprintf( _T("pA: %x\n"), pA );
pA->Print();
}
};
void DoWork()
{
B* pB = new B(); // but forget to initialize B::pA
pB->Print(); // here it should crash
}
///
// main() function
//
int main( int argc, char* argv[] )
{
__try
{
DoWork();
}
__except( CreateMiniDump( GetExceptionInformation() ), EXCEPTION_EXECUTE_HANDLER )
{
}
return 0;
}
///
// Minidump creation function
//
void CreateMiniDump( EXCEPTION_POINTERS* pep )
{
// Open the file
HANDLE hFile = CreateFile( _T("MidiDump.dmp"), GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
{
// Create the minidump
MINIDUMP_EXCEPTION_INFORMATION mdei;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = FALSE;
MINIDUMP_CALLBACK_INFORMATION mci;
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback;
mci.CallbackParam = 0;
MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |
MiniDumpWithDataSegs |
MiniDumpWithHandleData |
MiniDumpWithFullMemoryInfo |
MiniDumpWithThreadInfo |
MiniDumpWithUnloadedModules );
BOOL rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci );
if( !rv )
_tprintf( _T("MiniDumpWriteDump failed. Error: %u \n"), GetLastError() );
else
_tprintf( _T("Minidump created.\n") );
// Close the file
CloseHandle( hFile );
}
else
{
_tprintf( _T("CreateFile failed. Error: %u \n"), GetLastError() );
}
}
///
// Custom minidump callback
//
BOOL CALLBACK MyMiniDumpCallback(
PVOID pParam,
const PMINIDUMP_CALLBACK_INPUT pInput,
PMINIDUMP_CALLBACK_OUTPUT pOutput
)
{
BOOL bRet = FALSE;
// Check parameters
if( pInput == 0 )
return FALSE;
if( pOutput == 0 )
return FALSE;
// Process the callbacks
switch( pInput->CallbackType )
{
case IncludeModuleCallback:
{
// Include the module into the dump
bRet = TRUE;
}
break;
case IncludeThreadCallback:
{
// Include the thread into the dump
bRet = TRUE;
}
break;
case ModuleCallback:
{
// Are data sections available for this module ?
if( pOutput->ModuleWriteFlags & ModuleWriteDataSeg )
{
// Yes, they are, but do we need them?
if( !IsDataSectionNeeded( pInput->Module.FullPath ) )
{
wprintf( L"Excluding module data sections: %s \n", pInput->Module.FullPath );
pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
}
}
bRet = TRUE;
}
break;
case ThreadCallback:
{
// Include all thread information into the minidump
bRet = TRUE;
}
break;
case ThreadExCallback:
{
// Include this information
bRet = TRUE;
}
break;
case MemoryCallback:
{
// We do not include any information here -> return FALSE
bRet = FALSE;
}
break;
case CancelCallback:
break;
}
return bRet;
}
///
// This function determines whether we need data sections of the given module
//
bool IsDataSectionNeeded( const WCHAR* pModuleName )
{
// Check parameters
if( pModuleName == 0 )
{
_ASSERTE( _T("Parameter is null.") );
return false;
}
// Extract the module name
WCHAR szFileName[_MAX_FNAME] = L"";
_wsplitpath( pModuleName, NULL, NULL, szFileName, NULL );
// Compare the name with the list of known names and decide
// Note: For this to work, the executable name must be "mididump.exe"
if( wcsicmp( szFileName, L"mididump" ) == 0 )
{
return true;
}
else if( wcsicmp( szFileName, L"ntdll" ) == 0 )
{
return true;
}
// Complete
return false;
}
/MidiDump.cpp
///
//WriteUserStream_01.cpp
// WriteUserStream.cpp
//
// This example shows how to add a user data stream into the minidump
//
// Author: Oleg Starodumov (www.debuginfo.com)
//
//
///
// Include files
//
#include <windows.h>
#include <tchar.h>
#include <dbghelp.h>
#include <stdio.h>
///
// Directives
//
#pragma comment ( lib, "dbghelp.lib" )
///
// Function declarations
//
void CreateMiniDump( EXCEPTION_POINTERS* pep );
///
// Test data and code
//
// Contents of the user data streams
char Message1[] = "This is the first data stream...";
char Message2[] = "and this is the second data stream";
// Stream identifiers
// (LastReservedStream constant is defined in MINIDUMP_STREAM_TYPE
// enumeration in DbgHelp.h; all user data stream identifiers
// must be larger than LastReservedStream)
const ULONG32 cFirstStreamID = LastReservedStream + 1;
const ULONG32 cSecondStreamID = LastReservedStream + 2;
// Test function
void DoWork()
{
// Access violation
*(int*)0 = 1;
}
///
// main() function
//
int main( int argc, char* argv[] )
{
__try
{
DoWork();
}
__except( CreateMiniDump( GetExceptionInformation() ), EXCEPTION_EXECUTE_HANDLER )
{
}
return 0;
}
///
// Minidump creation function
//
void CreateMiniDump( EXCEPTION_POINTERS* pep )
{
// Open the file
HANDLE hFile = CreateFile( _T("UserData.dmp"), GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
{
// Create the minidump
// Exception information
MINIDUMP_EXCEPTION_INFORMATION mdei;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = FALSE;
// Minidump type
MINIDUMP_TYPE mdt = MiniDumpNormal;
// User data streams
MINIDUMP_USER_STREAM UserStreams[2];
UserStreams[0].Type = cFirstStreamID;
UserStreams[0].Buffer = Message1;
UserStreams[0].BufferSize = sizeof(Message1);
UserStreams[1].Type = cSecondStreamID;
UserStreams[1].Buffer = Message2;
UserStreams[1].BufferSize = sizeof(Message2);
MINIDUMP_USER_STREAM_INFORMATION musi;
musi.UserStreamCount = 2;
musi.UserStreamArray = UserStreams;
// Call MiniDumpWriteDump
BOOL rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, &musi, 0 );
if( !rv )
_tprintf( _T("MiniDumpWriteDump failed. Error: %u \n"), GetLastError() );
else
_tprintf( _T("Minidump created.\n") );
// Close the file
CloseHandle( hFile );
}
else
{
_tprintf( _T("CreateFile failed. Error: %u \n"), GetLastError() );
}
}
/WriteUserStream_01.cpp
///
//WriteUserStream_02.cpp
// WriteUserStream.cpp
//
// This example shows how to add a user data stream into the minidump
//
// Author: Oleg Starodumov (www.debuginfo.com)
//
//
///
// Include files
//
#include <windows.h>
#include <tchar.h>
#include <dbghelp.h>
#include <stdio.h>
///
// Directives
//
#pragma comment ( lib, "dbghelp.lib" )
///
// Function declarations
//
void CreateMiniDump( EXCEPTION_POINTERS* pep );
///
// Test data and code
//
// Contents of the user data streams
char Message1[] = "This is the first data stream...";
char Message2[] = "and this is the second data stream";
// Stream identifiers
// (LastReservedStream constant is defined in MINIDUMP_STREAM_TYPE
// enumeration in DbgHelp.h; all user data stream identifiers
// must be larger than LastReservedStream)
const ULONG32 cFirstStreamID = LastReservedStream + 1;
const ULONG32 cSecondStreamID = LastReservedStream + 2;
// Test function
void DoWork()
{
// Access violation
*(int*)0 = 1;
}
///
// main() function
//
int main( int argc, char* argv[] )
{
__try
{
DoWork();
}
__except( CreateMiniDump( GetExceptionInformation() ), EXCEPTION_EXECUTE_HANDLER )
{
}
return 0;
}
///
// Minidump creation function
//
void CreateMiniDump( EXCEPTION_POINTERS* pep )
{
// Open the file
HANDLE hFile = CreateFile( _T("UserData.dmp"), GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
{
// Create the minidump
// Exception information
MINIDUMP_EXCEPTION_INFORMATION mdei;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = FALSE;
// Minidump type
MINIDUMP_TYPE mdt = MiniDumpNormal;
// User data streams
MINIDUMP_USER_STREAM UserStreams[2];
UserStreams[0].Type = cFirstStreamID;
UserStreams[0].Buffer = Message1;
UserStreams[0].BufferSize = sizeof(Message1);
UserStreams[1].Type = cSecondStreamID;
UserStreams[1].Buffer = Message2;
UserStreams[1].BufferSize = sizeof(Message2);
MINIDUMP_USER_STREAM_INFORMATION musi;
musi.UserStreamCount = 2;
musi.UserStreamArray = UserStreams;
// Call MiniDumpWriteDump
BOOL rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, &musi, 0 );
if( !rv )
_tprintf( _T("MiniDumpWriteDump failed. Error: %u \n"), GetLastError() );
else
_tprintf( _T("Minidump created.\n") );
// Close the file
CloseHandle( hFile );
}
else
{
_tprintf( _T("CreateFile failed. Error: %u \n"), GetLastError() );
}
}
/WriteUserStream_02.cpp