void PrintCrashInformation(PEXCEPTION_POINTERS except) { echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); echo("Server has crashed. Reason was:\n"); echo(" %s at 0x%08X\n", GetExceptionDescription(except->ExceptionRecord->ExceptionCode), (unsigned long)except->ExceptionRecord->ExceptionAddress); echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); }
// called when an exception is detected (see below); provides detailed // debugging information and exits. // // note: keep memory allocs and locking to an absolute minimum, because // they may deadlock the process! long __stdcall wseh_ExceptionFilter(struct _EXCEPTION_POINTERS* ep) { // OutputDebugString raises an exception, which OUGHT to be swallowed // by WaitForDebugEvent but sometimes isn't. if we see it, ignore it. if(ep->ExceptionRecord->ExceptionCode == 0x40010006) // DBG_PRINTEXCEPTION_C return EXCEPTION_CONTINUE_EXECUTION; // if run in a debugger, let it handle exceptions (tends to be more // convenient since it can bring up the crash location) if(IsDebuggerPresent()) return EXCEPTION_CONTINUE_SEARCH; // make sure we don't recurse infinitely if this function raises an // SEH exception. (we may only have the guard page's 4 KB worth of // stack space if the exception is EXCEPTION_STACK_OVERFLOW) static intptr_t nestingLevel = 0; cpu_AtomicAdd(&nestingLevel, 1); if(nestingLevel >= 3) return EXCEPTION_CONTINUE_SEARCH; // someone is already holding the dbghelp lock - this is bad. // we'll report this problem first and then try to display the // exception info regardless (maybe dbghelp won't blow up). if(wutil_IsLocked(WDBG_SYM_CS) == 1) DEBUG_DISPLAY_ERROR(L"Exception raised while critical section is held - may deadlock.."); // a dump file is essential for debugging, so write it before // anything else goes wrong (especially before showing the error // dialog because the user could choose to exit immediately) wdbg_sym_WriteMinidump(ep); // extract details from ExceptionRecord. wchar_t descriptionBuf[150]; const wchar_t* description = GetExceptionDescription(ep, descriptionBuf, ARRAY_SIZE(descriptionBuf)); wchar_t file[DEBUG_FILE_CHARS] = {0}; int line = 0; wchar_t func[DEBUG_SYMBOL_CHARS] = {0}; GetExceptionLocus(ep, file, &line, func); wchar_t message[500]; const wchar_t* messageFormat = L"Much to our regret we must report the program has encountered an error.\r\n" L"\r\n" L"Please let us know at http://trac.wildfiregames.com/ and attach the crashlog.txt and crashlog.dmp files.\r\n" L"\r\n" L"Details: unhandled exception (%ls)\r\n"; swprintf_s(message, ARRAY_SIZE(message), messageFormat, description); size_t flags = 0; if(ep->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) flags = DE_NO_CONTINUE; const wchar_t* const lastFuncToSkip = WIDEN(STRINGIZE(DECORATED_NAME(wseh_ExceptionFilter))); ErrorReaction er = debug_DisplayError(message, flags, ep->ContextRecord, lastFuncToSkip, file,line,utf8_from_wstring(func).c_str(), 0); ENSURE(er == ER_CONTINUE); // nothing else possible // invoke the Win32 default handler - it calls ExitProcess for // most exception types. return EXCEPTION_CONTINUE_SEARCH; }
void PrintCrashInformation(PEXCEPTION_POINTERS except) { echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); echo("Server has crashed. Reason was:\n"); echo(" %s at 0x%08X\n", GetExceptionDescription(except->ExceptionRecord->ExceptionCode), (unsigned long)except->ExceptionRecord->ExceptionAddress); #ifdef REPACK echo("%s repack by %s has crashed. Visit %s for support.", REPACK, REPACK_AUTHOR, REPACK_WEBSITE); #endif echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); }
void PrintCrashInformation(PEXCEPTION_POINTERS except) { time_t curtime = time(NULL); tm * pTime = localtime(&curtime); echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); echo("Server has crashed. Reason was:\n"); echo(" %s at 0x%08X\n", GetExceptionDescription(except->ExceptionRecord->ExceptionCode), (unsigned long)except->ExceptionRecord->ExceptionAddress); if(pTime) echo("Logged at: %u %u %u %u %u", pTime->tm_mon, pTime->tm_mday, pTime->tm_hour, pTime->tm_min, pTime->tm_sec); echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); echo("Call Stack: \n"); CStackWalker sw; sw.ShowCallstack(); echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); }
// Entry point into the main exception handling routine. This routine is put into an except() // statment at the beginning of a thread and is called anytime that there is a program exception // The data is stored in a file called ErrorLog.txt in the data directory. // // data: pointer to the exception data // Message: Any message that should be printed out in the error log file // // returns: // int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const char *Message) { static bool BeenHere = false; // Going recursive! That must mean this routine crashed! if (BeenHere) { return EXCEPTION_CONTINUE_SEARCH; } BeenHere = true; char ModuleName[MAX_PATH]; char FileName[MAX_PATH] = "Unknown"; // Create a filename to record the error information to. // Storing it in the executable directory works well. if (GetModuleFileName(0, ModuleName, sizeof(ModuleName)) <= 0) { ModuleName[0] = 0; } char *FilePart = GetFilePart(ModuleName); // Extract the file name portion and remove it's file extension. We'll // use that name shortly. lstrcpy(FileName, FilePart); char *lastperiod = strrchr(FileName, '.'); if (lastperiod) { lastperiod[0] = 0; } // Replace the executable filename with our error log file name. lstrcpy(FilePart, "errorlog.txt"); HANDLE LogFile = CreateFile(ModuleName, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0); if (LogFile == INVALID_HANDLE_VALUE) { OutputDebugString("Error creating exception report"); return EXCEPTION_CONTINUE_SEARCH; } // Append to the error log. SetFilePointer(LogFile, 0, 0, FILE_END); // Print out some blank lines to separate this error log from any previous ones. hprintf(LogFile, "\r\n\r\n\r\n\r\n"); PEXCEPTION_RECORD Exception = data->ExceptionRecord; PCONTEXT Context = data->ContextRecord; char CrashModulePathName[MAX_PATH]; char *CrashModuleFileName = "Unknown"; MEMORY_BASIC_INFORMATION MemInfo; // VirtualQuery can be used to get the allocation base associated with a // code address, which is the same as the ModuleHandle. This can be used // to get the filename of the module that the crash happened in. if (VirtualQuery((void*)Context->Eip, &MemInfo, sizeof(MemInfo)) && GetModuleFileName((HINSTANCE)MemInfo.AllocationBase, CrashModulePathName, sizeof(CrashModulePathName)) > 0) { CrashModuleFileName = GetFilePart(CrashModulePathName); } // Print out the beginning of the error log in a Win95 error window // compatible format. hprintf(LogFile, "%s caused %s in module %s at %04x:%08x.\r\n", FileName, GetExceptionDescription(Exception->ExceptionCode), CrashModuleFileName, Context->SegCs, Context->Eip); hprintf(LogFile, "Exception handler called in %s.\r\n", Message); RecordSystemInformation(LogFile); // If the exception was an access violation, print out some additional // information, to the error log and the debugger. if (Exception->ExceptionCode == STATUS_ACCESS_VIOLATION && Exception->NumberParameters >= 2) { char DebugMessage[1000]; const char* readwrite = "Read from"; if (Exception->ExceptionInformation[0]) { readwrite = "Write to"; } wsprintf(DebugMessage, "%s location %08x caused an access violation.\r\n", readwrite, Exception->ExceptionInformation[1]); #ifdef _DEBUG // The VisualC++ debugger doesn't actually tell you whether a read // or a write caused the access violation, nor does it tell what // address was being read or written. So I fixed that. OutputDebugString("Exception handler: "); OutputDebugString(DebugMessage); #endif hprintf(LogFile, "%s", DebugMessage); } // Print out the register values in a Win95 error window compatible format. hprintf(LogFile, "\r\n"); hprintf(LogFile, "Registers:\r\n"); hprintf(LogFile, "EAX=%08x CS=%04x EIP=%08x EFLGS=%08x\r\n", Context->Eax, Context->SegCs, Context->Eip, Context->EFlags); hprintf(LogFile, "EBX=%08x SS=%04x ESP=%08x EBP=%08x\r\n", Context->Ebx, Context->SegSs, Context->Esp, Context->Ebp); hprintf(LogFile, "ECX=%08x DS=%04x ESI=%08x FS=%04x\r\n", Context->Ecx, Context->SegDs, Context->Esi, Context->SegFs); hprintf(LogFile, "EDX=%08x ES=%04x EDI=%08x GS=%04x\r\n", Context->Edx, Context->SegEs, Context->Edi, Context->SegGs); hprintf(LogFile, "Bytes at CS:EIP:\r\n"); // Print out the bytes of code at the instruction pointer. Since the // crash may have been caused by an instruction pointer that was bad, // this code needs to be wrapped in an exception handler, in case there // is no memory to read. If the dereferencing of code[] fails, the // exception handler will print '??'. unsigned char *code = (unsigned char*)Context->Eip; for (int codebyte = 0; codebyte < NumCodeBytes; codebyte++) { #ifdef _MSC_VER __try { #endif hprintf(LogFile, "%02x ", code[codebyte]); #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER) { hprintf(LogFile, "?? "); } #endif } #ifdef _MSC_VER // Time to print part or all of the stack to the error log. This allows // us to figure out the call stack, parameters, local variables, etc. hprintf(LogFile, "\r\n" "Stack dump:\r\n"); __try { // Esp contains the bottom of the stack, or at least the bottom of // the currently used area. DWORD* pStack = (DWORD *)Context->Esp; DWORD* pStackTop; __asm { // Load the top (highest address) of the stack from the // thread information block. It will be found there in // Win9x and Windows NT. mov eax, fs:[4] mov pStackTop, eax } if (pStackTop > pStack + MaxStackDump) { pStackTop = pStack + MaxStackDump; } int Count = 0; // Too many calls to WriteFile can take a long time, causing // confusing delays when programs crash. Therefore I implemented // simple buffering for the stack dumping code instead of calling // hprintf directly. char buffer[1000] = ""; const int safetyzone = 50; char* nearend = buffer + sizeof(buffer) - safetyzone; char* output = buffer; while (pStack + 1 <= pStackTop) { if ((Count % StackColumns) == 0) { output += wsprintf(output, "%08x: ", pStack); } char *Suffix = " "; if ((++Count % StackColumns) == 0 || pStack + 2 > pStackTop) { Suffix = "\r\n"; } output += wsprintf(output, "%08x%s", *pStack, Suffix); pStack++; // Check for when the buffer is almost full, and flush it to disk. if (output > nearend) { hprintf(LogFile, "%s", buffer); buffer[0] = 0; output = buffer; } } // Print out any final characters from the cache. hprintf(LogFile, "%s", buffer); } __except(EXCEPTION_EXECUTE_HANDLER) { hprintf(LogFile, "Exception encountered during stack dump.\r\n"); } #endif #ifndef NDEBUG if (safe_string[0]) hprintf(LogFile, "Last safe point: %s\r\n", safe_string); #endif RecordModuleList(LogFile); CloseHandle(LogFile); // Return the magic value which tells Win32 that this handler didn't // actually handle the exception - so that things will proceed as per // normal. return EXCEPTION_CONTINUE_SEARCH; }
void ExceptionHandler(unsigned int, PEXCEPTION_POINTERS lpCeption) { //Get time SYSTEMTIME st; GetLocalTime(&st); TCHAR szTime[120] = {0}; sprintf_s(szTime, 120, "%d-%d-%d-%d-%d-%d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); //Get current module name TCHAR* lpCurModuleName = _T("Current Module name"); TCHAR szModuleName[MAX_PATH] = {0}; if (GetModuleFileName(NULL, szModuleName, MAX_PATH) > 0) lpCurModuleName = GetFilePart(szModuleName); //Create log file TCHAR szFilePath[MAX_PATH] = {0}; TCHAR szLogPath[MAX_PATH] = {0}; GetCurrentDirectory(MAX_PATH, szFilePath); sprintf_s(szLogPath, MAX_PATH, "%s\\Exception-%s.log", szFilePath, szTime); HANDLE hLogFile = CreateFile(szLogPath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0); if (hLogFile == INVALID_HANDLE_VALUE) return;// EXCEPTION_CONTINUE_SEARCH; PEXCEPTION_RECORD Exception = lpCeption->ExceptionRecord; PCONTEXT Context = lpCeption->ContextRecord; TCHAR szCrashModuleName[MAX_PATH] = {0}; TCHAR* lpCrashName = _T("Exception Process Name"); MEMORY_BASIC_INFORMATION memInfo; // VirtualQuery can be used to get the allocation base associated with a // code address, which is the same as the ModuleHandle. This can be used // to get the filename of the module that the crash happened in. if (VirtualQuery((LPCVOID)Context->Eip, &memInfo, sizeof(memInfo)) && (GetModuleFileName((HMODULE)memInfo.AllocationBase, szCrashModuleName, MAX_PATH) > 0)) lpCrashName = GetFilePart(szCrashModuleName); WriteLogFile(hLogFile, "%s caused %s(0x%08x) in module %s at %04x:%08x.\r\n", lpCurModuleName, GetExceptionDescription(Exception->ExceptionCode), Exception->ExceptionCode, lpCrashName, Context->SegCs, Context->Eip); //Write system info to logfile DumpSystemInformation(hLogFile, lpCurModuleName); // Print out the bytes of code at the instruction pointer. Since the // crash may have been caused by an instruction pointer that was bad, // this code needs to be wrapped in an exception handler, in case there // is no memory to read. If the dereferencing of code[] fails, the // exception handler will print '??'. WriteLogFile(hLogFile, _T("\r\n\r\nCode Start CS:EIP:\r\n")); BYTE * code = (BYTE *)Context->Eip; for (int codebyte = 0; codebyte < 16; codebyte++) { __try { WriteLogFile(hLogFile, _T("%02x "), code[codebyte]); } __except(EXCEPTION_EXECUTE_HANDLER) { WriteLogFile(hLogFile, _T("?? ")); } } //Write Stack information to logfile DumpStackStak(hLogFile, lpCeption); //Write module of process information to logfile DumpModuleList(hLogFile); CloseHandle(hLogFile); //Create dump file sprintf_s(szLogPath, MAX_PATH, "%s\\Exception-%s.dmp", szFilePath, szTime); HANDLE hDumpFile = CreateFile(szLogPath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0); if (hDumpFile == INVALID_HANDLE_VALUE) return;// EXCEPTION_CONTINUE_SEARCH; MINIDUMP_EXCEPTION_INFORMATION eInfo; eInfo.ThreadId = GetCurrentThreadId(); eInfo.ExceptionPointers = lpCeption; eInfo.ClientPointers = FALSE; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &eInfo, NULL, NULL); CloseHandle(hDumpFile); }
void DoReport(LPCTSTR lpstrCmdLine, BOOL *pIsHandled) { WSADATA wsaData = {0}; WSAStartup(MAKEWORD(2, 2), &wsaData); //LogFinal(LOG::KBugReport) << L"Bugreport启动命令行: " << lpstrCmdLine; REPORT_CONTEXT report; std::wstring strProductName; const TCHAR * p = _tcsstr(lpstrCmdLine, _T("pid=")); if (p) { *pIsHandled = TRUE; DWORD client_process_id = _tcstoul(p + _tcslen(_T("pid=")), 0, 0); p = _tcsstr(lpstrCmdLine, _T("context=")); if (p) { void *addr = (void*)_tcstoul(p + _tcslen(_T("context=")), 0, 0); //YYBrowser Begin //by ZC. 2013-10-30 11:26. // hClientProcess客户进程,即是启动YGCrashReport的进程,不一定是崩溃的目标进程。 HANDLE client_process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, client_process_id); // 崩溃目标进程。 HANDLE target_process_handle = NULL; //YYBrowser End if (!client_process_handle) LogFinal(LOG::KBugReport) << L"打开进程句柄失败"; //解释REPORT_PARAMS CRASH_LAUNCH_PARAMS crash_launch_params = {0}; DWORD cbRead = 0; if (addr && ::ReadProcessMemory(client_process_handle, addr, &crash_launch_params, sizeof(crash_launch_params), &cbRead)) { LogFinal(LOG::KBugReport) << L"读取REPORT_PARAMS成功"; std::set<std::wstring> setSuspectModule; std::set<std::wstring> setModule; std::wstring strPathNoExt = GenerateNewFilePath(crash_launch_params.dwPID); report.strZipFilePath = strPathNoExt + _T(".zip"); report.strOSVer = GetOSVer(); AtoW(crash_launch_params.szProductName, -1, strProductName); report.dwReportId = crash_launch_params.dwReportId; report.strUserId = crash_launch_params.szUserId; report.strProductId = crash_launch_params.szProductId; report.strProductVer = crash_launch_params.szProductVer; report.strProductVerDetail = crash_launch_params.szProductVerDetail; //AtoW(crash_launch_params.szRestartExePath, -1, report.wstrRestartExePath); report.strDynaReleaseVer = crash_launch_params.szDynaReleaseVer; WriteBugInfo(report.dwReportId); report.dwCount24Hour = GetBugCount(report.dwReportId); //parse 自定义文件路径 if (crash_launch_params.nFileCount > 0) { char *pPaths = new char[MAX_PATH * crash_launch_params.nFileCount]; if (::ReadProcessMemory(client_process_handle, crash_launch_params.lpszCustomFilePaths, pPaths, MAX_PATH * crash_launch_params.nFileCount, &cbRead)) { for (UINT k = 0; k < cbRead / MAX_PATH; k++) { std::wstring wstrPath; AtoW(pPaths + k * MAX_PATH, -1, wstrPath); report.vecOtherFilePath.push_back(wstrPath); } } delete [] pPaths; pPaths = NULL; } //生成log std::string strLog; char szTemp[1024] = {0}; //Date time_t curTime = 0; time(&curTime); strftime(szTemp, _countof(szTemp)-1, "%Y-%m-%d %H.%M.%S\r\n", localtime(&curTime)); strLog += szTemp; strLog += "\r\n"; //异常信息 strLog += "Exception:\r\n"; const char *pModName = strrchr(crash_launch_params.szExcepModPath, '\\'); if (pModName) pModName++; else pModName = crash_launch_params.szExcepModPath; report.strExcepModuleName = pModName; _snprintf_s(szTemp, _countof(szTemp), _TRUNCATE, "Module=%s\r\n", pModName); strLog += szTemp; //YYBrowser Begin //打开目标进程。by ZC. 2013-10-30 11:30. target_process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, crash_launch_params.dwPID); //YYBrowser End //YYBrowser Begin //从目标进程中读出结构异常。by ZC. 2013-10-30 11:28. if (crash_launch_params.pExceptionInfo) { EXCEPTION_RECORD excep = {0}; CONTEXT ct = {0}; EXCEPTION_POINTERS ptr = {0}; if (::ReadProcessMemory(target_process_handle, crash_launch_params.pExceptionInfo, &ptr, sizeof(ptr), &cbRead) && ::ReadProcessMemory(target_process_handle, ptr.ExceptionRecord, &excep, sizeof(excep), &cbRead) && ::ReadProcessMemory(target_process_handle, ptr.ContextRecord, &ct, sizeof(ct), &cbRead)) { report.dwExcepAddr = (DWORD)excep.ExceptionAddress; report.dwExcepCode = excep.ExceptionCode; report.strExcepDiscription = GetExceptionDescription(excep.ExceptionCode); _snprintf_s(szTemp, _countof(szTemp), _TRUNCATE, "ExceptionCode=0x%08x, %s\r\n", excep.ExceptionCode, GetExceptionDescription(excep.ExceptionCode)); strLog += szTemp; _snprintf_s(szTemp, _countof(szTemp), _TRUNCATE, "eip=0x%08x, ebp=0x%08x, esp=0x%08x, eax=0x%08x, ebx=0x%08x, ecx=0x%08x, edx=0x%08x, esi=0x%08x, edi=0x%08x\r\n", ct.Eip, ct.Ebp, ct.Esp, ct.Eax, ct.Ebx, ct.Ecx, ct.Edx, ct.Esi, ct.Edi); strLog += szTemp; } strLog += "\r\n"; } //YYBrowser End strLog += "Summary:\r\n"; strLog += GetSummary(client_process_handle); strLog += "UserId(YY)=" + report.strUserId + "\r\n"; strLog += "ProductVer=" + report.strProductVer + "\r\n"; strLog += "DynaReleaseVer=" + report.strDynaReleaseVer + "\r\n"; strLog += "ProductVerDetail=" + report.strProductVerDetail + "\r\n"; _snprintf_s(szTemp, _countof(szTemp), _TRUNCATE, "ReportId=%u\r\n", report.dwReportId); strLog += szTemp; strLog += "\r\n"; std::string strLoginHistoryLog; std::string strLoginHistory = ReadLoginHistory(strLoginHistoryLog); //用户自定义信息 strLog += "CustomProperty:\r\n"; char *pCustomProperty = new char[crash_launch_params.cchCustomProperty + 1]; if (::ReadProcessMemory(client_process_handle, crash_launch_params.lpszCustomProperty, pCustomProperty, crash_launch_params.cchCustomProperty, &cbRead)) { pCustomProperty[cbRead/sizeof(char)] = 0; report.strCustomProperty = pCustomProperty; } strLog += report.strCustomProperty; if(strLoginHistory.size()>0) { if(report.strCustomProperty.size()>0) { report.strCustomProperty+="&"; } report.strCustomProperty+=strLoginHistory; } if(strLoginHistoryLog.size()>0) { strLog += "\r\n"; strLog += strLoginHistoryLog; } strLog += "\r\n"; //CallStack strLog += "Call Stack:\r\n"; char *pCallStack = new char[crash_launch_params.cchCallStack + 1]; cbRead = 0; if (::ReadProcessMemory(client_process_handle, crash_launch_params.lpszCallStack, pCallStack, crash_launch_params.cchCallStack, &cbRead)) { pCallStack[cbRead/sizeof(char)] = 0; strLog += pCallStack; } strLog += "\r\n"; //收集进程列表&检测运行环境 std::string strProcListA; std::wstring strProcListW; report.dwRunEnvironment = CheckRunEnvironment(strProcListW); WtoA(strProcListW.c_str(), -1, strProcListA); strLog += "Process List:\r\n"; strLog += strProcListA; strLog += "\r\n"; //收集版本的语言种类,不写入日志 report.strProductLang = GetLanguageName(); //模块列表 strLog += "Module List:\r\n"; strLog += GetModuleList(target_process_handle,&setModule,&setSuspectModule); strLog += "\r\n"; //程序Log strLog += "Log:\r\n"; TCHAR szExePath[MAX_PATH] = {0}; GetModuleFileNameEx(target_process_handle, NULL, szExePath, _countof(szExePath)); TCHAR *p = _tcsrchr(szExePath, _T('.')); if (p) *p = 0; TCHAR* pExeName = _tcsrchr(szExePath, _T('\\')); if (pExeName) pExeName++; else pExeName = szExePath; const DWORD dwMaxLogSize = 1024 * 200; // char *pContent = new char [dwMaxLogSize]; // GetLastLog(pExeName, reportParams.dwPID, 0, pContent, dwMaxLogSize); // strLog += pContent; // delete [] pContent; // pContent = NULL; strLog += "\r\n\r\n"; /************************************************************************/ /*功能:在日志文件中添加安装目录下所有dll和rcc文件的md5*/ /***************************只有yy.exe崩溃时,才会计算相关文件的md5*/ if (StrCmpIA(crash_launch_params.szProductId, "YY") == 0) { strLog += "[List *.dll and *.rcc files MD5:] \r\n\r\n"; TCHAR szCurrentProcesspath[MAX_PATH] = {0}; if ( GetModuleFileName(NULL,szCurrentProcesspath,_countof(szCurrentProcesspath)) > 0) { TCHAR* p_findDir = _tcsrchr(szCurrentProcesspath,_T('\\')); std::wstring rawCurrentProcessPath = szCurrentProcesspath; std::wstring strCurrentProcesspath = rawCurrentProcessPath.substr(0, p_findDir - szCurrentProcesspath); strLog += dwCalculateMD5(strCurrentProcesspath.c_str()); } else { strLog += "Get the files'MD5 failed!"; } } else { strLog += "Hint:\r\nThe crash was caused by the other products except the YY!"; } /************************************************************************/ TCHAR szLogPath[_MAX_PATH] = {0}; _sntprintf_s(szLogPath, _countof(szLogPath), _TRUNCATE, _T("%s.txt"), strPathNoExt.c_str()); report.strLogPath = szLogPath; LogFinal(LOG::KBugReport) << L"写入log文件: " << szLogPath; HANDLE hFile = ::CreateFile(szLogPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, NULL, NULL); DWORD dwWriten = 0; ::WriteFile(hFile, strLog.c_str(), strLog.size(), &dwWriten, NULL); ::CloseHandle(hFile); //生成dump TCHAR szDumpPath[_MAX_PATH] = {0}; _sntprintf_s(szDumpPath, _countof(szDumpPath), _TRUNCATE, _T("%s.dmp"), strPathNoExt.c_str()); LogFinal(LOG::KBugReport) << L"生成dump文件: " << szDumpPath; int nDumpType = (MiniDumpNormal|MiniDumpWithHandleData|MiniDumpWithIndirectlyReferencedMemory|MiniDumpWithUnloadedModules|MiniDumpWithProcessThreadData); if (!CreateDump(szDumpPath, crash_launch_params.dwPID, crash_launch_params.dwTID, crash_launch_params.pExceptionInfo, nDumpType, MyMiniDumpCallBack, &crash_launch_params)) { crash_launch_params.curCustomDataIdx = 0; CreateDump(szDumpPath, crash_launch_params.dwPID, crash_launch_params.dwTID, crash_launch_params.pExceptionInfo, MiniDumpNormal, MyMiniDumpCallBack, &crash_launch_params); } report.strDumpPath = szDumpPath; //生成fulldump CRegKey key; LONG lResult = key.Open(HKEY_CURRENT_USER, _T("Software\\duowan\\bugreport"), KEY_READ); if (ERROR_SUCCESS == lResult) { TCHAR szFullDump[1024] = {0}; DWORD dwSize = _countof(szFullDump); lResult = key.QueryValue(szFullDump, _T("fulldump"), &dwSize); if (ERROR_SUCCESS == lResult) { szFullDump[dwSize] = 0; if (_tcsicmp(szFullDump, _T("yes")) == 0) { nDumpType = (MiniDumpNormal | MiniDumpWithFullMemory | MiniDumpWithIndirectlyReferencedMemory | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData); TCHAR szFullDumpPath[_MAX_PATH] = {0}; ::GetTempPath(_countof(szFullDumpPath), szFullDumpPath); _tcsncat_s(szFullDumpPath, _countof(szFullDumpPath), _T("duowan\\fulldump.dmp"), _TRUNCATE); LogFinal(LOG::KBugReport) << L"生成fulldump文件: " << szFullDumpPath; CreateDump(szFullDumpPath, crash_launch_params.dwPID, crash_launch_params.dwTID, crash_launch_params.pExceptionInfo, nDumpType, MyMiniDumpCallBack, &crash_launch_params); } } } ::SetEvent(crash_launch_params.evDumpComplete); if (crash_launch_params.bShowReportUI) { LogFinal(LOG::KBugReport) << L"开始弹出崩溃界面"; std::string strRecv; bool bShowModifyStatus = false; //if(GetBugModifyStatus(&report,strRecv)) //{ // const char* p = strstr(strRecv.c_str(),"return=true"); // if(p) // { // bShowModifyStatus = true; // } //} CMessageLoop theLoop; _Module.AddMessageLoop(&theLoop); CDlgReport dlgMain(strProductName.c_str(), &report, crash_launch_params.dwPID, &setModule, &setSuspectModule, bShowModifyStatus, strRecv.c_str()); dlgMain.Create(NULL); dlgMain.ShowWindow(SW_SHOW); theLoop.Run(); _Module.RemoveMessageLoop(); } else { SendReport(&report, &setModule, &setSuspectModule); } } else { LogFinal(LOG::KBugReport) << L"读取崩溃进程REPORT_PARAMS失败"; } ::CloseHandle(target_process_handle); ::CloseHandle(client_process_handle); } } }