void CSetPgDebug::debugLogCommand(CESERVER_REQ* pInfo, BOOL abInput, DWORD anTick, DWORD anDur, LPCWSTR asPipe, CESERVER_REQ* pResult/*=NULL*/) { CSetPgDebug* pDbgPg = (CSetPgDebug*)gpSetCls->GetPageObj(thi_Debug); if (!pDbgPg) return; if (pDbgPg->GetActivityLoggingType() != glt_Commands) return; _ASSERTE(abInput==TRUE || pResult!=NULL || (pInfo->hdr.nCmd==CECMD_LANGCHANGE || pInfo->hdr.nCmd==CECMD_GUICHANGED || pInfo->hdr.nCmd==CMD_FARSETCHANGED || pInfo->hdr.nCmd==CECMD_ONACTIVATION)); LogCommandsData* pData = (LogCommandsData*)calloc(1,sizeof(LogCommandsData)); if (!pData) return; pData->bInput = abInput; pData->bMainThread = (abInput == FALSE) && isMainThread(); pData->nTick = anTick - pDbgPg->mn_ActivityCmdStartTick; pData->nDur = anDur; pData->nCmd = pInfo->hdr.nCmd; pData->nSize = pInfo->hdr.cbSize; pData->nPID = abInput ? pInfo->hdr.nSrcPID : pResult ? pResult->hdr.nSrcPID : 0; LPCWSTR pszName = asPipe ? PointToName(asPipe) : NULL; lstrcpyn(pData->szPipe, pszName ? pszName : L"", countof(pData->szPipe)); switch (pInfo->hdr.nCmd) { case CECMD_POSTCONMSG: _wsprintf(pData->szExtra, SKIPLEN(countof(pData->szExtra)) L"HWND=x%08X, Msg=%u, wParam=" WIN3264TEST(L"x%08X",L"x%08X%08X") L", lParam=" WIN3264TEST(L"x%08X",L"x%08X%08X") L": ", pInfo->Msg.hWnd, pInfo->Msg.nMsg, WIN3264WSPRINT(pInfo->Msg.wParam), WIN3264WSPRINT(pInfo->Msg.lParam)); GetClassName(pInfo->Msg.hWnd, pData->szExtra+lstrlen(pData->szExtra), countof(pData->szExtra)-lstrlen(pData->szExtra)); break; case CECMD_NEWCMD: lstrcpyn(pData->szExtra, pInfo->NewCmd.GetCommand(), countof(pData->szExtra)); break; case CECMD_GUIMACRO: lstrcpyn(pData->szExtra, pInfo->GuiMacro.sMacro, countof(pData->szExtra)); break; case CMD_POSTMACRO: lstrcpyn(pData->szExtra, (LPCWSTR)pInfo->wData, countof(pData->szExtra)); break; } PostMessage(pDbgPg->Dlg(), DBGMSG_LOG_ID, DBGMSG_LOG_CMD_MAGIC, (LPARAM)pData); }
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI OnSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) { //typedef LPTOP_LEVEL_EXCEPTION_FILTER(WINAPI* OnSetUnhandledExceptionFilter_t)(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); ORIGINAL_KRNL(SetUnhandledExceptionFilter); LPTOP_LEVEL_EXCEPTION_FILTER lpRc = F(SetUnhandledExceptionFilter)(lpTopLevelExceptionFilter); #ifdef _DEBUG DWORD dwErr = GetLastError(); wchar_t szDbgInfo[100]; msprintf(szDbgInfo, countof(szDbgInfo), L"SetUnhandledExceptionFilter(" WIN3264TEST(L"0x%08X",L"0x%08X%08X") L")=" WIN3264TEST(L"0x%08X",L"0x%08X%08X") L", code=%u\n", WIN3264WSPRINT(lpTopLevelExceptionFilter), WIN3264WSPRINT(lpRc), dwErr); DebugString(szDbgInfo); SetLastError(dwErr); #endif return lpRc; }
BOOL WINAPI OnVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect) { //typedef BOOL(WINAPI* OnVirtualProtect_t)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); ORIGINAL_KRNL(VirtualProtect); BOOL bResult = FALSE; if (F(VirtualProtect)) bResult = F(VirtualProtect)(lpAddress, dwSize, flNewProtect, lpflOldProtect); #ifdef _DEBUG DWORD dwErr = GetLastError(); wchar_t szDbgInfo[100]; msprintf(szDbgInfo, countof(szDbgInfo), L"VirtualProtect(" WIN3264TEST(L"0x%08X",L"0x%08X%08X") L"," WIN3264TEST(L"0x%08X",L"0x%08X%08X") L",%u,%u)=%u, code=%u\n", WIN3264WSPRINT(lpAddress), WIN3264WSPRINT(dwSize), flNewProtect, lpflOldProtect ? *lpflOldProtect : 0, bResult, dwErr); DebugString(szDbgInfo); SetLastError(dwErr); #endif return bResult; }
void ProcessDebugEvent() { static wchar_t wszDbgText[1024]; static char szDbgText[1024]; BOOL lbNonContinuable = FALSE; DEBUG_EVENT evt = {0}; BOOL lbEvent = WaitForDebugEvent(&evt,10); #ifdef _DEBUG DWORD dwErr = GetLastError(); #endif static bool bFirstExitThreadEvent = false; // Чтобы вывести на экран подсказку по возможностям "дебаггера" //HMODULE hCOMDLG32 = NULL; //typedef BOOL (WINAPI* GetSaveFileName_t)(LPOPENFILENAMEW lpofn); //GetSaveFileName_t _GetSaveFileName = NULL; DWORD dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED; if (lbEvent) { lbNonContinuable = FALSE; switch (evt.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: case CREATE_THREAD_DEBUG_EVENT: case EXIT_PROCESS_DEBUG_EVENT: case EXIT_THREAD_DEBUG_EVENT: case RIP_EVENT: { LPCSTR pszName = "Unknown"; switch (evt.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: pszName = "CREATE_PROCESS_DEBUG_EVENT"; break; case CREATE_THREAD_DEBUG_EVENT: pszName = "CREATE_THREAD_DEBUG_EVENT"; break; case EXIT_PROCESS_DEBUG_EVENT: pszName = "EXIT_PROCESS_DEBUG_EVENT"; break; case EXIT_THREAD_DEBUG_EVENT: pszName = "EXIT_THREAD_DEBUG_EVENT"; break; case RIP_EVENT: pszName = "RIP_EVENT"; break; } _wsprintfA(szDbgText, SKIPLEN(countof(szDbgText)) "{%i.%i} %s\n", evt.dwProcessId,evt.dwThreadId, pszName); _printf(szDbgText); if (!bFirstExitThreadEvent && evt.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT) { bFirstExitThreadEvent = true; if (gpSrv->DbgInfo.nDebugDumpProcess == 0) { _printf("ConEmuC: Press Ctrl+Break to create minidump of debugging process\n"); } else { // Сразу сделать дамп и выйти HandlerRoutine(CTRL_BREAK_EVENT); } } if (evt.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) { gpSrv->DbgInfo.nProcessCount++; _ASSERTE(gpSrv->DbgInfo.pDebugTreeProcesses!=NULL); CEDebugProcessInfo pi = {evt.dwProcessId}; gpSrv->DbgInfo.pDebugTreeProcesses->Set(evt.dwProcessId, pi); UpdateDebuggerTitle(); } else if (evt.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) { CEDebugProcessInfo pi = {}; if (gpSrv->DbgInfo.pDebugTreeProcesses && gpSrv->DbgInfo.pDebugTreeProcesses->Get(evt.dwProcessId, &pi, true) && pi.hProcess) { CloseHandle(pi.hProcess); } if (gpSrv->DbgInfo.nProcessCount > 0) gpSrv->DbgInfo.nProcessCount--; UpdateDebuggerTitle(); } break; } case LOAD_DLL_DEBUG_EVENT: case UNLOAD_DLL_DEBUG_EVENT: { LPCSTR pszName = "Unknown"; char szBase[32] = {}; char szFile[MAX_PATH+128] = {}; struct MY_FILE_NAME_INFO { DWORD FileNameLength; WCHAR FileName[1]; }; typedef BOOL (WINAPI* GetFileInformationByHandleEx_t)(HANDLE hFile, int FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize); static GetFileInformationByHandleEx_t _GetFileInformationByHandleEx = NULL; switch (evt.dwDebugEventCode) { case LOAD_DLL_DEBUG_EVENT: //6 Reports a load-dynamic-link-library (DLL) debugging event. The value of u.LoadDll specifies a LOAD_DLL_DEBUG_INFO structure. pszName = "LOAD_DLL_DEBUG_EVENT"; if (evt.u.LoadDll.hFile) { if (gnOsVer >= 0x0600) { if (!_GetFileInformationByHandleEx) _GetFileInformationByHandleEx = (GetFileInformationByHandleEx_t)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetFileInformationByHandleEx"); if (_GetFileInformationByHandleEx) { DWORD nSize = sizeof(MY_FILE_NAME_INFO)+MAX_PATH*sizeof(wchar_t); MY_FILE_NAME_INFO* pfi = (MY_FILE_NAME_INFO*)calloc(nSize+2,1); if (pfi) { pfi->FileNameLength = MAX_PATH; if (_GetFileInformationByHandleEx(evt.u.LoadDll.hFile, 2/*FileNameInfo*/, pfi, nSize) && pfi->FileName[0]) { wchar_t szFullPath[MAX_PATH+1] = {}, *pszFile; DWORD n = GetFullPathName(pfi->FileName, countof(szFullPath), szFullPath, &pszFile); if (!n || (n >= countof(szFullPath))) { lstrcpyn(szFullPath, pfi->FileName, countof(szFullPath)); pszFile = (wchar_t*)PointToName(pfi->FileName); } else if (!pszFile) { pszFile = (wchar_t*)PointToName(szFullPath); } lstrcpyA(szFile, ", "); WideCharToMultiByte(CP_OEMCP, 0, pszFile, -1, szFile+lstrlenA(szFile), 80, 0,0); lstrcatA(szFile, "\n\t"); WideCharToMultiByte(CP_OEMCP, 0, szFullPath, -1, szFile+lstrlenA(szFile), MAX_PATH, 0,0); } free(pfi); } } } CloseHandle(evt.u.LoadDll.hFile); } _wsprintfA(szBase, SKIPLEN(countof(szBase)) " at " WIN3264TEST("0x%08X","0x%08X%08X"), WIN3264WSPRINT((DWORD_PTR)evt.u.LoadDll.lpBaseOfDll)); break; case UNLOAD_DLL_DEBUG_EVENT: //7 Reports an unload-DLL debugging event. The value of u.UnloadDll specifies an UNLOAD_DLL_DEBUG_INFO structure. pszName = "UNLOAD_DLL_DEBUG_EVENT"; _wsprintfA(szBase, SKIPLEN(countof(szBase)) " at " WIN3264TEST("0x%08X","0x%08X%08X"), WIN3264WSPRINT((DWORD_PTR)evt.u.UnloadDll.lpBaseOfDll)); break; } _wsprintfA(szDbgText, SKIPLEN(countof(szDbgText)) "{%i.%i} %s%s%s\n", evt.dwProcessId,evt.dwThreadId, pszName, szBase, szFile); _printf(szDbgText); break; } case EXCEPTION_DEBUG_EVENT: //1 Reports an exception debugging event. The value of u.Exception specifies an EXCEPTION_DEBUG_INFO structure. { lbNonContinuable = (evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE)==EXCEPTION_NONCONTINUABLE; //static bool bAttachEventRecieved = false; //if (!bAttachEventRecieved) //{ // bAttachEventRecieved = true; // StringCchPrintfA(szDbgText, countof(szDbgText),"{%i.%i} Debugger attached successfully. (0x%08X address 0x%08X flags 0x%08X%s)\n", // evt.dwProcessId,evt.dwThreadId, // evt.u.Exception.ExceptionRecord.ExceptionCode, // evt.u.Exception.ExceptionRecord.ExceptionAddress, // evt.u.Exception.ExceptionRecord.ExceptionFlags, // (evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE) ? "(EXCEPTION_NONCONTINUABLE)" : ""); //} //else switch (evt.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: // The thread tried to read from or write to a virtual address for which it does not have the appropriate access. { if (evt.u.Exception.ExceptionRecord.NumberParameters>=2) { _wsprintfA(szDbgText, SKIPLEN(countof(szDbgText)) "{%i.%i} EXCEPTION_ACCESS_VIOLATION at " WIN3264TEST("0x%08X","0x%08X%08X") " flags 0x%08X%s %s of " WIN3264TEST("0x%08X","0x%08X%08X") " FC=%u\n", evt.dwProcessId,evt.dwThreadId, WIN3264WSPRINT((DWORD_PTR)evt.u.Exception.ExceptionRecord.ExceptionAddress), evt.u.Exception.ExceptionRecord.ExceptionFlags, ((evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE) ? "(EXCEPTION_NONCONTINUABLE)" : ""), ((evt.u.Exception.ExceptionRecord.ExceptionInformation[0]==0) ? "Read" : (evt.u.Exception.ExceptionRecord.ExceptionInformation[0]==1) ? "Write" : (evt.u.Exception.ExceptionRecord.ExceptionInformation[0]==8) ? "DEP" : "???"), WIN3264WSPRINT(evt.u.Exception.ExceptionRecord.ExceptionInformation[1]), evt.u.Exception.dwFirstChance ); } else { _wsprintfA(szDbgText, SKIPLEN(countof(szDbgText)) "{%i.%i} EXCEPTION_ACCESS_VIOLATION at " WIN3264TEST("0x%08X","0x%08X%08X") " flags 0x%08X%s FC=%u\n", evt.dwProcessId,evt.dwThreadId, WIN3264WSPRINT((DWORD_PTR)evt.u.Exception.ExceptionRecord.ExceptionAddress), evt.u.Exception.ExceptionRecord.ExceptionFlags, (evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE) ? "(EXCEPTION_NONCONTINUABLE)" : "", evt.u.Exception.dwFirstChance); } _printf(szDbgText); } break; default: { char szName[32]; LPCSTR pszName; pszName = szName; #define EXCASE(s) case s: pszName = #s; break switch(evt.u.Exception.ExceptionRecord.ExceptionCode) { EXCASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); // The thread tried to access an array element that is out of bounds and the underlying hardware supports bounds checking. EXCASE(EXCEPTION_BREAKPOINT); // A breakpoint was encountered. EXCASE(EXCEPTION_DATATYPE_MISALIGNMENT); // The thread tried to read or write data that is misaligned on hardware that does not provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries; 32-bit values on 4-byte boundaries, and so on. EXCASE(EXCEPTION_FLT_DENORMAL_OPERAND); // One of the operands in a floating-point operation is denormal. A denormal value is one that is too small to represent as a standard floating-point value. EXCASE(EXCEPTION_FLT_DIVIDE_BY_ZERO); // The thread tried to divide a floating-point value by a floating-point divisor of zero. EXCASE(EXCEPTION_FLT_INEXACT_RESULT); // The result of a floating-point operation cannot be represented exactly as a decimal fraction. EXCASE(EXCEPTION_FLT_INVALID_OPERATION); // This exception represents any floating-point exception not included in this list. EXCASE(EXCEPTION_FLT_OVERFLOW); // The exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type. EXCASE(EXCEPTION_FLT_STACK_CHECK); // The stack overflowed or underflowed as the result of a floating-point operation. EXCASE(EXCEPTION_FLT_UNDERFLOW); // The exponent of a floating-point operation is less than the magnitude allowed by the corresponding type. EXCASE(EXCEPTION_ILLEGAL_INSTRUCTION); // The thread tried to execute an invalid instruction. EXCASE(EXCEPTION_IN_PAGE_ERROR); // The thread tried to access a page that was not present, and the system was unable to load the page. For example, this exception might occur if a network connection is lost while running a program over the network. EXCASE(EXCEPTION_INT_DIVIDE_BY_ZERO); // The thread tried to divide an integer value by an integer divisor of zero. EXCASE(EXCEPTION_INT_OVERFLOW); // The result of an integer operation caused a carry out of the most significant bit of the result. EXCASE(EXCEPTION_INVALID_DISPOSITION); // An exception handler returned an invalid disposition to the exception dispatcher. Programmers using a high-level language such as C should never encounter this exception. EXCASE(EXCEPTION_NONCONTINUABLE_EXCEPTION); // The thread tried to continue execution after a noncontinuable exception occurred. EXCASE(EXCEPTION_PRIV_INSTRUCTION); // The thread tried to execute an instruction whose operation is not allowed in the current machine mode. EXCASE(EXCEPTION_SINGLE_STEP); // A trace trap or other single-instruction mechanism signaled that one instruction has been executed. EXCASE(EXCEPTION_STACK_OVERFLOW); // The thread used up its stack. default: _wsprintfA(szName, SKIPLEN(countof(szName)) "Exception 0x%08X", evt.u.Exception.ExceptionRecord.ExceptionCode); } _wsprintfA(szDbgText, SKIPLEN(countof(szDbgText)) "{%i.%i} %s at " WIN3264TEST("0x%08X","0x%08X%08X") " flags 0x%08X%s FC=%u\n", evt.dwProcessId,evt.dwThreadId, pszName, WIN3264WSPRINT((DWORD_PTR)evt.u.Exception.ExceptionRecord.ExceptionAddress), evt.u.Exception.ExceptionRecord.ExceptionFlags, (evt.u.Exception.ExceptionRecord.ExceptionFlags&EXCEPTION_NONCONTINUABLE) ? "(EXCEPTION_NONCONTINUABLE)" : "", evt.u.Exception.dwFirstChance); _printf(szDbgText); } } BOOL bDumpOnBreakPoint = gpSrv->DbgInfo.bDebuggerRequestDump; if (gpSrv->DbgInfo.bDebugProcessTree && (!lbNonContinuable && (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT))) { // Когда отладчик цепляется к процессу в первый раз - возникает EXCEPTION_BREAKPOINT CEDebugProcessInfo pi = {}; if (gpSrv->DbgInfo.pDebugTreeProcesses && gpSrv->DbgInfo.pDebugTreeProcesses->Get(evt.dwProcessId, &pi)) { if (!pi.bWasBreak) { pi.bWasBreak = TRUE; gpSrv->DbgInfo.pDebugTreeProcesses->Set(evt.dwProcessId, pi); } else { bDumpOnBreakPoint = TRUE; } } } if (gpSrv->DbgInfo.bDebuggerRequestDump || (!lbNonContinuable && !gpSrv->DbgInfo.bDebugProcessTree && (evt.u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT)) || (gpSrv->DbgInfo.bDebugProcessTree && ((evt.u.Exception.ExceptionRecord.ExceptionCode>=0xC0000000) || (bDumpOnBreakPoint && (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)))) ) { BOOL bGenerateTreeBreak = gpSrv->DbgInfo.bDebugProcessTree && (gpSrv->DbgInfo.bDebuggerRequestDump || lbNonContinuable); if (gpSrv->DbgInfo.bDebugProcessTree && !bGenerateTreeBreak && (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)) { if (gpSrv->DbgInfo.nWaitTreeBreaks == 0) { bGenerateTreeBreak = TRUE; gpSrv->DbgInfo.nWaitTreeBreaks++; } } gpSrv->DbgInfo.bDebuggerRequestDump = FALSE; // один раз char szConfirm[2048]; if (evt.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { if (gpSrv->DbgInfo.nDebugDumpProcess) szConfirm[0] = 0; else lstrcpynA(szConfirm, szDbgText, countof(szConfirm)); } else { _wsprintfA(szConfirm, SKIPLEN(countof(szConfirm)) "%s exception (FC=%u)\n", lbNonContinuable ? "Non continuable" : "Continuable", evt.u.Exception.dwFirstChance); StringCchCatA(szConfirm, countof(szConfirm), szDbgText); } StringCchCatA(szConfirm, countof(szConfirm), "\nCreate minidump (<No> - fulldump)?"); //GenerateTreeDebugBreak WriteMiniDump(evt.dwProcessId, evt.dwThreadId, &evt.u.Exception.ExceptionRecord, szConfirm, bGenerateTreeBreak); if (gpSrv->DbgInfo.bDebugProcessTree && (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)) { if (gpSrv->DbgInfo.nWaitTreeBreaks > 0) gpSrv->DbgInfo.nWaitTreeBreaks--; } } if (!lbNonContinuable /*|| (evt.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)*/) { dwContinueStatus = DBG_CONTINUE; } } break; case OUTPUT_DEBUG_STRING_EVENT: //8 Reports an output-debugging-string debugging event. The value of u.DebugString specifies an OUTPUT_DEBUG_STRING_INFO structure. { wszDbgText[0] = 0; if (evt.u.DebugString.nDebugStringLength >= 1024) evt.u.DebugString.nDebugStringLength = 1023; DWORD_PTR nRead = 0; HANDLE hProcess = GetProcessHandleForDebug(evt.dwProcessId); if (evt.u.DebugString.fUnicode) { if (!ReadProcessMemory(hProcess, evt.u.DebugString.lpDebugStringData, wszDbgText, 2*evt.u.DebugString.nDebugStringLength, &nRead)) { wcscpy_c(wszDbgText, L"???"); } else { wszDbgText[min(1023,nRead+1)] = 0; } static int nPrefixLen = lstrlen(CONEMU_CONHOST_CREATED_MSG); if (memcmp(wszDbgText, CONEMU_CONHOST_CREATED_MSG, nPrefixLen*sizeof(wszDbgText[0])) == 0) { LPWSTR pszEnd = NULL; DWORD nConHostPID = wcstoul(wszDbgText+nPrefixLen, &pszEnd, 10); if (nConHostPID && !gpSrv->DbgInfo.pDebugTreeProcesses->Get(nConHostPID, NULL)) { AttachConHost(nConHostPID); } } } else { if (!ReadProcessMemory(hProcess, evt.u.DebugString.lpDebugStringData, szDbgText, evt.u.DebugString.nDebugStringLength, &nRead)) { wcscpy_c(wszDbgText, L"???"); } else { szDbgText[min(1023,nRead+1)] = 0; // CP_ACP differs from CP_OEMCP, thats why we need some overhead... MultiByteToWideChar(CP_ACP, 0, szDbgText, -1, wszDbgText, 1024); } } WideCharToMultiByte(CP_OEMCP, 0, wszDbgText, -1, szDbgText, 1024, 0, 0); #ifdef CRTPRINTF { _printf("{PID=%i.TID=%i} ", evt.dwProcessId,evt.dwThreadId, wszDbgText); } #else { _printf("{PID=%i.TID=%i} %s", evt.dwProcessId,evt.dwThreadId, szDbgText); int nLen = lstrlenA(szDbgText); if (nLen > 0 && szDbgText[nLen-1] != '\n') _printf("\n"); } #endif dwContinueStatus = DBG_CONTINUE; } break; } // Продолжить отлаживаемый процесс ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, dwContinueStatus); } //if (hCOMDLG32) // FreeLibrary(hCOMDLG32); }
VOID CALLBACK LdrDllNotification(ULONG NotificationReason, const LDR_DLL_NOTIFICATION_DATA* NotificationData, PVOID Context) { DWORD dwSaveErrCode = GetLastError(); wchar_t szModule[MAX_PATH*2] = L""; HMODULE hModule; BOOL bMainThread = (GetCurrentThreadId() == gnHookMainThreadId); const UNICODE_STRING* FullDllName; //The full path name of the DLL module. const UNICODE_STRING* BaseDllName; //The base file name of the DLL module. switch (NotificationReason) { case LDR_DLL_NOTIFICATION_REASON_LOADED: FullDllName = NotificationData->Loaded.FullDllName; BaseDllName = NotificationData->Loaded.BaseDllName; hModule = (HMODULE)NotificationData->Loaded.DllBase; break; case LDR_DLL_NOTIFICATION_REASON_UNLOADED: FullDllName = NotificationData->Unloaded.FullDllName; BaseDllName = NotificationData->Unloaded.BaseDllName; hModule = (HMODULE)NotificationData->Unloaded.DllBase; break; default: return; } if (FullDllName && FullDllName->Buffer) memmove(szModule, FullDllName->Buffer, min(sizeof(szModule)-2,FullDllName->Length)); else if (BaseDllName && BaseDllName->Buffer) memmove(szModule, BaseDllName->Buffer, min(sizeof(szModule)-2,BaseDllName->Length)); #ifdef _DEBUG wchar_t szDbgInfo[MAX_PATH*3]; _wsprintf(szDbgInfo, SKIPLEN(countof(szDbgInfo)) L"ConEmuHk: Ldr(%s) " WIN3264TEST(L"0x%08X",L"0x%08X%08X") L" '%s'\n", (NotificationReason==LDR_DLL_NOTIFICATION_REASON_LOADED) ? L"Loaded" : L"Unload", WIN3264WSPRINT(hModule), szModule); DebugString(szDbgInfo); #endif switch (NotificationReason) { case LDR_DLL_NOTIFICATION_REASON_LOADED: if (PrepareNewModule(hModule, NULL, szModule, TRUE, TRUE)) { HookItem* ph = NULL; GetOriginalAddress((LPVOID)OnLoadLibraryW, HOOK_FN_ID(LoadLibraryW), NULL, &ph, true); if (ph && ph->PostCallBack) { SETARGS1(&hModule,szModule); ph->PostCallBack(&args); } } break; case LDR_DLL_NOTIFICATION_REASON_UNLOADED: UnprepareModule(hModule, szModule, 0); UnprepareModule(hModule, szModule, 2); break; } SetLastError(dwSaveErrCode); }
LPVOID WINAPI OnVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) { //typedef LPVOID(WINAPI* OnVirtualAlloc_t)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); ORIGINAL_KRNL(VirtualAlloc); LPVOID lpResult = F(VirtualAlloc)(lpAddress, dwSize, flAllocationType, flProtect); DWORD dwErr = GetLastError(); wchar_t szText[MAX_PATH*4]; if (lpResult == NULL) { wchar_t szTitle[64]; msprintf(szTitle, countof(szTitle), L"ConEmuHk, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); MEMORY_BASIC_INFORMATION mbi = {}; SIZE_T mbiSize = VirtualQuery(lpAddress, &mbi, sizeof(mbi)); wchar_t szOwnedModule[MAX_PATH] = L""; FindModuleByAddress((const BYTE*)lpAddress, szOwnedModule, countof(szOwnedModule)); msprintf(szText, countof(szText)-MAX_PATH, L"VirtualAlloc " WIN3264TEST(L"%u",L"x%X%08X") L" bytes failed (%08X..%08X)\n" L"ErrorCode=%u %s\n\n" L"Allocated information (" WIN3264TEST(L"x%08X",L"x%X%08X") L".." WIN3264TEST(L"x%08X",L"x%X%08X") L")\n" L"Size " WIN3264TEST(L"%u",L"x%X%08X") L" bytes State x%X Type x%X Protect x%X\n" L"Module: %s\n\n" L"Warning! This may cause an errors in Release!\n" L"Press <OK> to VirtualAlloc at the default address\n\n", WIN3264WSPRINT(dwSize), LODWORD(lpAddress), LODWORD((LPBYTE)lpAddress+dwSize), dwErr, (dwErr == 487) ? L"(ERROR_INVALID_ADDRESS)" : L"", WIN3264WSPRINT(mbi.BaseAddress), WIN3264WSPRINT(((LPBYTE)mbi.BaseAddress+mbi.RegionSize)), WIN3264WSPRINT(mbi.RegionSize), mbi.State, mbi.Type, mbi.Protect, szOwnedModule[0] ? szOwnedModule : L"<Unknown>", 0); GetModuleFileName(NULL, szText+lstrlen(szText), MAX_PATH); DebugString(szText); #if defined(REPORT_VIRTUAL_ALLOC) // clink use bunch of VirtualAlloc to try to find suitable memory location // Some processes raises that error too often (in debug) bool bReport = (!gbIsCmdProcess || (dwSize != 0x1000)) && !gbSkipVirtualAllocErr && !gbIsNodeJSProcess; if (bReport) { // Do not report for .Net application static int iNetChecked = 0; if (!iNetChecked) { HMODULE hClr = GetModuleHandle(L"mscoree.dll"); iNetChecked = hClr ? 2 : 1; } bReport = (iNetChecked == 1); } int iBtn = bReport ? GuiMessageBox(NULL, szText, szTitle, MB_SYSTEMMODAL|MB_OKCANCEL|MB_ICONSTOP) : IDCANCEL; if (iBtn == IDOK) { lpResult = F(VirtualAlloc)(NULL, dwSize, flAllocationType, flProtect); dwErr = GetLastError(); } #endif } msprintf(szText, countof(szText), L"VirtualAlloc(" WIN3264TEST(L"0x%08X",L"0x%08X%08X") L"," WIN3264TEST(L"0x%08X",L"0x%08X%08X") L",%u,%u)=" WIN3264TEST(L"0x%08X",L"0x%08X%08X") L"\n", WIN3264WSPRINT(lpAddress), WIN3264WSPRINT(dwSize), flAllocationType, flProtect, WIN3264WSPRINT(lpResult)); DebugString(szText); SetLastError(dwErr); return lpResult; }
bool InitDefTerm() { bool lbRc = true; wchar_t szInfo[MAX_PATH*2]; msprintf(szInfo, countof(szInfo), L"!!! TH32CS_SNAPMODULE, TID=%u, InitDefaultTerm\n", GetCurrentThreadId()); DebugStr(szInfo); // Don't call DefTermLogString here - gpDefTerm was not initialized yet _ASSERTEX(gpDefTerm==NULL); gpDefTerm = new CDefTermHk(); if (!gpDefTerm) { _ASSERTEX(gpDefTerm!=NULL); return false; } //_ASSERTE(FALSE && "InitDefaultTerm"); // При обновлении ConEmu может обновиться и ConEmuHk.dll // Но в процессы с "DefTerm" грузится копия dll-ки, поэтому // после обновления в уже хукнутый процесс загружается // вторая "ConEmuHk.YYMMDD.dll", а старую при этом нужно // выгрузить. Этим и займемся. HMODULE hPrevHooks = NULL; _ASSERTEX(gnSelfPID!=0 && ghOurModule!=NULL); HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, gnSelfPID); if (hSnap != INVALID_HANDLE_VALUE) { MODULEENTRY32 mi = {sizeof(mi)}; //wchar_t szOurName[MAX_PATH] = L""; //GetModuleFileName(ghOurModule, szOurName, MAX_PATH); wchar_t szMinor[8] = L""; lstrcpyn(szMinor, WSTRING(MVV_4a), countof(szMinor)); wchar_t szAddName[40]; msprintf(szAddName, countof(szAddName), CEDEFTERMDLLFORMAT /*L"ConEmuHk%s.%02u%02u%02u%s.dll"*/, WIN3264TEST(L"",L"64"), MVV_1, MVV_2, MVV_3, szMinor); //LPCWSTR pszOurName = PointToName(szOurName); wchar_t* pszDot = wcschr(szAddName, L'.'); wchar_t szCheckName[MAX_PATH+1]; if (pszDot && Module32First(hSnap, &mi)) { pszDot[1] = 0; // Need to check only name, without version number int nCurLen = lstrlen(szAddName); do { if (mi.hModule == ghOurModule) continue; lstrcpyn(szCheckName, PointToName(mi.szExePath), nCurLen+1); if (lstrcmpi(szCheckName, szAddName) == 0) { msprintf(szInfo, countof(szInfo), L"Prevous ConEmuHk module found at address " WIN3264TEST(L"0x%08X",L"0x%X%08X") L": %s", WIN3264WSPRINT(mi.hModule), mi.szExePath); DefTermLogString(szInfo); hPrevHooks = mi.hModule; break; // Prev (old version) instance found! } } while (Module32Next(hSnap, &mi)); } CloseHandle(hSnap); } // Old library was found, unload it before continue if (hPrevHooks) { DefTermLogString(L"Trying to unload previous ConEmuHk module"); if (!FreeLibrary(hPrevHooks)) { lbRc = false; gpDefTerm->DisplayLastError(L"Unloading failed", GetLastError()); } else { DefTermLogString(L"Unloading succeeded"); } } // For Visual Studio check all spawned processes (children of gnSelfPID), find *.vshost.exe if (gbIsVStudio) { //_ASSERTEX(FALSE && "Continue to find existing *.vshost.exe"); HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnap != INVALID_HANDLE_VALUE) { PROCESSENTRY32 pe = {sizeof(pe)}; if (Process32First(hSnap, &pe)) do { if (pe.th32ParentProcessID == gnSelfPID) { if (IsVsNetHostExe(pe.szExeFile)) // *.vshost.exe { // Found! Hook it! DefTermLogString(L"Child VsNetHost found, hooking"); gpDefTerm->StartDefTermHooker(pe.th32ProcessID); break; } } } while (Process32Next(hSnap, &pe)); CloseHandle(hSnap); } } DefTermLogString(L"InitDefaultTerm finished, calling StartDefTerm"); gpDefTerm->StartDefTerm(); return lbRc; }
void __cdecl xf_dump() { #ifndef CONEMU_MINIMAL PROCESS_HEAP_ENTRY ent = {NULL}; HeapLock(ghHeap); //HeapCompact(ghHeap,0); char sBlockInfo[255]; PVOID pLast = NULL; size_t cbUsedSize = 0, cbBrokenSize = 0; DWORD cCount = 0; while (HeapWalk(ghHeap, &ent)) { if (pLast == ent.lpData) { msprintf(sBlockInfo, countof(sBlockInfo), "!!! HeapWalk cycled at 0x%08X, size=0x%08X\n", (DWORD)ent.lpData, ent.cbData); OutputDebugStringA(sBlockInfo); _ASSERTE(pLast != ent.lpData); break; } if (((int)ent.cbData) < 0) { msprintf(sBlockInfo, countof(sBlockInfo), "!!! Invalid memory block size at 0x%08X, size=0x%08X\n", (DWORD)ent.lpData, ent.cbData); OutputDebugStringA(sBlockInfo); _ASSERTE(((int)ent.cbData) >= 0); break; } if (ent.wFlags & PROCESS_HEAP_ENTRY_BUSY) { xf_mem_block* p = (xf_mem_block*)ent.lpData; if (p->bBlockUsed==TRUE && (p->nBlockSize+sizeof(xf_mem_block)+8)==ent.cbData) { msprintf(sBlockInfo, countof(sBlockInfo), "Used memory block at 0x" WIN3264TEST("%08X","%08X%08X") ", size %u\n Allocated from: %s\n", WIN3264WSPRINT(ent.lpData), ent.cbData, p->sCreatedFrom); cbUsedSize += p->nBlockSize; } else { msprintf(sBlockInfo, countof(sBlockInfo), "Used memory block at 0x" WIN3264TEST("%08X","%08X%08X") ", size %u\n Allocated from: %s\n", WIN3264WSPRINT(ent.lpData), ent.cbData, "<Header information broken!>"); cbBrokenSize += ent.cbData; } cCount++; pLast = ent.lpData; OutputDebugStringA(sBlockInfo); } } HeapUnlock(ghHeap); msprintf(sBlockInfo, countof(sBlockInfo), "Used size 0x" WIN3264TEST("%08X","%08X%08X") ", broken size 0x" WIN3264TEST("%08X","%08X%08X") ", total blocks %u\n", WIN3264WSPRINT(cbUsedSize), WIN3264WSPRINT(cbBrokenSize), cCount); OutputDebugStringA(sBlockInfo); #endif }