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); } }
// ConEmuC -OsVerInfo int OsVerInfo() { OSVERSIONINFOEX osv = {sizeof(osv)}; GetOsVersionInformational((OSVERSIONINFO*)&osv); UINT DBCS = IsDbcs(); UINT HWFS = IsHwFullScreenAvailable(); UINT W5fam = IsWin5family(); UINT WXPSP1 = IsWinXPSP1(); UINT W6 = IsWin6(); UINT W7 = IsWin7(); UINT W10 = IsWin10(); UINT Wx64 = IsWindows64(); UINT WINE = IsWine(); UINT WPE = IsWinPE(); UINT TELNET = isTerminalMode(); wchar_t szInfo[200]; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"OS version information\n" L"%u.%u build %u SP%u.%u suite=x%04X type=%u\n" L"W5fam=%u WXPSP1=%u W6=%u W7=%u W10=%u Wx64=%u\n" L"HWFS=%u DBCS=%u WINE=%u WPE=%u TELNET=%u\n", osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber, osv.wServicePackMajor, osv.wServicePackMinor, osv.wSuiteMask, osv.wProductType, W5fam, WXPSP1, W6, W7, W10, Wx64, HWFS, DBCS, WINE, WPE, TELNET); _wprintf(szInfo); return MAKEWORD(osv.dwMinorVersion, osv.dwMajorVersion); }
CAttachDlg::CAttachDlg() : mh_Dlg(NULL) , mh_List(NULL) , mn_AttachType(0) , mn_AttachPID(0) , mh_AttachHWND(NULL) , mp_ProcessData(NULL) { mb_IsWin64 = IsWindows64(); }
// 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; }
bool IsHwFullScreenAvailable() { if (IsWindows64()) return false; // HW FullScreen was available in Win2k & WinXP (32bit) _ASSERTE(_WIN32_WINNT_VISTA==0x600); OSVERSIONINFOEXW osvi = {sizeof(osvi), HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA)}; DWORDLONG const dwlConditionMask = VerSetConditionMask(VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_MINORVERSION, VER_GREATER_EQUAL); if (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask)) return false; // Vista or higher - not available else return true; }
int RegGetStringValue(HKEY hk, LPCWSTR pszSubKey, LPCWSTR pszValueName, CEStr& rszData, DWORD Wow64Flags /*= 0*/) { int iLen = -1; HKEY hkChild = hk; DWORD cbSize = 0; LONG lrc; rszData.Empty(); if (pszSubKey && *pszSubKey) { if (hk == NULL) { lrc = RegGetStringValue(HKEY_CURRENT_USER, pszSubKey, pszValueName, rszData, 0); if (lrc < 0) { bool isWin64 = IsWindows64(); lrc = RegGetStringValue(HKEY_LOCAL_MACHINE, pszSubKey, pszValueName, rszData, isWin64 ? KEY_WOW64_64KEY : 0); if ((lrc < 0) && isWin64) { lrc = RegGetStringValue(HKEY_LOCAL_MACHINE, pszSubKey, pszValueName, rszData, KEY_WOW64_32KEY); } } if (lrc > 0) { return lrc; } } if (0 != (lrc = RegOpenKeyEx(hk, pszSubKey, 0, KEY_READ|Wow64Flags, &hkChild))) hkChild = NULL; } if (hkChild && (0 == (lrc = RegQueryValueEx(hkChild, pszValueName, NULL, NULL, NULL, &cbSize)))) { wchar_t* pszData = rszData.GetBuffer((cbSize>>1)+2); // +wchar_t+1byte (на возможные ошибки хранения данных в реестре) if (pszData) { pszData[cbSize>>1] = 0; // Make sure it will be 0-terminated if (0 == (lrc = RegQueryValueEx(hkChild, pszValueName, NULL, NULL, (LPBYTE)pszData, &cbSize))) { iLen = lstrlen(pszData); } else { rszData.Empty(); } } }
// Найти "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; }
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; }
// Вернуть путь к папке, содержащей 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 Init() { mb_IsWindows64 = IsWindows64(); memset(&m_Store, 0, sizeof(m_Store)); mp_Last = &m_Store; mp_LastKey = NULL; memset(&m_HKCU, 0, sizeof(m_HKCU)); memset(&m_HKLM, 0, sizeof(m_HKLM)); memset(&m_HKLM32, 0, sizeof(m_HKLM32)); memset(&m_HKLM64, 0, sizeof(m_HKLM64)); // Common HKCU m_HKCU.hKey = HKEY_CURRENT_USER; m_HKCU.rkt = RKT_HKCU; // Native for process m_HKLM.hKey = HKEY_LOCAL_MACHINE; #ifdef _WIN64 m_HKLM.rkt = RKT_HKLM64; #else m_HKLM.rkt = RKT_HKLM32; #endif // When specified KEY_WOW64_64KEY/KEY_WOW64_32KEY m_HKLM32.hKey = HKEY_LOCAL_MACHINE; m_HKLM32.rkt = RKT_HKLM32; m_HKLM64.hKey = HKEY_LOCAL_MACHINE; m_HKLM64.rkt = mb_IsWindows64 ? RKT_HKLM64 : RKT_HKLM32; };
// используется в GUI при загрузке настроек void FindComspec(ConEmuComspec* pOpt, bool bCmdAlso /*= true*/) { if (!pOpt) return; pOpt->Comspec32[0] = 0; pOpt->Comspec64[0] = 0; // Ищем tcc.exe if (pOpt->csType == cst_AutoTccCmd) { HKEY hk; BOOL bWin64 = IsWindows64(); wchar_t szPath[MAX_PATH+1]; // If tcc.exe can be found near to ConEmu location LPCWSTR ppszPredefined[] = { L"%ConEmuBaseDir%\\tcc.exe", L"%ConEmuDir%\\tcc.exe", // Sort of PortableApps locations L"%ConEmuDir%\\..\\tcc\\tcc.exe", L"%ConEmuDir%\\..\\..\\tcc\\tcc.exe", // End of predefined list NULL}; for (INT_PTR i = 0; ppszPredefined[i]; i++) { DWORD nExpand = ExpandEnvironmentStrings(ppszPredefined[i], szPath, countof(szPath)); if (nExpand && (nExpand < countof(szPath))) { if (FileExists(szPath)) { wcscpy_c(pOpt->Comspec32, szPath); wcscpy_c(pOpt->Comspec64, szPath); break; } } } // On this step - check "Take Command"! if (!*pOpt->Comspec32 || !*pOpt->Comspec64) { // [HKEY_LOCAL_MACHINE\SOFTWARE\JP Software\Take Command 13.0] // @="\"C:\\Program Files\\JPSoft\\TCMD13\\tcmd.exe\"" for (int b = 0; b <= 1; b++) { // b==0 - 32bit, b==1 - 64bit if (b && !bWin64) continue; bool bFound = false; DWORD nOpt = (b == 0) ? (bWin64 ? KEY_WOW64_32KEY : 0) : (bWin64 ? KEY_WOW64_64KEY : 0); if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\JP Software", 0, KEY_READ|nOpt, &hk)) { wchar_t szName[MAX_PATH+1]; DWORD nLen; for (DWORD k = 0; !bFound && !RegEnumKeyEx(hk, k, szName, &(nLen = countof(szName)-1), 0,0,0,0); k++) { HKEY hk2; if (!RegOpenKeyEx(hk, szName, 0, KEY_READ|nOpt, &hk2)) { // Just in case, check "Path" too LPCWSTR rsNames[] = {NULL, L"Path"}; for (size_t n = 0; n < countof(rsNames); n++) { ZeroStruct(szPath); DWORD nSize = (countof(szPath)-1)*sizeof(szPath[0]); if (!RegQueryValueExW(hk2, rsNames[n], NULL, NULL, (LPBYTE)szPath, &nSize) && *szPath) { wchar_t* psz, *pszEnd; psz = (wchar_t*)Unquote(szPath, true); pszEnd = wcsrchr(psz, L'\\'); if (!pszEnd || lstrcmpi(pszEnd, L"\\tcmd.exe") || !FileExists(psz)) continue; lstrcpyn(pszEnd+1, L"tcc.exe", 8); if (FileExists(psz)) { bFound = true; if (b == 0) wcscpy_c(pOpt->Comspec32, psz); else wcscpy_c(pOpt->Comspec64, psz); } } } // for (size_t n = 0; n < countof(rsNames); n++) RegCloseKey(hk2); } } // for, подключи RegCloseKey(hk); } // L"SOFTWARE\\JP Software" } // for (int b = 0; b <= 1; b++) // Если установлен TCMD - предпочтительно использовать именно его, независимо от битности if (*pOpt->Comspec32 && !*pOpt->Comspec64) wcscpy_c(pOpt->Comspec64, pOpt->Comspec32); else if (*pOpt->Comspec64 && !*pOpt->Comspec32) wcscpy_c(pOpt->Comspec32, pOpt->Comspec64); } // If "Take Command" not installed - try "TCC/LE" if (!*pOpt->Comspec32 || !*pOpt->Comspec64) { // [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{16A21882-4138-4ADA-A390-F62DC27E4504}] // "DisplayVersion"="13.04.60" // "Publisher"="JP Software" // "DisplayName"="Take Command 13.0" // или // "DisplayName"="TCC/LE 13.0" // и наконец // "InstallLocation"="C:\\Program Files\\JPSoft\\TCMD13\\" for (int b = 0; b <= 1; b++) { // b==0 - 32bit, b==1 - 64bit if (b && !bWin64) continue; if (((b == 0) ? *pOpt->Comspec32 : *pOpt->Comspec64)) continue; // этот уже нашелся в TCMD bool bFound = false; DWORD nOpt = (b == 0) ? (bWin64 ? KEY_WOW64_32KEY : 0) : (bWin64 ? KEY_WOW64_64KEY : 0); if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, KEY_READ|nOpt, &hk)) { wchar_t szName[MAX_PATH+1]; DWORD nLen; for (DWORD n = 0; !bFound && !RegEnumKeyEx(hk, n, szName, &(nLen = countof(szName)-1), 0,0,0,0); n++) { if (*szName != L'{') continue; HKEY hk2; if (!RegOpenKeyEx(hk, szName, 0, KEY_READ|nOpt, &hk2)) { ZeroStruct(szPath); DWORD nSize = (countof(szPath) - 1)*sizeof(szPath[0]); if (!RegQueryValueExW(hk2, L"Publisher", NULL, NULL, (LPBYTE)szPath, &nSize) && !lstrcmpi(szPath, L"JP Software")) { nSize = (countof(szPath)-12)*sizeof(szPath[0]); if (!RegQueryValueExW(hk2, L"InstallLocation", NULL, NULL, (LPBYTE)szPath, &nSize) && *szPath) { wchar_t* psz, *pszEnd; if (szPath[0] == L'"') { psz = szPath + 1; pszEnd = wcschr(psz, L'"'); if (pszEnd) *pszEnd = 0; } else { psz = szPath; } if (*psz) { pszEnd = psz+lstrlen(psz); if (*(pszEnd-1) != L'\\') *(pszEnd++) = L'\\'; lstrcpyn(pszEnd, L"tcc.exe", 8); if (FileExists(psz)) { bFound = true; if (b == 0) wcscpy_c(pOpt->Comspec32, psz); else wcscpy_c(pOpt->Comspec64, psz); } } } } RegCloseKey(hk2); } } // for, подключи RegCloseKey(hk); } // L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" } // for (int b = 0; b <= 1; b++) } // Попытаться "в лоб" из "Program Files" if (!*pOpt->Comspec32 && !*pOpt->Comspec64) { const wchar_t* pszTcmd = L"C:\\Program Files\\JPSoft\\TCMD13\\tcc.exe"; const wchar_t* pszTccLe = L"C:\\Program Files\\JPSoft\\TCCLE13\\tcc.exe"; if (FileExists(pszTcmd)) wcscpy_c(pOpt->Comspec32, pszTcmd); else if (FileExists(pszTccLe)) wcscpy_c(pOpt->Comspec32, pszTccLe); } if (*pOpt->Comspec32 && !*pOpt->Comspec64) wcscpy_c(pOpt->Comspec64, pOpt->Comspec32); else if (*pOpt->Comspec64 && !*pOpt->Comspec32) wcscpy_c(pOpt->Comspec32, pOpt->Comspec64); } // if (pOpt->csType == cst_AutoTccCmd) // С поиском tcc закончили. Теперь, если pOpt->Comspec32/pOpt->Comspec64 остались не заполнены // нужно сначала попытаться обработать переменную окружения ComSpec, а потом - просто "cmd.exe" if (!*pOpt->Comspec32) GetComspecFromEnvVar(pOpt->Comspec32, countof(pOpt->Comspec32), csb_x32); if (!*pOpt->Comspec64) GetComspecFromEnvVar(pOpt->Comspec64, countof(pOpt->Comspec64), csb_x64); }
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; }
LPCWSTR GetComspecFromEnvVar(wchar_t* pszComspec, DWORD cchMax, ComSpecBits Bits/* = csb_SameOS*/) { if (!pszComspec || (cchMax < MAX_PATH)) { _ASSERTE(pszComspec && (cchMax >= MAX_PATH)); return NULL; } *pszComspec = 0; BOOL bWin64 = IsWindows64(); if (!((Bits == csb_x32) || (Bits == csb_x64))) { if (GetEnvironmentVariable(L"ComSpec", pszComspec, cchMax)) { // Не должен быть (даже случайно) ConEmuC.exe const wchar_t* pszName = PointToName(pszComspec); if (!pszName || !lstrcmpi(pszName, L"ConEmuC.exe") || !lstrcmpi(pszName, L"ConEmuC64.exe") || !FileExists(pszComspec)) // ну и существовать должен { pszComspec[0] = 0; } } } // Если не удалось определить через переменную окружения - пробуем обычный "cmd.exe" из System32 if (pszComspec[0] == 0) { int n = GetWindowsDirectory(pszComspec, cchMax - 20); if (n > 0 && (((DWORD)n) < (cchMax - 20))) { // Добавить \System32\cmd.exe // Warning! 'c:\Windows\SysNative\cmd.exe' не прокатит, т.к. доступен // только для 32битных приложений. А нам нужно в общем виде. // Если из 32битного нужно запустить 64битный cmd.exe - нужно выключать редиректор. if (!bWin64 || (Bits != csb_x32)) { _wcscat_c(pszComspec, cchMax, (pszComspec[n-1] == L'\\') ? L"System32\\cmd.exe" : L"\\System32\\cmd.exe"); } else { _wcscat_c(pszComspec, cchMax, (pszComspec[n-1] == L'\\') ? L"SysWOW64\\cmd.exe" : L"\\SysWOW64\\cmd.exe"); } } } if (pszComspec[0] && !FileExists(pszComspec)) { _ASSERTE("Comspec not found! File not exists!"); pszComspec[0] = 0; } // Last chance if (pszComspec[0] == 0) { _ASSERTE(pszComspec[0] != 0); // Уже должен был быть определен //lstrcpyn(pszComspec, L"cmd.exe", cchMax); wchar_t *psFilePart; DWORD n = SearchPathW(NULL, L"cmd.exe", NULL, cchMax, pszComspec, &psFilePart); if (!n || (n >= cchMax)) _wcscpy_c(pszComspec, cchMax, L"cmd.exe"); } return pszComspec; }
// CIR_OK=0 - OK, CIR_AlreadyInjected=1 - Already injected, иначе - ошибка // Здесь вызывается CreateRemoteThread CINFILTRATE_EXIT_CODES InjectRemote(DWORD nRemotePID, bool abDefTermOnly /*= false */) { CINFILTRATE_EXIT_CODES iRc = CIR_GeneralError/*-1*/; bool lbWin64 = WIN3264TEST((IsWindows64()!=0),true); bool is32bit; int nBits; 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]; wchar_t szName[64]; HANDLE hEvent = NULL; HANDLE hDefTermReady = NULL; bool bAlreadyHooked = false; HANDLE hSnap = NULL; MODULEENTRY32 mi = {sizeof(mi)}; HMODULE ptrOuterKernel = NULL; if (!GetModuleFileName(NULL, szSelf, MAX_PATH)) { iRc = CIR_GetModuleFileName/*-200*/; goto wrap; } wcscpy_c(szHooks, szSelf); pszNamePtr = (wchar_t*)PointToName(szHooks); if (!pszNamePtr) { iRc = CIR_GetModuleFileName/*-200*/; goto wrap; } // Hey, may be ConEmuHk.dll is already loaded? hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, nRemotePID); if (!hSnap || (hSnap == INVALID_HANDLE_VALUE)) { iRc = CIR_SnapshotCantBeOpened/*-113*/; goto wrap; } else if (hSnap && Module32First(hSnap, &mi)) { // 130829 - Let load newer(!) ConEmuHk.dll into target process. // 141201 - Also we need to be sure in kernel32.dll address LPCWSTR pszConEmuHk = WIN3264TEST(L"conemuhk.", L"conemuhk64."); size_t nDllNameLen = lstrlen(pszConEmuHk); // Out preferred module name wchar_t szOurName[40] = {}; wchar_t szMinor[8] = L""; lstrcpyn(szMinor, _CRT_WIDE(MVV_4a), countof(szMinor)); _wsprintf(szOurName, SKIPLEN(countof(szOurName)) CEDEFTERMDLLFORMAT /*L"ConEmuHk%s.%02u%02u%02u%s.dll"*/, WIN3264TEST(L"",L"64"), MVV_1, MVV_2, MVV_3, szMinor); CharLowerBuff(szOurName, lstrlen(szOurName)); // Go to enumeration wchar_t szName[64]; do { LPCWSTR pszName = PointToName(mi.szModule); // Name of ConEmuHk*.*.dll module may be changed (copied to %APPDATA%) if (!pszName || !*pszName) continue; lstrcpyn(szName, pszName, countof(szName)); CharLowerBuff(szName, lstrlen(szName)); if (!ptrOuterKernel && (lstrcmp(szName, L"kernel32.dll") == 0)) { ptrOuterKernel = mi.hModule; } // ConEmuHk*.*.dll? if (!bAlreadyHooked && (wmemcmp(szName, pszConEmuHk, nDllNameLen) == 0) && (wmemcmp(szName+lstrlen(szName)-4, L".dll", 4) == 0)) { // Yes! ConEmuHk.dll already loaded into nRemotePID! // But what is the version? Let don't downgrade loaded version! if (lstrcmp(szName, szOurName) >= 0) { // OK, szName is newer or equal to our build bAlreadyHooked = true; } } // Stop enumeration? if (bAlreadyHooked && ptrOuterKernel) break; } while (Module32Next(hSnap, &mi)); // Check done } SafeCloseHandle(hSnap); // Already hooked? if (bAlreadyHooked) { iRc = CIR_AlreadyInjected/*1*/; goto wrap; } if (!ptrOuterKernel) { iRc = CIR_OuterKernelAddr/*-112*/; goto wrap; } // Check, if we can access that process hProc = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, nRemotePID); if (hProc == NULL) { iRc = CIR_OpenProcess/*-201*/; goto wrap; } // Go to hook // Preparing Events _wsprintf(szName, SKIPLEN(countof(szName)) CEDEFAULTTERMHOOK, nRemotePID); if (!abDefTermOnly) { // When running in normal mode (NOT set up as default terminal) // we need full initialization procedure, not a light one when hooking explorer.exe hEvent = OpenEvent(EVENT_MODIFY_STATE|SYNCHRONIZE, FALSE, szName); if (hEvent) { ResetEvent(hEvent); CloseHandle(hEvent); } } else { hEvent = CreateEvent(LocalSecurity(), FALSE, FALSE, szName); SetEvent(hEvent); _wsprintf(szName, SKIPLEN(countof(szName)) CEDEFAULTTERMHOOKOK, nRemotePID); hDefTermReady = CreateEvent(LocalSecurity(), FALSE, FALSE, szName); ResetEvent(hDefTermReady); } // Creating as remote thread. // Resetting this event notify ConEmuHk about // 1) need to determine MainThreadId // 2) need to start pipe server _wsprintf(szName, SKIPLEN(countof(szName)) CECONEMUROOTTHREAD, nRemotePID); hEvent = OpenEvent(EVENT_MODIFY_STATE|SYNCHRONIZE, FALSE, szName); if (hEvent) { ResetEvent(hEvent); CloseHandle(hEvent); } // Определить битность процесса, Если он 32битный, а текущий - ConEmuC64.exe // Перезапустить 32битную версию ConEmuC.exe nBits = GetProcessBits(nRemotePID, hProc); if (nBits == 0) { // Do not even expected, ConEmu GUI must run ConEmuC elevated if required. iRc = CIR_GetProcessBits/*-204*/; goto wrap; } is32bit = (nBits == 32); 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 = CIR_CreateProcess/*-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 = CIR_WrapperResult/*-203*/; SetLastError(nWrapperResult); goto wrap; } // Значит всю работу сделал враппер iRc = CIR_OK/*0*/; goto wrap; } // Поехали _wcscpy_c(pszNamePtr, 16, is32bit ? L"ConEmuHk.dll" : L"ConEmuHk64.dll"); if (!FileExists(szHooks)) { iRc = CIR_ConEmuHkNotFound/*-250*/; goto wrap; } if (abDefTermOnly) { CINFILTRATE_EXIT_CODES iFRc = PrepareHookModule(szHooks); if (iFRc != 0) { iRc = iFRc; goto wrap; } } iRc = InfiltrateDll(hProc, ptrOuterKernel, szHooks); // Если создавали временную копию - запланировать ее удаление if (abDefTermOnly && (lstrcmpi(szHooks, szSelf) != 0)) { MoveFileEx(szHooks, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); } wrap: if (hProc != NULL) CloseHandle(hProc); // But check the result of the operation //_ASSERTE(FALSE && "WaitForSingleObject(hDefTermReady)"); if ((iRc == 0) && hDefTermReady) { _ASSERTE(abDefTermOnly); DWORD nWaitReady = WaitForSingleObject(hDefTermReady, CEDEFAULTTERMHOOKWAIT/*==0*/); if (nWaitReady == WAIT_TIMEOUT) { iRc = CIR_DefTermWaitingFailed/*-300*/; // Failed to start hooking thread in remote process } } return iRc; }
void ConEmuUpdateSettings::ResetToDefaults() { // Указатели должны быть освобождены перед вызовом _ASSERTE(szUpdateExeCmdLine==NULL); szUpdateVerLocation = NULL; isUpdateCheckOnStartup = false; isUpdateCheckHourly = false; isUpdateConfirmDownload = true; // true-Show MessageBox, false-notify via TSA only isUpdateUseBuilds = 0; // 0-спросить пользователя при первом запуске, 1-stable only, 2-latest isUpdateUseProxy = false; szUpdateProxy = szUpdateProxyUser = szUpdateProxyPassword = NULL; // "Server:port" // Проверяем, была ли программа установлена через ConEmuSetup.exe? isUpdateDownloadSetup = 0; // 0-Auto, 1-Installer (ConEmuSetup.exe), 2-7z archieve (ConEmu.7z), WinRar or 7z required isSetupDetected = 0; // 0-пока не проверялся, 1-установлено через Installer, пути совпали, 2-Installer не запускался szUpdateExeCmdLineDef = lstrdup(L"\"%1\" /p:%3 /qr"); SafeFree(szUpdateExeCmdLine); bool bWinRar = false; wchar_t* pszArcPath = NULL; BOOL bWin64 = IsWindows64(); for (int i = 0; !(pszArcPath && *pszArcPath) && (i <= 5); i++) { SettingsRegistry regArc; switch (i) { case 0: if (regArc.OpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\7-Zip", KEY_READ|(bWin64?KEY_WOW64_32KEY:0))) { regArc.Load(L"Path", &pszArcPath); } break; case 1: if (bWin64 && regArc.OpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\7-Zip", KEY_READ|KEY_WOW64_64KEY)) { regArc.Load(L"Path", &pszArcPath); } break; case 2: if (regArc.OpenKey(HKEY_CURRENT_USER, L"SOFTWARE\\7-Zip", KEY_READ)) { regArc.Load(L"Path", &pszArcPath); } break; case 3: if (regArc.OpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\WinRAR", KEY_READ|(bWin64?KEY_WOW64_32KEY:0))) { bWinRar = true; regArc.Load(L"exe32", &pszArcPath); } break; case 4: if (bWin64 && regArc.OpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\WinRAR", KEY_READ|KEY_WOW64_64KEY)) { bWinRar = true; regArc.Load(L"exe64", &pszArcPath); } break; case 5: if (regArc.OpenKey(HKEY_CURRENT_USER, L"SOFTWARE\\WinRAR", KEY_READ)) { bWinRar = true; if (!regArc.Load(L"exe32", &pszArcPath) && bWin64) { regArc.Load(L"exe64", &pszArcPath); } } break; } } if (!pszArcPath || !*pszArcPath) { szUpdateArcCmdLineDef = lstrdup(L"\"%ProgramFiles%\\7-Zip\\7zg.exe\" x -y \"%1\""); // "%1"-archive file, "%2"-ConEmu base dir } else { LPCWSTR pszExt = PointToExt(pszArcPath); int cchMax = lstrlen(pszArcPath)+64; szUpdateArcCmdLineDef = (wchar_t*)malloc(cchMax*sizeof(wchar_t)); if (szUpdateArcCmdLineDef) { if (pszExt && lstrcmpi(pszExt, L".exe") == 0) { _ASSERTE(bWinRar==true); //Issue 537: old WinRAR beta's fails //_wsprintf(szUpdateArcCmdLineDef, SKIPLEN(cchMax) L"\"%s\" x -y \"%%1\"%s", pszArcPath, bWinRar ? L" \"%%2\\\"" : L""); _wsprintf(szUpdateArcCmdLineDef, SKIPLEN(cchMax) L"\"%s\" x -y \"%%1\"", pszArcPath); } else { _ASSERTE(bWinRar==false); int nLen = lstrlen(pszArcPath); bool bNeedSlash = (*pszArcPath && (pszArcPath[nLen-1] != L'\\')) ? true : false; _wsprintf(szUpdateArcCmdLineDef, SKIPLEN(cchMax) L"\"%s%s7zg.exe\" x -y \"%%1\"", pszArcPath, bNeedSlash ? L"\\" : L""); } } } SafeFree(pszArcPath); SafeFree(szUpdateArcCmdLine); szUpdateDownloadPath = lstrdup(L"%TEMP%\\ConEmu"); isUpdateLeavePackages = false; szUpdatePostUpdateCmd = lstrdup(L"echo Last successful update>ConEmuUpdate.info && date /t>>ConEmuUpdate.info && time /t>>ConEmuUpdate.info"); // Юзер может чего-то свое делать с распакованными файлами }
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) #endif { hInst = hInstance; isWin64 = IsWindows64(); GetVersionEx(&gOSVer); int nInstallVer = 0; wsprintf(gsTitle, L"ConEmu %s installer", CONEMUVERL); lstrcpyn(gsRunAsAdm, L"Run installer as administrator", countof(gsRunAsAdm)); wchar_t szArg[MAX_PATH+1]; LPCWSTR pszCmdToken = GetCommandLine(); LPCWSTR pszCmdLineW = pszCmdToken; gsTempFolder[0] = 0; while (0 == NextArg(&pszCmdToken, szArg)) { if (lstrcmp(szArg, L"/?") == 0 || lstrcmp(szArg, L"-?") == 0) { MessageBox(NULL, L"Usage:\nConEmuSetup [/e[:<extract path>]] [/p:x86 | /p:x64] [<msi args>]", gsTitle, MB_ICONINFORMATION); return 1; } if (*szArg == L'/') { if (szArg[1] == L'e' || szArg[1] == L'E') { gbExtractOnly = true; if (szArg[2] == L':' && szArg[3]) { lstrcpyn(gsTempFolder, (szArg[3]==L'"') ? (szArg+4) : (szArg+3), countof(gsTempFolder)); } continue; } if (lstrcmpi(szArg, L"/p:x86") == 0) nInstallVer = Ver86; else if (lstrcmpi(szArg, L"/p:x64") == 0) nInstallVer = Ver64; else pszCmdToken = pszCmdLineW; break; } else if (*szArg == L'-') { pszCmdToken = pszCmdLineW; break; } pszCmdLineW = pszCmdToken; } if (!gbExtractOnly) { wchar_t szInstallPath[MAX_PATH+32]; bool bInstalled; HKEY hk; lstrcpyn(gsMessage, L"Choose version to install", countof(gsMessage)); szInstallPath[0] = 0; bInstalled = false; struct {HKEY hk; LPCWSTR path; LPCWSTR name; bool our;} Keys[] = { {HKEY_LOCAL_MACHINE,L"SOFTWARE\\ConEmu",L"InstallDir",true}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far Manager",L"InstallDir"}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far2",L"InstallDir"}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far",L"InstallDir"}, }; for (size_t s = 0; s < countof(Keys); s++) { if (!RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ, &hk) || !RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ|KEY_WOW64_32KEY, &hk)) { wchar_t szPath[MAX_PATH+1] = {}; DWORD cbSize = sizeof(szPath)-2; LONG lRc = RegQueryValueEx(hk, Keys[s].name, NULL, NULL, (LPBYTE)szPath, &cbSize); RegCloseKey(hk); if (!lRc && *szPath) { bInstalled = Keys[s].our; lstrcpy(szInstallPath, szPath); cbSize = lstrlen(szInstallPath); if (szInstallPath[cbSize-1] == L'\\') szInstallPath[cbSize-1] = 0; break; } } } if (szInstallPath[0] == 0) { GetEnvironmentVariable(L"ProgramFiles", szInstallPath, MAX_PATH); int nLen = lstrlen(szInstallPath); lstrcat(szInstallPath, (nLen > 0 && szInstallPath[nLen-1] != L'\\') ? L"\\ConEmu" : L"ConEmu"); } wsprintf(gsVer86, L"%s x86\n%s installation folder is\n%s", CONEMUVERL, bInstalled ? L"Current" : L"Default", szInstallPath); if (isWin64) { szInstallPath[0] = 0; bInstalled = false; struct {HKEY hk; LPCWSTR path; LPCWSTR name; bool our;} Keys[] = { {HKEY_LOCAL_MACHINE,L"SOFTWARE\\ConEmu",L"InstallDir_x64",true}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far Manager",L"InstallDir_x64"}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far2",L"InstallDir_x64"}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far",L"InstallDir_x64"}, }; for (size_t s = 0; s < countof(Keys); s++) { if (!RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ|KEY_WOW64_64KEY, &hk)) { wchar_t szPath[MAX_PATH+1] = {}; DWORD cbSize = sizeof(szPath)-2; LONG lRc = RegQueryValueEx(hk, Keys[s].name, NULL, NULL, (LPBYTE)szPath, &cbSize); RegCloseKey(hk); if (!lRc && *szPath) { bInstalled = Keys[s].our; lstrcpy(szInstallPath, szPath); cbSize = lstrlen(szInstallPath); if (szInstallPath[cbSize-1] == L'\\') szInstallPath[cbSize-1] = 0; break; } } } if (szInstallPath[0] == 0) { GetEnvironmentVariable(L"ProgramW6432", szInstallPath, MAX_PATH); int nLen = lstrlen(szInstallPath); lstrcat(szInstallPath, (nLen > 0 && szInstallPath[nLen-1] != L'\\') ? L"\\ConEmu" : L"ConEmu"); } wsprintf(gsVer64, L"%s x64\n%s installation folder is\n%s", CONEMUVERL, bInstalled ? L"Current" : L"Default", szInstallPath); wsprintf(gsFull, L"%s\n\nPress `Yes` to install x64 version\nPress `No` to install x86 version", gsMessage); } else { gsVer64[0] = 0; } } else { wchar_t szPath[MAX_PATH+1]; if (*gsTempFolder) { lstrcpy(szPath, gsTempFolder); } else { GetTempPath(countof(szPath) - 14, szPath); wchar_t* pszSubDir = szPath+lstrlen(szPath); lstrcpy(pszSubDir, L"ConEmu"); pszSubDir += 6; lstrcpy(pszSubDir, CONEMUVERL); } lstrcpyn(gsMessage, L"Choose version to extract", countof(gsMessage)); wsprintf(gsVer86, L"%s x86\nExtract installation files to\n%s", CONEMUVERL, szPath); wsprintf(gsVer64, L"%s x64\nExtract installation files to\n%s", CONEMUVERL, szPath); wsprintf(gsFull, L"%s\n\nPress `Yes` to extract x64 version\nPress `No` to extract x86 version\n\n%s", gsMessage, szPath); } if (nInstallVer == 0) nInstallVer = ChooseVersion(); // IDCANCEL/Ver86/Ver64 if (nInstallVer != Ver86 && nInstallVer != Ver64) return 1; if (gbExtractOnly && *gsTempFolder) { CreateDirectory(gsTempFolder, NULL); } else { GetTempPath(countof(gsTempFolder) - 14, gsTempFolder); wchar_t* pszSubDir = gsTempFolder+lstrlen(gsTempFolder); lstrcpy(pszSubDir, L"ConEmu"); pszSubDir += 6; lstrcpy(pszSubDir, CONEMUVERL); pszSubDir += lstrlen(pszSubDir); if (!CreateDirectory(gsTempFolder, NULL)) { bool lbCreated = false; SYSTEMTIME st = {}; GetLocalTime(&st); for (int i = 0; i < 100; i++) { wsprintf(pszSubDir, L"_%02i%02i%02i%i", st.wHour, st.wMinute, st.wSecond, i); if (CreateDirectory(gsTempFolder, NULL)) { lbCreated = true; break; } } if (!lbCreated) { return ReportError(10, L"Can't create temp folder\n%s", gsTempFolder); } } } wsprintf(gsMsiFile, L"%s\\ConEmu.%s.%s.msi", gsTempFolder, CONEMUVERL, (nInstallVer == Ver86) ? L"x86" : L"x64"); wsprintf(gsCabFile, L"%s\\ConEmu.cab", gsTempFolder); bool lbNeedExe = false; if (!gbExtractOnly && gOSVer.dwMajorVersion >= 6) lbNeedExe = true; if (!lbNeedExe) gsExeFile[0] = 0; else wsprintf(gsExeFile, L"%s\\ConEmuSetup.exe", gsTempFolder); int iExpMsi = ExportFile(nInstallVer, gsMsiFile); int iExpCab = (iExpMsi == 0) ? ExportFile(CABFILE, gsCabFile) : -1; int iExpExe = (!lbNeedExe) ? 0 : (iExpCab == 0) ? ExportFile(EXEFILE, gsExeFile) : -1; if (iExpMsi != 0 || iExpCab != 0 || iExpExe != 0) { DeleteFile(gsMsiFile); DeleteFile(gsCabFile); if (*gsExeFile) DeleteFile(gsExeFile); RemoveDirectory(gsTempFolder); return (iExpMsi != 0) ? iExpMsi : iExpCab; } if (gbExtractOnly) { wchar_t szMessage[MAX_PATH*2]; wsprintf(szMessage, L"Installation files was extracted successfully\n%s", gsTempFolder); MessageBox(NULL, szMessage, gsTitle, MB_ICONINFORMATION); return 0; } int iInstRc = 0; SHELLEXECUTEINFO sei = {sizeof(sei)}; wchar_t* pszParms = NULL; sei.fMask = SEE_MASK_NOCLOSEPROCESS|/*SEE_MASK_NOASYNC*/0x00000100; //|/*SEE_MASK_NOZONECHECKS*/0x00800000; sei.lpVerb = L"open"; if (gOSVer.dwMajorVersion<=5 || !gbUseElevation) { sei.lpFile = gsMsiFile; sei.lpParameters = pszCmdToken; } else { sei.lpFile = gsExeFile; int nMaxLen = lstrlen(gsMsiFile) + (pszCmdToken ? lstrlen(pszCmdToken) : 0) + 64; pszParms = (wchar_t*)malloc(nMaxLen*sizeof(wchar_t)); wsprintf(pszParms, L"/i \"%s\" %s", gsMsiFile, pszCmdToken ? pszCmdToken : L""); sei.lpParameters = pszParms; } sei.lpDirectory = gsTempFolder; sei.nShow = SW_SHOWNORMAL; BOOL lbExecute = ShellExecuteEx(&sei); #if 0 if (!lbExecute && lbNeedExe) { DWORD nErr = GetLastError(); if (nErr == 1223) { // Отмена пользователем UAC, или правов не хватило? sei.fMask = SEE_MASK_NOCLOSEPROCESS|/*SEE_MASK_NOASYNC*/0x00000100; //|/*SEE_MASK_NOZONECHECKS*/0x00800000; sei.lpVerb = L"open"; sei.lpFile = gsMsiFile; sei.lpParameters = pszCmdToken; sei.lpDirectory = gsTempFolder; sei.nShow = SW_SHOWNORMAL; lbExecute = ShellExecuteEx(&sei); } } #endif if (!lbExecute) { iInstRc = ReportError(20, L"Installer failed\n%s", gsMsiFile); } else { if (!sei.hProcess) { iInstRc = ReportError(21, L"Installer failed\n%s", gsMsiFile); } else { WaitForSingleObject(sei.hProcess, INFINITE); DWORD nCode = 0; SetLastError(0); //1602 - это похоже "Отмена" пользователем if (!GetExitCodeProcess(sei.hProcess, &nCode) || (nCode != 0 && nCode != 1602)) { wchar_t szFormat[128]; wsprintf(szFormat, L"Installer failed\n%%s\nExitCode=%u", nCode); iInstRc = ReportError(100+nCode, szFormat, gsMsiFile); } } } DeleteFile(gsMsiFile); DeleteFile(gsCabFile); if (*gsExeFile) DeleteFile(gsExeFile); RemoveDirectory(gsTempFolder); return iInstRc; }
// Returns true, if application was found in registry: // [HKCU|HKLM]\Software\Microsoft\Windows\CurrentVersion\App Paths // Also, function may change local process %PATH% variable bool SearchAppPaths(LPCWSTR asFilePath, CmdArg& rsFound, bool abSetPath, CmdArg* rpsPathRestore /*= NULL*/) { if (rpsPathRestore) rpsPathRestore->Empty(); if (!asFilePath || !*asFilePath) return false; LPCWSTR pszSearchFile = PointToName(asFilePath); LPCWSTR pszExt = PointToExt(pszSearchFile); // Lets try find it in "App Paths" // "HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" // "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" LPCWSTR pszRoot = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\"; HKEY hk; LONG lRc; CmdArg lsName; lsName.Attach(lstrmerge(pszRoot, pszSearchFile, pszExt ? NULL : L".exe")); // Seems like 32-bit and 64-bit registry branches are the same now, but just in case - will check both DWORD nWOW[2] = {WIN3264TEST(KEY_WOW64_32KEY,KEY_WOW64_64KEY), WIN3264TEST(KEY_WOW64_64KEY,KEY_WOW64_32KEY)}; for (int i = 0; i < 3; i++) { bool bFound = false; DWORD nFlags = ((i && IsWindows64()) ? nWOW[i-1] : 0); if ((i == 2) && !nFlags) break; // This is 32-bit OS lRc = RegOpenKeyEx(i ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, lsName, 0, KEY_READ|nFlags, &hk); if (lRc != 0) continue; wchar_t szVal[MAX_PATH+1] = L""; DWORD nType, nSize = sizeof(szVal)-sizeof(szVal[0]); lRc = RegQueryValueEx(hk, NULL, NULL, &nType, (LPBYTE)szVal, &nSize); if (lRc == 0) { wchar_t *pszCheck = NULL; if (nType == REG_SZ) { pszCheck = szVal; } else if (nType == REG_EXPAND_SZ) { pszCheck = ExpandEnvStr(szVal); } // May be quoted if (pszCheck) { LPCWSTR pszPath = Unquote(pszCheck, true); if (FileExists(pszPath)) { // asFilePath will be invalid after .Set rsFound.Set(pszPath); bFound = true; if (pszCheck != szVal) free(pszCheck); // The program may require additional "%PATH%". So, if allowed... if (abSetPath) { nSize = 0; lRc = RegQueryValueEx(hk, L"PATH", NULL, &nType, NULL, &nSize); if (lRc == 0 && nSize) { wchar_t* pszCurPath = GetEnvVar(L"PATH"); wchar_t* pszAddPath = (wchar_t*)calloc(nSize+4,1); wchar_t* pszNewPath = NULL; if (pszAddPath) { lRc = RegQueryValueEx(hk, L"PATH", NULL, &nType, (LPBYTE)pszAddPath, &nSize); if (lRc == 0 && *pszAddPath) { // Если в "%PATH%" этого нет (в начале) - принудительно добавить int iCurLen = pszCurPath ? lstrlen(pszCurPath) : 0; int iAddLen = lstrlen(pszAddPath); bool bNeedAdd = true; if ((iCurLen >= iAddLen) && (pszCurPath[iAddLen] == L';' || pszCurPath[iAddLen] == 0)) { wchar_t ch = pszCurPath[iAddLen]; pszCurPath[iAddLen] = 0; if (lstrcmpi(pszCurPath, pszAddPath) == 0) bNeedAdd = false; pszCurPath[iAddLen] = ch; } // Если пути еще нет if (bNeedAdd) { if (rpsPathRestore) { rpsPathRestore->SavePathVar(pszCurPath); } pszNewPath = lstrmerge(pszAddPath, L";", pszCurPath); if (pszNewPath) { SetEnvironmentVariable(L"PATH", pszNewPath); } else { _ASSERTE(pszNewPath!=NULL && "Allocation failed?"); } } } } SafeFree(pszAddPath); SafeFree(pszCurPath); SafeFree(pszNewPath); } } } } } RegCloseKey(hk); if (bFound) return true; } return false; }
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 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; }
bool CAttachDlg::CanAttachWindow(HWND hFind, DWORD nSkipPID, CProcessData* apProcessData, CAttachDlg::AttachWndInfo& Info) { static bool bIsWin64 = IsWindows64(); ZeroStruct(Info); DWORD_PTR nStyle = GetWindowLongPtr(hFind, GWL_STYLE); DWORD_PTR nStyleEx = GetWindowLongPtr(hFind, GWL_EXSTYLE); if (!GetWindowThreadProcessId(hFind, &Info.nPID)) Info.nPID = 0; if (!Info.nPID) return false; bool lbCan = ((nStyle & (WS_VISIBLE/*|WS_CAPTION|WS_MAXIMIZEBOX*/)) == (WS_VISIBLE/*|WS_CAPTION|WS_MAXIMIZEBOX*/)); if (lbCan) { // Более тщательно стили проверить lbCan = ((nStyle & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX) || ((nStyle & WS_THICKFRAME) == WS_THICKFRAME); } if (lbCan && Info.nPID == GetCurrentProcessId()) lbCan = false; if (lbCan && Info.nPID == nSkipPID) lbCan = false; if (lbCan && (nStyle & WS_CHILD)) lbCan = false; if (lbCan && (nStyleEx & WS_EX_TOOLWINDOW)) lbCan = false; if (lbCan && gpConEmu->isOurConsoleWindow(hFind)) lbCan = false; if (lbCan && gpConEmu->mp_Inside && (hFind == gpConEmu->mp_Inside->mh_InsideParentRoot)) lbCan = false; GetClassName(hFind, Info.szClass, countof(Info.szClass)); GetWindowText(hFind, Info.szTitle, countof(Info.szTitle)); if (gpSetCls->isAdvLogging) { wchar_t szLogInfo[MAX_PATH*3]; _wsprintf(szLogInfo, SKIPLEN(countof(szLogInfo)) L"Attach:%s x%08X/x%08X/x%08X {%s} \"%s\"", Info.szExeName, LODWORD(hFind), nStyle, nStyleEx, Info.szClass, Info.szTitle); CVConGroup::LogString(szLogInfo); } if (!lbCan) return false; _wsprintf(Info.szPid, SKIPLEN(countof(Info.szPid)) L"%u", Info.nPID); const wchar_t sz32bit[] = L" [32]"; const wchar_t sz64bit[] = L" [64]"; HANDLE h; DEBUGTEST(DWORD nErr); bool lbExeFound = false; if (apProcessData) { lbExeFound = apProcessData->GetProcessName(Info.nPID, Info.szExeName, countof(Info.szExeName), Info.szExePathName, countof(Info.szExePathName), &Info.nImageBits); if (lbExeFound) { //ListView_SetItemText(hList, nItem, alc_File, szExeName); //ListView_SetItemText(hList, nItem, alc_Path, szExePathName); if (bIsWin64 && Info.nImageBits) { wcscat_c(Info.szPid, (Info.nImageBits == 64) ? sz64bit : sz32bit); } } } if (!lbExeFound) { Info.nImageBits = GetProcessBits(Info.nPID); if (bIsWin64 && Info.nImageBits) { wcscat_c(Info.szPid, (Info.nImageBits == 64) ? sz64bit : sz32bit); } h = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Info.nPID); if (h && h != INVALID_HANDLE_VALUE) { MODULEENTRY32 mi = {sizeof(mi)}; if (Module32First(h, &mi)) { lstrcpyn(Info.szExeName, *mi.szModule ? mi.szModule : (wchar_t*)PointToName(mi.szExePath), countof(Info.szExeName)); lstrcpyn(Info.szExePathName, mi.szExePath, countof(Info.szExePathName)); lbExeFound = true; } else { if (bIsWin64) { wcscat_c(Info.szPid, sz64bit); } } CloseHandle(h); } else { #ifdef _DEBUG nErr = GetLastError(); _ASSERTE(nErr == 5 || (nErr == 299 && Info.nImageBits == 64)); #endif wcscpy_c(Info.szExeName, L"???"); } #if 0 //#ifdef _WIN64 -- no need to call TH32CS_SNAPMODULE32, simple TH32CS_SNAPMODULE will handle both if it can if (!lbExeFound) { h = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32, Info.nPID); if (h && h != INVALID_HANDLE_VALUE) { MODULEENTRY32 mi = {sizeof(mi)}; if (Module32First(h, &mi)) { //ListView_SetItemText(hList, nItem, alc_File, *mi.szModule ? mi.szModule : (wchar_t*)PointToName(mi.szExePath)); lstrcpyn(Info.szExeName, *mi.szModule ? mi.szModule : (wchar_t*)PointToName(mi.szExePath), countof(Info.szExeName)); //ListView_SetItemText(hList, nItem, alc_Path, mi.szExePath); lstrcpyn(Info.szExePathName, mi.szExePath, countof(Info.szExePathName)); } CloseHandle(h); } } #endif } if (!lbExeFound) { // Так можно получить только имя файла процесса PROCESSENTRY32 pi = {sizeof(pi)}; h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (h && h != INVALID_HANDLE_VALUE) { if (Process32First(h, &pi)) { do { if (pi.th32ProcessID == Info.nPID) { lstrcpyn(Info.szExeName, pi.szExeFile, countof(Info.szExeName)); break; } } while (Process32Next(h, &pi)); } } } wcscpy_c(Info.szType, isConsoleClass(Info.szClass) ? szTypeCon : szTypeGui); return true; }
// 0 - SUCCEEDED, otherwise - error code int WINAPI MountVirtualHive(LPCWSTR asHive, PHKEY phKey, LPCWSTR asXPMountName, wchar_t* pszErrInfo, int cchErrInfoMax, BOOL* pbKeyMounted) { int lRc = -1; if (pszErrInfo && cchErrInfoMax) *pszErrInfo = 0; // если передали буфер для ошибки - сразу его почистить *pbKeyMounted = FALSE; OSVERSIONINFO osv = {sizeof(OSVERSIONINFO)}; GetVersionEx(&osv); HMODULE hAdvapi32 = LoadLibrary(L"advapi32.dll"); //LPCWSTR pszKeyName = NULL; LPCWSTR ppszKeys[] = { L"HKCU", L"HKCU\\Software", L"HKLM", L"HKLM\\Software", L"HKLM64", L"HKLM64\\Software" }; size_t nRootKeys = IsWindows64() ? countof(ppszKeys) : (countof(ppszKeys) - 2); if (!hAdvapi32) { if (pszErrInfo && cchErrInfoMax) msprintf(pszErrInfo, cchErrInfoMax, L"LoadLibrary(advapi32.dll) failed, code=0x%08X!\n", GetLastError()); lRc = -2; goto wrap; } if (osv.dwMajorVersion >= 6) { // Vista+ typedef LONG (WINAPI* RegLoadAppKey_t)(LPCWSTR lpFile, PHKEY phkResult, REGSAM samDesired, DWORD dwOptions, DWORD Reserved); RegLoadAppKey_t RegLoadAppKey_f = (RegLoadAppKey_t)GetProcAddress(hAdvapi32, "RegLoadAppKeyW"); if (!RegLoadAppKey_f) { if (pszErrInfo && cchErrInfoMax) msprintf(pszErrInfo, cchErrInfoMax, L"RegLoadAppKeyW not found, code=0x%08X!\n", GetLastError()); lRc = -3; goto wrap; } else { if ((lRc = RegLoadAppKey_f(asHive, phKey, KEY_ALL_ACCESS, 0, 0)) != 0) { if ((lRc = RegLoadAppKey_f(asHive, phKey, KEY_READ, 0, 0)) != 0) { if (pszErrInfo && cchErrInfoMax) msprintf(pszErrInfo, cchErrInfoMax, L"RegLoadAppKey failed, code=0x%08X!", (DWORD)lRc); lRc = -4; //-V112 goto wrap; } } *pbKeyMounted = TRUE; } } else if (!asXPMountName || !*asXPMountName) { lRc = -7; if (pszErrInfo && cchErrInfoMax) lstrcpyn(pszErrInfo, L"XPMountName is empty!", cchErrInfoMax); goto wrap; } else { CBackupPrivileges se; if (!se.BackupPrivilegesAcuire(TRUE)) { if (pszErrInfo && cchErrInfoMax) msprintf(pszErrInfo, cchErrInfoMax, L"Aquiring SE_BACKUP_NAME/SE_RESTORE_NAME failed, code=0x%08X!\nYou must be Administrator or Backup operator", GetLastError()); lRc = -5; goto wrap; } //_wcscpy_c(rsXPMountName, cchXPMountMax, VIRTUAL_REGISTRY_GUID); //WARNING("###: Докинуть в конец что-нть уникальное, например CRC пути к hive"); // Hive уже мог быть подключен другой копией ConEmu. TODO("При выходе - может возникнуть конфликт? Кто первый сделает RegUnloadKey..."); if ((lRc = RegOpenKeyEx(HKEY_USERS, asXPMountName, 0, KEY_ALL_ACCESS, phKey)) == 0) { goto wrap; // успешно - hive уже подключен } else if ((lRc = RegOpenKeyEx(HKEY_USERS, asXPMountName, 0, KEY_READ, phKey)) == 0) { goto wrap; // успешно - hive уже подключен (ReadOnly) } // Hive еще не был подключен if ((lRc = RegLoadKey(HKEY_USERS, asXPMountName, asHive)) != 0) { if (pszErrInfo && cchErrInfoMax) msprintf(pszErrInfo, cchErrInfoMax, L"RegLoadKey failed, code=0x%08X!", (DWORD)lRc); lRc = -6; goto wrap; } // Ключ смонтирован, нужно его будет демонтировать при выходе *pbKeyMounted = TRUE; if ((lRc = RegOpenKeyEx(HKEY_USERS, asXPMountName, 0, KEY_ALL_ACCESS, phKey)) == 0) { goto wrap; // успешно - hive уже подключен } else if ((lRc = RegOpenKeyEx(HKEY_USERS, asXPMountName, 0, KEY_READ, phKey)) == 0) { goto wrap; // успешно - hive уже подключен (ReadOnly) } } // Нужно проверить, можно ли создать/открыть необходимые ключи for (UINT i = 0; i < nRootKeys; i++) { HKEY hTest = NULL; LPCWSTR pszKeyName = ppszKeys[i]; lRc = RegCreateKeyEx(*phKey, pszKeyName, 0,0,0, KEY_ALL_ACCESS, 0, &hTest, 0); if (lRc != 0) lRc = RegCreateKeyEx(*phKey, pszKeyName, 0,0,0, KEY_READ, 0, &hTest, 0); if (lRc != 0) { if (pszErrInfo && cchErrInfoMax) msprintf(pszErrInfo, cchErrInfoMax, L"RegCreateKeyEx(%s) failed, code=0x%08X!", pszKeyName, (DWORD)lRc); RegCloseKey(*phKey); *phKey = NULL; if (asXPMountName && *asXPMountName) UnMountVirtualHive(asXPMountName, NULL, 0); lRc = -8; goto wrap; } } wrap: if (hAdvapi32) FreeLibrary(hAdvapi32); // Decrease counter return lRc; }
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) #endif { hInst = hInstance; isWin64 = IsWindows64(); GetVersionEx(&gOSVer); int nInstallVer = 0; wsprintf(gsTitle, msgConEmuInstaller, CONEMUVERL); lstrcpyn(gsRunAsAdm, msgRunSetupAsAdmin, countof(gsRunAsAdm)); wchar_t szArg[MAX_PATH+1]; LPCWSTR pszCmdToken = GetCommandLine(); LPCWSTR pszCmdLineW = pszCmdToken; CTempDir temp_dir; // gsTempFolder[0] = 0; while (0 == NextArg(&pszCmdToken, szArg)) { if (lstrcmp(szArg, L"/?") == 0 || lstrcmp(szArg, L"-?") == 0 || lstrcmp(szArg, L"-h") == 0 || lstrcmp(szArg, L"-help") == 0 || lstrcmp(szArg, L"--help") == 0) { MessageBox(NULL, msgUsageExample, gsTitle, MB_ICONINFORMATION); return exit_Cancelled; } if (*szArg == L'/') { if (szArg[1] == L'e' || szArg[1] == L'E') { gbExtractOnly = true; if (szArg[2] == L':' && szArg[3]) { lstrcpyn(gsTempFolder, (szArg[3]==L'"') ? (szArg+4) : (szArg+3), countof(gsTempFolder)); } continue; } if (memcmp(szArg, L"/p:x", 4*sizeof(*szArg)) == 0) { gbAlreadyAdmin = IsUserAdmin(); if (lstrcmpi(szArg+4, L"86") == 0) { nInstallVer = Ver86; } else if (lstrcmpi(szArg+4, L"86,adm") == 0) { nInstallVer = Ver86; gbUseElevation = !gbAlreadyAdmin; } else if (lstrcmpi(szArg+4, L"64") == 0) { nInstallVer = Ver64; } else if (lstrcmpi(szArg+4, L"64,adm") == 0) { nInstallVer = Ver64; gbUseElevation = !gbAlreadyAdmin; } } else pszCmdToken = pszCmdLineW; break; } else if (*szArg == L'-') { pszCmdToken = pszCmdLineW; break; } pszCmdLineW = pszCmdToken; } if (!temp_dir.Acquire()) { return exit_CreateDirectory; } if (!gbExtractOnly) { // If pszCmdToken is not empty - set global var gbAutoMode = (pszCmdToken && *pszCmdToken); wchar_t szInstallPath[MAX_PATH+32]; bool bInstalled; HKEY hk; lstrcpyn(gsMessage, msgChooseInstallVer, countof(gsMessage)); szInstallPath[0] = 0; bInstalled = false; struct {HKEY hk; LPCWSTR path; LPCWSTR name; bool our;} Keys[] = { {HKEY_LOCAL_MACHINE,L"SOFTWARE\\ConEmu",L"InstallDir",true}, //Current installer does not use FarManager installation dir anymore //{HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far Manager",L"InstallDir"}, //{HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far2",L"InstallDir"}, //{HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far",L"InstallDir"}, }; for (size_t s = 0; s < countof(Keys); s++) { if (!RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ, &hk) || !RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ|KEY_WOW64_32KEY, &hk)) { wchar_t szPath[MAX_PATH+1] = {}; DWORD cbSize = sizeof(szPath)-2; LONG lRc = RegQueryValueEx(hk, Keys[s].name, NULL, NULL, (LPBYTE)szPath, &cbSize); RegCloseKey(hk); if (!lRc && *szPath) { bInstalled = Keys[s].our; lstrcpy(szInstallPath, szPath); cbSize = lstrlen(szInstallPath); if (szInstallPath[cbSize-1] == L'\\') szInstallPath[cbSize-1] = 0; break; } } } if (szInstallPath[0] == 0) { GetEnvironmentVariable(L"ProgramFiles", szInstallPath, MAX_PATH); int nLen = lstrlen(szInstallPath); lstrcat(szInstallPath, (nLen > 0 && szInstallPath[nLen-1] != L'\\') ? L"\\ConEmu" : L"ConEmu"); } wsprintf(gsVer86, msgInstallFolderIs, CONEMUVERL, L"x86", bInstalled ? msgPathCurrent : msgPathDefault, szInstallPath); if (isWin64) { szInstallPath[0] = 0; bInstalled = false; struct {HKEY hk; LPCWSTR path; LPCWSTR name; bool our;} Keys[] = { {HKEY_LOCAL_MACHINE,L"SOFTWARE\\ConEmu",L"InstallDir_x64",true}, //Current installer does not use FarManager installation dir anymore //{HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far Manager",L"InstallDir_x64"}, //{HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far2",L"InstallDir_x64"}, //{HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far",L"InstallDir_x64"}, }; for (size_t s = 0; s < countof(Keys); s++) { if (!RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ|KEY_WOW64_64KEY, &hk)) { wchar_t szPath[MAX_PATH+1] = {}; DWORD cbSize = sizeof(szPath)-2; LONG lRc = RegQueryValueEx(hk, Keys[s].name, NULL, NULL, (LPBYTE)szPath, &cbSize); RegCloseKey(hk); if (!lRc && *szPath) { bInstalled = Keys[s].our; lstrcpy(szInstallPath, szPath); cbSize = lstrlen(szInstallPath); if (szInstallPath[cbSize-1] == L'\\') szInstallPath[cbSize-1] = 0; break; } } } if (szInstallPath[0] == 0) { GetEnvironmentVariable(L"ProgramW6432", szInstallPath, MAX_PATH); int nLen = lstrlen(szInstallPath); lstrcat(szInstallPath, (nLen > 0 && szInstallPath[nLen-1] != L'\\') ? L"\\ConEmu" : L"ConEmu"); } wsprintf(gsVer64, msgInstallFolderIs, CONEMUVERL, L"x64", bInstalled ? msgPathCurrent : msgPathDefault, szInstallPath); wsprintf(gsFull, msgInstallConfirm, gsMessage); } else { gsVer64[0] = 0; } } else { LPCWSTR szPath = gsTempFolder; lstrcpyn(gsMessage, msgChooseExtractVer, countof(gsMessage)); wsprintf(gsVer86, msgExtractX86X64, CONEMUVERL, L"x86", szPath); wsprintf(gsVer64, msgExtractX86X64, CONEMUVERL, L"x64", szPath); wsprintf(gsFull, msgExtractConfirm, gsMessage, szPath); } if (nInstallVer == 0) { nInstallVer = ChooseVersion(); // IDCANCEL/Ver86/Ver64 } if (nInstallVer != Ver86 && nInstallVer != Ver64) { return exit_Cancelled; } // Preparing full paths wsprintf(gsMsiFile, L"%s\\ConEmu.%s.%s.msi", gsTempFolder, CONEMUVERL, (nInstallVer == Ver86) ? L"x86" : L"x64"); wsprintf(gsCabFile, L"%s\\ConEmu.cab", gsTempFolder); bool lbNeedExe = false; if (!gbExtractOnly && gOSVer.dwMajorVersion >= 6) lbNeedExe = true; if (!lbNeedExe) gsExeFile[0] = 0; else wsprintf(gsExeFile, L"%s\\ConEmuSetup.exe", gsTempFolder); int iExpMsi = ExportFile(nInstallVer, gsMsiFile); int iExpCab = (iExpMsi == 0) ? ExportFile(CABFILE, gsCabFile) : -1; int iExpExe = (!lbNeedExe) ? 0 : (iExpCab == 0) ? ExportFile(EXEFILE, gsExeFile) : -1; if (iExpMsi != 0 || iExpCab != 0 || iExpExe != 0) { DeleteFile(gsMsiFile); DeleteFile(gsCabFile); if (*gsExeFile) DeleteFile(gsExeFile); return (iExpMsi != 0) ? iExpMsi : iExpCab; } if (gbExtractOnly) { temp_dir.DontRemove(); wchar_t szMessage[MAX_PATH*2]; wsprintf(szMessage, msgExtractedSuccessfully, gsTempFolder); MessageBox(NULL, szMessage, gsTitle, MB_ICONINFORMATION); return exit_Succeeded; } int iInstRc = exit_Succeeded; SHELLEXECUTEINFO sei = {sizeof(sei)}; wchar_t* pszParms = NULL; sei.fMask = SEE_MASK_NOCLOSEPROCESS|/*SEE_MASK_NOASYNC*/0x00000100; //|/*SEE_MASK_NOZONECHECKS*/0x00800000; sei.lpVerb = L"open"; if (gOSVer.dwMajorVersion<=5 || !gbUseElevation) { sei.lpFile = gsMsiFile; sei.lpParameters = pszCmdToken; } else { // Executor has `<requestedExecutionLevel level="requireAdministrator" ...>` in manifest sei.lpFile = gsExeFile; int nMaxLen = lstrlen(gsMsiFile) + (pszCmdToken ? lstrlen(pszCmdToken) : 0) + 64; pszParms = (wchar_t*)malloc(nMaxLen*sizeof(wchar_t)); wsprintf(pszParms, L"/i \"%s\" %s", gsMsiFile, pszCmdToken ? pszCmdToken : L""); sei.lpParameters = pszParms; } sei.lpDirectory = gsTempFolder; sei.nShow = SW_SHOWNORMAL; BOOL lbExecute = ShellExecuteEx(&sei); #if 0 if (!lbExecute && lbNeedExe) { DWORD nErr = GetLastError(); if (nErr == 1223) { // Отмена пользователем UAC, или правов не хватило? sei.fMask = SEE_MASK_NOCLOSEPROCESS|/*SEE_MASK_NOASYNC*/0x00000100; //|/*SEE_MASK_NOZONECHECKS*/0x00800000; sei.lpVerb = L"open"; sei.lpFile = gsMsiFile; sei.lpParameters = pszCmdToken; sei.lpDirectory = gsTempFolder; sei.nShow = SW_SHOWNORMAL; lbExecute = ShellExecuteEx(&sei); } } #endif if (!lbExecute) { iInstRc = ReportError(exit_ShellExecuteEx, msgInstallerFailed, gsMsiFile); } else { if (!sei.hProcess) { iInstRc = ReportError(exit_NullProcess, msgInstallerFailed, gsMsiFile); } else { WaitForSingleObject(sei.hProcess, INFINITE); DWORD nCode = 0; SetLastError(0); wchar_t szFormat[256]; if (GetExitCodeProcess(sei.hProcess, &nCode)) { switch (nCode) { case 0: iInstRc = exit_Succeeded; break; case 1602: // cancelled by user iInstRc = exit_Cancelled; // don't show any errors break; case 3010: // reboot is required wsprintf(szFormat, msgRebootRequired, nCode); iInstRc = ReportError(exit_AddWin32Code+nCode, szFormat, gsMsiFile); break; default: wsprintf(szFormat, msgInstallerFailedEx, nCode); iInstRc = ReportError(exit_AddWin32Code+nCode, szFormat, gsMsiFile); } } else { lstrcpyn(szFormat, msgExitCodeFailed, countof(szFormat)); iInstRc = ReportError(exit_ExitCodeProcess, szFormat, gsMsiFile); } } } DeleteFile(gsMsiFile); DeleteFile(gsCabFile); if (*gsExeFile) DeleteFile(gsExeFile); return iInstRc; }
bool GetImageSubsystem(const wchar_t *FileName,DWORD& ImageSubsystem,DWORD& ImageBits/*16/32/64*/,DWORD& FileAttrs) { bool Result = false; ImageSubsystem = IMAGE_SUBSYSTEM_UNKNOWN; ImageBits = 0; FileAttrs = (DWORD)-1; wchar_t* pszExpand = NULL; // Пытаться в UNC? Хотя сам CreateProcess UNC не поддерживает, так что смысла пока нет HANDLE hModuleFile = CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); // Переменные окружения if ((hModuleFile == INVALID_HANDLE_VALUE) && FileName && wcschr(FileName, L'%')) { pszExpand = ExpandEnvStr(FileName); if (pszExpand) { hModuleFile = CreateFile(pszExpand,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); if (hModuleFile != INVALID_HANDLE_VALUE) { FileName = pszExpand; } } } #if 0 // Если не указан путь к файлу - попробовать найти его в %PATH% if (hModuleFile != INVALID_HANDLE_VALUE && FileName && wcschr(FileName, L'\\') == NULL && wcschr(FileName, L'.') != NULL) { DWORD nErrCode = GetLastError(); if (nErrCode) { wchar_t szFind[MAX_PATH], *psz; DWORD nLen = SearchPath(NULL, FileName, NULL, countof(szFind), szFind, &psz); if (nLen && nLen < countof(szFind)) hModuleFile = CreateFile(szFind,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); } } #endif if (hModuleFile != INVALID_HANDLE_VALUE) { BY_HANDLE_FILE_INFORMATION bfi = {0}; IMAGE_DOS_HEADER DOSHeader; DWORD ReadSize; if (GetFileInformationByHandle(hModuleFile, &bfi)) FileAttrs = bfi.dwFileAttributes; // Это это батник - сразу вернуть IMAGE_SUBSYSTEM_BATCH_FILE LPCWSTR pszExt = PointToExt(FileName); if (pszExt && (!lstrcmpi(pszExt, L".cmd") || !lstrcmpiW(pszExt, L".bat") || !lstrcmpiW(pszExt, L".btm") // take command )) { CloseHandle(hModuleFile); ImageSubsystem = IMAGE_SUBSYSTEM_BATCH_FILE; ImageBits = IsWindows64() ? 64 : 32; //-V112 Result = true; goto wrap; } if (ReadFile(hModuleFile,&DOSHeader,sizeof(DOSHeader),&ReadSize,NULL)) { _ASSERTE(IMAGE_DOS_SIGNATURE==0x5A4D); if (DOSHeader.e_magic != IMAGE_DOS_SIGNATURE) { //const wchar_t *pszExt = wcsrchr(FileName, L'.'); if (pszExt && lstrcmpiW(pszExt, L".com") == 0) { ImageSubsystem = IMAGE_SUBSYSTEM_DOS_EXECUTABLE; ImageBits = 16; Result = true; } } else { ImageSubsystem = IMAGE_SUBSYSTEM_DOS_EXECUTABLE; ImageBits = 16; Result = true; if (SetFilePointer(hModuleFile,DOSHeader.e_lfanew,NULL,FILE_BEGIN)) { IMAGE_HEADERS PEHeader; if (ReadFile(hModuleFile,&PEHeader,sizeof(PEHeader),&ReadSize,NULL)) { _ASSERTE(IMAGE_NT_SIGNATURE==0x00004550); if (PEHeader.Signature == IMAGE_NT_SIGNATURE) { switch(PEHeader.OptionalHeader32.Magic) { case IMAGE_NT_OPTIONAL_HDR32_MAGIC: { ImageSubsystem = PEHeader.OptionalHeader32.Subsystem; _ASSERTE((ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) || (ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)); ImageBits = 32; //-V112 } break; case IMAGE_NT_OPTIONAL_HDR64_MAGIC: { ImageSubsystem = PEHeader.OptionalHeader64.Subsystem; _ASSERTE((ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) || (ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)); ImageBits = 64; } break; /*default: { // unknown magic }*/ } } else if ((WORD)PEHeader.Signature == IMAGE_OS2_SIGNATURE) { ImageBits = 32; //-V112 /* NE, хмм... а как определить что оно ГУЕВОЕ? Andrzej Novosiolov <*****@*****.**> AN> ориентироваться по флагу "Target operating system" NE-заголовка AN> (1 байт по смещению 0x36). Если там Windows (значения 2, 4) - подразумеваем AN> GUI, если OS/2 и прочая экзотика (остальные значения) - подразумеваем консоль. */ BYTE ne_exetyp = reinterpret_cast<PIMAGE_OS2_HEADER>(&PEHeader)->ne_exetyp; if (ne_exetyp==2||ne_exetyp==4) //-V112 { ImageSubsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; } else { ImageSubsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; } } /*else { // unknown signature }*/ } /*else { // обломс вышел с чтением следующего заголовка ;-( }*/ } /*else { // видимо улетели куда нить в трубу, т.к. dos_head.e_lfanew указал // слишком в неправдоподное место (например это чистой воды DOS-файл) }*/ } /*else { // это не исполняемый файл - у него нету заголовка MZ, например, NLM-модуль // TODO: здесь можно разбирать POSIX нотацию, например "/usr/bin/sh" }*/ } /*else { // ошибка чтения }*/ CloseHandle(hModuleFile); } /*else { // ошибка открытия }*/ wrap: SafeFree(pszExpand); return Result; }
bool InitRegistryRoot(CESERVER_CONSOLE_MAPPING_HDR* pInfo) { wchar_t szTitle[64]; msprintf(szTitle, countof(szTitle), L"ConEmuHk, PID=%u", GetCurrentProcessId()); if (!ghAdvapi32) { GuiMessageBox(ghConEmuWnd, L"ConEmuHk: InitRegistryRoot was called, but ghAdvapi32 is null!\n", szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); return false; } if (!RegOpenKeyEx_f) { _ASSERTE(RegOpenKeyEx_f!=NULL); RegOpenKeyEx_f = (RegOpenKeyEx_t)GetProcAddress(ghAdvapi32, "RegOpenKeyExW"); if (!RegOpenKeyEx_f) { GuiMessageBox(ghConEmuWnd, L"ConEmuHk: InitRegistryRoot was called, but GetProcAddress(RegOpenKeyExW) is null!\n", szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); return false; } } if (!RegCreateKeyEx_f) { _ASSERTE(RegCreateKeyEx_f!=NULL); RegCreateKeyEx_f = (RegCreateKeyEx_t)GetProcAddress(ghAdvapi32, "RegCreateKeyExW"); if (!RegCreateKeyEx_f) { GuiMessageBox(ghConEmuWnd, L"ConEmuHk: InitRegistryRoot was called, but GetProcAddress(RegCreateKeyExW) is null!\n", szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); return false; } } if (!RegCloseKey_f) { _ASSERTE(RegCloseKey_f!=NULL); RegCloseKey_f = (RegCloseKey_t)GetProcAddress(ghAdvapi32, "RegCloseKey"); if (!RegCloseKey_f) { GuiMessageBox(ghConEmuWnd, L"ConEmuHk: InitRegistryRoot was called, but GetProcAddress(RegCloseKey) is null!\n", szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); return false; } } if (ghNewKeyRoot == NULL) { //OSVERSIONINFO osv = {sizeof(OSVERSIONINFO)}; //GetVersionEx(&osv); //if (osv.dwMajorVersion >= 6) if (!*pInfo->sMountKey) { // Vista+ typedef LONG (WINAPI* RegLoadAppKey_t)(LPCWSTR lpFile, PHKEY phkResult, REGSAM samDesired, DWORD dwOptions, DWORD Reserved); RegLoadAppKey_t RegLoadAppKey_f = (RegLoadAppKey_t)GetProcAddress(ghAdvapi32, "RegLoadAppKeyW"); if (RegLoadAppKey_f) { LONG lRc = 0; if ((lRc = RegLoadAppKey_f(pInfo->sHiveFileName, &ghNewKeyRoot, KEY_ALL_ACCESS, 0, 0)) != 0) { if ((lRc = RegLoadAppKey_f(pInfo->sHiveFileName, &ghNewKeyRoot, KEY_READ, 0, 0)) != 0) { wchar_t szDbgMsg[128]; msprintf(szDbgMsg, countof(szDbgMsg), L"ConEmuHk: RegLoadAppKey failed, code=0x%08X!\n", (DWORD)lRc); GuiMessageBox(ghConEmuWnd, szDbgMsg, szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); ghNewKeyRoot = NULL; } } } else { GuiMessageBox(ghConEmuWnd, L"ConEmuHk: InitRegistryRoot was called, but GetProcAddress(RegLoadAppKeyW) is null!\n", szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); ghNewKeyRoot = NULL; } } else { // XP Only. т.к. для монтирования хайва требуются права админа HKEY hkRoot = pInfo->hMountRoot; if (hkRoot == HKEY_CURRENT_USER) { // Значит это "HKCU\Software\ConEmu Virtual Registry" if (RegOpenKeyEx_f(HKEY_CURRENT_USER, VIRTUAL_REGISTRY_ROOT, 0, KEY_ALL_ACCESS, &hkRoot)) { GuiMessageBox(ghConEmuWnd, L"ConEmuHk: RegOpenKeyEx(" VIRTUAL_REGISTRY_ROOT L") failed!\n", szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); ghNewKeyRoot = NULL; hkRoot = NULL; } } if (hkRoot && RegOpenKeyEx_f(hkRoot, pInfo->sMountKey, 0, KEY_ALL_ACCESS, &ghNewKeyRoot)) { if (RegOpenKeyEx_f(hkRoot, pInfo->sMountKey, 0, KEY_READ, &ghNewKeyRoot)) { wchar_t szErrMsg[512]; msprintf(szErrMsg, countof(szErrMsg), L"ConEmuHk: RegOpenKeyEx(0x%X,'%s') failed!\n", (DWORD)(LONG)(LONG_PTR)hkRoot, pInfo->sMountKey); GuiMessageBox(ghConEmuWnd, szErrMsg, szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); ghNewKeyRoot = NULL; } } } if (!ghNewKeyRoot) { ghNewKeyRoot = (HKEY)-1; } else { LONG lRc = 0; LPCWSTR pszKeyName = NULL; if (!lRc) lRc = RegCreateKeyEx_f(ghNewKeyRoot, pszKeyName=L"HKCU", 0,0,0, KEY_ALL_ACCESS, 0, &ghNewHKCU, 0); if (!lRc) lRc = RegCreateKeyEx_f(ghNewKeyRoot, pszKeyName=L"HKCU\\Software", 0,0,0, KEY_ALL_ACCESS, 0, &ghNewHKCUSoftware, 0); if (!lRc) lRc = RegCreateKeyEx_f(ghNewKeyRoot, pszKeyName=L"HKLM", 0,0,0, KEY_ALL_ACCESS, 0, &ghNewHKLM32, 0); if (!lRc) lRc = RegCreateKeyEx_f(ghNewKeyRoot, pszKeyName=L"HKLM\\Software", 0,0,0, KEY_ALL_ACCESS, 0, &ghNewHKLM32Software, 0); if (!lRc && IsWindows64()) { // эта ветка не должна выполняться в 32битных ОС if (!lRc) lRc = RegCreateKeyEx_f(ghNewKeyRoot, pszKeyName=L"HKLM64", 0,0,0, KEY_ALL_ACCESS, 0, &ghNewHKLM64, 0); if (!lRc) lRc = RegCreateKeyEx_f(ghNewKeyRoot, pszKeyName=L"HKLM64\\Software", 0,0,0, KEY_ALL_ACCESS, 0, &ghNewHKLM64Software, 0); } if (lRc != 0) { CloseRootKeys(); ghNewKeyRoot = (HKEY)-1; // чтобы не пытаться открыть повторно wchar_t szErrInfo[MAX_PATH]; msprintf(szErrInfo, countof(szErrInfo), L"ConEmuHk: Virtual subkey (%s) creation failed! ErrCode=0x%08X\n", pszKeyName ? pszKeyName : L"<NULL>", (DWORD)lRc); GuiMessageBox(ghConEmuWnd, szErrInfo, szTitle, MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); } // Для консистентности if (!ghNewHKLM64) ghNewHKLM64 = ghNewHKLM32; if (!ghNewHKLM64Software) ghNewHKLM64Software = ghNewHKLM32Software; } } if ((ghNewKeyRoot == NULL) || (ghNewKeyRoot == (HKEY)-1)) { DEBUGSTR(L"ConEmuHk: Registry virtualization failed!\n"); return false; } else { DEBUGSTR(L"ConEmuHk: Registry virtualization succeeded\n"); } return true; }
bool FindImageSubsystem(const wchar_t *Module, /*wchar_t* pstrDest,*/ DWORD& ImageSubsystem, DWORD& ImageBits, DWORD& FileAttrs) { if (!Module || !*Module) return false; bool Result = false; //ImageSubsystem = IMAGE_SUBSYSTEM_UNKNOWN; // Исключения нас не интересуют - команда уже сформирована и отдана в CreateProcess! //// нулевой проход - смотрим исключения //// Берем "исключения" из реестра, которые должны исполняться директом, //// например, некоторые внутренние команды ком. процессора. //string strExcludeCmds; //GetRegKey(strSystemExecutor,L"ExcludeCmds",strExcludeCmds,L""); //UserDefinedList ExcludeCmdsList; //ExcludeCmdsList.Set(strExcludeCmds); //while (!ExcludeCmdsList.IsEmpty()) //{ // if (!StrCmpI(Module,ExcludeCmdsList.GetNext())) // { // ImageSubsystem=IMAGE_SUBSYSTEM_WINDOWS_CUI; // Result=true; // break; // } //} //string strFullName=Module; LPCWSTR ModuleExt = PointToExt(Module); wchar_t *strPathExt/*[32767]*/ = NULL; //(L".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WSH"); wchar_t *strPathEnv/*[32767]*/ = NULL; wchar_t *strExpand/*[32767]*/ = NULL; wchar_t *strTmpName/*[32767]*/ = NULL; wchar_t *pszFilePart = NULL; DWORD nPathExtLen = 0; LPCWSTR pszPathExtEnd = NULL; LPWSTR Ext = NULL; typedef LONG (WINAPI *RegOpenKeyExW_t)(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); RegOpenKeyExW_t _RegOpenKeyEx = NULL; typedef LONG (WINAPI *RegQueryValueExW_t)(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); RegQueryValueExW_t _RegQueryValueEx = NULL; typedef LONG (WINAPI *RegCloseKey_t)(HKEY hKey); RegCloseKey_t _RegCloseKey = NULL; HMODULE hAdvApi = NULL; int cchstrPathExt = 32767; strPathExt = (wchar_t*)malloc(cchstrPathExt*sizeof(wchar_t)); *strPathExt = 0; int cchstrPathEnv = 32767; strPathEnv = (wchar_t*)malloc(cchstrPathEnv*sizeof(wchar_t)); *strPathEnv = 0; int cchstrExpand = 32767; strExpand = (wchar_t*)malloc(cchstrExpand*sizeof(wchar_t)); *strExpand = 0; int cchstrTmpName = 32767; strTmpName = (wchar_t*)malloc(cchstrTmpName*sizeof(wchar_t)); *strTmpName = 0; nPathExtLen = GetEnvironmentVariable(L"PATHEXT", strPathExt, cchstrPathExt-2); if (!nPathExtLen) { _wcscpy_c(strPathExt, cchstrPathExt, L".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WSH"); nPathExtLen = lstrlen(strPathExt); } pszPathExtEnd = strPathExt+nPathExtLen; // Разбить на токены strPathExt[nPathExtLen] = strPathExt[nPathExtLen+1] = 0; Ext = wcschr(strPathExt, L';'); while (Ext) { *Ext = 0; Ext = wcschr(Ext+1, L';'); } TODO("Проверить на превышение длин строк"); // первый проход - в текущем каталоге LPWSTR pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; _wcscpyn_c(strTmpName, cchstrTmpName, Module, cchstrTmpName); //-V501 if (!ModuleExt) { if (!*Ext) continue; _wcscatn_c(strTmpName, cchstrTmpName, Ext, cchstrTmpName); } if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits/*16/32/64*/, FileAttrs)) { Result = true; goto wrap; } if (ModuleExt) { break; } } // второй проход - по правилам SearchPath // поиск по переменной PATH if (GetEnvironmentVariable(L"PATH", strPathEnv, cchstrPathEnv)) { LPWSTR pszPathEnvEnd = strPathEnv + lstrlen(strPathEnv); LPWSTR pszPathCur = strPathEnv; while (pszPathCur && (pszPathCur < pszPathEnvEnd)) { LPWSTR Path = pszPathCur; LPWSTR pszPathNext = wcschr(pszPathCur, L';'); if (pszPathNext) { *pszPathNext = 0; pszPathCur = pszPathNext+1; } else { pszPathCur = pszPathEnvEnd; } if (!*Path) continue; pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; if (SearchPath(Path, Module, Ext, cchstrTmpName, strTmpName, &pszFilePart)) { if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } } } pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; if (SearchPath(NULL, Module, Ext, cchstrTmpName, strTmpName, &pszFilePart)) { if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } // третий проход - лезем в реестр в "App Paths" if (!wcschr(Module, L'\\')) { hAdvApi = LoadLibrary(L"AdvApi32.dll"); if (!hAdvApi) goto wrap; _RegOpenKeyEx = (RegOpenKeyExW_t)GetProcAddress(hAdvApi, "RegOpenKeyExW"); _RegQueryValueEx = (RegQueryValueExW_t)GetProcAddress(hAdvApi, "RegQueryValueExW"); _RegCloseKey = (RegCloseKey_t)GetProcAddress(hAdvApi, "RegCloseKey"); if (!_RegOpenKeyEx || !_RegQueryValueEx || !_RegCloseKey) goto wrap; LPCWSTR RegPath = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\"; // В строке Module заменить исполняемый модуль на полный путь, который // берется из SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths // Сначала смотрим в HKCU, затем - в HKLM HKEY RootFindKey[] = {HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_LOCAL_MACHINE}; BOOL lbAddExt = FALSE; pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { if (!lbAddExt) { Ext = NULL; lbAddExt = TRUE; } else { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; } _wcscpy_c(strTmpName, cchstrTmpName, RegPath); _wcscatn_c(strTmpName, cchstrTmpName, Module, cchstrTmpName); if (Ext) _wcscatn_c(strTmpName, cchstrTmpName, Ext, cchstrTmpName); DWORD samDesired = KEY_QUERY_VALUE; DWORD RedirectionFlag = 0; // App Paths key is shared in Windows 7 and above OSVERSIONINFO osv = {sizeof(OSVERSIONINFO)}; GetVersionEx(&osv); if (osv.dwMajorVersion < 6 || (osv.dwMajorVersion == 6 && osv.dwMinorVersion < 1)) { #ifdef _WIN64 RedirectionFlag = KEY_WOW64_32KEY; #else RedirectionFlag = IsWindows64() ? KEY_WOW64_64KEY : 0; #endif } for (size_t i = 0; i < countof(RootFindKey); i++) { if (i == (countof(RootFindKey)-1)) { if (RedirectionFlag) samDesired |= RedirectionFlag; else break; } HKEY hKey; if (_RegOpenKeyEx(RootFindKey[i], strTmpName, 0, samDesired, &hKey) == ERROR_SUCCESS) { DWORD nType = 0, nSize = sizeof(strTmpName)-2; int RegResult = _RegQueryValueEx(hKey, L"", NULL, &nType, (LPBYTE)strTmpName, &nSize); _RegCloseKey(hKey); if ((RegResult == ERROR_SUCCESS) && (nType == REG_SZ || nType == REG_EXPAND_SZ || nType == REG_MULTI_SZ)) { strTmpName[(nSize >> 1)+1] = 0; if (!ExpandEnvironmentStrings(strTmpName, strExpand, cchstrExpand)) _wcscpy_c(strExpand, cchstrExpand, strTmpName); if (GetImageSubsystem(Unquote(strExpand), ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } }
DWORD WINAPI DebugThread(LPVOID lpvParam) { DWORD nWait = WAIT_TIMEOUT; wchar_t szInfo[1024]; wchar_t szPID[20]; int iAttachedCount = 0; CEStr szOtherBitPids, szOtherDebugCmd; // Дополнительная инициализация, чтобы закрытие дебагера (наш процесс) не привело // к закрытию "отлаживаемой" программы pfnDebugActiveProcessStop = (FDebugActiveProcessStop)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugActiveProcessStop"); pfnDebugSetProcessKillOnExit = (FDebugSetProcessKillOnExit)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugSetProcessKillOnExit"); // Affect GetProcessHandleForDebug gpSrv->DbgInfo.bDebuggerActive = TRUE; // If dump was requested if (gpSrv->DbgInfo.nDebugDumpProcess) { gpSrv->DbgInfo.bUserRequestDump = TRUE; } // "/DEBUGEXE" or "/DEBUGTREE" 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); CEStr lsInfo(lstrmerge(szInfo, gpSrv->DbgInfo.pszDebuggingCmdLine, L"\n")); _wprintf(lsInfo); return CERR_CANTSTARTDEBUGGER; } gpSrv->hRootProcess = pi.hProcess; gpSrv->hRootThread = pi.hThread; gpSrv->dwRootProcess = pi.dwProcessId; gpSrv->dwRootThread = pi.dwThreadId; gpSrv->dwRootStartTime = GetTickCount(); // Let's know that at least one process is debugging iAttachedCount++; } /* ************************* */ int iDbgIdx = 0; bool bSetKillOnExit = true; while (true) { HANDLE hDbgProcess = NULL; DWORD nDbgProcessID = 0; if ((iDbgIdx++) == 0) { 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 /DEBUGEXE or /DEBUGTREE was used if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { _printf("Bitness of ConEmuC and debugging program does not match\n"); continue; } // Добавить процесс в список для запуска альтернативного дебаггера соотвествующей битности // Force trailing "," even if only one PID specified ( --> bDebugMultiProcess = TRUE) lstrmerge(&szOtherBitPids.ms_Arg, _itow(nDbgProcessID, szPID, 10), L","); // Может там еще процессы в списке на дамп? continue; } } if (gpSrv->DbgInfo.pszDebuggingCmdLine == NULL) { if (DebugActiveProcess(nDbgProcessID)) { iAttachedCount++; } else { 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); // Может другие подцепить получится? continue; } } // To avoid debugged processes killing if (bSetKillOnExit && pfnDebugSetProcessKillOnExit) { // affects all current and future debuggees connected to the calling thread if (pfnDebugSetProcessKillOnExit(FALSE/*KillOnExit*/)) { bSetKillOnExit = false; } } } // Different bitness, need to start appropriate debugger if (szOtherBitPids.ms_Arg && *szOtherBitPids.ms_Arg) { wchar_t szExe[MAX_PATH+5], *pszName; if (!GetModuleFileName(NULL, szExe, MAX_PATH)) { _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"GetModuleFileName(NULL) failed. ErrCode=0x%08X\n", GetLastError()); _wprintf(szInfo); } else if (!(pszName = (wchar_t*)PointToName(szExe))) { _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"GetModuleFileName(NULL) returns invalid path\n%s\n", szExe); _wprintf(szInfo); } else { *pszName = 0; // Reverted to current bitness wcscat_c(szExe, WIN3264TEST(L"ConEmuC64.exe", L"ConEmuC.exe")); szOtherDebugCmd.Attach(lstrmerge(L"\"", szExe, L"\" " L"/DEBUGPID=", szOtherBitPids.ms_Arg, (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, szOtherDebugCmd.ms_Arg, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { // Ждать не будем } else { DWORD dwErr = GetLastError(); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start external debugger, ErrCode=0x%08X\n", dwErr); CEStr lsInfo(lstrmerge(szInfo, szOtherDebugCmd, L"\n")); _wprintf(lsInfo); } } } //_ASSERTE(FALSE && "Continue to dump"); // If neither /DEBUG[EXE|TREE] nor /DEBUGPID was not succeeded if (iAttachedCount == 0) { gpSrv->DbgInfo.bDebuggerActive = FALSE; return CERR_CANTSTARTDEBUGGER; } else if (iAttachedCount > 1) { _ASSERTE(gpSrv->DbgInfo.bDebugMultiProcess && "Already must be set from arguments parser"); gpSrv->DbgInfo.bDebugMultiProcess = TRUE; } if (gpSrv->DbgInfo.bUserRequestDump) { gpSrv->DbgInfo.nWaitTreeBreaks = iAttachedCount; } /* **************** */ // To avoid debugged processes killing (JIC, must be called already) if (bSetKillOnExit && pfnDebugSetProcessKillOnExit) { // affects all current and future debuggees connected to the calling thread if (pfnDebugSetProcessKillOnExit(FALSE/*KillOnExit*/)) { bSetKillOnExit = false; } } 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; }