void RegisterConsoleFontHKLM(LPCWSTR pszFontFace) { if (!pszFontFace || !*pszFontFace) return; HKEY hk; DWORD nRights = KEY_ALL_ACCESS|WIN3264TEST((IsWindows64() ? KEY_WOW64_64KEY : 0),0); if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont", 0, nRights, &hk)) { wchar_t szId[32] = {0}, szFont[255]; DWORD dwLen, dwType; for (DWORD i = 0; i <20; i++) { szId[i] = L'0'; szId[i+1] = 0; wmemset(szFont, 0, 255); if (RegQueryValueExW(hk, szId, NULL, &dwType, (LPBYTE)szFont, &(dwLen = 255*2))) { RegSetValueExW(hk, szId, 0, REG_SZ, (LPBYTE)pszFontFace, (lstrlen(pszFontFace)+1)*2); break; } if (lstrcmpi(szFont, pszFontFace) == 0) { break; // он уже добавлен } } RegCloseKey(hk); } }
bool HkFunc::Init(LPCWSTR asModule, HMODULE hModule) { if ((State != sNotChecked) && (State != sUnloaded) && (State != sConEmuHk)) return (State == sHooked || State == sConEmuHk); BOOL bTrampolined = FALSE; typedef BOOL (WINAPI* RequestTrampolines_t)(LPCWSTR asModule, HMODULE hModule); RequestTrampolines_t fnRequestTrampolines; // WARNING! Heap may be not initialized in this step! HMODULE hConEmuHk = GetModuleHandle(WIN3264TEST(L"ConEmuHk.dll",L"ConEmuHk64.dll")); if (hConEmuHk != NULL) { fnRequestTrampolines = (RequestTrampolines_t)GetProcAddress(hConEmuHk, "RequestTrampolines"); if (!fnRequestTrampolines) { // Old build? _ASSERTE(fnRequestTrampolines!=NULL); } else { bTrampolined = fnRequestTrampolines(asModule, hModule); } } State = bTrampolined ? sHooked : sNotHooked; return (State == sHooked || State == sConEmuHk); }
int RegEnumKeys(HKEY hkRoot, LPCWSTR pszParentPath, RegEnumKeysCallback fn, LPARAM lParam) { int iRc = -1; HKEY hk = NULL, hkChild = NULL; bool bContinue = true; LONG lrc; bool ib64 = IsWindows64(); for (int s = 0; s < (ib64 ? 2 : 1); s++) { DWORD samDesired = KEY_READ; if (ib64) { if (s == 0) samDesired |= WIN3264TEST(KEY_WOW64_32KEY,KEY_WOW64_64KEY); else samDesired |= WIN3264TEST(KEY_WOW64_64KEY,KEY_WOW64_32KEY); } if (0 == (lrc = RegOpenKeyEx(hkRoot, pszParentPath, 0, samDesired, &hk))) { iRc = 0; UINT n = 0; wchar_t szSubKey[MAX_PATH] = L""; DWORD cchMax = countof(szSubKey) - 1; while (0 == (lrc = RegEnumKeyEx(hk, n++, szSubKey, &cchMax, NULL, NULL, NULL, NULL))) { if (0 == (lrc = RegOpenKeyEx(hk, szSubKey, 0, samDesired, &hkChild))) { if (fn != NULL) { if (!fn(hkChild, szSubKey, lParam)) break; } iRc++; RegCloseKey(hkChild); } cchMax = countof(szSubKey) - 1; } RegCloseKey(hk); } } return iRc; }
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); }
void PrintVersion() { wchar_t szProgInfo[255], szVer[32]; MultiByteToWideChar(CP_ACP, 0, CONEMUVERS, -1, szVer, countof(szVer)); _wsprintf(szProgInfo, SKIPLEN(countof(szProgInfo)) L"ConEmuC build %s %s. " CECOPYRIGHTSTRING_W L"\n", szVer, WIN3264TEST(L"x86",L"x64")); _wprintf(szProgInfo); }
bool IsClinkLoaded() { // Check processes supported if (!gbIsCmdProcess && !gbIsPowerShellProcess) return false; // Check, if clink library is loaded HMODULE hClink = GetModuleHandle(WIN3264TEST(L"clink_dll_x86.dll", L"clink_dll_x64.dll")); return (hClink != NULL); }
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; }
// May be called from "C" programs VOID WINAPI OnExitProcess(UINT uExitCode) { //typedef BOOL (WINAPI* OnExitProcess_t)(UINT uExitCode); ORIGINAL_KRNL(ExitProcess); #if 0 if (gbIsLessProcess) { _ASSERTE(FALSE && "Continue to ExitProcess"); } #endif gnDllState |= ds_OnExitProcess; #ifdef PRINT_ON_EXITPROCESS_CALLS wchar_t szInfo[80]; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"\n\x1B[1;31;40m::ExitProcess(%u) called\x1B[m\n", uExitCode); WriteProcessed(szInfo, lstrlen(szInfo), NULL); #endif // And terminate our threads DoDllStop(false, ds_OnExitProcess); bool bUseForceTerminate; // Issue 1865: Due to possible dead locks in LdrpAcquireLoaderLock() call TerminateProcess bUseForceTerminate = gbHookServerForcedTermination; #ifdef USE_GH_272_WORKAROUND // gh#272: For unknown yet reason existance of nvd3d9wrap.dll (or nvd3d9wrapx.dll on 64-bit) // caused stack overflow with following calls // // nvd3d9wrap!GetNVDisplayW+0x174f // nvd3d9wrap!GetNVDisplayW+0x174f // user32!_UserClientDllInitialize+0x2ca // ntdll!LdrpCallInitRoutine+0x14 // ntdll!LdrShutdownProcess+0x1aa // ntdll!RtlExitUserProcess+0x74 // kernel32!ExitProcessStub+0x12 // CallExit!main+0x47 if (!bUseForceTerminate && GetModuleHandle(WIN3264TEST(L"nvd3d9wrap.dll",L"nvd3d9wrapx.dll"))) { bUseForceTerminate = true; } #endif // USE_GH_272_WORKAROUND if (bUseForceTerminate) { ORIGINAL_KRNL(TerminateProcess); F(TerminateProcess)(GetCurrentProcess(), uExitCode); return; // Assume not to get here } F(ExitProcess)(uExitCode); }
/* ************** */ HMODULE WINAPI OnLoadLibraryWWork(FARPROC lpfn, HookItem *ph, BOOL bMainThread, const wchar_t* lpFileName) { typedef HMODULE(WINAPI* OnLoadLibraryW_t)(const wchar_t* lpFileName); HMODULE module = NULL; OnLoadLibraryLog(NULL,lpFileName); // Спрятать ExtendedConsole.dll с глаз долой, в сервисную папку "ConEmu" if (lpFileName && ((lstrcmpiW(lpFileName, L"ExtendedConsole.dll") == 0) || lstrcmpiW(lpFileName, L"ExtendedConsole64.dll") == 0)) { CESERVER_CONSOLE_MAPPING_HDR *Info = (CESERVER_CONSOLE_MAPPING_HDR*)calloc(1,sizeof(*Info)); if (Info && ::LoadSrvMapping(ghConWnd, *Info)) { size_t cchMax = countof(Info->ComSpec.ConEmuBaseDir)+64; wchar_t* pszFullPath = (wchar_t*)calloc(cchMax,sizeof(*pszFullPath)); if (pszFullPath) { _wcscpy_c(pszFullPath, cchMax, Info->ComSpec.ConEmuBaseDir); _wcscat_c(pszFullPath, cchMax, WIN3264TEST(L"\\ExtendedConsole.dll",L"\\ExtendedConsole64.dll")); module = ((OnLoadLibraryW_t)lpfn)(pszFullPath); SafeFree(pszFullPath); } } SafeFree(Info); } if (!module) module = ((OnLoadLibraryW_t)lpfn)(lpFileName); DWORD dwLoadErrCode = GetLastError(); if (gbLdrDllNotificationUsed) return module; // Issue 1079: Almost hangs with PHP if (lstrcmpi(lpFileName, L"kernel32.dll") == 0) return module; if (PrepareNewModule(module, NULL, lpFileName)) { if (ph && ph->PostCallBack) { SETARGS1(&module,lpFileName); ph->PostCallBack(&args); } } SetLastError(dwLoadErrCode); return module; }
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; }
// Check running process bits - 32/64 int GetProcessBits(DWORD nPID, HANDLE hProcess /*= NULL*/) { if (!IsWindows64()) return 32; int ImageBits = WIN3264TEST(32,64); //-V112 typedef BOOL (WINAPI* IsWow64Process_t)(HANDLE, PBOOL); static IsWow64Process_t IsWow64Process_f = NULL; if (!IsWow64Process_f) { HMODULE hKernel = GetModuleHandle(L"kernel32.dll"); if (hKernel) { IsWow64Process_f = (IsWow64Process_t)GetProcAddress(hKernel, "IsWow64Process"); } } if (IsWow64Process_f) { BOOL bWow64 = FALSE; HANDLE h = hProcess ? hProcess : OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, nPID); // IsWow64Process would be succeessfull for PROCESS_QUERY_LIMITED_INFORMATION (Vista+) if ((h == NULL) && IsWin6()) { // PROCESS_QUERY_LIMITED_INFORMATION not defined in GCC h = OpenProcess(0x1000/*PROCESS_QUERY_LIMITED_INFORMATION*/, FALSE, nPID); } if (h == NULL) { // If it is blocked due to access rights - try to find alternative ways (by path or PERF COUNTER) ImageBits = 0; } else if (IsWow64Process_f(h, &bWow64) && !bWow64) { ImageBits = 64; } else { ImageBits = 32; } if (h && (h != hProcess)) CloseHandle(h); } return ImageBits; }
/// Check running process bitness - 32/64 int GetProcessBits(DWORD nPID, HANDLE hProcess /*= NULL*/) { if (!IsWindows64()) return 32; int ImageBits = WIN3264TEST(32,64); //-V112 static BOOL (WINAPI* IsWow64Process_f)(HANDLE, PBOOL) = NULL; if (!IsWow64Process_f) { // Kernel32.dll is always loaded due to static link MModule kernel(GetModuleHandle(L"kernel32.dll")); kernel.GetProcAddress("IsWow64Process", IsWow64Process_f); // 64-bit OS must have this function _ASSERTE(IsWow64Process_f != NULL); } if (IsWow64Process_f) { BOOL bWow64 = FALSE; HANDLE h = hProcess ? hProcess : OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, nPID); // IsWow64Process would be succeessfull for PROCESS_QUERY_LIMITED_INFORMATION (Vista+) if ((h == NULL) && IsWin6()) { // PROCESS_QUERY_LIMITED_INFORMATION not defined in GCC h = OpenProcess(0x1000/*PROCESS_QUERY_LIMITED_INFORMATION*/, FALSE, nPID); } if (h == NULL) { // If it is blocked due to access rights - try to find alternative ways (by path or PERF COUNTER) ImageBits = 0; } else if (IsWow64Process_f(h, &bWow64) && !bWow64) { ImageBits = 64; } else { ImageBits = 32; } if (h && (h != hProcess)) CloseHandle(h); } return ImageBits; }
LRESULT CSetPgUpdate::OnInitDialog(HWND hDlg, bool abInitial) { ConEmuUpdateSettings* p = &gpSet->UpdSet; SetDlgItemText(hDlg, tUpdateVerLocation, p->UpdateVerLocation()); checkDlgButton(hDlg, cbUpdateCheckOnStartup, p->isUpdateCheckOnStartup); checkDlgButton(hDlg, cbUpdateCheckHourly, p->isUpdateCheckHourly); checkDlgButton(hDlg, cbUpdateConfirmDownload, !p->isUpdateConfirmDownload); checkRadioButton(hDlg, rbUpdateStableOnly, rbUpdateLatestAvailable, (p->isUpdateUseBuilds==1) ? rbUpdateStableOnly : (p->isUpdateUseBuilds==3) ? rbUpdatePreview : rbUpdateLatestAvailable); checkDlgButton(hDlg, cbUpdateInetTool, p->isUpdateInetTool); SetDlgItemText(hDlg, tUpdateInetTool, p->GetUpdateInetToolCmd()); checkDlgButton(hDlg, cbUpdateUseProxy, p->isUpdateUseProxy); SetDlgItemText(hDlg, tUpdateProxy, p->szUpdateProxy); SetDlgItemText(hDlg, tUpdateProxyUser, p->szUpdateProxyUser); SetDlgItemText(hDlg, tUpdateProxyPassword, p->szUpdateProxyPassword); OnButtonClicked(hDlg, NULL, cbUpdateInetTool); // Enable/Disable command field, button '...' and ‘Proxy’ fields int nPackage = p->UpdateDownloadSetup(); // 1-exe, 2-7zip checkRadioButton(hDlg, rbUpdateUseExe, rbUpdateUseArc, (nPackage==1) ? rbUpdateUseExe : rbUpdateUseArc); wchar_t szCPU[4] = L""; SetDlgItemText(hDlg, tUpdateExeCmdLine, p->UpdateExeCmdLine(szCPU)); SetDlgItemText(hDlg, tUpdateArcCmdLine, p->UpdateArcCmdLine()); SetDlgItemText(hDlg, tUpdatePostUpdateCmd, p->szUpdatePostUpdateCmd); enableDlgItem(hDlg, (nPackage==1) ? tUpdateArcCmdLine : tUpdateExeCmdLine, FALSE); // Show used or preferred installer bitness CEStr szFormat, szTitle; INT_PTR iLen; if ((iLen = GetString(hDlg, rbUpdateUseExe, &szFormat.ms_Val)) > 0) { if (wcsstr(szFormat.ms_Val, L"%s") != NULL) { wchar_t* psz = szTitle.GetBuffer(iLen+4); if (psz) { _wsprintf(psz, SKIPLEN(iLen+4) szFormat.ms_Val, (nPackage == 1) ? szCPU : WIN3264TEST(L"x86",L"x64")); SetDlgItemText(hDlg, rbUpdateUseExe, szTitle); } } } checkDlgButton(hDlg, cbUpdateLeavePackages, p->isUpdateLeavePackages); SetDlgItemText(hDlg, tUpdateDownloadPath, p->szUpdateDownloadPath); return 0; }
// Найти "ComSpec" и вернуть lstrdup на него wchar_t* GetComspec(const ConEmuComspec* pOpt) { wchar_t* pszComSpec = NULL; if (pOpt) { if ((pOpt->csType == cst_Explicit) && *pOpt->ComspecExplicit) { pszComSpec = lstrdup(pOpt->ComspecExplicit); } if (!pszComSpec && (pOpt->csBits == csb_SameOS)) { BOOL bWin64 = IsWindows64(); if (bWin64 ? *pOpt->Comspec64 : *pOpt->Comspec32) pszComSpec = lstrdup(bWin64 ? pOpt->Comspec64 : pOpt->Comspec32); } if (!pszComSpec && (pOpt->csBits == csb_SameApp)) { BOOL bWin64 = WIN3264TEST(FALSE,TRUE); if (bWin64 ? *pOpt->Comspec64 : *pOpt->Comspec32) pszComSpec = lstrdup(bWin64 ? pOpt->Comspec64 : pOpt->Comspec32); } if (!pszComSpec) { BOOL bWin64 = (pOpt->csBits != csb_x32); if (bWin64 ? *pOpt->Comspec64 : *pOpt->Comspec32) pszComSpec = lstrdup(bWin64 ? pOpt->Comspec64 : pOpt->Comspec32); } } else { _ASSERTE(pOpt && L"pOpt должен быть передан, по идее"); } if (!pszComSpec) { wchar_t szComSpec[MAX_PATH]; pszComSpec = lstrdup(GetComspecFromEnvVar(szComSpec, countof(szComSpec))); } // Уже должно быть хоть что-то _ASSERTE(pszComSpec && *pszComSpec); return pszComSpec; }
// 1-установлено через Installer, пути совпали, 2-Installer не запускался BYTE ConEmuUpdateSettings::UpdateDownloadSetup() { if (isUpdateDownloadSetup) return isUpdateDownloadSetup; // если 0 - пока не проверялся if (isSetupDetected == 0) { HKEY hk; LONG lRc; //bool bUseSetupExe = false; wchar_t szInstallDir[MAX_PATH+2], szExeDir[MAX_PATH+2]; wcscpy_c(szExeDir, gpConEmu->ms_ConEmuExeDir); wcscat_c(szExeDir, L"\\"); for (size_t i = 0; i <= 2; i++) { DWORD dwSam = KEY_READ | ((i == 0) ? 0 : (i == 1) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY); LPCWSTR pszName = ((i == 0) ? WIN3264TEST(L"InstallDir",L"InstallDir_x64") : (i == 1) ? L"InstallDir" : L"InstallDir_x64"); lRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\ConEmu", 0, dwSam, &hk); if (lRc == 0) { _ASSERTE(countof(szInstallDir)>(MAX_PATH+1)); DWORD dwSize = MAX_PATH*sizeof(*szInstallDir); if (0 == RegQueryValueEx(hk, pszName, NULL, NULL, (LPBYTE)szInstallDir, &dwSize) && *szInstallDir) { size_t nLen = _tcslen(szInstallDir); if (szInstallDir[nLen-1] != L'\\') wcscat_c(szInstallDir, L"\\"); if (lstrcmpi(szInstallDir, szExeDir) == 0) { isSetupDetected = 1; } } RegCloseKey(hk); } } if (!isSetupDetected) isSetupDetected = 2; } // Если признаки установки через "ConEmuSetup.exe" не найдены, или пути не совпали - грузим через 7z _ASSERTE(isSetupDetected!=0); return isSetupDetected ? isSetupDetected : 2; }
void ConEmuAbout::OnInfo_About(LPCWSTR asPageName /*= NULL*/) { InitCommCtrls(); bool bOk = false; { DontEnable de; HWND hParent = (ghOpWnd && IsWindowVisible(ghOpWnd)) ? ghOpWnd : ghWnd; // Modal dialog INT_PTR iRc = DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_ABOUT), hParent, aboutProc, (LPARAM)asPageName); bOk = (iRc != 0 && iRc != -1); ZeroStruct(m_Btns); mh_AboutDlg = NULL; #ifdef _DEBUG // Any problems with dialog resource? if (!bOk) DisplayLastError(L"DialogBoxParam(IDD_ABOUT) failed"); #endif } if (!bOk) { WCHAR szTitle[255]; LPCWSTR pszBits = WIN3264TEST(L"x86",L"x64"); LPCWSTR pszDebug = L""; #ifdef _DEBUG pszDebug = L"[DEBUG] "; #endif _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"About ConEmu (%02u%02u%02u%s %s%s)", (MVV_1%100),MVV_2,MVV_3,_T(MVV_4a), pszDebug, pszBits); DontEnable de; MSGBOXPARAMS mb = {sizeof(MSGBOXPARAMS), ghWnd, g_hInstance, pAbout, szTitle, MB_USERICON, MAKEINTRESOURCE(IMAGE_ICON), 0, NULL, LANG_NEUTRAL }; MessageBoxIndirectW(&mb); //MessageBoxW(ghWnd, pHelp, szTitle, MB_ICONQUESTION); } }
void ExecutePrepareCmd(CESERVER_REQ_HDR* pHdr, DWORD nCmd, size_t cbSize) { if (!pHdr) return; pHdr->nCmd = nCmd; pHdr->bAsync = FALSE; // сброс pHdr->nSrcThreadId = GetCurrentThreadId(); pHdr->nSrcPID = GetCurrentProcessId(); // Обмен данными идет и между 32bit & 64bit процессами, размеры __int64 недопустимы _ASSERTE(cbSize == (DWORD)cbSize); pHdr->cbSize = (DWORD)cbSize; pHdr->nVersion = CESERVER_REQ_VER; pHdr->nCreateTick = GetTickCount(); _ASSERTE(ghWorkingModule!=0); pHdr->hModule = ghWorkingModule; pHdr->nBits = WIN3264TEST(32,64); pHdr->nLastError = GetLastError(); pHdr->IsDebugging = IsDebuggerPresent(); }
// Вернуть путь к папке, содержащей ConEmuC.exe BOOL IsConEmuExeExist(LPCWSTR szExePath, wchar_t (&rsConEmuExe)[MAX_PATH+1]) { BOOL lbExeFound = FALSE; BOOL isWin64 = WIN3264TEST(IsWindows64(),TRUE); //if (szExePath[lstrlen(szExePath)-1] != L'\\') // wcscat_c(szExePath, L"\\"); _ASSERTE(szExePath && *szExePath && (szExePath[lstrlen(szExePath)-1] == L'\\')); wcscpy_c(rsConEmuExe, szExePath); wchar_t* pszName = rsConEmuExe+lstrlen(rsConEmuExe); LPCWSTR szGuiExe[2] = {L"ConEmu64.exe", L"ConEmu.exe"}; for (size_t s = 0; !lbExeFound && (s < countof(szGuiExe)); s++) { if (!s && !isWin64) continue; wcscpy_add(pszName, rsConEmuExe, szGuiExe[s]); lbExeFound = FileExists(rsConEmuExe); } return lbExeFound; }
void UnitModuleTest() { wchar_t* pszConEmuCD = lstrmerge(gpConEmu->ms_ConEmuBaseDir, WIN3264TEST(L"\\ConEmuCD.dll",L"\\ConEmuCD64.dll")); HMODULE hMod, hGetMod; bool bTest; _ASSERTE(!IsModuleValid((HMODULE)NULL)); _ASSERTE(!IsModuleValid((HMODULE)INVALID_HANDLE_VALUE)); hMod = GetModuleHandle(L"kernel32.dll"); if (hMod) { bTest = IsModuleValid(hMod); _ASSERTE(bTest); } else { _ASSERTE(FALSE && "GetModuleHandle(kernel32) failed"); } hMod = LoadLibrary(pszConEmuCD); if (hMod) { bTest = IsModuleValid(hMod); _ASSERTE(bTest); FreeLibrary(hMod); bTest = IsModuleValid(hMod); // Due to unknown reason (KIS?) FreeLibrary was not able to release hMod sometimes hGetMod = GetModuleHandle(pszConEmuCD); if (!hGetMod) bTest = IsModuleValid(hMod); _ASSERTE(!bTest || (hGetMod!=NULL)); } else { _ASSERTE(FALSE && "LoadLibrary(pszConEmuCD) failed"); } }
void CPluginAnsi::SetStartupInfoPtr(void *aInfo) { INIT_FAR_PSI(::InfoA, ::FSFA, (PluginStartupInfo*)aInfo); mb_StartupInfoOk = true; DWORD nFarVer = 0; if (InfoA->AdvControl(InfoA->ModuleNumber, ACTL_GETFARVERSION, &nFarVer)) { if (HIBYTE(LOWORD(nFarVer)) == 1) { gFarVersion.dwBuild = HIWORD(nFarVer); gFarVersion.dwVerMajor = (HIBYTE(LOWORD(nFarVer))); gFarVersion.dwVerMinor = (LOBYTE(LOWORD(nFarVer))); _ASSERTE(gFarVersion.dwBits == WIN3264TEST(32,64)); } else { _ASSERTE(HIBYTE(HIWORD(nFarVer)) == 1); } } SetRootRegKey(ToUnicode(InfoA->RootKey)); }
void CPluginW2800::SetStartupInfoPtr(void *aInfo) { INIT_FAR_PSI(::InfoW2800, ::FSFW2800, (PluginStartupInfo*)aInfo); mb_StartupInfoOk = true; VersionInfo FarVer = {0}; if (InfoW2800->AdvControl(&guid_ConEmu, ACTL_GETFARMANAGERVERSION, 0, &FarVer)) { if (FarVer.Major == 3) { gFarVersion.dwBuild = FarVer.Build; _ASSERTE(FarVer.Major<=0xFFFF && FarVer.Minor<=0xFFFF); gFarVersion.dwVerMajor = (WORD)FarVer.Major; gFarVersion.dwVerMinor = (WORD)FarVer.Minor; gFarVersion.Bis = (FarVer.Stage==VS_BIS); _ASSERTE(gFarVersion.dwBits == WIN3264TEST(32,64)); } else { _ASSERTE(FarVer.Major == 3); } } }
DWORD WINAPI DebugThread(LPVOID lpvParam) { DWORD nWait = WAIT_TIMEOUT; //DWORD nExternalExitCode = -1; wchar_t szInfo[1024]; if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; if (gpSrv->DbgInfo.bDebugProcessTree) { SetEnvironmentVariable(ENV_CONEMU_BLOCKCHILDDEBUGGERS_W, ENV_CONEMU_BLOCKCHILDDEBUGGERS_YES); } if (!CreateProcess(NULL, gpSrv->DbgInfo.pszDebuggingCmdLine, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE| DEBUG_PROCESS | (gpSrv->DbgInfo.bDebugProcessTree ? 0 : DEBUG_ONLY_THIS_PROCESS), NULL, NULL, &si, &pi)) { DWORD dwErr = GetLastError(); wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(gpSrv->dwRootProcess, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start debugging process. ErrCode=0x%08X\n", dwErr); lstrcpyn(szInfo+lstrlen(szInfo), gpSrv->DbgInfo.pszDebuggingCmdLine, 400); wcscat_c(szInfo, L"\n"); _wprintf(szInfo); return CERR_CANTSTARTDEBUGGER; } gpSrv->hRootProcess = pi.hProcess; gpSrv->hRootThread = pi.hThread; gpSrv->dwRootProcess = pi.dwProcessId; gpSrv->dwRootThread = pi.dwThreadId; gpSrv->dwRootStartTime = GetTickCount(); } /* ************************* */ int iDbgIdx = 0, iAttachedCount = 0; while (true) { HANDLE hDbgProcess = NULL; DWORD nDbgProcessID = 0; bool bFirstPID = ((iDbgIdx++) == 0); if (bFirstPID) { hDbgProcess = gpSrv->hRootProcess; nDbgProcessID = gpSrv->dwRootProcess; } else { // Взять из pDebugAttachProcesses if (!gpSrv->DbgInfo.pDebugAttachProcesses) break; if (!gpSrv->DbgInfo.pDebugAttachProcesses->pop_back(nDbgProcessID)) break; hDbgProcess = GetProcessHandleForDebug(nDbgProcessID); if (!hDbgProcess) { _ASSERTE(hDbgProcess!=NULL && "Can't open debugging process handle"); continue; } } _ASSERTE(hDbgProcess!=NULL && "Process handle must be opened"); // Битность отладчика должна соответствовать битности приложения! if (IsWindows64()) { int nBits = GetProcessBits(nDbgProcessID, hDbgProcess); if ((nBits == 32 || nBits == 64) && (nBits != WIN3264TEST(32,64))) { if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { _printf("Bitness of ConEmuC and debugging program does not match\n"); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } wchar_t szExe[MAX_PATH+16]; wchar_t szCmdLine[MAX_PATH*2]; if (GetModuleFileName(NULL, szExe, countof(szExe)-16)) { wchar_t* pszName = (wchar_t*)PointToName(szExe); _wcscpy_c(pszName, 16, (nBits == 32) ? L"ConEmuC.exe" : L"ConEmuC64.exe"); _wsprintf(szCmdLine, SKIPLEN(countof(szCmdLine)) L"\"%s\" /DEBUGPID=%u %s", szExe, nDbgProcessID, (gpSrv->DbgInfo.nDebugDumpProcess == 1) ? L"/DUMP" : (gpSrv->DbgInfo.nDebugDumpProcess == 2) ? L"/MINIDUMP" : (gpSrv->DbgInfo.nDebugDumpProcess == 3) ? L"/FULLDUMP" : L""); STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; if (CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { // Ждать НЕ будем, сразу на выход //HANDLE hEvents[2] = {pi.hProcess, ghExitQueryEvent}; //nWait = WaitForMultipleObjects(countof(hEvents), hEvents, FALSE, INFINITE); //if (nWait == WAIT_OBJECT_0) //{ // //GetExitCodeProcess(pi.hProcess, &nExternalExitCode); // nExternalExitCode = 0; //} //CloseHandle(pi.hProcess); //CloseHandle(pi.hThread); //if (nExternalExitCode == 0) //{ // goto done; //} // Может там еще процессы в списке на дамп? continue; } else { DWORD dwErr = GetLastError(); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start external debugger '%s'. ErrCode=0x%08X\n", szCmdLine, dwErr); _wprintf(szInfo); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } } wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(nDbgProcessID, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Bits are incompatible. Can't debug '%s' PID=%i\n", szProc[0] ? szProc : L"not found", nDbgProcessID); _wprintf(szInfo); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } } if (gpSrv->DbgInfo.pszDebuggingCmdLine == NULL) { if (!DebugActiveProcess(nDbgProcessID)) { DWORD dwErr = GetLastError(); wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(nDbgProcessID, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't attach debugger to '%s' PID=%i. ErrCode=0x%08X\n", szProc[0] ? szProc : L"not found", nDbgProcessID, dwErr); _wprintf(szInfo); return CERR_CANTSTARTDEBUGGER; } } iAttachedCount++; } if (iAttachedCount == 0) { return CERR_CANTSTARTDEBUGGER; } /* **************** */ // Дополнительная инициализация, чтобы закрытие дебагера (наш процесс) не привело // к закрытию "отлаживаемой" программы pfnDebugActiveProcessStop = (FDebugActiveProcessStop)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugActiveProcessStop"); pfnDebugSetProcessKillOnExit = (FDebugSetProcessKillOnExit)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugSetProcessKillOnExit"); if (pfnDebugSetProcessKillOnExit) pfnDebugSetProcessKillOnExit(FALSE/*KillOnExit*/); gpSrv->DbgInfo.bDebuggerActive = TRUE; PrintDebugInfo(); SetEvent(gpSrv->DbgInfo.hDebugReady); while (nWait == WAIT_TIMEOUT) { ProcessDebugEvent(); if (ghExitQueryEvent) nWait = WaitForSingleObject(ghExitQueryEvent, 0); } //done: gbRootAliveLess10sec = FALSE; gbInShutdown = TRUE; gbAlwaysConfirmExit = FALSE; _ASSERTE(gbTerminateOnCtrlBreak==FALSE); if (!nExitQueryPlace) nExitQueryPlace = 12+(nExitPlaceStep); SetTerminateEvent(ste_DebugThread); return 0; }
BOOL FindConEmuBaseDir(wchar_t (&rsConEmuBaseDir)[MAX_PATH+1], wchar_t (&rsConEmuExe)[MAX_PATH+1], HMODULE hPluginDll /*= NULL*/) { // Сначала пробуем Mapping консоли (вдруг есть?) { MFileMapping<CESERVER_CONSOLE_MAPPING_HDR> ConMap; ConMap.InitName(CECONMAPNAME, (DWORD)myGetConsoleWindow()); //-V205 CESERVER_CONSOLE_MAPPING_HDR* p = ConMap.Open(); if (p && p->ComSpec.ConEmuBaseDir[0]) { // Успешно wcscpy_c(rsConEmuBaseDir, p->ComSpec.ConEmuBaseDir); wcscpy_c(rsConEmuExe, p->sConEmuExe); return TRUE; } } // Теперь - пробуем найти существующее окно ConEmu HWND hConEmu = FindWindow(VirtualConsoleClassMain, NULL); DWORD dwGuiPID = 0; if (hConEmu) { if (GetWindowThreadProcessId(hConEmu, &dwGuiPID) && dwGuiPID) { MFileMapping<ConEmuGuiMapping> GuiMap; GuiMap.InitName(CEGUIINFOMAPNAME, dwGuiPID); ConEmuGuiMapping* p = GuiMap.Open(); if (p && p->ComSpec.ConEmuBaseDir[0]) { wcscpy_c(rsConEmuBaseDir, p->ComSpec.ConEmuBaseDir); wcscpy_c(rsConEmuExe, p->sConEmuExe); return TRUE; } } } wchar_t szExePath[MAX_PATH+1]; HKEY hkRoot[] = {NULL,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_LOCAL_MACHINE}; DWORD samDesired = KEY_QUERY_VALUE; BOOL isWin64 = WIN3264TEST(IsWindows64(),TRUE); DWORD RedirectionFlag = WIN3264TEST((isWin64 ? KEY_WOW64_64KEY : 0),KEY_WOW64_32KEY); //#ifdef _WIN64 // isWin64 = TRUE; // RedirectionFlag = KEY_WOW64_32KEY; //#else // isWin64 = IsWindows64(); // RedirectionFlag = isWin64 ? KEY_WOW64_64KEY : 0; //#endif for (size_t i = 0; i < countof(hkRoot); i++) { szExePath[0] = 0; if (i == 0) { // Запущенного ConEmu.exe нет, можно поискать в каталоге текущего приложения if (!GetModuleFileName(NULL, szExePath, countof(szExePath)-20)) continue; wchar_t* pszName = wcsrchr(szExePath, L'\\'); if (!pszName) continue; *(pszName+1) = 0; // Проверяем наличие файлов // LPCWSTR szGuiExe[2] = {L"ConEmu64.exe", L"ConEmu.exe"}; if (!IsConEmuExeExist(szExePath, rsConEmuExe) && hPluginDll) { // Попробовать найти наш exe-шник от пути плагина? if (!GetModuleFileName(hPluginDll, szExePath, countof(szExePath)-1)) continue; wchar_t* pszName = wcsrchr(szExePath, L'\\'); if (!pszName) continue; *(pszName+1) = 0; int nLen = lstrlen(szExePath); LPCWSTR pszCompare = L"\\Plugins\\ConEmu\\"; if (nLen <= lstrlen(pszCompare)) continue; nLen = lstrlen(pszCompare); int iCmp = lstrcmpi(pszName-nLen+1, pszCompare); if (iCmp != 0) continue; *(pszName-nLen+2) = 0; } } else { // Остался последний шанс - если ConEmu установлен через MSI, то путь указан в реестре // [HKEY_LOCAL_MACHINE\SOFTWARE\ConEmu] // "InstallDir"="C:\\Utils\\Far180\\" if (i == (countof(hkRoot)-1)) { if (RedirectionFlag) samDesired |= RedirectionFlag; else break; } HKEY hKey; if (RegOpenKeyEx(hkRoot[i], L"Software\\ConEmu", 0, samDesired, &hKey) != ERROR_SUCCESS) continue; memset(szExePath, 0, countof(szExePath)); DWORD nType = 0, nSize = sizeof(szExePath)-20*sizeof(wchar_t); int RegResult = RegQueryValueEx(hKey, L"", NULL, &nType, (LPBYTE)szExePath, &nSize); RegCloseKey(hKey); if (RegResult != ERROR_SUCCESS) continue; } if (szExePath[0]) { // Хоть и задано в реестре - файлов может не быть. Проверяем if (szExePath[lstrlen(szExePath)-1] != L'\\') wcscat_c(szExePath, L"\\"); // Проверяем наличие файлов // LPCWSTR szGuiExe[2] = {L"ConEmu64.exe", L"ConEmu.exe"}; BOOL lbExeFound = IsConEmuExeExist(szExePath, rsConEmuExe); // Если GUI-exe найден - ищем "base" if (lbExeFound) { wchar_t* pszName = szExePath+lstrlen(szExePath); LPCWSTR szSrvExe[4] = {L"ConEmuC64.exe", L"ConEmu\\ConEmuC64.exe", L"ConEmuC.exe", L"ConEmu\\ConEmuC.exe"}; for (size_t s = 0; s < countof(szSrvExe); s++) { if ((s <=1) && !isWin64) continue; wcscpy_add(pszName, szExePath, szSrvExe[s]); if (FileExists(szExePath)) { pszName = wcsrchr(szExePath, L'\\'); if (pszName) { *pszName = 0; // БЕЗ слеша на конце! wcscpy_c(rsConEmuBaseDir, szExePath); return TRUE; } } } } } } // Не удалось return FALSE; }
bool CAttachDlg::OnStartAttach() { bool lbRc = false; // Тут нужно получить инфу из списка и дернуть собственно аттач wchar_t szItem[128] = {}; //DWORD nPID = 0, nBits = WIN3264TEST(32,64); //AttachProcessType nType = apt_Unknown; wchar_t *psz; int iSel, iCur; DWORD nTID; HANDLE hThread = NULL; AttachParm *pParm = NULL; MArray<AttachParm> Parms; //HWND hAttachWnd = NULL; ShowWindow(mh_Dlg, SW_HIDE); BOOL bAlternativeMode = (IsDlgButtonChecked(mh_Dlg, IDC_ATTACH_ALT) != 0); iSel = ListView_GetNextItem(mh_List, -1, LVNI_SELECTED); while (iSel >= 0) { iCur = iSel; iSel = ListView_GetNextItem(mh_List, iCur, LVNI_SELECTED); AttachParm L = {NULL, 0, WIN3264TEST(32,64), apt_Unknown, bAlternativeMode}; ListView_GetItemText(mh_List, iCur, alc_PID, szItem, countof(szItem)-1); L.nPID = wcstoul(szItem, &psz, 10); if (L.nPID) { psz = wcschr(szItem, L'['); if (!psz) { _ASSERTE(FALSE && "Process bitness was not detected?"); } else { L.nBits = wcstoul(psz+1, &psz, 10); } } ListView_GetItemText(mh_List, iCur, alc_Type, szItem, countof(szItem)); if (lstrcmp(szItem, szTypeCon) == 0) L.nType = apt_Console; else if (lstrcmp(szItem, szTypeGui) == 0) L.nType = apt_Gui; ListView_GetItemText(mh_List, iCur, alc_HWND, szItem, countof(szItem)); L.hAttachWnd = (szItem[0]==L'0' && szItem[1]==L'x') ? (HWND)(DWORD_PTR)wcstoul(szItem+2, &psz, 16) : NULL; if (!L.nPID || !L.nBits || !L.nType || !L.hAttachWnd) { MBoxAssert(L.nPID && L.nBits && L.nType && L.hAttachWnd); goto wrap; } Parms.push_back(L); } if (Parms.empty()) { goto wrap; } else { AttachParm N = {NULL}; Parms.push_back(N); } //// Чтобы клик от мышки в консоль не провалился //WARNING("Клик от мышки в консоль проваливается"); //gpConEmu->mouse.nSkipEvents[0] = WM_LBUTTONUP; //gpConEmu->mouse.nSkipEvents[1] = 0; //gpConEmu->mouse.nReplaceDblClk = 0; // Все, диалог закрываем, чтобы не мешался Close(); // Работу делаем в фоновом потоке, чтобы не блокировать главный // (к окну ConEmu должна подцепиться новая вкладка) pParm = Parms.detach(); if (!pParm) { _wsprintf(szItem, SKIPLEN(countof(szItem)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); DisplayLastError(L"Parms.detach() failed", -1, 0, szItem); goto wrap; } else { hThread = apiCreateThread((LPTHREAD_START_ROUTINE)StartAttachThread, pParm, &nTID, "CAttachDlg::StartAttachThread#1"); if (!hThread) { DWORD dwErr = GetLastError(); _wsprintf(szItem, SKIPLEN(countof(szItem)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); DisplayLastError(L"Can't start attach thread", dwErr, 0, szItem); } else lbRc = true; } wrap: // We don't need this handle if (hThread) CloseHandle(hThread); return lbRc; }
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 UpdateComspec(ConEmuComspec* pOpt, bool DontModifyPath /*= false*/) { if (!pOpt) { _ASSERTE(pOpt!=NULL); return; } if (pOpt->isUpdateEnv && (pOpt->csType != cst_EnvVar)) { //if (pOpt->csType == cst_AutoTccCmd) -- always, if isUpdateEnv { LPCWSTR pszNew = NULL; switch (pOpt->csBits) { case csb_SameOS: pszNew = IsWindows64() ? pOpt->Comspec64 : pOpt->Comspec32; break; case csb_SameApp: pszNew = WIN3264TEST(pOpt->Comspec32,pOpt->Comspec64); break; case csb_x32: pszNew = pOpt->Comspec32; break; default: _ASSERTE(pOpt->csBits==csb_SameOS || pOpt->csBits==csb_SameApp || pOpt->csBits==csb_x32); pszNew = NULL; } if (pszNew && *pszNew) { #ifdef SHOW_COMSPEC_CHANGE wchar_t szCurrent[MAX_PATH]; GetEnvironmentVariable(L"ComSpec", szCurrent, countof(szCurrent)); if (lstrcmpi(szCurrent, pszNew)) { wchar_t szMsg[MAX_PATH*4], szProc[MAX_PATH] = {}, szPid[MAX_PATH]; GetModuleFileName(NULL, szProc, countof(szProc)); _wsprintf(szPid, SKIPLEN(countof(szPid)) L"PID=%u, '%s'", GetCurrentProcessId(), PointToName(szProc)); _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"Changing %%ComSpec%% in %s\nCur=%s\nNew=%s", szPid , szCurrent, pszNew); MessageBox(NULL, szMsg, szPid, MB_SYSTEMMODAL); } #endif _ASSERTE(wcschr(pszNew, L'%')==NULL); SetEnvVarExpanded(L"ComSpec", pszNew); } } } if (pOpt->AddConEmu2Path && !DontModifyPath) { if ((pOpt->ConEmuBaseDir[0] == 0) || (pOpt->ConEmuExeDir[0] == 0)) { _ASSERTE(pOpt->ConEmuBaseDir[0] != 0); _ASSERTE(pOpt->ConEmuExeDir[0] != 0); } else { wchar_t* pszCur = GetEnvVar(L"PATH"); if (!pszCur) pszCur = lstrdup(L""); DWORD n = lstrlen(pszCur); wchar_t* pszUpr = lstrdup(pszCur); wchar_t* pszDirUpr = (wchar_t*)malloc(MAX_PATH*sizeof(*pszCur)); MCHKHEAP; if (!pszUpr || !pszDirUpr) { _ASSERTE(pszUpr && pszDirUpr); } else { bool bChanged = false; wchar_t* pszAdd = NULL; CharUpperBuff(pszUpr, n); for (int i = 0; i <= 1; i++) { // Put '%ConEmuExeDir' on first place switch (i) { case 1: if (!(pOpt->AddConEmu2Path & CEAP_AddConEmuExeDir)) continue; pszAdd = pOpt->ConEmuExeDir; break; case 0: if (!(pOpt->AddConEmu2Path & CEAP_AddConEmuBaseDir)) continue; if (lstrcmp(pOpt->ConEmuExeDir, pOpt->ConEmuBaseDir) == 0) continue; // второй раз ту же директорию не добавляем pszAdd = pOpt->ConEmuBaseDir; break; } int nDirLen = lstrlen(pszAdd); lstrcpyn(pszDirUpr, pszAdd, MAX_PATH); CharUpperBuff(pszDirUpr, nDirLen); MCHKHEAP; // Need to find exact match! bool bFound = false; LPCWSTR pszFind = wcsstr(pszUpr, pszDirUpr); while (pszFind) { if (pszFind[nDirLen] == L';' || pszFind[nDirLen] == 0) { // OK, found bFound = true; break; } // Next try (may be partial match of subdirs...) pszFind = wcsstr(pszFind+nDirLen, pszDirUpr); } if (!bFound) { wchar_t* pszNew = lstrmerge(pszAdd, L";", pszCur); if (!pszNew) { _ASSERTE(pszNew && "Failed to reallocate PATH variable"); break; } MCHKHEAP; SafeFree(pszCur); pszCur = pszNew; bChanged = true; // Set flag, check next dir } } MCHKHEAP; if (bChanged) { SetEnvironmentVariable(L"PATH", pszCur); } } MCHKHEAP; SafeFree(pszUpr); SafeFree(pszDirUpr); MCHKHEAP; SafeFree(pszCur); } } }
int PrepareHookModule(wchar_t (&szModule)[MAX_PATH+16]) { int iRc = -251; wchar_t szNewPath[MAX_PATH+16] = {}, szAddName[32] = {}, szVer[2] = {}; INT_PTR nLen = 0; bool bAlreadyExists = false; // Copy szModule to CSIDL_LOCAL_APPDATA and return new path HRESULT hr = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0/*SHGFP_TYPE_CURRENT*/, szNewPath); if ((hr != S_OK) || !*szNewPath) { iRc = -251; goto wrap; } szVer[0] = MVV_4a[0]; _wsprintf(szAddName, SKIPLEN(countof(szAddName)) L"\\" CEDEFTERMDLLFORMAT /*L"ConEmuHk%s.%02u%02u%02u%s.dll"*/, WIN3264TEST(L"",L"64"), MVV_1, MVV_2, MVV_3, szVer); nLen = lstrlen(szNewPath); if (szNewPath[nLen-1] != L'\\') { szNewPath[nLen++] = L'\\'; szNewPath[nLen] = 0; } if ((nLen + lstrlen(szAddName) + 8) >= countof(szNewPath)) { iRc = -252; goto wrap; } wcscat_c(szNewPath, L"ConEmu"); if (!DirectoryExists(szNewPath)) { if (!CreateDirectory(szNewPath, NULL)) { iRc = -253; goto wrap; } } wcscat_c(szNewPath, szAddName); if ((bAlreadyExists = FileExists(szNewPath)) && FileCompare(szNewPath, szModule)) { // OK, file exists and match the required } else { if (bAlreadyExists) { _ASSERTE(FALSE && "Continue to overwrite existing ConEmuHk in AppLocal"); // Try to delete or rename old version if (!DeleteFile(szNewPath)) { //SYSTEMTIME st; GetLocalTime(&st); wchar_t szBakPath[MAX_PATH+32]; wcscpy_c(szBakPath, szNewPath); wchar_t* pszExt = (wchar_t*)PointToExt(szBakPath); msprintf(pszExt, 16, L".%u.dll", GetTickCount()); DeleteFile(szBakPath); MoveFile(szNewPath, szBakPath); } } if (!CopyFile(szModule, szNewPath, FALSE)) { iRc = -254; goto wrap; } } wcscpy_c(szModule, szNewPath); iRc = 0; wrap: return iRc; }
int InjectRemote(DWORD nRemotePID, bool abDefTermOnly /*= false */) { int iRc = -1; bool lbWin64 = WIN3264TEST((IsWindows64()!=0),true); bool is32bit; DWORD nWrapperWait = (DWORD)-1, nWrapperResult = (DWORD)-1; HANDLE hProc = NULL; wchar_t szSelf[MAX_PATH+16], szHooks[MAX_PATH+16]; wchar_t *pszNamePtr, szArgs[32]; if (!GetModuleFileName(NULL, szSelf, MAX_PATH)) { iRc = -200; goto wrap; } wcscpy_c(szHooks, szSelf); pszNamePtr = (wchar_t*)PointToName(szHooks); if (!pszNamePtr) { iRc = -200; goto wrap; } hProc = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, nRemotePID); if (hProc == NULL) { iRc = -201; goto wrap; } // Определить битность процесса, Если он 32битный, а текущий - ConEmuC64.exe // Перезапустить 32битную версию ConEmuC.exe if (!lbWin64) { is32bit = true; // x86 OS! } else { is32bit = false; // x64 OS! // Проверяем, кто такой nRemotePID HMODULE hKernel = GetModuleHandleW(L"kernel32.dll"); if (hKernel) { typedef BOOL (WINAPI* IsWow64Process_t)(HANDLE hProcess, PBOOL Wow64Process); IsWow64Process_t IsWow64Process_f = (IsWow64Process_t)GetProcAddress(hKernel, "IsWow64Process"); if (IsWow64Process_f) { BOOL bWow64 = FALSE; if (IsWow64Process_f(hProc, &bWow64) && bWow64) { // По идее, такого быть не должно. ConEmu должен был запустить 32битный conemuC.exe #ifdef _WIN64 _ASSERTE(bWow64==FALSE); #endif is32bit = true; } } } } if (is32bit != WIN3264TEST(true,false)) { // По идее, такого быть не должно. ConEmu должен был запустить соответствующий conemuC*.exe _ASSERTE(is32bit == WIN3264TEST(true,false)); PROCESS_INFORMATION pi = {}; STARTUPINFO si = {sizeof(si)}; _wcscpy_c(pszNamePtr, 16, is32bit ? L"ConEmuC.exe" : L"ConEmuC64.exe"); _wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /INJECT=%u", nRemotePID); if (!CreateProcess(szHooks, szArgs, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { iRc = -202; goto wrap; } nWrapperWait = WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &nWrapperResult); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if ((nWrapperResult != CERR_HOOKS_WAS_SET) && (nWrapperResult != CERR_HOOKS_WAS_ALREADY_SET)) { iRc = -203; SetLastError(nWrapperResult); goto wrap; } // Значит всю работу сделал враппер iRc = 0; goto wrap; } // Поехали _wcscpy_c(pszNamePtr, 16, is32bit ? L"ConEmuHk.dll" : L"ConEmuHk64.dll"); if (!FileExists(szHooks)) { iRc = -250; goto wrap; } if (abDefTermOnly) { int iFRc = PrepareHookModule(szHooks); if (iFRc != 0) { iRc = iFRc; goto wrap; } } iRc = InfiltrateDll(hProc, szHooks); // Если создавали временную копию - запланировать ее удаление if (abDefTermOnly && (lstrcmpi(szHooks, szSelf) != 0)) { MoveFileEx(szHooks, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); } wrap: if (hProc != NULL) CloseHandle(hProc); return iRc; }
// Warning, напрямую НЕ вызывать. Пользоваться "общей" PostMacro void CPluginW2800::PostMacroApi(const wchar_t* asMacro, INPUT_RECORD* apRec, bool abShowParseErrors) { if (!InfoW2800 || !InfoW2800->AdvControl) return; MacroSendMacroText mcr = {sizeof(MacroSendMacroText)}; //mcr.Flags = 0; // По умолчанию - вывод на экран разрешен bool bEnableOutput = true; while ((asMacro[0] == L'@' || asMacro[0] == L'^') && asMacro[1] && asMacro[1] != L' ') { switch (*asMacro) { case L'@': bEnableOutput = false; break; case L'^': mcr.Flags |= KMFLAGS_NOSENDKEYSTOPLUGINS; break; } asMacro++; } if (bEnableOutput) mcr.Flags |= KMFLAGS_ENABLEOUTPUT; // This macro was not adopted to Lua? _ASSERTE(*asMacro && *asMacro != L'$'); // Вообще говоря, если тут попадается макрос в старом формате - то мы уже ничего не сделаем... // Начиная с Far 3 build 2851 - все макросы переведены на Lua mcr.SequenceText = asMacro; if (apRec) mcr.AKey = *apRec; mcr.Flags |= KMFLAGS_SILENTCHECK; if (!InfoW2800->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, MSSC_CHECK, &mcr)) { if (abShowParseErrors) { wchar_t* pszErrText = NULL; size_t iRcSize = InfoW2800->MacroControl(&guid_ConEmu, MCTL_GETLASTERROR, 0, NULL); MacroParseResult* Result = iRcSize ? (MacroParseResult*)calloc(iRcSize,1) : NULL; if (Result) { Result->StructSize = sizeof(*Result); _ASSERTE(FALSE && "Check MCTL_GETLASTERROR"); InfoW2800->MacroControl(&guid_ConEmu, MCTL_GETLASTERROR, iRcSize, Result); size_t cchMax = (Result->ErrSrc ? lstrlen(Result->ErrSrc) : 0) + lstrlen(asMacro) + 255; pszErrText = (wchar_t*)malloc(cchMax*sizeof(wchar_t)); _wsprintf(pszErrText, SKIPLEN(cchMax) L"Error in Macro. Far %u.%u build %u r%u\n" L"ConEmu plugin %02u%02u%02u%s[%u] {2800}\n" L"Code: %u, Line: %u, Col: %u%s%s\n" L"----------------------------------\n" L"%s", gFarVersion.dwVerMajor, gFarVersion.dwVerMinor, gFarVersion.dwBuild, gFarVersion.Bis ? 1 : 0, MVV_1, MVV_2, MVV_3, _CRT_WIDE(MVV_4a), WIN3264TEST(32,64), Result->ErrCode, (UINT)(int)Result->ErrPos.Y+1, (UINT)(int)Result->ErrPos.X+1, Result->ErrSrc ? L", Hint: " : L"", Result->ErrSrc ? Result->ErrSrc : L"", asMacro); SafeFree(Result); } else { size_t cchMax = lstrlen(asMacro) + 255; pszErrText = (wchar_t*)malloc(cchMax*sizeof(wchar_t)); _wsprintf(pszErrText, SKIPLEN(cchMax) L"Error in Macro. Far %u.%u build %u r%u\n" L"ConEmu plugin %02u%02u%02u%s[%u] {2800}\n" L"----------------------------------\n" L"%s", gFarVersion.dwVerMajor, gFarVersion.dwVerMinor, gFarVersion.dwBuild, gFarVersion.Bis ? 1 : 0, MVV_1, MVV_2, MVV_3, _CRT_WIDE(MVV_4a), WIN3264TEST(32,64), asMacro); } if (pszErrText) { DWORD nTID; HANDLE h = apiCreateThread(BackgroundMacroError, pszErrText, &nTID, "BackgroundMacroError"); SafeCloseHandle(h); } } } else { //gFarVersion.dwBuild InfoW2800->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, 0, &mcr); } }
// 0 - OK, иначе - ошибка // Здесь вызывается CreateRemoteThread int InfiltrateDll(HANDLE hProcess, LPCWSTR asConEmuHk) { int iRc = -150; //if (iRc != -150) //{ // InfiltrateProc(NULL); InfiltrateEnd(); //} //const size_t cb = ((size_t)InfiltrateEnd) - ((size_t)InfiltrateProc); InfiltrateArg dat = {}; HMODULE hKernel = NULL; HANDLE hThread = NULL; DWORD id = 0; LPTHREAD_START_ROUTINE pRemoteProc = NULL; PVOID pRemoteDat = NULL; CreateRemoteThread_t _CreateRemoteThread = NULL; char FuncName[20]; void* ptrCode; size_t cbCode; //_ASSERTE("InfiltrateDll"==(void*)TRUE); cbCode = GetInfiltrateProc(&ptrCode); // Примерно, проверка размера кода созданного компилятором if (cbCode != WIN3264TEST(68,79)) { _ASSERTE(cbCode == WIN3264TEST(68,79)); iRc = -100; goto wrap; } if (lstrlen(asConEmuHk) >= (int)countof(dat.szConEmuHk)) { iRc = -101; goto wrap; } // Исполняемый код загрузки библиотеки pRemoteProc = (LPTHREAD_START_ROUTINE) VirtualAllocEx( hProcess, // Target process NULL, // Let the VMM decide where cbCode, // Size MEM_COMMIT, // Commit the memory PAGE_EXECUTE_READWRITE); // Protections if (!pRemoteProc) { iRc = -102; goto wrap; } if (!WriteProcessMemory( hProcess, // Target process (void*)pRemoteProc, // Source for code ptrCode, // The code cbCode, // Code length NULL)) // We don't care { iRc = -103; goto wrap; } // Путь к нашей библиотеке lstrcpyn(dat.szConEmuHk, asConEmuHk, countof(dat.szConEmuHk)); // Kernel-процедуры hKernel = LoadLibrary(L"Kernel32.dll"); if (!hKernel) { iRc = -104; goto wrap; } // Избежать статической линковки и строки "CreateRemoteThread" в бинарнике FuncName[ 0] = 'C'; FuncName[ 2] = 'e'; FuncName[ 4] = 't'; FuncName[ 6] = 'R'; FuncName[ 8] = 'm'; FuncName[ 1] = 'r'; FuncName[ 3] = 'a'; FuncName[ 5] = 'e'; FuncName[ 7] = 'e'; FuncName[ 9] = 'o'; FuncName[10] = 't'; FuncName[12] = 'T'; FuncName[14] = 'r'; FuncName[16] = 'a'; FuncName[11] = 'e'; FuncName[13] = 'h'; FuncName[15] = 'e'; FuncName[17] = 'd'; FuncName[18] = 0; _CreateRemoteThread = (CreateRemoteThread_t)GetProcAddress(hKernel, FuncName); // Functions for external process. MUST BE SAME ADDRESSES AS CURRENT PROCESS. // kernel32.dll компонуется таким образом, что всегда загружается по одному определенному адресу в памяти // Поэтому адреса процедур для приложений одинаковой битности совпадают (в разных процессах) dat._GetLastError = (GetLastError_t)GetProcAddress(hKernel, "GetLastError"); dat._SetLastError = (SetLastError_t)GetProcAddress(hKernel, "SetLastError"); dat._LoadLibraryW = (LoadLibraryW_t)GetLoadLibraryAddress(); // GetProcAddress(hKernel, "LoadLibraryW"); if (!_CreateRemoteThread || !dat._LoadLibraryW || !dat._SetLastError || !dat._GetLastError) { iRc = -105; goto wrap; } else { // Проверим, что адреса этих функций действительно лежат в модуле Kernel32.dll // и не были кем-то перехвачены до нас. FARPROC proc[] = {(FARPROC)dat._GetLastError, (FARPROC)dat._SetLastError, (FARPROC)dat._LoadLibraryW}; if (!CheckCallbackPtr(hKernel, countof(proc), proc, TRUE, TRUE)) { // Если функции перехвачены - попытка выполнить код по этим адресам // скорее всего приведет к ошибке доступа, что не есть гут. iRc = -111; goto wrap; } } // Копируем параметры в процесс pRemoteDat = VirtualAllocEx(hProcess, NULL, sizeof(InfiltrateArg), MEM_COMMIT, PAGE_READWRITE); if(!pRemoteDat) { iRc = -106; goto wrap; } if (!WriteProcessMemory(hProcess, pRemoteDat, &dat, sizeof(InfiltrateArg), NULL)) { iRc = -107; goto wrap; } // Запускаем поток в процессе hProcess // В принципе, на эту функцию могут ругаться антивирусы hThread = _CreateRemoteThread( hProcess, // Target process NULL, // No security 4096 * 16, // 16 pages of stack pRemoteProc, // Thread routine address pRemoteDat, // Data 0, // Run NOW &id); if (!hThread) { iRc = -108; goto wrap; } // Дождаться пока поток завершится WaitForSingleObject(hThread, INFINITE); // И считать результат if (!ReadProcessMemory( hProcess, // Target process pRemoteDat, // Their data &dat, // Our data sizeof(InfiltrateArg), // Size NULL)) // We don't care { iRc = -109; goto wrap; } // Вернуть результат загрузки SetLastError((dat.hInst != NULL) ? 0 : (DWORD)dat.ErrCode); iRc = (dat.hInst != NULL) ? 0 : -110; wrap: if (hKernel) FreeLibrary(hKernel); if (hThread) CloseHandle(hThread); if(pRemoteProc) VirtualFreeEx(hProcess, (void*)pRemoteProc, cbCode, MEM_RELEASE); if(pRemoteDat) VirtualFreeEx(hProcess, pRemoteDat, sizeof(InfiltrateArg), MEM_RELEASE); return iRc; }