// gpSrv->dwRootProcess void WriteMiniDump(DWORD dwProcessId, DWORD dwThreadId, EXCEPTION_RECORD *pExceptionRecord, LPCSTR asConfirmText /*= NULL*/, BOOL bTreeBreak /*= FALSE*/) { MINIDUMP_TYPE dumpType = MiniDumpNormal; char szTitleA[64]; _wsprintfA(szTitleA, SKIPLEN(countof(szTitleA)) "ConEmuC Debugging PID=%u, Debugger PID=%u", dwProcessId, GetCurrentProcessId()); wchar_t szTitle[64]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmuC Debugging PID=%u, Debugger PID=%u", dwProcessId, GetCurrentProcessId()); int nBtn = 0; if (gpSrv->DbgInfo.nDebugDumpProcess == 2 || gpSrv->DbgInfo.nDebugDumpProcess == 3) nBtn = (gpSrv->DbgInfo.nDebugDumpProcess == 2) ? IDYES : IDNO; else nBtn = MessageBoxA(NULL, asConfirmText ? asConfirmText : "Create minidump (<No> - fulldump)?", szTitleA, MB_YESNOCANCEL|MB_SYSTEMMODAL); switch (nBtn) { case IDYES: break; case IDNO: dumpType = MiniDumpWithFullMemory; break; default: return; } // Т.к. в режиме "ProcessTree" мы пишем пачку дампов - спрашивать тип дампа будем один раз. if (gpSrv->DbgInfo.bDebugProcessTree && (gpSrv->DbgInfo.nDebugDumpProcess <= 1)) { gpSrv->DbgInfo.nDebugDumpProcess = (nBtn == IDNO) ? 3 : 2; } if (bTreeBreak) { GenerateTreeDebugBreak(dwProcessId); } bool bDumpSucceeded = false; HANDLE hDmpFile = NULL; //HMODULE hDbghelp = NULL; wchar_t szErrInfo[MAX_PATH*2]; wchar_t dmpfile[MAX_PATH]; dmpfile[0] = 0; typedef BOOL (WINAPI* MiniDumpWriteDump_t)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam); MiniDumpWriteDump_t MiniDumpWriteDump_f = NULL; while (GetSaveDumpName(dwProcessId, (dumpType == MiniDumpWithFullMemory), dmpfile, countof(dmpfile))) { if (hDmpFile != INVALID_HANDLE_VALUE && hDmpFile != NULL) { CloseHandle(hDmpFile); hDmpFile = NULL; } hDmpFile = CreateFileW(dmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, NULL); if (hDmpFile == INVALID_HANDLE_VALUE) { DWORD nErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't create debug dump file\n%s\nErrCode=0x%08X\n\nChoose another name?", dmpfile, nErr); if (MessageBoxW(NULL, szErrInfo, szTitle, MB_YESNO|MB_SYSTEMMODAL|MB_ICONSTOP)!=IDYES) break; continue; // еще раз выбрать } if (!gpSrv->DbgInfo.hDbghelp) { gpSrv->DbgInfo.hDbghelp = LoadLibraryW(L"Dbghelp.dll"); if (gpSrv->DbgInfo.hDbghelp == NULL) { DWORD nErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't load debug library 'Dbghelp.dll'\nErrCode=0x%08X\n\nTry again?", nErr); if (MessageBoxW(NULL, szErrInfo, szTitle, MB_YESNO|MB_SYSTEMMODAL|MB_ICONSTOP)!=IDYES) break; continue; // еще раз выбрать } } if (gpSrv->DbgInfo.MiniDumpWriteDump_f) { MiniDumpWriteDump_f = (MiniDumpWriteDump_t)gpSrv->DbgInfo.MiniDumpWriteDump_f; } else if (!MiniDumpWriteDump_f) { MiniDumpWriteDump_f = (MiniDumpWriteDump_t)GetProcAddress(gpSrv->DbgInfo.hDbghelp, "MiniDumpWriteDump"); if (!MiniDumpWriteDump_f) { DWORD nErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't locate 'MiniDumpWriteDump' in library 'Dbghelp.dll', ErrCode=%u", nErr); MessageBoxW(NULL, szErrInfo, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL); break; } gpSrv->DbgInfo.MiniDumpWriteDump_f = (FARPROC)MiniDumpWriteDump_f; } if (MiniDumpWriteDump_f) { MINIDUMP_EXCEPTION_INFORMATION mei = {dwThreadId}; EXCEPTION_POINTERS ep = {pExceptionRecord}; ep.ContextRecord = NULL; // Непонятно, откуда его можно взять mei.ExceptionPointers = &ep; mei.ClientPointers = FALSE; PMINIDUMP_EXCEPTION_INFORMATION pmei = NULL; // пока _printf("Creating minidump: "); _wprintf(dmpfile); _printf("..."); HANDLE hProcess = GetProcessHandleForDebug(dwProcessId); BOOL lbDumpRc = MiniDumpWriteDump_f( hProcess, dwProcessId, hDmpFile, dumpType, pmei, NULL, NULL); if (!lbDumpRc) { DWORD nErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"MiniDumpWriteDump failed.\nErrorCode=0x%08X", nErr); _printf("\nFailed, ErrorCode=0x%08X\n", nErr); MessageBoxW(NULL, szErrInfo, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL); } else { _printf("\nMiniDumpWriteDump succeeded\n"); bDumpSucceeded = true; } break; } } // end while (GetSaveDumpName(dwProcessId, (dumpType == MiniDumpWithFullMemory), dmpfile, countof(dmpfile))) if (hDmpFile != INVALID_HANDLE_VALUE && hDmpFile != NULL) { CloseHandle(hDmpFile); } //if (hDbghelp) //{ // FreeLibrary(hDbghelp); //} //if (hCOMDLG32) //{ // FreeLibrary(hCOMDLG32); //} // В Win2k еще не было функции "отцепиться от процесса" if (bDumpSucceeded && gpSrv->DbgInfo.nDebugDumpProcess && !gpSrv->DbgInfo.bDebugProcessTree && (gnOsVer >= 0x0501)) { // Дело сделали, закрываемся SetTerminateEvent(ste_WriteMiniDump); //if (pfnGetConsoleProcessList) //{ // DWORD nCurCount = 0; // DWORD nConsolePids[128] = {}; // nCurCount = pfnGetConsoleProcessList(nConsolePids, countof(nConsolePids)); // // Но только если в консоли кроме нас никого нет // if (nCurCount == 0) // { // PostMessage(ghConWnd, WM_CLOSE, 0, 0); // } // else // { // SetTerminateEvent(); // } //} } }
// gpSrv->dwRootProcess void WriteMiniDump(DWORD dwProcessId, DWORD dwThreadId, EXCEPTION_RECORD *pExceptionRecord, LPCSTR asConfirmText /*= NULL*/, BOOL bTreeBreak /*= FALSE*/) { // 2 - minidump, 3 - fulldump int nConfirmDumpType = ConfirmDumpType(dwProcessId, asConfirmText); if (nConfirmDumpType < 2) { // Отмена return; } MINIDUMP_TYPE dumpType = (nConfirmDumpType == 2) ? MiniDumpNormal : MiniDumpWithFullMemory; // Т.к. в режиме "ProcessTree" мы пишем пачку дампов - спрашивать тип дампа будем один раз. if (IsDumpMulti() // several processes were attached && (gpSrv->DbgInfo.nDebugDumpProcess <= 1)) // 2 - minidump, 3 - fulldump { gpSrv->DbgInfo.nDebugDumpProcess = nConfirmDumpType; } if (bTreeBreak) { GenerateTreeDebugBreak(dwProcessId); } bool bDumpSucceeded = false; HANDLE hDmpFile = NULL; //HMODULE hDbghelp = NULL; wchar_t szErrInfo[MAX_PATH*2]; wchar_t szTitle[64]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) CE_CONEMUC_NAME_W L" Debugging PID=%u, Debugger PID=%u", dwProcessId, GetCurrentProcessId()); wchar_t dmpfile[MAX_PATH] = L""; dmpfile[0] = 0; FormatDumpName(dmpfile, countof(dmpfile), dwProcessId, false, (dumpType == MiniDumpWithFullMemory)); typedef BOOL (WINAPI* MiniDumpWriteDump_t)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam); MiniDumpWriteDump_t MiniDumpWriteDump_f = NULL; while (GetSaveDumpName(dwProcessId, (dumpType == MiniDumpWithFullMemory), dmpfile, countof(dmpfile))) { if (hDmpFile != INVALID_HANDLE_VALUE && hDmpFile != NULL) { CloseHandle(hDmpFile); hDmpFile = NULL; } hDmpFile = CreateFileW(dmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, NULL); if (hDmpFile == INVALID_HANDLE_VALUE) { DWORD nErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't create debug dump file\n%s\nErrCode=0x%08X\n\nChoose another name?", dmpfile, nErr); if (MessageBoxW(NULL, szErrInfo, szTitle, MB_YESNO|MB_SYSTEMMODAL|MB_ICONSTOP)!=IDYES) break; continue; // еще раз выбрать } if (!gpSrv->DbgInfo.hDbghelp) { gpSrv->DbgInfo.hDbghelp = LoadLibraryW(L"Dbghelp.dll"); if (gpSrv->DbgInfo.hDbghelp == NULL) { DWORD nErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't load debug library 'Dbghelp.dll'\nErrCode=0x%08X\n\nTry again?", nErr); if (MessageBoxW(NULL, szErrInfo, szTitle, MB_YESNO|MB_SYSTEMMODAL|MB_ICONSTOP)!=IDYES) break; continue; // еще раз выбрать } } if (gpSrv->DbgInfo.MiniDumpWriteDump_f) { MiniDumpWriteDump_f = (MiniDumpWriteDump_t)gpSrv->DbgInfo.MiniDumpWriteDump_f; } else if (!MiniDumpWriteDump_f) { MiniDumpWriteDump_f = (MiniDumpWriteDump_t)GetProcAddress(gpSrv->DbgInfo.hDbghelp, "MiniDumpWriteDump"); if (!MiniDumpWriteDump_f) { DWORD nErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't locate 'MiniDumpWriteDump' in library 'Dbghelp.dll', ErrCode=%u", nErr); MessageBoxW(NULL, szErrInfo, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL); break; } gpSrv->DbgInfo.MiniDumpWriteDump_f = (FARPROC)MiniDumpWriteDump_f; } if (MiniDumpWriteDump_f) { MINIDUMP_EXCEPTION_INFORMATION mei = {dwThreadId}; EXCEPTION_POINTERS ep = {pExceptionRecord}; ep.ContextRecord = NULL; // Непонятно, откуда его можно взять mei.ExceptionPointers = &ep; mei.ClientPointers = FALSE; PMINIDUMP_EXCEPTION_INFORMATION pmei = NULL; // пока _printf("Creating minidump: "); _wprintf(dmpfile); _printf("..."); HANDLE hProcess = GetProcessHandleForDebug(dwProcessId); BOOL lbDumpRc = MiniDumpWriteDump_f( hProcess, dwProcessId, hDmpFile, dumpType, pmei, NULL, NULL); if (!lbDumpRc) { DWORD nErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"MiniDumpWriteDump failed.\nErrorCode=0x%08X", nErr); _printf("\nFailed, ErrorCode=0x%08X\n", nErr); MessageBoxW(NULL, szErrInfo, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL); } else { int iLeft = (gpSrv->DbgInfo.nWaitTreeBreaks > 0) ? (gpSrv->DbgInfo.nWaitTreeBreaks - 1) : 0; _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"\nMiniDumpWriteDump succeeded, %i left\n", iLeft); bDumpSucceeded = true; } break; } } // end while (GetSaveDumpName(dwProcessId, (dumpType == MiniDumpWithFullMemory), dmpfile, countof(dmpfile))) if (hDmpFile != INVALID_HANDLE_VALUE && hDmpFile != NULL) { CloseHandle(hDmpFile); } // В Win2k еще не было функции "отцепиться от процесса" if ((gnOsVer >= 0x0501) && bDumpSucceeded && gpSrv->DbgInfo.bUserRequestDump // И все дампы были созданы && (gpSrv->DbgInfo.nWaitTreeBreaks <= 1) // И это не ключи /DEBUGEXE или /DEBUGTREE && !gpSrv->DbgInfo.pszDebuggingCmdLine ) { // По завершении создания дампов - выйти SetTerminateEvent(ste_WriteMiniDump); } }