BOOL IsVisibleRectLocked(COORD& crLocked) { CESERVER_CONSOLE_MAPPING_HDR SrvMap; if (LoadSrvMapping(ghConWnd, SrvMap)) { if (SrvMap.bLockVisibleArea && (SrvMap.crLockedVisible.X > 0) && (SrvMap.crLockedVisible.Y > 0)) { crLocked = SrvMap.crLockedVisible; return TRUE; } } return FALSE; }
bool DoStateCheck(ConEmuStateCheck eStateCheck) { LogFunction(L"DoStateCheck"); bool bOn = false; switch (eStateCheck) { case ec_IsConEmu: case ec_IsAnsi: if (ghConWnd) { CESERVER_CONSOLE_MAPPING_HDR* pInfo = (CESERVER_CONSOLE_MAPPING_HDR*)malloc(sizeof(*pInfo)); if (pInfo && LoadSrvMapping(ghConWnd, *pInfo)) { _ASSERTE(pInfo->ComSpec.ConEmuExeDir[0] && pInfo->ComSpec.ConEmuBaseDir[0]); HWND hWnd = pInfo->hConEmuWndDc; if (hWnd && IsWindow(hWnd)) { switch (eStateCheck) { case ec_IsConEmu: bOn = true; break; case ec_IsAnsi: bOn = ((pInfo->Flags & CECF_ProcessAnsi) != 0); break; default: ; } } } SafeFree(pInfo); } break; case ec_IsAdmin: bOn = IsUserAdmin(); break; case ec_IsRedirect: bOn = IsOutputRedirected(); break; case ec_IsTerm: bOn = isTerminalMode(); break; default: _ASSERTE(FALSE && "Unsupported StateCheck code"); } return bOn; }
// Do the attach procedure for the requested process bool CAttachDlg::StartAttach(HWND ahAttachWnd, DWORD anPID, DWORD anBits, AttachProcessType anType, BOOL abAltMode) { bool lbRc = false; wchar_t szPipe[MAX_PATH]; PROCESS_INFORMATION pi = {}; STARTUPINFO si = {sizeof(si)}; SHELLEXECUTEINFO sei = {sizeof(sei)}; CESERVER_REQ *pIn = NULL, *pOut = NULL; HANDLE hPipeTest = NULL; HANDLE hPluginTest = NULL; HANDLE hProcTest = NULL; DWORD nErrCode = 0; bool lbCreate; CESERVER_CONSOLE_MAPPING_HDR srv; DWORD nWrapperWait = -1; DWORD nWrapperResult = -1; if (!ahAttachWnd || !anPID || !anBits || !anType) { MBoxAssert(ahAttachWnd && anPID && anBits && anType); goto wrap; } if (gpSetCls->isAdvLogging) { wchar_t szInfo[128]; _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"CAttachDlg::StartAttach HWND=x%08X, PID=%u, Bits%u, Type=%u, AltMode=%u", (DWORD)(DWORD_PTR)ahAttachWnd, anPID, anBits, (UINT)anType, abAltMode); gpConEmu->LogString(szInfo); } if (LoadSrvMapping(ahAttachWnd, srv)) { pIn = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR)); pOut = ExecuteSrvCmd(srv.nServerPID, pIn, ghWnd); if (pOut && (pOut->hdr.cbSize >= (sizeof(CESERVER_REQ_HDR)+sizeof(DWORD))) && (pOut->dwData[0] != 0)) { // Our console server had been already started // and we successfully have completed the attach lbRc = true; goto wrap; } ExecuteFreeResult(pIn); ExecuteFreeResult(pOut); } // Is it a Far Manager with our ConEmu.dll plugin loaded? _wsprintf(szPipe, SKIPLEN(countof(szPipe)) CEPLUGINPIPENAME, L".", anPID); hPluginTest = CreateFile(szPipe, GENERIC_READ|GENERIC_WRITE, 0, LocalSecurity(), OPEN_EXISTING, 0, NULL); if (hPluginTest && hPluginTest != INVALID_HANDLE_VALUE) { CloseHandle(hPluginTest); goto DoPluginCall; } // May be there is already ConEmuHk[64].dll loaded? Either it is already in the another ConEmu VCon? _wsprintf(szPipe, SKIPLEN(countof(szPipe)) CEHOOKSPIPENAME, L".", anPID); hPipeTest = CreateFile(szPipe, GENERIC_READ|GENERIC_WRITE, 0, LocalSecurity(), OPEN_EXISTING, 0, NULL); if (hPipeTest && hPipeTest != INVALID_HANDLE_VALUE) { CloseHandle(hPipeTest); goto DoExecute; } wchar_t szSrv[MAX_PATH+64], szArgs[128]; wcscpy_c(szSrv, gpConEmu->ms_ConEmuBaseDir); wcscat_c(szSrv, (anBits==64) ? L"\\ConEmuC64.exe" : L"\\ConEmuC.exe"); if (abAltMode && (anType == apt_Console)) { _wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /ATTACH /CONPID=%u /GID=%u /GHWND=%08X", anPID, GetCurrentProcessId(), LODWORD(ghWnd)); } else { _wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /INJECT=%u", anPID); abAltMode = FALSE; } si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; if (anType == apt_Gui) { gpConEmu->CreateGuiAttachMapping(anPID); } hProcTest = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, anPID); // If the attaching process is running as admin (elevated) we have to run ConEmuC as admin too if (hProcTest == NULL) { nErrCode = GetLastError(); MBoxAssert(hProcTest!=NULL || nErrCode==ERROR_ACCESS_DENIED); sei.hwnd = ghWnd; sei.fMask = (abAltMode ? 0 : SEE_MASK_NO_CONSOLE)|SEE_MASK_NOCLOSEPROCESS|SEE_MASK_NOASYNC; sei.lpVerb = L"runas"; sei.lpFile = szSrv; sei.lpParameters = szArgs; sei.lpDirectory = gpConEmu->ms_ConEmuBaseDir; sei.nShow = SW_SHOWMINIMIZED; lbCreate = ShellExecuteEx(&sei); if (lbCreate) { MBoxAssert(sei.hProcess!=NULL); pi.hProcess = sei.hProcess; } } else { // Normal start DWORD dwFlags = 0 | (abAltMode ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE) | CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS; lbCreate = CreateProcess(szSrv, szArgs, NULL, NULL, FALSE, dwFlags, NULL, NULL, &si, &pi); } if (!lbCreate) { wchar_t szErrMsg[MAX_PATH+255], szTitle[128]; DWORD dwErr = GetLastError(); _wsprintf(szErrMsg, SKIPLEN(countof(szErrMsg)) L"Can't start %s server\n%s %s", abAltMode ? L"injection" : L"console", szSrv, szArgs); _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); DisplayLastError(szErrMsg, dwErr, 0, szTitle); goto wrap; } if (abAltMode) { lbRc = true; goto wrap; } nWrapperWait = WaitForSingleObject(pi.hProcess, INFINITE); nWrapperResult = -1; GetExitCodeProcess(pi.hProcess, &nWrapperResult); CloseHandle(pi.hProcess); if (pi.hThread) CloseHandle(pi.hThread); if (((int)nWrapperResult != CERR_HOOKS_WAS_SET) && ((int)nWrapperResult != CERR_HOOKS_WAS_ALREADY_SET)) { goto wrap; } DoExecute: // Not the attaching process has our ConEmuHk[64].dll loaded // and we can request to start console server for that console or ChildGui pIn = ExecuteNewCmd(CECMD_STARTSERVER, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START)); pIn->NewServer.nGuiPID = GetCurrentProcessId(); pIn->NewServer.hGuiWnd = ghWnd; if (anType == apt_Gui) { _ASSERTE(ahAttachWnd && IsWindow(ahAttachWnd)); pIn->NewServer.hAppWnd = ahAttachWnd; } goto DoPipeCall; DoPluginCall: // Ask Far Manager plugin to do the attach pIn = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR)); goto DoPipeCall; DoPipeCall: pOut = ExecuteCmd(szPipe, pIn, 500, ghWnd); if (!pOut || (pOut->hdr.cbSize < pIn->hdr.cbSize) || (pOut->dwData[0] == 0)) { _ASSERTE(pOut && pOut->hdr.cbSize == (sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START))); wchar_t szMsg[255], szTitle[128]; wcscpy_c(szMsg, L"Failed to start console server in the remote process"); if (hPluginTest && hPluginTest != INVALID_HANDLE_VALUE) wcscat_c(szMsg, L"\nFar ConEmu plugin was loaded"); if (hPipeTest && hPipeTest != INVALID_HANDLE_VALUE) wcscat_c(szMsg, L"\nHooks already were set"); _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); DisplayLastError(szMsg, (pOut && (pOut->hdr.cbSize >= pIn->hdr.cbSize)) ? pOut->dwData[1] : -1, 0, szTitle); goto wrap; } lbRc = true; wrap: SafeCloseHandle(hProcTest); UNREFERENCED_PARAMETER(nErrCode); UNREFERENCED_PARAMETER(nWrapperWait); ExecuteFreeResult(pIn); ExecuteFreeResult(pOut); return lbRc; }
bool CAttachDlg::StartAttach(HWND ahAttachWnd, DWORD anPID, DWORD anBits, AttachProcessType anType, BOOL abAltMode) { bool lbRc = false; // Тут нужно получить инфу из списка и дернуть собственно аттач wchar_t szPipe[MAX_PATH]; PROCESS_INFORMATION pi = {}; STARTUPINFO si = {sizeof(si)}; SHELLEXECUTEINFO sei = {sizeof(sei)}; CESERVER_REQ *pIn = NULL, *pOut = NULL; HANDLE hPipeTest = NULL, hProcTest = NULL; DWORD nErrCode = 0; bool lbCreate; CESERVER_CONSOLE_MAPPING_HDR srv; DWORD nWrapperWait = -1; DWORD nWrapperResult = -1; if (!ahAttachWnd || !anPID || !anBits || !anType) { MBoxAssert(ahAttachWnd && anPID && anBits && anType); goto wrap; } if (gpSetCls->isAdvLogging) { wchar_t szInfo[128]; _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"CAttachDlg::StartAttach HWND=x%08X, PID=%u, Bits%u, Type=%u, AltMode=%u", (DWORD)(DWORD_PTR)ahAttachWnd, anPID, anBits, (UINT)anType, abAltMode); gpConEmu->LogString(szInfo); } if (LoadSrvMapping(ahAttachWnd, srv)) { pIn = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR)); pOut = ExecuteSrvCmd(srv.nServerPID, pIn, ghWnd); if (pOut && (pOut->hdr.cbSize >= (sizeof(CESERVER_REQ_HDR)+sizeof(DWORD))) && (pOut->dwData[0] != 0)) { lbRc = true; // Успешно подцепились goto wrap; } ExecuteFreeResult(pIn); ExecuteFreeResult(pOut); } // Может быть в процессе уже есть ConEmuHk.dll? Или этот процесс вообще уже во вкладке другого ConEmu? _wsprintf(szPipe, SKIPLEN(countof(szPipe)) CEHOOKSPIPENAME, L".", anPID); hPipeTest = CreateFile(szPipe, GENERIC_READ|GENERIC_WRITE, 0, LocalSecurity(), OPEN_EXISTING, 0, NULL); if (hPipeTest && hPipeTest != INVALID_HANDLE_VALUE) { CloseHandle(hPipeTest); goto DoExecute; } wchar_t szSrv[MAX_PATH+64], szArgs[128]; wcscpy_c(szSrv, gpConEmu->ms_ConEmuBaseDir); wcscat_c(szSrv, (anBits==64) ? L"\\ConEmuC64.exe" : L"\\ConEmuC.exe"); if (abAltMode && (anType == apt_Console)) { _wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /ATTACH /CONPID=%u /GID=%u /GHWND=%08X", anPID, GetCurrentProcessId(), (DWORD)ghWnd); } else { _wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /INJECT=%u", anPID); abAltMode = FALSE; } TODO("Определить, может он уже под админом? Тогда и ConEmuC.exe под админом запускать нужно"); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; if (anType == apt_Gui) { gpConEmu->CreateGuiAttachMapping(anPID); } hProcTest = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, anPID); if (hProcTest == NULL) { nErrCode = GetLastError(); MBoxAssert(hProcTest!=NULL || nErrCode==ERROR_ACCESS_DENIED); sei.hwnd = ghWnd; sei.fMask = (abAltMode ? 0 : SEE_MASK_NO_CONSOLE)|SEE_MASK_NOCLOSEPROCESS|SEE_MASK_NOASYNC; sei.lpVerb = L"runas"; sei.lpFile = szSrv; sei.lpParameters = szArgs; sei.lpDirectory = gpConEmu->ms_ConEmuBaseDir; sei.nShow = SW_SHOWMINIMIZED; lbCreate = ShellExecuteEx(&sei); if (lbCreate) { MBoxAssert(sei.hProcess!=NULL); pi.hProcess = sei.hProcess; } } else { lbCreate = CreateProcess(szSrv, szArgs, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|(abAltMode ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE), NULL, NULL, &si, &pi); } if (!lbCreate) { wchar_t szErrMsg[MAX_PATH+255], szTitle[128]; DWORD dwErr = GetLastError(); _wsprintf(szErrMsg, SKIPLEN(countof(szErrMsg)) L"Can't start %s server\n%s %s", abAltMode ? L"injection" : L"console", szSrv, szArgs); _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); DisplayLastError(szErrMsg, dwErr, 0, szTitle); goto wrap; } if (abAltMode) { TODO("Подождать бы завершения процесса, или пока он подцепится к GUI"); lbRc = true; goto wrap; } nWrapperWait = WaitForSingleObject(pi.hProcess, INFINITE); nWrapperResult = -1; GetExitCodeProcess(pi.hProcess, &nWrapperResult); CloseHandle(pi.hProcess); if (pi.hThread) CloseHandle(pi.hThread); if (((int)nWrapperResult != CERR_HOOKS_WAS_SET) && ((int)nWrapperResult != CERR_HOOKS_WAS_ALREADY_SET)) { goto wrap; } DoExecute: // Теперь можно дернуть созданный в удаленном процессе пайп для запуска в той консоли сервера. pIn = ExecuteNewCmd(CECMD_STARTSERVER, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START)); pIn->NewServer.nGuiPID = GetCurrentProcessId(); pIn->NewServer.hGuiWnd = ghWnd; if (anType == apt_Gui) { _ASSERTE(ahAttachWnd && IsWindow(ahAttachWnd)); pIn->NewServer.hAppWnd = ahAttachWnd; } pOut = ExecuteCmd(szPipe, pIn, 500, ghWnd); if (!pOut || (pOut->hdr.cbSize < pIn->hdr.cbSize) || (pOut->dwData[0] == 0)) { _ASSERTE(pOut && pOut->hdr.cbSize == (sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START))); wchar_t szMsg[255], szTitle[128]; wcscpy_c(szMsg, L"Failed to start console server in the remote process"); if (hPipeTest && hPipeTest != INVALID_HANDLE_VALUE) wcscat_c(szMsg, L"\nHooks already was set"); _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); DisplayLastError(szMsg, (pOut && (pOut->hdr.cbSize >= pIn->hdr.cbSize)) ? pOut->dwData[1] : -1, 0, szTitle); goto wrap; } lbRc = true; wrap: UNREFERENCED_PARAMETER(nErrCode); UNREFERENCED_PARAMETER(nWrapperWait); ExecuteFreeResult(pIn); ExecuteFreeResult(pOut); return lbRc; }