void DefTermLogString(LPCSTR asMessage, LPCWSTR asLabel /*= NULL*/) { if (!gpDefTerm || !asMessage || !*asMessage) return; INT_PTR iLen = lstrlenA(asMessage); CEStr lsMsg; MultiByteToWideChar(CP_ACP, 0, asMessage, iLen, lsMsg.GetBuffer(iLen), iLen); DefTermLogString(lsMsg.ms_Arg, asLabel); }
// Called from OnShellExecCmdLine HRESULT OurShellExecCmdLine(HWND hwnd, LPCWSTR pwszCommand, LPCWSTR pwszStartDir, bool bRunAsAdmin, bool bForce) { HRESULT hr = E_UNEXPECTED; BOOL bShell = FALSE; CEStr lsLog = lstrmerge(L"OnShellExecCmdLine", bRunAsAdmin ? L"(RunAs): " : L": ", pwszCommand); DefTermLogString(lsLog); // Bad thing, ShellExecuteEx needs File&Parm, but we get both in pwszCommand CmdArg szExe; LPCWSTR pszFile = pwszCommand; LPCWSTR pszParm = pwszCommand; if (NextArg(&pszParm, szExe) == 0) { pszFile = szExe; pszParm = SkipNonPrintable(pszParm); } else { // Failed pszFile = pwszCommand; pszParm = NULL; } if (!bForce) { DWORD nCheckSybsystem1 = 0, nCheckBits1 = 0; if (!FindImageSubsystem(pszFile, nCheckSybsystem1, nCheckBits1)) { hr = (HRESULT)-1; DefTermLogString(L"OnShellExecCmdLine: FindImageSubsystem failed"); goto wrap; } if (nCheckSybsystem1 != IMAGE_SUBSYSTEM_WINDOWS_CUI) { hr = (HRESULT)-1; DefTermLogString(L"OnShellExecCmdLine: !=IMAGE_SUBSYSTEM_WINDOWS_CUI"); goto wrap; } } // "Run as admin" was requested? if (bRunAsAdmin) { SHELLEXECUTEINFO sei = {sizeof(sei), 0, hwnd, L"runas", pszFile, pszParm, pwszStartDir, SW_SHOWNORMAL}; bShell = OnShellExecuteExW(&sei); } else { wchar_t* pwCommand = lstrdup(pwszCommand); DWORD nCreateFlags = CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT|CREATE_DEFAULT_ERROR_MODE; STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; bShell = OnCreateProcessW(NULL, pwCommand, NULL, NULL, FALSE, nCreateFlags, NULL, pwszStartDir, &si, &pi); if (bShell) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } } hr = bShell ? S_OK : HRESULT_FROM_WIN32(GetLastError()); wrap: return hr; }
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; }