HWND CDefTermHk::AllocHiddenConsole(bool bTempForVS) { // функция AttachConsole есть только в WinXP и выше AttachConsole_t _AttachConsole = GetAttachConsoleProc(); if (!_AttachConsole) return NULL; DefTermMsg(L"AllocHiddenConsole"); ReloadSettings(); _ASSERTEX(isDefaultTerminalEnabled() && (gbIsNetVsHost || bTempForVS)); if (!isDefaultTerminalEnabled()) { // Disabled in settings or registry return NULL; } HANDLE hSrvProcess = NULL; DWORD nAttachPID = bTempForVS ? 0 : gnSelfPID; DWORD nSrvPID = StartConsoleServer(nAttachPID, true, &hSrvProcess); if (!nSrvPID) { // Failed to start process? return NULL; } _ASSERTEX(hSrvProcess!=NULL); HWND hCreatedCon = NULL; // Do while server process is alive DWORD nStart = GetTickCount(), nMaxDelta = 30000, nDelta = 0; DWORD nWait = WaitForSingleObject(hSrvProcess, 0); while (nWait != WAIT_OBJECT_0) { if (_AttachConsole(nSrvPID)) { hCreatedCon = GetRealConsoleWindow(); if (hCreatedCon) break; } nWait = WaitForSingleObject(hSrvProcess, 150); nDelta = (GetTickCount() - nStart); if (nDelta > nMaxDelta) break; } return hCreatedCon; }
void CDefTermHk::OnAllocConsoleFinished() { if (!gbPrepareDefaultTerminal || !this) { _ASSERTEX((gbPrepareDefaultTerminal && gpDefTerm) && "Must be called in DefTerm mode only"); return; } if (!ghConWnd || !IsWindow(ghConWnd)) { _ASSERTEX(FALSE && "ghConWnd must be initialized already!"); return; } ReloadSettings(); _ASSERTEX(isDefaultTerminalEnabled() && gbIsNetVsHost); if (!isDefaultTerminalEnabled()) { // Disabled in settings or registry return; } // По идее, после AllocConsole окно RealConsole всегда видимо BOOL bConWasVisible = IsWindowVisible(ghConWnd); _ASSERTEX(bConWasVisible); // Чтобы минимизировать "мелькания" - сразу спрячем его ShowWindow(ghConWnd, SW_HIDE); DefTermMsg(L"Console window hided"); if (!StartConsoleServer(gnSelfPID, false, NULL)) { if (bConWasVisible) ShowWindow(ghConWnd, SW_SHOW); DefTermMsg(L"Starting attach server failed?"); } }
BOOL WINAPI OnAllocConsole(void) { //typedef BOOL (WINAPI* OnAllocConsole_t)(void); ORIGINALFAST(AllocConsole); BOOL lbRc = FALSE, lbAllocated = FALSE; COORD crLocked; HMODULE hKernel = NULL; DWORD nErrCode = 0; BOOL lbAttachRc = FALSE; HWND hOldConWnd = GetRealConsoleWindow(); if (ph && ph->PreCallBack) { SETARGS(&lbRc); if (!ph->PreCallBack(&args)) return lbRc; } if (gbPrepareDefaultTerminal && gbIsNetVsHost) { if (!ghConWnd) gnVsHostStartConsole = 2; else gnVsHostStartConsole = 0; } // Попытаться создать консольное окно "по тихому" if (gpDefTerm && !hOldConWnd && !gnServerPID) { HWND hCreatedCon = gpDefTerm->AllocHiddenConsole(false); if (hCreatedCon) { hOldConWnd = hCreatedCon; lbAllocated = TRUE; } } // GUI приложение во вкладке. Если окна консоли еще нет - попробовать прицепиться // к родительской консоли (консоли серверного процесса) if ((gbAttachGuiClient || ghAttachGuiClient) && !gbPrepareDefaultTerminal) { if (AttachServerConsole()) { hOldConWnd = GetRealConsoleWindow(); lbAllocated = TRUE; // Консоль уже есть, ничего не надо } } DefTermMsg(L"AllocConsole calling"); if (!lbAllocated && F(AllocConsole)) { lbRc = F(AllocConsole)(); if (lbRc && !gbPrepareDefaultTerminal && IsVisibleRectLocked(crLocked)) { // Размер _видимой_ области. Консольным приложениям запрещено менять его "изнутри". // Размер может менять только пользователь ресайзом окна ConEmu HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi = {}; if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) { //specified width and height cannot be less than the width and height of the console screen buffer's window SMALL_RECT rNewRect = {0, 0, crLocked.X-1, crLocked.Y-1}; OnSetConsoleWindowInfo(hStdOut, TRUE, &rNewRect); #ifdef _DEBUG COORD crNewSize = {crLocked.X, max(crLocked.Y, csbi.dwSize.Y)}; #endif hkFunc.setConsoleScreenBufferSize(hStdOut, crLocked); } } } //InitializeConsoleInputSemaphore(); if (ph && ph->PostCallBack) { SETARGS(&lbRc); ph->PostCallBack(&args); } HWND hNewConWnd = GetRealConsoleWindow(); // Обновить ghConWnd и мэппинг OnConWndChanged(hNewConWnd); #ifdef _DEBUG //_ASSERTEX(lbRc && ghConWnd); wchar_t szAlloc[500], szFile[MAX_PATH]; GetModuleFileName(NULL, szFile, countof(szFile)); msprintf(szAlloc, countof(szAlloc), L"OnAllocConsole\nOld=x%08X, New=x%08X, ghConWnd=x%08X\ngbPrepareDefaultTerminal=%i, gbIsNetVsHost=%i\n%s", LODWORD(hOldConWnd), LODWORD(hNewConWnd), LODWORD(ghConWnd), gbPrepareDefaultTerminal, gbIsNetVsHost, szFile); // VisualStudio host file calls AllocConsole TWICE(!) // Second call is totally spare (console already created) //MessageBox(NULL, szAlloc, L"OnAllocConsole called", MB_SYSTEMMODAL); #endif if (hNewConWnd && (hNewConWnd != hOldConWnd) && gpDefTerm && gbIsNetVsHost) { DefTermMsg(L"Calling gpDefTerm->OnAllocConsoleFinished"); gpDefTerm->OnAllocConsoleFinished(); SetLastError(0); } else if (hNewConWnd) { DefTermMsg(L"Console was already allocated"); } else { DefTermMsg(L"Something was wrong"); } TODO("Можно бы по настройке установить параметры. Кодовую страницу, например"); return lbRc; }
void CDefTermHk::ShowTrayIconError(LPCWSTR asErrText) { LogHookingStatus(asErrText); DefTermMsg(asErrText); }
BOOL WINAPI OnShowWindow(HWND hWnd, int nCmdShow) { //typedef BOOL (WINAPI* OnShowWindow_t)(HWND hWnd, int nCmdShow); ORIGINAL_EX(ShowWindow); BOOL lbRc = FALSE, lbGuiAttach = FALSE, lbInactiveTab = FALSE; static bool bShowWndCalled = false; if (gbPrepareDefaultTerminal && ghConWnd && (hWnd == ghConWnd) && nCmdShow && (gnVsHostStartConsole > 0)) { DefTermMsg(L"ShowWindow(hConWnd) calling"); nCmdShow = SW_HIDE; gnVsHostStartConsole--; } if (ghConEmuWndDC && (hWnd == ghConEmuWndDC || hWnd == ghConWnd)) { #ifdef _DEBUG if (hWnd == ghConEmuWndDC) { static bool bShowWarned = false; if (!bShowWarned) { bShowWarned = true; _ASSERTE(hWnd != ghConEmuWndDC && L"OnShowWindow(ghConEmuWndDC)"); } } else { static bool bShowWarned = false; if (!bShowWarned) { bShowWarned = true; _ASSERTE(hWnd != ghConEmuWndDC && L"OnShowWindow(ghConWnd)"); } } #endif return TRUE; // обманем } if ((ghAttachGuiClient == hWnd) || (!ghAttachGuiClient && gbAttachGuiClient)) OnShowGuiClientWindow(hWnd, nCmdShow, lbGuiAttach, lbInactiveTab); if (F(ShowWindow)) { lbRc = F(ShowWindow)(hWnd, nCmdShow); // Первый вызов может быть обломным, из-за того, что корневой процесс // запускается с wShowCmd=SW_HIDE (чтобы не мелькал) if (!bShowWndCalled) { bShowWndCalled = true; if (!lbRc && nCmdShow && !IsWindowVisible(hWnd)) { F(ShowWindow)(hWnd, nCmdShow); } } // Если вкладка НЕ активная - то вернуть фокус в ConEmu if (lbGuiAttach && lbInactiveTab && nCmdShow && ghConEmuWnd) { SetForegroundWindow(ghConEmuWnd); } } DWORD dwErr = GetLastError(); if (lbGuiAttach) OnPostShowGuiClientWindow(hWnd, nCmdShow); SetLastError(dwErr); return lbRc; }
void CDefTermHk::ShowTrayIconError(LPCWSTR asErrText) { DefTermMsg(asErrText); }
int CDefTermHk::DisplayLastError(LPCWSTR asLabel, DWORD dwError/*=0*/, DWORD dwMsgFlags/*=0*/, LPCWSTR asTitle/*=NULL*/, HWND hParent/*=NULL*/) { DefTermMsg(asLabel); return 0; }