DWORD WINAPI OnGetConsoleAliasesW(LPWSTR AliasBuffer, DWORD AliasBufferLength, LPWSTR ExeName) { //typedef DWORD (WINAPI* OnGetConsoleAliasesW_t)(LPWSTR AliasBuffer, DWORD AliasBufferLength, LPWSTR ExeName); ORIGINALFAST(GetConsoleAliasesW); DWORD nError = 0; DWORD nRc = F(GetConsoleAliasesW)(AliasBuffer,AliasBufferLength,ExeName); if (!nRc) { nError = GetLastError(); // финт ушами if (nError == ERROR_NOT_ENOUGH_MEMORY) // && gdwServerPID) { DWORD nServerPID = gnServerPID; HWND hConWnd = GetRealConsoleWindow(); _ASSERTE(hConWnd == ghConWnd); //MFileMapping<CESERVER_CONSOLE_MAPPING_HDR> ConInfo; //ConInfo.InitName(CECONMAPNAME, (DWORD)hConWnd); //-V205 //CESERVER_CONSOLE_MAPPING_HDR *pInfo = ConInfo.Open(); //if (pInfo // && (pInfo->cbSize >= sizeof(CESERVER_CONSOLE_MAPPING_HDR)) // //&& (pInfo->nProtocolVersion == CESERVER_REQ_VER) // ) //{ // nServerPID = pInfo->nServerPID; // ConInfo.CloseMap(); //} if (nServerPID) { CESERVER_REQ_HDR In; ExecutePrepareCmd(&In, CECMD_GETALIASES, sizeof(CESERVER_REQ_HDR)); CESERVER_REQ* pOut = ExecuteSrvCmd(nServerPID/*gdwServerPID*/, (CESERVER_REQ*)&In, hConWnd); if (pOut) { size_t nData = min(AliasBufferLength,(pOut->hdr.cbSize-sizeof(pOut->hdr))); if (nData) { memmove(AliasBuffer, pOut->Data, nData); nRc = TRUE; } ExecuteFreeResult(pOut); } } } if (!nRc) SetLastError(nError); // вернуть, вдруг какая функция его поменяла } return nRc; }
void SendStopped() { if (gbNonGuiMode || !gnServerPID) return; CESERVER_REQ *pIn = NULL, *pOut = NULL; size_t nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOP); pIn = ExecuteNewCmd(CECMD_CMDSTARTSTOP,nSize); if (pIn) { pIn->StartStop.nStarted = sst_AppStop; if (!GetModuleFileName(NULL, pIn->StartStop.sModuleName, countof(pIn->StartStop.sModuleName))) pIn->StartStop.sModuleName[0] = 0; pIn->StartStop.hWnd = ghConWnd; pIn->StartStop.dwPID = gnSelfPID; pIn->StartStop.nSubSystem = gnImageSubsystem; pIn->StartStop.bWasBufferHeight = gbWasBufferHeight; pIn->StartStop.nOtherPID = gnPrevAltServerPID; HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // НЕ MyGet..., а то можем заблокироваться... // ghConOut может быть NULL, если ошибка произошла во время разбора аргументов GetConsoleScreenBufferInfo(hOut, &pIn->StartStop.sbi); pIn->StartStop.crMaxSize = MyGetLargestConsoleWindowSize(hOut); pOut = ExecuteSrvCmd(gnServerPID, pIn, ghConWnd, TRUE/*bAsyncNoResult*/); ExecuteFreeResult(pIn); pIn = NULL; if (pOut) { ExecuteFreeResult(pOut); pOut = NULL; } } }
// 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; }
void ComspecDone(int aiRc) { #ifdef _DEBUG xf_dump_chk(); xf_validate(NULL); #endif //WARNING("Послать в GUI CONEMUCMDSTOPPED"); LogSize(NULL, 0, "ComspecDone"); // Это необходимо делать, т.к. при смене буфера (SetConsoleActiveScreenBuffer) приложением, // дескриптор нужно закрыть, иначе conhost может не вернуть предыдущий буфер //ConOutCloseHandle() // Поддержка алиасов if (gpSrv->szComSpecName[0] && gpSrv->szSelfName[0]) { // Скопировать алиасы из cmd.exe в conemuc.exe wchar_t *pszPostAliases = NULL; DWORD nPostAliasSize; BOOL lbChanged = (gpSrv->pszPreAliases == NULL); if (!GetAliases(gpSrv->szComSpecName, &pszPostAliases, &nPostAliasSize)) { if (pszPostAliases) _wprintf(pszPostAliases); } else { if (!lbChanged) { lbChanged = (gpSrv->nPreAliasSize!=nPostAliasSize); } if (!lbChanged && gpSrv->nPreAliasSize && gpSrv->pszPreAliases && pszPostAliases) { lbChanged = memcmp(gpSrv->pszPreAliases,pszPostAliases,gpSrv->nPreAliasSize)!=0; } if (lbChanged) { xf_dump_chk(); if (gnMainServerPID) { MCHKHEAP; CESERVER_REQ* pIn = ExecuteNewCmd(CECMD_SAVEALIASES,sizeof(CESERVER_REQ_HDR)+nPostAliasSize); if (pIn) { MCHKHEAP; memmove(pIn->Data, pszPostAliases, nPostAliasSize); MCHKHEAP; CESERVER_REQ* pOut = ExecuteSrvCmd(gnMainServerPID, pIn, GetConEmuHWND(2), FALSE, 0, TRUE); MCHKHEAP; if (pOut) ExecuteFreeResult(pOut); ExecuteFreeResult(pIn); MCHKHEAP; } } xf_dump_chk(); wchar_t *pszNewName = pszPostAliases, *pszNewTarget, *pszNewLine; while (pszNewName && *pszNewName) { pszNewLine = pszNewName + lstrlen(pszNewName); pszNewTarget = wcschr(pszNewName, L'='); if (pszNewTarget) { *pszNewTarget = 0; pszNewTarget++; } if (*pszNewTarget == 0) pszNewTarget = NULL; AddConsoleAlias(pszNewName, pszNewTarget, gpSrv->szSelfName); pszNewName = pszNewLine+1; } xf_dump_chk(); } } if (pszPostAliases) { free(pszPostAliases); pszPostAliases = NULL; } } xf_dump_chk(); //TODO("Уведомить плагин через пайп (если родитель - FAR) что процесс завершен. Плагин должен считать и запомнить содержимое консоли и только потом вернуть управление в ConEmuC!"); DWORD dwErr1 = 0; //, dwErr2 = 0; HANDLE hOut1 = NULL, hOut2 = NULL; BOOL lbRc1 = FALSE, lbRc2 = FALSE; CONSOLE_SCREEN_BUFFER_INFO sbi1 = {{0,0}}, sbi2 = {{0,0}}; #ifdef _DEBUG HWND hWndCon = GetConEmuHWND(2); #endif // Тут нужна реальная, а не скорректированная информация! if (!gbNonGuiMode) { // Если GUI не сможет через сервер вернуть высоту буфера - это нужно сделать нам! lbRc1 = GetConsoleScreenBufferInfo(hOut1 = GetStdHandle(STD_OUTPUT_HANDLE), &sbi1); if (!lbRc1) dwErr1 = GetLastError(); xf_dump_chk(); } //PRAGMA_ERROR("Размер должен возвращать сам GUI, через серверный ConEmuC!"); #ifdef SHOW_STARTED_MSGBOX MessageBox(GetConEmuHWND(2), L"ConEmuC (comspec mode) is about to TERMINATE", L"ConEmuC.ComSpec", 0); #endif #ifdef _DEBUG xf_dump_chk(); xf_validate(NULL); #endif if (!gbNonGuiMode && (gpSrv->dwParentFarPID != 0)) { //// Вернуть размер буфера (высота И ширина) //if (gpSrv->sbi.dwSize.X && gpSrv->sbi.dwSize.Y) { // SMALL_RECT rc = {0}; // SetConsoleSize(0, gpSrv->sbi.dwSize, rc, "ComspecDone"); //} //ConOutCloseHandle() CONSOLE_SCREEN_BUFFER_INFO l_csbi = {{0}}; lbRc2 = GetConsoleScreenBufferInfo(hOut2 = GetStdHandle(STD_OUTPUT_HANDLE), &l_csbi); CESERVER_REQ *pOut = SendStopped(&l_csbi); if (pOut) { if (!pOut->StartStopRet.bWasBufferHeight) { //gpSrv->sbi.dwSize = pIn->StartStop.sbi.dwSize; lbRc1 = FALSE; // Консольное приложение самостоятельно сбросило буферный режим. Не дергаться... } else { lbRc1 = TRUE; } ExecuteFreeResult(pOut); pOut = NULL; } if (!gbWasBufferHeight) { lbRc2 = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi2); #ifdef _DEBUG if (sbi2.dwSize.Y > 200) { wchar_t szTitle[128]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmuC (PID=%i)", GetCurrentProcessId()); MessageBox(NULL, L"BufferHeight was not turned OFF", szTitle, MB_SETFOREGROUND|MB_SYSTEMMODAL); } #endif if (lbRc1 && lbRc2 && sbi2.dwSize.Y == sbi1.dwSize.Y) { // GUI не смог вернуть высоту буфера... // Это плохо, т.к. фар высоту буфера не меняет и будет сильно глючить на N сотнях строк... int nNeedHeight = gpSrv->sbi.dwSize.Y; if (nNeedHeight < 10) { nNeedHeight = (sbi2.srWindow.Bottom-sbi2.srWindow.Top+1); } if (sbi2.dwSize.Y != nNeedHeight) { _ASSERTE(sbi2.dwSize.Y == nNeedHeight); PRINT_COMSPEC(L"Error: BufferHeight was not changed from %i\n", sbi2.dwSize.Y); SMALL_RECT rc = {0}; sbi2.dwSize.Y = nNeedHeight; if (gpLogSize) LogSize(&sbi2.dwSize, 0, ":ComspecDone.RetSize.before"); SetConsoleSize(0, sbi2.dwSize, rc, "ComspecDone.Force"); if (gpLogSize) LogSize(NULL, 0, ":ComspecDone.RetSize.after"); } } } } if (gpSrv->pszPreAliases) { free(gpSrv->pszPreAliases); gpSrv->pszPreAliases = NULL; } //SafeCloseHandle(ghCtrlCEvent); //SafeCloseHandle(ghCtrlBreakEvent); }
// Due to Microsoft bug we need to lock Server reading thread to avoid crash of kernel // http://conemu.github.io/en/MicrosoftBugs.html#Exception_in_ReadConsoleOutput void LockServerReadingThread(bool bLock, COORD dwSize, CESERVER_REQ*& pIn, CESERVER_REQ*& pOut) { DWORD nServerPID = gnServerPID; if (!nServerPID) return; DWORD nErrSave = GetLastError(); if (bLock) { HANDLE hOurThreadHandle = NULL; // We need to give our thread handle (to server process) to avoid // locking of server reading thread (in case of our thread fails) DWORD dwErr = -1; HANDLE hServer = OpenProcess(PROCESS_DUP_HANDLE, FALSE, nServerPID); if (!hServer) { dwErr = GetLastError(); _ASSERTEX(hServer!=NULL && "Open server handle fails, Can't dup handle!"); } else { if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), hServer, &hOurThreadHandle, SYNCHRONIZE|THREAD_QUERY_INFORMATION, FALSE, 0)) { dwErr = GetLastError(); _ASSERTEX(hServer!=NULL && "DuplicateHandle fails, Can't dup handle!"); hOurThreadHandle = NULL; } CloseHandle(hServer); } pIn = ExecuteNewCmd(CECMD_SETCONSCRBUF, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SETCONSCRBUF)); if (pIn) { pIn->SetConScrBuf.bLock = TRUE; pIn->SetConScrBuf.dwSize = dwSize; // Informational pIn->SetConScrBuf.hRequestor = hOurThreadHandle; } } else { if (pIn) { pIn->SetConScrBuf.bLock = FALSE; } } if (pIn) { ExecuteFreeResult(pOut); pOut = ExecuteSrvCmd(nServerPID, pIn, ghConWnd); if (pOut && pOut->DataSize() >= sizeof(CESERVER_REQ_SETCONSCRBUF)) { pIn->SetConScrBuf.hTemp = pOut->SetConScrBuf.hTemp; } } if (!bLock) { ExecuteFreeResult(pIn); ExecuteFreeResult(pOut); } // Transparently to calling function... SetLastError(nErrSave); }
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; }
void SendStarted() { if (gnServerPID == 0) { gbNonGuiMode = TRUE; // Не посылать ExecuteGuiCmd при выходе. Это не наша консоль return; // Режим ComSpec, но сервера нет, соответственно, в GUI ничего посылать не нужно } CESERVER_REQ *pIn = NULL, *pOut = NULL; size_t nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOP); //-V119 pIn = ExecuteNewCmd(CECMD_CMDSTARTSTOP, nSize); if (pIn) { if (!GetModuleFileName(NULL, pIn->StartStop.sModuleName, countof(pIn->StartStop.sModuleName))) pIn->StartStop.sModuleName[0] = 0; #ifdef _DEBUG LPCWSTR pszFileName = wcsrchr(pIn->StartStop.sModuleName, L'\\'); #endif pIn->StartStop.nStarted = sst_AppStart; pIn->StartStop.hWnd = ghConWnd; pIn->StartStop.dwPID = gnSelfPID; pIn->StartStop.nImageBits = WIN3264TEST(32,64); pIn->StartStop.nSubSystem = gnImageSubsystem; //pIn->StartStop.bRootIsCmdExe = gbRootIsCmdExe; //2009-09-14 // НЕ MyGet..., а то можем заблокироваться... HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hOut, &pIn->StartStop.sbi); gbWasBufferHeight = (pIn->StartStop.sbi.dwSize.Y > (pIn->StartStop.sbi.srWindow.Bottom - pIn->StartStop.sbi.srWindow.Top + 100)); pIn->StartStop.crMaxSize = MyGetLargestConsoleWindowSize(hOut); BOOL bAsync = FALSE; if (ghConWnd && (gnGuiPID != 0) && (gnImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)) bAsync = TRUE; pOut = ExecuteSrvCmd(gnServerPID, pIn, ghConWnd, bAsync); if (bAsync || pOut) { if (pOut) { gbWasBufferHeight = pOut->StartStopRet.bWasBufferHeight; gnGuiPID = pOut->StartStopRet.dwPID; ghConEmuWnd = pOut->StartStopRet.hWnd; _ASSERTE(ghConEmuWnd==NULL || gnGuiPID!=0); ghConEmuWndDC = pOut->StartStopRet.hWndDC; _ASSERTE(ghConEmuWndDC && user->isWindow(ghConEmuWndDC)); gnServerPID = pOut->StartStopRet.dwMainSrvPID; ExecuteFreeResult(pOut); pOut = NULL; } } else { gbNonGuiMode = TRUE; // Не посылать ExecuteGuiCmd при выходе. Это не наша консоль } ExecuteFreeResult(pIn); pIn = NULL; } }