2020
2121#ifdef RTS_ENABLE_CRASHDUMP
2222#include " Common/MiniDumper.h"
23+ #include < wctype.h>
2324#include " Common/GameMemory.h"
2425#include " gitinfo.h"
2526
@@ -78,7 +79,7 @@ MiniDumper::MiniDumper()
7879 m_executablePath[0 ] = 0 ;
7980};
8081
81- LONG WINAPI MiniDumper::DumpingExceptionFilter (struct _EXCEPTION_POINTERS * e_info)
82+ LONG WINAPI MiniDumper::DumpingExceptionFilter (_EXCEPTION_POINTERS* e_info)
8283{
8384 // Store the exception info in the global variables for later use by the dumping thread
8485 g_exceptionRecord = *(e_info->ExceptionRecord );
@@ -109,7 +110,7 @@ void MiniDumper::TriggerMiniDump(DumpType dumpType)
109110 }
110111}
111112
112- void MiniDumper::TriggerMiniDumpForException (struct _EXCEPTION_POINTERS * e_info, DumpType dumpType)
113+ void MiniDumper::TriggerMiniDumpForException (_EXCEPTION_POINTERS* e_info, DumpType dumpType)
113114{
114115 if (!m_miniDumpInitialized)
115116 {
@@ -247,21 +248,21 @@ void MiniDumper::ShutdownDumpThread()
247248 ::SetEvent (m_quitting);
248249
249250 DWORD waitRet = ::WaitForSingleObject (m_dumpThread, 3000 );
250- if (waitRet != WAIT_OBJECT_0 )
251+ switch (waitRet)
251252 {
252- if (waitRet == WAIT_TIMEOUT)
253- {
254- DEBUG_LOG (( " MiniDumper::ShutdownDumpThread: Waiting for dumping thread to exit timed out, killing thread " , waitRet)) ;
255- ::TerminateThread (m_dumpThread, DUMPER_EXIT_FORCED_TERMINATE);
256- }
257- else if (waitRet == WAIT_FAILED)
258- {
259- DEBUG_LOG (( " MiniDumper::ShutdownDumpThread: Waiting for minidump triggering failed: status=%u, error=%u " , waitRet, :: GetLastError ()));
260- }
261- else
262- {
263- DEBUG_LOG ((" MiniDumper::ShutdownDumpThread: Waiting for minidump triggering failed: status=%u" , waitRet));
264- }
253+ case WAIT_OBJECT_0:
254+ // Wait for thread exit was successful
255+ break ;
256+ case WAIT_TIMEOUT:
257+ DEBUG_LOG (( " MiniDumper::ShutdownDumpThread: Waiting for dumping thread to exit timed out, killing thread " , waitRet));
258+ ::TerminateThread (m_dumpThread, DUMPER_EXIT_FORCED_TERMINATE);
259+ break ;
260+ case WAIT_FAILED:
261+ DEBUG_LOG (( " MiniDumper::ShutdownDumpThread: Waiting for minidump triggering failed: status=%u, error=%u " , waitRet, :: GetLastError ()));
262+ break ;
263+ default :
264+ DEBUG_LOG ((" MiniDumper::ShutdownDumpThread: Waiting for minidump triggering failed: status=%u" , waitRet));
265+ break ;
265266 }
266267 }
267268}
@@ -310,30 +311,23 @@ DWORD MiniDumper::ThreadProcInternal()
310311 {
311312 HANDLE waitEvents[2 ] = { m_dumpRequested, m_quitting };
312313 DWORD event = ::WaitForMultipleObjects (ARRAY_SIZE (waitEvents), waitEvents, FALSE , INFINITE);
313- if (event == WAIT_OBJECT_0 + 0 )
314+ switch (event)
314315 {
316+ case WAIT_OBJECT_0 + 0 :
315317 // A dump is requested (m_dumpRequested)
316318 ::ResetEvent (m_dumpComplete);
317319 CreateMiniDump (m_requestedDumpType);
318320 ::ResetEvent (m_dumpRequested);
319321 ::SetEvent (m_dumpComplete);
320- }
321- else if (event == WAIT_OBJECT_0 + 1 )
322- {
322+ break ;
323+ case WAIT_OBJECT_0 + 1 :
323324 // Quit (m_quitting)
324325 return DUMPER_EXIT_SUCCESS;
325- }
326- else
327- {
328- if (event == WAIT_FAILED)
329- {
330- DEBUG_LOG ((" MiniDumper::ThreadProcInternal: Waiting for events failed: status=%u, error=%u" , event, ::GetLastError ()));
331- }
332- else
333- {
334- DEBUG_LOG ((" MiniDumper::ThreadProcInternal: Waiting for events failed: status=%u" , event));
335- }
336-
326+ case WAIT_FAILED:
327+ DEBUG_LOG ((" MiniDumper::ThreadProcInternal: Waiting for events failed: status=%u, error=%u" , event, ::GetLastError ()));
328+ return DUMPER_EXIT_FAILURE_WAIT;
329+ default :
330+ DEBUG_LOG ((" MiniDumper::ThreadProcInternal: Waiting for events failed: status=%u" , event));
337331 return DUMPER_EXIT_FAILURE_WAIT;
338332 }
339333 }
@@ -371,7 +365,7 @@ void MiniDumper::CreateMiniDump(DumpType dumpType)
371365 sysTime.wDay , sysTime.wHour , sysTime.wMinute , sysTime.wSecond ,
372366 GitShortSHA1, currentProcessId);
373367
374- HANDLE dumpFile = CreateFile (m_dumpFile, GENERIC_READ | GENERIC_WRITE, 0 , NULL , CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
368+ HANDLE dumpFile = :: CreateFile (m_dumpFile, GENERIC_READ | GENERIC_WRITE, 0 , NULL , CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
375369 if (dumpFile == NULL || dumpFile == INVALID_HANDLE_VALUE)
376370 {
377371 DEBUG_LOG ((" MiniDumper::CreateMiniDump: Unable to create dump file '%s': error=%u" , m_dumpFile, ::GetLastError ()));
@@ -446,6 +440,26 @@ BOOL CALLBACK MiniDumper::MiniDumpCallback(PVOID CallbackParam, PMINIDUMP_CALLBA
446440 return dumper->CallbackInternal (*CallbackInput, *CallbackOutput);
447441}
448442
443+ Bool MiniDumper::ShouldWriteDataSegsForModule (const PWCHAR module ) const
444+ {
445+ // Only include data segments for the game, ntdll and kernel32 modules to keep dump size low
446+ constexpr const static WideChar* wanted_modules[] = { L" ntdll.dll" , L" kernel32.dll" };
447+ if (EndsWithCaseInsensitive (module , m_executablePath))
448+ {
449+ return true ;
450+ }
451+
452+ for (size_t i = 0 ; i < ARRAY_SIZE (wanted_modules); ++i)
453+ {
454+ if (EndsWithCaseInsensitive (module , wanted_modules[i]))
455+ {
456+ return true ;
457+ }
458+ }
459+
460+ return false ;
461+ }
462+
449463// This is where the memory regions and things are being filtered
450464BOOL MiniDumper::CallbackInternal (const MINIDUMP_CALLBACK_INPUT& input, MINIDUMP_CALLBACK_OUTPUT& output)
451465{
@@ -456,12 +470,9 @@ BOOL MiniDumper::CallbackInternal(const MINIDUMP_CALLBACK_INPUT& input, MINIDUMP
456470 retVal = TRUE ;
457471 break ;
458472 case ModuleCallback:
459- {
460- // Only include data segments for the game and ntdll modules to keep dump size low
461473 if (output.ModuleWriteFlags & ModuleWriteDataSeg)
462474 {
463- if (::StrCmpIW (input.Module .FullPath , m_executablePath) && !::StrStrIW (input.Module .FullPath , L" ntdll.dll" ) &&
464- !::StrStrIW (input.Module .FullPath , L" kernel32.dll" ))
475+ if (!ShouldWriteDataSegsForModule (input.Module .FullPath ))
465476 {
466477 // Exclude data segments for the module
467478 output.ModuleWriteFlags &= (~ModuleWriteDataSeg);
@@ -470,7 +481,6 @@ BOOL MiniDumper::CallbackInternal(const MINIDUMP_CALLBACK_INPUT& input, MINIDUMP
470481
471482 retVal = TRUE ;
472483 break ;
473- }
474484 case IncludeThreadCallback:
475485 // We want all threads except the dumping thread
476486 if (input.IncludeThread .ThreadId == m_dumpThreadId)
@@ -485,7 +495,6 @@ BOOL MiniDumper::CallbackInternal(const MINIDUMP_CALLBACK_INPUT& input, MINIDUMP
485495 retVal = TRUE ;
486496 break ;
487497 case MemoryCallback:
488- {
489498#ifndef DISABLE_GAMEMEMORY
490499 do
491500 {
@@ -496,14 +505,11 @@ BOOL MiniDumper::CallbackInternal(const MINIDUMP_CALLBACK_INPUT& input, MINIDUMP
496505 retVal = FALSE ;
497506#endif
498507 break ;
499- }
500508 case ReadMemoryFailureCallback:
501- {
502509 DEBUG_LOG ((" MiniDumper::CallbackInternal: ReadMemoryFailure with MemoryBase=%llu, MemorySize=%lu: error=%u" ,
503510 input.ReadMemoryFailure .Offset , input.ReadMemoryFailure .Bytes , input.ReadMemoryFailure .FailureStatus ));
504511 retVal = TRUE ;
505512 break ;
506- }
507513 case CancelCallback:
508514 output.Cancel = FALSE ;
509515 output.CheckCancel = FALSE ;
@@ -701,4 +707,26 @@ void MiniDumper::KeepNewestFiles(const std::string& directory, const DumpType du
701707 }
702708 }
703709}
710+
711+ bool MiniDumper::EndsWithCaseInsensitive (const WideChar* str, const WideChar* suffix)
712+ {
713+ size_t strlen = wcslen (str);
714+ size_t sufflen = wcslen (suffix);
715+ if (sufflen > strlen)
716+ {
717+ return false ;
718+ }
719+
720+ for (size_t index = 0 ; index < sufflen; ++index)
721+ {
722+ WideChar suffchar = towlower (suffix[index]);
723+ WideChar strchar = towlower (str[strlen - sufflen + index]);
724+ if (suffchar != strchar)
725+ {
726+ return false ;
727+ }
728+ }
729+
730+ return true ;
731+ }
704732#endif
0 commit comments