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"); // Юзер может чего-то свое делать с распакованными файлами }
// IDYES - Close All consoles // IDNO - Close active console only // IDCANCEL - As is int ConfirmCloseConsoles(const ConfirmCloseParam& Parm) { DontEnable de; wchar_t szText[512], *pszText; int nBtn = IDCANCEL; static LONG lCounter = 0; LONG l = InterlockedIncrement(&lCounter); if (l > 1) { if (l == 2) { _ASSERTE(FALSE && "Confirm stack overflow!"); } goto wrap; } if (Parm.rpLeaveConEmuOpened) *Parm.rpLeaveConEmuOpened = false; // Use TaskDialog? if (gOSVer.dwMajorVersion >= 6) { // must be already initialized: CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); wchar_t szMessage[128]; lstrcpyn(szMessage, Parm.asSingleConsole ? Parm.asSingleConsole : Parm.bForceKill ? L"Confirm killing?" : L"Confirm closing?", countof(szMessage)); wchar_t szWWW[MAX_PATH]; _wsprintf(szWWW, SKIPLEN(countof(szWWW)) L"<a href=\"%s\">%s</a>", gsHomePage, gsHomePage); wchar_t szCloseAll[MAX_PATH*2]; wchar_t *pszText; if (Parm.asSingleConsole) { wcscpy_c(szCloseAll, L"Yes\n"); pszText = szCloseAll + _tcslen(szCloseAll); lstrcpyn(pszText, Parm.asSingleTitle, min(MAX_PATH,(countof(szCloseAll)-(pszText-szCloseAll)))); pszText += _tcslen(pszText); } else { _wsprintf(szCloseAll, SKIPLEN(countof(szCloseAll)) (Parm.bGroup && (Parm.nConsoles>1)) ? ((Parm.bGroup == ConfirmCloseParam::eGroup) ? L"Close group (%u console%s)" : L"Close (%u console%s)") : L"Close all %u console%s.", Parm.nConsoles, (Parm.nConsoles>1)?L"s":L""); pszText = szCloseAll + _tcslen(szCloseAll); } if ((Parm.asSingleConsole == NULL) || (Parm.nOperations || Parm.nUnsavedEditors)) { //if (nOperations) { _wsprintf(pszText, SKIPLEN(countof(szCloseAll)-(pszText-szCloseAll)) L"\nIncomplete operations: %i", Parm.nOperations); pszText += _tcslen(pszText); } //if (nUnsavedEditors) { _wsprintf(pszText, SKIPLEN(countof(szCloseAll)-(pszText-szCloseAll)) L"\nUnsaved editor windows: %i", Parm.nUnsavedEditors); pszText += _tcslen(pszText); } } wchar_t szCloseOne[MAX_PATH]; wcscpy_c(szCloseOne, L"Close active console only"); if (Parm.nConsoles > 1) { CVConGuard VCon; int iCon = gpConEmu->GetActiveVCon(&VCon); if (iCon >= 0) { pszText = szCloseOne + _tcslen(szCloseOne); _wsprintf(pszText, SKIPLEN(countof(szCloseOne)-(pszText-szCloseOne)) L"\n#%u: ", (iCon+1)); pszText += _tcslen(pszText); lstrcpyn(pszText, VCon->RCon()->GetTitle(true), countof(szCloseOne)-(pszText-szCloseOne)); } } const wchar_t* szCancel = L"Cancel\nDon't close anything"; int nButtonPressed = 0; TASKDIALOGCONFIG config = {sizeof(config)}; TASKDIALOG_BUTTON buttons[] = { { IDYES, szCloseAll }, { IDNO, szCloseOne }, { IDCANCEL, szCancel }, }; config.cButtons = countof(buttons); if (Parm.nConsoles <= 1) { buttons[1] = buttons[2]; config.cButtons--; } config.hwndParent = ghWnd; config.hInstance = NULL /*g_hInstance*/; config.dwFlags = TDF_USE_HICON_MAIN|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION |TDF_ENABLE_HYPERLINKS; //|TDIF_SIZE_TO_CONTENT|TDF_CAN_BE_MINIMIZED; //config.pszMainIcon = MAKEINTRESOURCE(IDI_ICON1); config.hMainIcon = hClassIcon; config.pszWindowTitle = gpConEmu->GetDefaultTitle(); config.pszMainInstruction = szMessage; //config.pszContent = L"..."; config.pButtons = buttons; config.nDefaultButton = IDYES; config.pszFooter = szWWW; //{ // config.dwFlags |= TDF_VERIFICATION_FLAG_CHECKED; // config.pszVerificationText = L"Text on checkbox"; //} HRESULT hr = TaskDialog(&config, &nButtonPressed, NULL, NULL); if (hr == S_OK) { switch (nButtonPressed) { case IDCANCEL: // user cancelled the dialog case IDYES: case IDNO: nBtn = nButtonPressed; goto wrap; default: _ASSERTE(nButtonPressed==IDCANCEL||nButtonPressed==IDYES||nButtonPressed==IDNO); break; // should never happen } } } // Иначе - через стандартный MessageBox if (Parm.asSingleConsole) { lstrcpyn(szText, Parm.asSingleConsole ? Parm.asSingleConsole : Parm.bForceKill ? L"Confirm killing?" : L"Confirm closing?", min(128,countof(szText))); wcscat_c(szText, L"\r\n\r\n"); int nLen = lstrlen(szText); lstrcpyn(szText+nLen, Parm.asSingleTitle, countof(szText)-nLen); } else { _wsprintf(szText, SKIPLEN(countof(szText)) L"About to close %u console%s.\r\n", Parm.nConsoles, (Parm.nConsoles>1)?L"s":L""); } pszText = szText+_tcslen(szText); if (Parm.nOperations || Parm.nUnsavedEditors) { *(pszText++) = L'\r'; *(pszText++) = L'\n'; *(pszText) = 0; if (Parm.nOperations) { _wsprintf(pszText, SKIPLEN(countof(szText)-(pszText-szText)) L"Incomplete operations: %i\r\n", Parm.nOperations); pszText += _tcslen(pszText); } if (Parm.nUnsavedEditors) { _wsprintf(pszText, SKIPLEN(countof(szText)-(pszText-szText)) L"Unsaved editor windows: %i\r\n", Parm.nUnsavedEditors); pszText += _tcslen(pszText); } } if (Parm.nConsoles > 1) { wcscat_c(szText, L"\r\nPress button <No> to close active console only\r\n" L"\r\nProceed with close ConEmu?"); } nBtn = MsgBox(szText, (/*rpPanes ? MB_OKCANCEL :*/ (Parm.nConsoles>1) ? MB_YESNOCANCEL : MB_OKCANCEL)|MB_ICONEXCLAMATION, gpConEmu->GetDefaultTitle(), ghWnd); if (nBtn == IDOK) { nBtn = IDYES; // для однозначности } wrap: InterlockedDecrement(&lCounter); return nBtn; }
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); }
int main(int argc, char** argv) { gn_argc = argc; gp_argv = argv; int iRc = 0; HMODULE hConEmu = NULL; wchar_t szErrInfo[200]; DWORD dwErr; typedef int (__stdcall* ConsoleMain2_t)(BOOL abAlternative); ConsoleMain2_t lfConsoleMain2; #ifdef _DEBUG HMODULE hConEmuHk = GetModuleHandle(WIN3264TEST(L"ConEmuHk.dll",L"ConEmuHk64.dll")); _ASSERTE(hConEmuHk==NULL && "Hooks must not be loaded into ConEmuC[64].exe!"); #endif #if defined(SHOW_STARTED_MSGBOX) if (!IsDebuggerPresent()) { wchar_t szTitle[100]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) WIN3264TEST(L"ConEmuC",L"ConEmuC64") L" Loaded (PID=%i)", GetCurrentProcessId()); const wchar_t* pszCmdLine = GetCommandLineW(); MessageBox(NULL,pszCmdLine,szTitle,0); } #endif // Обязательно, иначе по CtrlC мы свалимся SetConsoleCtrlHandler((PHANDLER_ROUTINE)HandlerRoutine, true); #ifdef _DEBUG UnitTests(); #endif // Some command we can process internally if (ProcessCommandLine(iRc, hConEmu)) { // Done, exiting goto wrap; } // Otherwise - do the full cycle if (!hConEmu) hConEmu = LoadLibrary(WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll")); dwErr = GetLastError(); if (!hConEmu) { _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't load library \"%s\", ErrorCode=0x%08X\n", WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll"), dwErr); _wprintf(szErrInfo); _ASSERTE(FALSE && "LoadLibrary failed"); iRc = CERR_CONEMUHK_NOTFOUND; goto wrap; } // Загрузить функи из ConEmuHk lfConsoleMain2 = (ConsoleMain2_t)GetProcAddress(hConEmu, "ConsoleMain2"); gfHandlerRoutine = (PHANDLER_ROUTINE)GetProcAddress(hConEmu, "HandlerRoutine"); if (!lfConsoleMain2 || !gfHandlerRoutine) { dwErr = GetLastError(); _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Procedure \"%s\" not found in library \"%s\"", lfConsoleMain2 ? L"HandlerRoutine" : L"ConsoleMain2", WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll")); _wprintf(szErrInfo); _ASSERTE(FALSE && "GetProcAddress failed"); FreeLibrary(hConEmu); iRc = CERR_CONSOLEMAIN_NOTFOUND; goto wrap; } // Main dll entry point for Server & ComSpec iRc = lfConsoleMain2(0/*WorkMode*/); // Exiting gfHandlerRoutine = NULL; //FreeLibrary(hConEmu); -- Shutdown Server/Comspec уже выполнен wrap: //-- bottle neck: relatively long deinitialization ExitProcess(iRc); return iRc; }
// // IDataObject::SetData // HRESULT __stdcall CDataObject::SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease) { _ASSERTE(pMedium && pMedium->pUnkForRelease==NULL); #ifdef _DEBUG LPCWSTR pszName = GetFormatName(pFormatEtc->cfFormat, true); DWORD nData = (DWORD)-1; if (lstrcmp(pszName, L"IsShowingLayered")==0 || lstrcmp(pszName, L"IsShowingText")==0 || lstrcmp(pszName, L"DragContext")==0 || lstrcmp(pszName, L"UsingDefaultDragImage")==0 || lstrcmp(pszName, L"DragSourceHelperFlags")==0 || lstrcmp(pszName, L"DragWindow")==0 || lstrcmp(pszName, L"DisableDragText")==0 ) { LPDWORD pdw = (LPDWORD)GlobalLock(pMedium->hGlobal); if (pdw) { nData = *pdw; } GlobalUnlock(pMedium->hGlobal); } wchar_t szDbg[255]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"CDataObject::SetData {cfFormat=%s, lindex=%i, tymed=x%02X(%u)}, {tymed=x%02X}", GetFormatName(pFormatEtc->cfFormat), pFormatEtc->lindex, pFormatEtc->tymed, pFormatEtc->tymed, pMedium->tymed); if (nData != (DWORD)-1) { int nLen = lstrlen(szDbg); _wsprintf(szDbg+nLen, SKIPLEN(countof(szDbg)-nLen) L", Data=x%02X(%u)", nData, nData); } wcscat_c(szDbg, L"\n"); DEBUGSTRDATA(szDbg); #endif DEBUGTEST(bool bNew = false); LONG nIndex = LookupFormatEtc(pFormatEtc); if (nIndex >= 0) { if ((pMedium != &(m_Data[nIndex].StgMedium)) && (pMedium->hGlobal != &(m_Data[nIndex].StgMedium))) { if (m_Data[nIndex].fRelease) { ReleaseStgMedium(&m_Data[nIndex].StgMedium); } else { ZeroStruct(m_Data[nIndex].StgMedium); } } else { Assert((pMedium != &(m_Data[nIndex].StgMedium)) && (pMedium->hGlobal != &(m_Data[nIndex].StgMedium))); } } else // if (nIndex < 0) { DEBUGTEST(bNew = true); _ASSERTE(nIndex < 0); DragData newItem = {}; newItem.FormatEtc = *pFormatEtc; nIndex = m_Data.push_back(newItem); } m_Data[nIndex].fUsed = TRUE; m_Data[nIndex].fRelease = fRelease; m_Data[nIndex].StgMedium = *pMedium; return S_OK; }
LRESULT CConEmuChild::ChildWndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam) { LRESULT result = 0; // Logger MSG msgStr = {hWnd, messg, wParam, lParam}; ConEmuMsgLogger::Log(msgStr, ConEmuMsgLogger::msgCanvas); if (gpSetCls->isAdvLogging >= 4) { gpConEmu->LogMessage(hWnd, messg, wParam, lParam); } CVConGuard guard; CVirtualConsole* pVCon = NULL; if (messg == WM_CREATE || messg == WM_NCCREATE) { LPCREATESTRUCT lp = (LPCREATESTRUCT)lParam; guard = (CVirtualConsole*)lp->lpCreateParams; pVCon = guard.VCon(); if (pVCon) { gVConDcMap.Set(hWnd, pVCon); pVCon->m_TAutoCopy.Init(hWnd, TIMER_AUTOCOPY, TIMER_AUTOCOPY_DELAY); pVCon->m_TScrollShow.Init(hWnd, TIMER_SCROLL_SHOW, TIMER_SCROLL_SHOW_DELAY); pVCon->m_TScrollHide.Init(hWnd, TIMER_SCROLL_HIDE, TIMER_SCROLL_HIDE_DELAY); #ifndef SKIP_HIDE_TIMER pVCon->m_TScrollCheck.Init(hWnd, TIMER_SCROLL_CHECK, TIMER_SCROLL_CHECK_DELAY); #endif } } else if (hWnd != ghDcInDestroing) { if (!gVConDcMap.Get(hWnd, &pVCon) || !guard.Attach(pVCon)) pVCon = NULL; } if (messg == WM_SYSCHAR) { _ASSERTE(FALSE); // по идее, фокуса тут быть не должно // Чтобы не пищало result = TRUE; goto wrap; } if (!pVCon) { _ASSERTE(pVCon!=NULL || hWnd==ghDcInDestroing); result = DefWindowProc(hWnd, messg, wParam, lParam); goto wrap; } switch (messg) { case WM_SHOWWINDOW: { #ifdef _DEBUG HWND hGui = pVCon->GuiWnd(); if (hGui) { _ASSERTE(((wParam==0) || pVCon->RCon()->isGuiForceConView()) && "Show DC while GuiWnd exists"); } #endif result = DefWindowProc(hWnd, messg, wParam, lParam); break; } case WM_SETFOCUS: // Если в консоли работает "GUI" окно (GUI режим), то фокус нужно отдать туда. { // Фокус должен быть в главном окне! За исключением случая работы в GUI режиме. pVCon->setFocus(); } return 0; case WM_ERASEBKGND: result = 0; break; case WM_PAINT: result = pVCon->OnPaint(); break; case WM_PRINTCLIENT: if (wParam && (lParam & PRF_CLIENT)) { pVCon->PrintClient((HDC)wParam, false, NULL); } break; case WM_SIZE: #ifdef _DEBUG { RECT rc; GetClientRect(hWnd, &rc); short cx = LOWORD(lParam); rc.left = rc.left; } #endif result = pVCon->OnSize(wParam, lParam); break; case WM_MOVE: result = pVCon->OnMove(wParam, lParam); break; case WM_CREATE: break; case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_MOUSEWHEEL: case WM_ACTIVATE: case WM_ACTIVATEAPP: //case WM_MOUSEACTIVATE: case WM_KILLFOCUS: //case WM_SETFOCUS: case WM_MOUSEMOVE: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_XBUTTONDOWN: case WM_XBUTTONUP: case WM_XBUTTONDBLCLK: case WM_VSCROLL: // Вся обработка в родителе { switch (messg) { case WM_VSCROLL: switch (LOWORD(wParam)) { case SB_THUMBTRACK: case SB_THUMBPOSITION: pVCon->mb_VTracking = TRUE; break; case SB_ENDSCROLL: pVCon->mb_VTracking = FALSE; break; } pVCon->RCon()->OnSetScrollPos(wParam); break; case WM_LBUTTONUP: pVCon->mb_VTracking = FALSE; break; } TODO("Обработка ghWndWork"); HWND hParent = ghWnd; static bool bInFixStyle = false; if (!bInFixStyle) { hParent = GetParent(hWnd); if (hParent != ghWnd) { // Неправомерные действия плагинов фара? bInFixStyle = true; _ASSERTE(GetParent(hWnd)==ghWnd); SetParent(hWnd, ghWnd); bInFixStyle = false; hParent = ghWnd; } DWORD curStyle = GetWindowLong(hWnd, GWL_STYLE); if ((curStyle & CRITICAL_DCWND_STYLES) != (pVCon->mn_WndDCStyle & CRITICAL_DCWND_STYLES)) { // DC window styles was changed externally! bInFixStyle = true; _ASSERTEX(((curStyle & CRITICAL_DCWND_STYLES) != (pVCon->mn_WndDCStyle & CRITICAL_DCWND_STYLES))); SetWindowLongPtr(hWnd, GWL_STYLE, (LONG_PTR)(DWORD_PTR)pVCon->mn_WndDCStyle); bInFixStyle = false; } } if (messg >= WM_MOUSEFIRST && messg <= WM_MOUSELAST) { POINT pt = {LOWORD(lParam),HIWORD(lParam)}; MapWindowPoints(hWnd, hParent, &pt, 1); lParam = MAKELONG(pt.x,pt.y); } result = gpConEmu->WndProc(hParent, messg, wParam, lParam); } break; case WM_IME_NOTIFY: break; case WM_INPUTLANGCHANGE: case WM_INPUTLANGCHANGEREQUEST: { #ifdef _DEBUG if (IsDebuggerPresent()) { WCHAR szMsg[128]; _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"InChild %s(CP:%i, HKL:0x%08X)\n", (messg == WM_INPUTLANGCHANGE) ? L"WM_INPUTLANGCHANGE" : L"WM_INPUTLANGCHANGEREQUEST", (DWORD)wParam, (DWORD)lParam); DEBUGSTRLANG(szMsg); } #endif result = DefWindowProc(hWnd, messg, wParam, lParam); } break; #ifdef _DEBUG case WM_WINDOWPOSCHANGING: { WINDOWPOS* pwp = (WINDOWPOS*)lParam; result = DefWindowProc(hWnd, messg, wParam, lParam); } return result; case WM_WINDOWPOSCHANGED: { WINDOWPOS* pwp = (WINDOWPOS*)lParam; result = DefWindowProc(hWnd, messg, wParam, lParam); } break; #endif case WM_SETCURSOR: { gpConEmu->WndProc(hWnd, messg, wParam, lParam); //if (!result) // result = DefWindowProc(hWnd, messg, wParam, lParam); } // If an application processes this message, it should return TRUE to halt further processing or FALSE to continue. break; case WM_SYSCOMMAND: // -- лишние ограничения, похоже result = DefWindowProc(hWnd, messg, wParam, lParam); //if (wParam >= SC_SIZE && wParam <= SC_CONTEXTHELP/*0xF180*/) //{ // // Изменение размеров/максимизация/и т.п. окна консоли - запрещена // _ASSERTE(!(wParam >= SC_SIZE && wParam <= SC_CONTEXTHELP)); //} //else //{ // // По идее, сюда ничего приходить больше не должно // _ASSERTE(FALSE); //} break; case WM_TIMER: { switch(wParam) { #ifndef SKIP_HIDE_TIMER // Не будем прятать по таймеру - только по движению мышки case TIMER_SCROLL_CHECK: if (pVCon->mb_Scroll2Visible) { if (!pVCon->CheckMouseOverScroll()) { pVCon->HideScroll(FALSE/*abImmediate*/); } } break; #endif case TIMER_SCROLL_SHOW: if (pVCon->CheckMouseOverScroll() || pVCon->CheckScrollAutoPopup()) pVCon->ShowScroll(TRUE/*abImmediate*/); else pVCon->mb_Scroll2Visible = FALSE; if (pVCon->m_TScrollShow.IsStarted()) pVCon->m_TScrollShow.Stop(); break; case TIMER_SCROLL_HIDE: if (!pVCon->CheckMouseOverScroll()) pVCon->HideScroll(TRUE/*abImmediate*/); else pVCon->mb_Scroll2Visible = TRUE; if (pVCon->m_TScrollHide.IsStarted()) pVCon->m_TScrollHide.Stop(); break; case TIMER_AUTOCOPY: pVCon->SetAutoCopyTimer(false); if (!isPressed(VK_LBUTTON)) { pVCon->RCon()->AutoCopyTimer(); } break; } break; } // case WM_TIMER: case WM_GESTURENOTIFY: case WM_GESTURE: { gpConEmu->ProcessGestureMessage(hWnd, messg, wParam, lParam, result); break; } // case WM_GESTURE, WM_GESTURENOTIFY default: // Сообщение приходит из ConEmuPlugin if (messg == pVCon->mn_MsgTabChanged) { if (gpSet->isTabs) { //изменились табы, их нужно перечитать #ifdef MSGLOGGER WCHAR szDbg[128]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"Tabs:Notified(%i)\n", (DWORD)wParam); DEBUGSTRTABS(szDbg); #endif TODO("здесь хорошо бы вместо OnTimer реально обновить mn_TopProcessID") // иначе во время запуска PID фара еще может быть не известен... //gpConEmu->OnTimer(0,0); не получилось. индекс конмана не менялся, из-за этого индекс активного фара так и остался 0 WARNING("gpConEmu->mp_TabBar->Retrieve() ничего уже не делает вообще"); _ASSERTE(FALSE); gpConEmu->mp_TabBar->Retrieve(); } } else if (messg == pVCon->mn_MsgPostFullPaint) { pVCon->Redraw(); } else if (messg == pVCon->mn_MsgSavePaneSnapshoot) { pVCon->SavePaneSnapshoot(); } else if (messg == pVCon->mn_MsgDetachPosted) { pVCon->RCon()->Detach(true, (lParam == 1)); } else if (messg == gn_MsgVConTerminated) { CVirtualConsole* pVCon = (CVirtualConsole*)lParam; #ifdef _DEBUG int i = -100; wchar_t szDbg[200]; { lstrcpy(szDbg, L"gn_MsgVConTerminated"); i = CVConGroup::GetVConIndex(pVCon); if (i >= 1) { ConEmuTab tab = {0}; pVCon->RCon()->GetTab(0, &tab); tab.Name[128] = 0; // чтобы не вылезло из szDbg wsprintf(szDbg+_tcslen(szDbg), L": #%i: %s", i, tab.Name); } lstrcat(szDbg, L"\n"); DEBUGSTRCONS(szDbg); } #endif // Do not "Guard" lParam here, validation will be made in ProcessVConClosed CConEmuChild::ProcessVConClosed(pVCon, TRUE); return 0; } #ifdef _DEBUG else if (messg == pVCon->mn_MsgCreateDbgDlg) { pVCon->CreateDbgDlg(); } #endif else if (messg) { result = DefWindowProc(hWnd, messg, wParam, lParam); } } wrap: return result; }
bool CConEmuUpdate::QueryConfirmation(CConEmuUpdate::UpdateStep step, LPCWSTR asParm) { if (mb_RequestTerminate) { return false; } bool lbRc = false; wchar_t* pszMsg = NULL; size_t cchMax; switch (step) { case us_ConfirmDownload: { cchMax = _tcslen(asParm)+300; pszMsg = (wchar_t*)malloc(cchMax*sizeof(*pszMsg)); if (mb_ManualCallMode == 2) { lbRc = true; } else if (mp_Set->isUpdateConfirmDownload || mb_ManualCallMode) { wchar_t* pszDup = lstrdup(asParm); wchar_t* pszFile = pszDup ? wcsrchr(pszDup, L'/') : NULL; if (pszFile) { pszFile[1] = 0; pszFile = (wchar_t*)(asParm + (pszFile - pszDup + 1)); asParm = pszDup; } _wsprintf(pszMsg, SKIPLEN(cchMax) L"New %s version available: %s\n\nVersions on server\n%s\n\n%s\n%s\n\nDownload?", (mp_Set->isUpdateUseBuilds==1) ? L"stable" : (mp_Set->isUpdateUseBuilds==3) ? L"preview" : L"developer", ms_NewVersion, ms_VerOnServer, asParm ? asParm : L"", pszFile ? pszFile : L""); SafeFree(pszDup); m_UpdateStep = step; lbRc = QueryConfirmationInt(pszMsg); } else { _wsprintf(pszMsg, SKIPLEN(cchMax) L"New %s version available: %s\nClick here to download", (mp_Set->isUpdateUseBuilds==1) ? L"stable" : (mp_Set->isUpdateUseBuilds==3) ? L"preview" : L"developer", ms_NewVersion); Icon.ShowTrayIcon(pszMsg, tsa_Source_Updater); lbRc = false; } } break; case us_ConfirmUpdate: cchMax = 512; pszMsg = (wchar_t*)malloc(cchMax*sizeof(*pszMsg)); _wsprintf(pszMsg, SKIPLEN(cchMax) L"Do you want to close ConEmu and\n" L"update to %s version %s?", mb_DroppedMode ? L"dropped" : (mp_Set->isUpdateUseBuilds==1) ? L"new stable" : (mp_Set->isUpdateUseBuilds==3) ? L"new preview" : L"new developer", ms_NewVersion); m_UpdateStep = step; lbRc = QueryConfirmationInt(pszMsg); break; default: _ASSERTE(step==us_ConfirmDownload); lbRc = false; } SafeFree(pszMsg); return lbRc; }
// вызывается при получении нового Background (CECMD_SETBACKGROUND) из плагина // и для очистки при закрытии (рестарте) консоли SetBackgroundResult CBackground::SetPluginBackgroundImageData(CESERVER_REQ_SETBACKGROUND* apImgData, bool&/*OUT*/ bUpdate) { if (!this) return esbr_Unexpected; //if (!isMainThread()) //{ //// При вызове из серверной нити (только что пришло из плагина) //if (mp_RCon->isConsoleClosing()) // return esbr_ConEmuInShutdown; bool bIsEmf = false; UINT nSize = IsBackgroundValid(apImgData, &bIsEmf); if (!nSize) { _ASSERTE(FALSE && "!IsBackgroundValid(apImgData, NULL)"); return esbr_InvalidArg; } if (!apImgData->bEnabled) { //mb_BkImgDelete = TRUE; mb_BkImgExist = FALSE; NeedBackgroundUpdate(); //Update(true/*bForce*/); bUpdate = true; return gpSet->isBgPluginAllowed ? esbr_OK : esbr_PluginForbidden; } #ifdef _DEBUG if ((GetKeyState(VK_SCROLL) & 1)) { static UINT nBackIdx = 0; wchar_t szFileName[32]; _wsprintf(szFileName, SKIPLEN(countof(szFileName)) L"PluginBack_%04u.bmp", nBackIdx++); char szAdvInfo[512]; BITMAPINFOHEADER* pBmp = (BITMAPINFOHEADER*)((&apImgData->bmp)+1); _wsprintfA(szAdvInfo, SKIPLEN(countof(szAdvInfo)) "\r\nnType=%i, bEnabled=%i,\r\nWidth=%i, Height=%i, Bits=%i, Encoding=%i\r\n", apImgData->nType, apImgData->bEnabled, pBmp->biWidth, pBmp->biHeight, pBmp->biBitCount, pBmp->biCompression); HANDLE hFile = CreateFile(szFileName, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (hFile != INVALID_HANDLE_VALUE) { DWORD cbWrite; WriteFile(hFile, &apImgData->bmp, apImgData->bmp.bfSize, &cbWrite, 0); WriteFile(hFile, szAdvInfo, lstrlenA(szAdvInfo), &cbWrite, 0); CloseHandle(hFile); } } #endif // // Поскольку вызов асинхронный (сразу возвращаем в плагин), то нужно сделать копию данных // CESERVER_REQ_SETBACKGROUND* pCopy = (CESERVER_REQ_SETBACKGROUND*)malloc(nSize); // if (!pCopy) // return esbr_Unexpected; // memmove(pCopy, apImgData, nSize); // // Запомнить последний актуальный, и послать в главную нить // mp_LastImgData = pCopy; // mb_BkImgDelete = FALSE; // gpConEmu->PostSetBackground(this, pCopy); // return gpSet->isBgPluginAllowed ? esbr_OK : esbr_PluginForbidden; //} //// Если вызов пришел во время закрытия консоли - игнорировать //if (mp_RCon->isConsoleClosing()) ////// Этот apImgData уже не актуален. Во время обработки сообщения пришел новый Background. //// || (mp_LastImgData && mp_LastImgData != apImgData)) //{ // free(apImgData); // return esbr_Unexpected; //} // Ссылку на актуальный - не сбрасываем. Она просто информационная, и есть возможность наколоться с многопоточностью //mp_LastImgData = NULL; //UINT nSize = IsBackgroundValid(apImgData); //if (!nSize) //{ // // Не допустимый apImgData. Вроде такого быть не должно - все уже проверено // _ASSERTE(IsBackgroundValid(apImgData) != 0); // //free(apImgData); // return esbr_InvalidArg; //} //MSectionLock SBK; SBK.Lock(&csBkImgData); //_ASSERTE(isMainThread()); if (!mcs_BkImgData) mcs_BkImgData = new MSection(); MSectionLock SC; SC.Lock(mcs_BkImgData, TRUE); if (bIsEmf) { if (!mp_BkEmfData || mn_BkEmfDataMax < nSize) { if (mp_BkEmfData) { free(mp_BkEmfData); mp_BkEmfData = NULL; mb_BkImgChanged = mb_BkEmfChanged = TRUE; mb_BkImgExist = FALSE; mn_BkImgWidth = mn_BkImgHeight = 0; } mn_BkEmfDataMax = nSize+8192; mp_BkEmfData = (CESERVER_REQ_SETBACKGROUND*)malloc(mn_BkEmfDataMax); } } else { if (!mp_BkImgData || mn_BkImgDataMax < nSize) { if (mp_BkImgData) { free(mp_BkImgData); mp_BkImgData = NULL; mb_BkImgChanged = TRUE; mb_BkImgExist = FALSE; mn_BkImgWidth = mn_BkImgHeight = 0; } mp_BkImgData = (CESERVER_REQ_SETBACKGROUND*)malloc(nSize); } } SetBackgroundResult rc; if (!(bIsEmf ? mp_BkEmfData : mp_BkImgData)) { _ASSERTE((bIsEmf ? mp_BkEmfData : mp_BkImgData)!=NULL); rc = esbr_Unexpected; } else { if (bIsEmf) memmove(mp_BkEmfData, apImgData, nSize); else memmove(mp_BkImgData, apImgData, nSize); mb_BkImgChanged = TRUE; mb_BkEmfChanged = bIsEmf; mb_BkImgExist = TRUE; BITMAPINFOHEADER* pBmp = bIsEmf ? (&mp_BkEmfData->bi) : (&mp_BkImgData->bi); mn_BkImgWidth = pBmp->biWidth; mn_BkImgHeight = pBmp->biHeight; NeedBackgroundUpdate(); //// Это была копия данных - нужно освободить //free(apImgData); apImgData = NULL; if (/*gpConEmu->isVisible(this) &&*/ gpSet->isBgPluginAllowed) { //Update(true/*bForce*/); bUpdate = true; } rc = esbr_OK; } return rc; }
BOOL WINAPI PlugServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam) { BOOL lbRc = FALSE; //HANDLE hPipe = (HANDLE)ahPipe; //CESERVER_REQ *pIn=NULL; //BYTE cbBuffer[64]; // Для большей части команд нам хватит //DWORD cbRead = 0, cbWritten = 0, dwErr = 0; BOOL fSuccess = FALSE; MSectionThread SCT(csTabs); // Send a message to the pipe server and read the response. //fSuccess = ReadFile(hPipe, cbBuffer, sizeof(cbBuffer), &cbRead, NULL); //dwErr = GetLastError(); //if (!fSuccess && (dwErr != ERROR_MORE_DATA)) //{ // _ASSERTE("ReadFile(pipe) failed"==NULL); // CloseHandle(hPipe); // return 0; //} //pIn = (CESERVER_REQ*)cbBuffer; // Пока cast, если нужно больше - выделим память //_ASSERTE(pIn->hdr.cbSize>=sizeof(CESERVER_REQ_HDR) && cbRead>=sizeof(CESERVER_REQ_HDR)); //_ASSERTE(pIn->hdr.nVersion == CESERVER_REQ_VER); if (pIn->hdr.cbSize < sizeof(CESERVER_REQ_HDR) || /*in.nSize < cbRead ||*/ pIn->hdr.nVersion != CESERVER_REQ_VER) { //CloseHandle(hPipe); gpPlugServer->BreakConnection(pInst); return FALSE; } //int nAllSize = pIn->hdr.cbSize; //pIn = (CESERVER_REQ*)Alloc(nAllSize,1); //_ASSERTE(pIn!=NULL); //if (!pIn) //{ // CloseHandle(hPipe); // return 0; //} //memmove(pIn, cbBuffer, cbRead); //_ASSERTE(pIn->hdr.nVersion==CESERVER_REQ_VER); //LPBYTE ptrData = ((LPBYTE)pIn)+cbRead; //nAllSize -= cbRead; //while(nAllSize>0) //{ // //_tprintf(TEXT("%s\n"), chReadBuf); // // Break if TransactNamedPipe or ReadFile is successful // if (fSuccess) // break; // // Read from the pipe if there is more data in the message. // fSuccess = ReadFile( // hPipe, // pipe handle // ptrData, // buffer to receive reply // nAllSize, // size of buffer // &cbRead, // number of bytes read // NULL); // not overlapped // // Exit if an error other than ERROR_MORE_DATA occurs. // if (!fSuccess && ((dwErr = GetLastError()) != ERROR_MORE_DATA)) // break; // ptrData += cbRead; // nAllSize -= cbRead; //} //TODO("Может возникнуть ASSERT, если консоль была закрыта в процессе чтения"); //_ASSERTE(nAllSize==0); //if (nAllSize>0) //{ // if (((LPVOID)cbBuffer) != ((LPVOID)pIn)) // Free(pIn); // CloseHandle(hPipe); // return 0; // удалось считать не все данные //} UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR); // Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат //fSuccess = WriteFile( hPipe, pOut, pOut->nSize, &cbWritten, NULL); if (pIn->hdr.nCmd == CMD_LANGCHANGE) { _ASSERTE(nDataSize>=4); //-V112 // LayoutName: "00000409", "00010409", ... // А HKL от него отличается, так что передаем DWORD // HKL в x64 выглядит как: "0x0000000000020409", "0xFFFFFFFFF0010409" DWORD hkl = pIn->dwData[0]; DWORD dwLastError = 0; HKL hkl1 = NULL, hkl2 = NULL; if (hkl) { WCHAR szLoc[10]; _wsprintf(szLoc, SKIPLEN(countof(szLoc)) L"%08x", hkl); hkl1 = LoadKeyboardLayout(szLoc, KLF_ACTIVATE|KLF_REORDER|KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS); hkl2 = ActivateKeyboardLayout(hkl1, KLF_SETFORPROCESS|KLF_REORDER); if (!hkl2) dwLastError = GetLastError(); else fSuccess = TRUE; } pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = fSuccess; ppReply->dwData[1] = fSuccess ? ((DWORD)(LONG)(LONG_PTR)hkl2) : dwLastError; } } //} else if (pIn->hdr.nCmd == CMD_DEFFONT) { // // исключение - асинхронный, результат не требуется // SetConsoleFontSizeTo(FarHwnd, 4, 6); // MoveWindow(FarHwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 1); // чтобы убрать возможные полосы прокрутки... else if (pIn->hdr.nCmd == CMD_REQTABS || pIn->hdr.nCmd == CMD_SETWINDOW) { MSectionLock SC; SC.Lock(csTabs, FALSE, 1000); DWORD nSetWindowWait = (DWORD)-1; if (pIn->hdr.nCmd == CMD_SETWINDOW) { ResetEvent(ghSetWndSendTabsEvent); // Для FAR2 - сброс QSearch выполняется в том же макро, в котором актирируется окно if (gFarVersion.dwVerMajor == 1 && pIn->dwData[1]) { // А вот для FAR1 - нужно шаманить ProcessCommand(CMD_CLOSEQSEARCH, TRUE/*bReqMainThread*/, pIn->dwData/*хоть и не нужно?*/); } // Пересылается 2 DWORD BOOL bCmdRc = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->dwData); DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW waiting...\n"); WARNING("Почему для FAR1 не ждем? Есть возможность заблокироваться в 1.7 или что?"); if ((gFarVersion.dwVerMajor >= 2) && bCmdRc) { DWORD nTimeout = 2000; #ifdef _DEBUG if (IsDebuggerPresent()) nTimeout = 120000; #endif nSetWindowWait = WaitForSingleObject(ghSetWndSendTabsEvent, nTimeout); } DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW finished\n"); } if (gpTabs) { //fSuccess = WriteFile(hPipe, gpTabs, gpTabs->hdr.cbSize, &cbWritten, NULL); pcbReplySize = gpTabs->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { memmove(ppReply->Data, gpTabs->Data, pcbReplySize - sizeof(ppReply->hdr)); lbRc = TRUE; } } SC.Unlock(); } else if (pIn->hdr.nCmd == CMD_FARSETCHANGED) { // Установить переменные окружения // Плагин это получает в ответ на CECMD_RESOURCES, посланное в GUI при загрузке плагина _ASSERTE(nDataSize>=8); FAR_REQ_FARSETCHANGED *pFarSet = (FAR_REQ_FARSETCHANGED*)pIn->Data; cmd_FarSetChanged(pFarSet); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = TRUE; } //_ASSERTE(nDataSize<sizeof(gsMonitorEnvVar)); //gbMonitorEnvVar = false; //// Плагин FarCall "нарушает" COMSPEC (копирует содержимое запускаемого процесса) //bool lbOk = false; //if (nDataSize<sizeof(gsMonitorEnvVar)) //{ // memcpy(gsMonitorEnvVar, pszName, nDataSize); // lbOk = true; //} //UpdateEnvVar(pszName); ////while (*pszName && *pszValue) { //// const wchar_t* pszChanged = pszValue; //// // Для ConEmuOutput == AUTO выбирается по версии ФАРа //// if (!lstrcmpi(pszName, L"ConEmuOutput") && !lstrcmp(pszChanged, L"AUTO")) { //// if (gFarVersion.dwVerMajor==1) //// pszChanged = L"ANSI"; //// else //// pszChanged = L"UNICODE"; //// } //// // Если в pszValue пустая строка - удаление переменной //// SetEnvironmentVariableW(pszName, (*pszChanged != 0) ? pszChanged : NULL); //// // //// pszName = pszValue + lstrlenW(pszValue) + 1; //// if (*pszName == 0) break; //// pszValue = pszName + lstrlenW(pszName) + 1; ////} //gbMonitorEnvVar = lbOk; } else if (pIn->hdr.nCmd == CMD_DRAGFROM) { #ifdef _DEBUG BOOL *pbClickNeed = (BOOL*)pIn->Data; COORD *crMouse = (COORD *)(pbClickNeed+1); #endif ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, pIn->Data); CESERVER_REQ* pCmdRet = NULL; ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet); if (pCmdRet) { //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL); pcbReplySize = pCmdRet->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr)); } Free(pCmdRet); } //if (gpCmdRet && gpCmdRet == pCmdRet) //{ // Free(gpCmdRet); // gpCmdRet = NULL; gpData = NULL; gpCursor = NULL; //} } else if (pIn->hdr.nCmd == CMD_EMENU) { COORD *crMouse = (COORD *)pIn->Data; #ifdef _DEBUG const wchar_t *pszUserMacro = (wchar_t*)(crMouse+1); #endif DWORD ClickArg[2] = {TRUE, MAKELONG(crMouse->X, crMouse->Y)}; // Выделить файл под курсором DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) begin\n"); BOOL lb1 = ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, ClickArg/*pIn->Data*/); DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) done\n"); // А теперь, собственно вызовем меню DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) begin\n"); BOOL lb2 = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data); DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) done\n"); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = lb1; ppReply->dwData[1] = lb1; } } else if (pIn->hdr.nCmd == CMD_ACTIVEWNDTYPE) { int nWindowType = -1; //CESERVER_REQ Out; //ExecutePrepareCmd(&Out, CMD_ACTIVEWNDTYPE, sizeof(CESERVER_REQ_HDR)+sizeof(DWORD)); if (gFarVersion.dwVerMajor>=2) nWindowType = GetActiveWindowType(); //fSuccess = WriteFile(hPipe, &Out, Out.hdr.cbSize, &cbWritten, NULL); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = nDataSize; } } else { CESERVER_REQ* pCmdRet = NULL; BOOL lbCmd = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet); if (pCmdRet) { //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL); pcbReplySize = pCmdRet->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr)); } Free(pCmdRet); } //if (gpCmdRet && gpCmdRet == pCmdRet) { // Free(gpCmdRet); // gpCmdRet = NULL; gpData = NULL; gpCursor = NULL; //} } //// Освободить память //if (((LPVOID)cbBuffer) != ((LPVOID)pIn)) // Free(pIn); //CloseHandle(hPipe); return lbRc; }
// В asDir могут быть переменные окружения. wchar_t* CConEmuUpdate::CreateTempFile(LPCWSTR asDir, LPCWSTR asFileNameTempl, HANDLE& hFile) { wchar_t szFile[MAX_PATH*2+2]; wchar_t szName[128]; if (!asDir || !*asDir) asDir = L"%TEMP%\\ConEmu"; if (!asFileNameTempl || !*asFileNameTempl) asFileNameTempl = L"ConEmu.tmp"; if (wcschr(asDir, L'%')) { DWORD nExp = ExpandEnvironmentStrings(asDir, szFile, MAX_PATH); if (!nExp || (nExp >= MAX_PATH)) { ReportError(L"CreateTempFile.ExpandEnvironmentStrings(%s) failed, code=%u", asDir, GetLastError()); return NULL; } } else { lstrcpyn(szFile, asDir, MAX_PATH); } // Checking %TEMP% for valid path LPCWSTR pszColon1, pszColon2; if ((pszColon1 = wcschr(szFile, L':')) != NULL) { if ((pszColon2 = wcschr(pszColon1+1, L':')) != NULL) { ReportError(L"Invalid download path (%%TEMP%% variable?)\n%s", szFile, 0); return NULL; } } int nLen = lstrlen(szFile); if (nLen <= 0) { ReportError(L"CreateTempFile.asDir(%s) failed, path is null", asDir, 0); return NULL; } if (szFile[nLen-1] != L'\\') { szFile[nLen++] = L'\\'; szFile[nLen] = 0; } wchar_t* pszFilePart = szFile + nLen; wchar_t* pszDirectory = lstrdup(szFile); LPCWSTR pszName = PointToName(asFileNameTempl); _ASSERTE(pszName == asFileNameTempl); if (!pszName || !*pszName || (*pszName == L'.')) { _ASSERTE(pszName && *pszName && (*pszName != L'.')); pszName = L"ConEmu"; } LPCWSTR pszExt = PointToExt(pszName); if (pszExt == NULL) { _ASSERTE(pszExt != NULL); pszExt = L".tmp"; } lstrcpyn(szName, pszName, countof(szName)-16); wchar_t* psz = wcsrchr(szName, L'.'); if (psz) *psz = 0; wchar_t* pszResult = NULL; DWORD dwErr = 0; for (UINT i = 0; i <= 9999; i++) { _wcscpy_c(pszFilePart, MAX_PATH, szName); if (i) _wsprintf(pszFilePart+_tcslen(pszFilePart), SKIPLEN(16) L"(%u)", i); _wcscat_c(pszFilePart, MAX_PATH, pszExt); hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_TEMPORARY, NULL); //ERROR_PATH_NOT_FOUND? if (!hFile || (hFile == INVALID_HANDLE_VALUE)) { dwErr = GetLastError(); // на первом обломе - попытаться создать директорию, может ее просто нет? if ((dwErr == ERROR_PATH_NOT_FOUND) && (i == 0)) { if (!MyCreateDirectory(pszDirectory)) { ReportError(L"CreateTempFile.asDir(%s) failed", asDir, 0); goto wrap; } } } if (hFile && hFile != INVALID_HANDLE_VALUE) { psz = lstrdup(szFile); if (!psz) { CloseHandle(hFile); hFile = NULL; ReportError(L"Can't allocate memory (%i bytes)", lstrlen(szFile)); } pszResult = psz; goto wrap; } } ReportError(L"Can't create temp file(%s), code=%u", szFile, dwErr); hFile = NULL; wrap: SafeFree(pszDirectory); return pszResult; }
BOOL ReloadFarInfoW995(/*BOOL abFull*/) { if (!InfoW995 || !FSFW995) return FALSE; if (!gpFarInfo) { _ASSERTE(gpFarInfo!=NULL); return FALSE; } // Заполнить gpFarInfo-> //BYTE nFarColors[col_LastIndex]; // Массив цветов фара //DWORD nFarInterfaceSettings; //DWORD nFarPanelSettings; //DWORD nFarConfirmationSettings; //BOOL bFarPanelAllowed, bFarLeftPanel, bFarRightPanel; // FCTL_CHECKPANELSEXIST, FCTL_GETPANELSHORTINFO,... //CEFAR_SHORT_PANEL_INFO FarLeftPanel, FarRightPanel; DWORD ldwConsoleMode = 0; GetConsoleMode(/*ghConIn*/GetStdHandle(STD_INPUT_HANDLE), &ldwConsoleMode); #ifdef _DEBUG static DWORD ldwDbgMode = 0; if (IsDebuggerPresent()) { if (ldwDbgMode != ldwConsoleMode) { wchar_t szDbg[128]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"Far.ConEmuW: ConsoleMode(STD_INPUT_HANDLE)=0x%08X\n", ldwConsoleMode); OutputDebugStringW(szDbg); ldwDbgMode = ldwConsoleMode; } } #endif gpFarInfo->nFarConsoleMode = ldwConsoleMode; LoadFarColorsW995(gpFarInfo->nFarColors); //_ASSERTE(FPS_SHOWCOLUMNTITLES==0x20 && FPS_SHOWSTATUSLINE==0x40); //-V112 LoadFarSettingsW995(&gpFarInfo->FarInterfaceSettings, &gpFarInfo->FarPanelSettings); //gpFarInfo->nFarConfirmationSettings = // (DWORD)InfoW995->AdvControl(InfoW995->ModuleNumber, ACTL_GETCONFIRMATIONS, 0); gpFarInfo->bMacroActive = IsMacroActiveW995(); ActlKeyMacro area = {MCMD_GETAREA}; INT_PTR nArea = InfoW995->AdvControl(InfoW995->ModuleNumber, ACTL_KEYMACRO, &area); switch(nArea) { case MACROAREA_SHELL: case MACROAREA_INFOPANEL: case MACROAREA_QVIEWPANEL: case MACROAREA_TREEPANEL: case MACROAREA_SEARCH: gpFarInfo->nMacroArea = fma_Panels; break; case MACROAREA_VIEWER: gpFarInfo->nMacroArea = fma_Viewer; break; case MACROAREA_EDITOR: gpFarInfo->nMacroArea = fma_Editor; break; case MACROAREA_DIALOG: case MACROAREA_DISKS: case MACROAREA_FINDFOLDER: case MACROAREA_AUTOCOMPLETION: case MACROAREA_MAINMENU: case MACROAREA_MENU: case MACROAREA_USERMENU: gpFarInfo->nMacroArea = fma_Dialog; break; default: gpFarInfo->nMacroArea = fma_Unknown; } gpFarInfo->bFarPanelAllowed = InfoW995->Control(PANEL_NONE, FCTL_CHECKPANELSEXIST, 0, 0); gpFarInfo->bFarPanelInfoFilled = FALSE; gpFarInfo->bFarLeftPanel = FALSE; gpFarInfo->bFarRightPanel = FALSE; // -- пока, во избежание глюков в FAR при неожиданных запросах информации о панелях //if (FALSE == (gpFarInfo->bFarPanelAllowed)) { // gpConMapInfo->bFarLeftPanel = FALSE; // gpConMapInfo->bFarRightPanel = FALSE; //} else { // PanelInfo piA = {}, piP = {}; // BOOL lbActive = InfoW995->Control(PANEL_ACTIVE, FCTL_GETPANELINFO, 0, (LONG_PTR)&piA); // BOOL lbPassive = InfoW995->Control(PANEL_PASSIVE, FCTL_GETPANELINFO, 0, (LONG_PTR)&piP); // if (!lbActive && !lbPassive) // { // gpConMapInfo->bFarLeftPanel = FALSE; // gpConMapInfo->bFarRightPanel = FALSE; // } else { // PanelInfo *ppiL = NULL; // PanelInfo *ppiR = NULL; // if (lbActive) { // if (piA.Flags & PFLAGS_PANELLEFT) ppiL = &piA; else ppiR = &piA; // } // if (lbPassive) { // if (piP.Flags & PFLAGS_PANELLEFT) ppiL = &piP; else ppiR = &piP; // } // gpConMapInfo->bFarLeftPanel = ppiL!=NULL; // gpConMapInfo->bFarRightPanel = ppiR!=NULL; // if (ppiL) FarPanel2CePanel(ppiL, &(gpConMapInfo->FarLeftPanel)); // if (ppiR) FarPanel2CePanel(ppiR, &(gpConMapInfo->FarRightPanel)); // } //} return TRUE; }
int InjectRemote(DWORD nRemotePID, bool abDefTermOnly /*= false */) { int iRc = -1; BOOL lbWin64 = WIN3264TEST(IsWindows64(),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(szSelf, 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 != 0) { 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; }
int PrepareHookModule(wchar_t (&szModule)[MAX_PATH+16]) { int iRc = -251; wchar_t szNewPath[MAX_PATH+16] = {}, szAddName[32] = {}, szVer[2] = {}; INT_PTR nLen = 0; bool bAlreadyExists = false; // Copy szModule to CSIDL_LOCAL_APPDATA and return new path HRESULT hr = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, szNewPath); if ((hr != S_OK) || !*szNewPath) { iRc = -251; goto wrap; } szVer[0] = MVV_4a[0]; _wsprintf(szAddName, SKIPLEN(countof(szAddName)) L"\\" CEDEFTERMDLLFORMAT /*L"ConEmuHk%s.%02u%02u%02u%s.dll"*/, WIN3264TEST(L"",L"64"), MVV_1, MVV_2, MVV_3, szVer); nLen = lstrlen(szNewPath); if (szNewPath[nLen-1] != L'\\') { szNewPath[nLen++] = L'\\'; szNewPath[nLen] = 0; } if ((nLen + lstrlen(szAddName) + 8) >= countof(szNewPath)) { iRc = -252; goto wrap; } wcscat_c(szNewPath, L"ConEmu"); if (!DirectoryExists(szNewPath)) { if (!CreateDirectory(szNewPath, NULL)) { iRc = -253; goto wrap; } } wcscat_c(szNewPath, szAddName); if ((bAlreadyExists = FileExists(szNewPath)) && FileCompare(szNewPath, szModule)) { // OK, file exists and match the required } else { if (bAlreadyExists) { _ASSERTE(FALSE && "Continue to overwrite existing ConEmuHk in AppLocal"); // Try to delete or rename old version if (!DeleteFile(szNewPath)) { //SYSTEMTIME st; GetLocalTime(&st); wchar_t szBakPath[MAX_PATH+32]; wcscpy_c(szBakPath, szNewPath); wchar_t* pszExt = (wchar_t*)PointToExt(szBakPath); msprintf(pszExt, 16, L".%u.dll", GetTickCount()); DeleteFile(szBakPath); MoveFile(szNewPath, szBakPath); } } if (!CopyFile(szModule, szNewPath, FALSE)) { iRc = -254; goto wrap; } } wcscpy_c(szModule, szNewPath); iRc = 0; wrap: return iRc; }
//// Эта функция пайп не закрывает! //void CGuiServer::GuiServerThreadCommand(HANDLE hPipe) BOOL CGuiServer::GuiServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam) { BOOL lbRc = FALSE; CGuiServer* pGSrv = (CGuiServer*)lParam; if (!pGSrv) { _ASSERTE(((CGuiServer*)lParam)!=NULL); pGSrv = &gpConEmu->m_GuiServer; } if (pIn->hdr.bAsync) pGSrv->mp_GuiServer->BreakConnection(pInst); gpSetCls->debugLogCommand(pIn, TRUE, timeGetTime(), 0, pGSrv ? pGSrv->ms_ServerPipe : NULL); #ifdef _DEBUG UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR); #endif // Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат #ifdef ALLOW_WINE_MSG if (gbIsWine) { wchar_t szMsg[128]; msprintf(szMsg, countof(szMsg), L"CGuiServer::GuiServerCommand.\nGUI TID=%u\nSrcPID=%u, SrcTID=%u, Cmd=%u", GetCurrentThreadId(), pIn->hdr.nSrcPID, pIn->hdr.nSrcThreadId, pIn->hdr.nCmd); MessageBox(szMsg, MB_ICONINFORMATION); } #endif switch (pIn->hdr.nCmd) { case CECMD_NEWCMD: { // Приходит из другой копии ConEmu.exe, когда она запущена с ключом /single, /showhide, /showhideTSA DEBUGSTR(L"GUI recieved CECMD_NEWCMD\n"); if (gpSetCls->isAdvLogging) { size_t cchAll = 120 + _tcslen(pIn->NewCmd.szConEmu) + _tcslen(pIn->NewCmd.szCurDir) + _tcslen(pIn->NewCmd.szCommand); wchar_t* pszInfo = (wchar_t*)malloc(cchAll*sizeof(*pszInfo)); if (pszInfo) { _wsprintf(pszInfo, SKIPLEN(cchAll) L"CECMD_NEWCMD: Wnd=x%08X, Act=%u, ConEmu=%s, Dir=%s, Cmd=%s", (DWORD)(DWORD_PTR)pIn->NewCmd.hFromConWnd, pIn->NewCmd.ShowHide, pIn->NewCmd.szConEmu, pIn->NewCmd.szCurDir, pIn->NewCmd.szCommand); gpConEmu->LogString(pszInfo); free(pszInfo); } } BOOL bAccepted = FALSE; if (pIn->NewCmd.szConEmu[0]) { bAccepted = (lstrcmpi(gpConEmu->ms_ConEmuExeDir, pIn->NewCmd.szConEmu) == 0); } else { bAccepted = TRUE; } if (bAccepted) { bool bCreateTab = (pIn->NewCmd.ShowHide == sih_None || pIn->NewCmd.ShowHide == sih_StartDetached); gpConEmu->OnMinimizeRestore(bCreateTab ? sih_SetForeground : pIn->NewCmd.ShowHide); // Может быть пусто if (bCreateTab && pIn->NewCmd.szCommand[0]) { RConStartArgs *pArgs = new RConStartArgs; pArgs->bDetached = (pIn->NewCmd.ShowHide == sih_StartDetached); pArgs->pszSpecialCmd = lstrdup(pIn->NewCmd.szCommand); if (pIn->NewCmd.szCurDir[0] == 0) { _ASSERTE(pIn->NewCmd.szCurDir[0] != 0); } else { pArgs->pszStartupDir = lstrdup(pIn->NewCmd.szCurDir); } if (gpSet->isMulti || CVConGroup::isDetached()) { gpConEmu->PostCreateCon(pArgs); } else { // Если хотят в одном окне - только одну консоль gpConEmu->CreateWnd(pArgs); SafeDelete(pArgs); } } else { _ASSERTE(pIn->NewCmd.ShowHide==sih_ShowMinimize || pIn->NewCmd.ShowHide==sih_ShowHideTSA || pIn->NewCmd.ShowHide==sih_Show); } } pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE); lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize); if (lbRc) { ppReply->Data[0] = bAccepted; } break; } //CECMD_NEWCMD case CECMD_TABSCMD: { // 0: спрятать/показать табы, 1: перейти на следующую, 2: перейти на предыдущую, 3: commit switch DEBUGSTR(L"GUI recieved CECMD_TABSCMD\n"); _ASSERTE(nDataSize>=1); DWORD nTabCmd = pIn->Data[0]; gpConEmu->TabCommand((ConEmuTabCommand)nTabCmd); pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->Data[0] = TRUE; } break; } // CECMD_TABSCMD #if 0 case CECMD_GETALLTABS: { int nConCount = gpConEmu->GetConCount(); int nActiveCon = gpConEmu->ActiveConNum(); size_t cchMax = nConCount*16; size_t cchCount = 0; CVirtualConsole* pVCon; CESERVER_REQ_GETALLTABS::TabInfo* pTabs = (CESERVER_REQ_GETALLTABS::TabInfo*)calloc(cchMax, sizeof(*pTabs)); for (int V = 0; (pVCon = gpConEmu->GetVCon(V)) != NULL; V++) { if (!pTabs) { _ASSERTE(pTabs!=NULL); break; } CRealConsole* pRCon = pVCon->RCon(); if (!pRCon) continue; ConEmuTab tab; wchar_t szModified[4]; for (int T = 0; pRCon->GetTab(T, &tab); T++) { if (cchCount >= cchMax) { pTabs = (CESERVER_REQ_GETALLTABS::TabInfo*)realloc(pTabs, (cchMax+32)*sizeof(*pTabs)); if (!pTabs) { _ASSERTE(pTabs!=NULL); break; } cchMax += 32; _ASSERTE(cchCount<cchMax); } pTabs[cchCount].ActiveConsole == (V == nActiveCon); pTabs[cchCount].ActiveTab == (tab.Current != 0); pTabs[cchCount].Disabled = ((tab.Type & fwt_Disabled) == fwt_Disabled); pTabs[cchCount].ConsoleIdx = V; pTabs[cchCount].TabIdx = T; // Text wcscpy_c(szModified, tab.Modified ? L" * " : L" "); if (V == nActiveCon) { if (T < 9) _wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/&%i]%s", V+1, T+1, szModified); else if (T == 9) _wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/1&0]%s", V+1, szModified); else _wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/%i]%s", V+1, T+1, szModified); } else { _wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/%i]%s", V+1, T+1, szModified); } cchCount++; } } if (cchCount && pTabs) { pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_GETALLTABS)+((cchCount-1)*sizeof(CESERVER_REQ_GETALLTABS::TabInfo)); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->GetAllTabs.Count = cchCount; memmove(ppReply->GetAllTabs.Tabs, pTabs, cchCount*sizeof(*pTabs)); } } SafeFree(pTabs); break; } // CECMD_GETALLTABS case CECMD_ACTIVATETAB: { BOOL lbTabOk = FALSE; CVirtualConsole *pVCon = gpConEmu->GetVCon(pIn->dwData[0]); if (pVCon && pVCon->RCon()) { lbTabOk = pVCon->RCon()->ActivateFarWindow(pIn->dwData[1]); } pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = lbTabOk; } break; } // CECMD_ACTIVATETAB #endif case CECMD_ATTACH2GUI: { // Получен запрос на Attach из сервера pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET); if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) goto wrap; //CESERVER_REQ* pOut = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET)); gpConEmu->AttachRequested(pIn->StartStop.hWnd, &(pIn->StartStop), &(ppReply->StartStopRet)); _ASSERTE((ppReply->StartStopRet.nBufferHeight == 0) || ((int)ppReply->StartStopRet.nBufferHeight > pIn->StartStop.sbi.dwSize.X)); lbRc = TRUE; //ExecuteFreeResult(pOut); break; } // CECMD_ATTACH2GUI case CECMD_SRVSTARTSTOP: { pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET); if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) goto wrap; if (pIn->SrvStartStop.Started == srv_Started) { // Запущен процесс сервера HWND hConWnd = (HWND)pIn->dwData[1]; _ASSERTE(hConWnd && IsWindow(hConWnd)); DWORD nStartTick = timeGetTime(); //LRESULT l = 0; //DWORD_PTR dwRc = 0; //2010-05-21 Поскольку это критично - лучше ждать до упора, хотя может быть DeadLock? //l = SendMessageTimeout(ghWnd, gpConEmu->mn_MsgSrvStarted, (WPARAM)hConWnd, pIn->hdr.nSrcPID, // SMTO_BLOCK, 5000, &dwRc); //111002 - вернуть должен HWND окна отрисовки (дочернее окно ConEmu) MsgSrvStartedArg arg = {hConWnd, pIn->hdr.nSrcPID, pIn->SrvStartStop.dwKeybLayout, nStartTick}; SendMessage(ghWnd, gpConEmu->mn_MsgSrvStarted, 0, (LPARAM)&arg); HWND hWndDC = arg.hWndDc; HWND hWndBack = arg.hWndBack; _ASSERTE(hWndDC!=NULL); #ifdef _DEBUG DWORD dwErr = GetLastError(), nEndTick = timeGetTime(), nDelta = nEndTick - nStartTick; if (hWndDC && nDelta >= EXECUTE_CMD_WARN_TIMEOUT) { if (!IsDebuggerPresent()) { //_ASSERTE(nDelta <= EXECUTE_CMD_WARN_TIMEOUT || (pIn->hdr.nCmd == CECMD_CMDSTARTSTOP && nDelta <= EXECUTE_CMD_WARN_TIMEOUT2)); _ASSERTEX(nDelta <= EXECUTE_CMD_WARN_TIMEOUT); } } #endif //pIn->dwData[0] = (DWORD)ghWnd; //-V205 //pIn->dwData[1] = (DWORD)dwRc; //-V205 //pIn->dwData[0] = (l == 0) ? 0 : 1; ppReply->StartStopRet.hWnd = ghWnd; ppReply->StartStopRet.hWndDc = hWndDC; ppReply->StartStopRet.hWndBack = hWndBack; ppReply->StartStopRet.dwPID = GetCurrentProcessId(); } else if (pIn->SrvStartStop.Started == srv_Stopped) { // Процесс сервера завершается CRealConsole* pRCon = NULL; CVConGuard VCon; for (size_t i = 0;; i++) { if (!CVConGroup::GetVCon(i, &VCon)) break; pRCon = VCon->RCon(); if (pRCon && (pRCon->GetServerPID(true) == pIn->hdr.nSrcPID || pRCon->GetServerPID(false) == pIn->hdr.nSrcPID)) { break; } pRCon = NULL; } if (pRCon) pRCon->OnServerClosing(pIn->hdr.nSrcPID); //pIn->dwData[0] = 1; } else { _ASSERTE((pIn->dwData[0] == 1) || (pIn->dwData[0] == 101)); } lbRc = TRUE; //// Отправляем //fSuccess = WriteFile( // hPipe, // handle to pipe // pOut, // buffer to write from // pOut->hdr.cbSize, // number of bytes to write // &cbWritten, // number of bytes written // NULL); // not overlapped I/O //ExecuteFreeResult(pOut); break; } // CECMD_SRVSTARTSTOP case CECMD_ASSERT: { DWORD nBtn = MessageBox(NULL, pIn->AssertInfo.szDebugInfo, pIn->AssertInfo.szTitle, pIn->AssertInfo.nBtns); pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = nBtn; } //ExecutePrepareCmd(&pIn->hdr, CECMD_ASSERT, sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)); //pIn->dwData[0] = nBtn; //// Отправляем //fSuccess = WriteFile( // hPipe, // handle to pipe // pIn, // buffer to write from // pIn->hdr.cbSize, // number of bytes to write // &cbWritten, // number of bytes written // NULL); // not overlapped I/O break; } // CECMD_ASSERT case CECMD_ATTACHGUIAPP: { pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP); if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) goto wrap; ppReply->AttachGuiApp = pIn->AttachGuiApp; //CESERVER_REQ Out; //ExecutePrepareCmd(&Out.hdr, CECMD_ATTACHGUIAPP, sizeof(CESERVER_REQ_HDR)+sizeof(Out.AttachGuiApp)); //Out.AttachGuiApp = pIn->AttachGuiApp; #ifdef SHOW_GUIATTACH_START if (pIn->AttachGuiApp.hWindow == NULL) { wchar_t szDbg[1024]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"AttachGuiApp requested from:\n%s\nPID=%u", pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID); //MBoxA(szDbg); MessageBox(NULL, szDbg, L"ConEmu", MB_SYSTEMMODAL); } #endif // Уведомить ожидающую вкладку CRealConsole* pRCon = gpConEmu->AttachRequestedGui(pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID); if (pRCon) { CVConGuard VCon(pRCon->VCon()); RECT rcPrev = ppReply->AttachGuiApp.rcWindow; HWND hBack = pRCon->VCon()->GetBack(); //// Размер должен быть независим от возможности наличия прокрутки в VCon //GetWindowRect(hBack, &ppReply->AttachGuiApp.rcWindow); //ppReply->AttachGuiApp.rcWindow.right -= ppReply->AttachGuiApp.rcWindow.left; //ppReply->AttachGuiApp.rcWindow.bottom -= ppReply->AttachGuiApp.rcWindow.top; //ppReply->AttachGuiApp.rcWindow.left = ppReply->AttachGuiApp.rcWindow.top = 0; ////MapWindowPoints(NULL, hBack, (LPPOINT)&ppReply->AttachGuiApp.rcWindow, 2); //pRCon->CorrectGuiChildRect(ppReply->AttachGuiApp.nStyle, ppReply->AttachGuiApp.nStyleEx, ppReply->AttachGuiApp.rcWindow); // Уведомить RCon и ConEmuC, что гуй подцепился // Вызывается два раза. Первый (при запуске exe) ahGuiWnd==NULL, второй - после фактического создания окна pRCon->SetGuiMode(pIn->AttachGuiApp.nFlags, pIn->AttachGuiApp.hAppWindow, pIn->AttachGuiApp.Styles.nStyle, pIn->AttachGuiApp.Styles.nStyleEx, pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID, rcPrev); ppReply->AttachGuiApp.nFlags = agaf_Success | (pRCon->isActive(false) ? 0 : agaf_Inactive); ppReply->AttachGuiApp.nPID = pRCon->GetServerPID(); ppReply->AttachGuiApp.hConEmuDc = pRCon->GetView(); ppReply->AttachGuiApp.hConEmuBack = hBack; ppReply->AttachGuiApp.hConEmuWnd = ghWnd; ppReply->AttachGuiApp.hAppWindow = pIn->AttachGuiApp.hAppWindow; ppReply->AttachGuiApp.hSrvConWnd = pRCon->ConWnd(); ppReply->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(gpConEmu->mn_MainThreadId); ZeroStruct(ppReply->AttachGuiApp.Styles.Shifts); CRealConsole::CorrectGuiChildRect(pIn->AttachGuiApp.Styles.nStyle, pIn->AttachGuiApp.Styles.nStyleEx, ppReply->AttachGuiApp.Styles.Shifts); } else { ppReply->AttachGuiApp.nFlags = agaf_Fail; } lbRc = TRUE; //// Отправляем //fSuccess = WriteFile( // hPipe, // handle to pipe // &Out, // buffer to write from // Out.hdr.cbSize, // number of bytes to write // &cbWritten, // number of bytes written // NULL); // not overlapped I/O break; } // CECMD_ATTACHGUIAPP case CECMD_GUICLIENTSHIFT: { pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(GuiStylesAndShifts); if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) goto wrap; ppReply->GuiAppShifts = pIn->GuiAppShifts; ZeroStruct(ppReply->GuiAppShifts.Shifts); CRealConsole::CorrectGuiChildRect(pIn->GuiAppShifts.nStyle, pIn->GuiAppShifts.nStyleEx, ppReply->GuiAppShifts.Shifts); lbRc = TRUE; break; } // CECMD_GUICLIENTSHIFT } //// Освободить память //if (pIn && (LPVOID)pIn != (LPVOID)&in) //{ // free(pIn); pIn = NULL; //} wrap: return lbRc; }
bool CConEmuUpdate::StartLocalUpdate(LPCWSTR asDownloadedPackage) { bool bRc = false; LPCWSTR pszName, pszExt; HANDLE hTarget = NULL; wchar_t *pszLocalPackage = NULL, *pszBatchFile = NULL; DWORD nLocalCRC = 0; BOOL lbDownloadRc = FALSE, lbExecuteRc = FALSE; LPCWSTR pszPackPref = L"conemupack."; size_t lnPackPref = _tcslen(pszPackPref); LPCWSTR pszSetupPref = L"conemusetup."; size_t lnSetupPref = _tcslen(pszSetupPref); _ASSERTE(gpConEmu && gpConEmu->isMainThread()); if (InUpdate() != us_NotStarted) { MBoxError(L"Checking for updates already started"); goto wrap; } if (mb_InCheckProcedure) { Assert(mb_InCheckProcedure==FALSE); goto wrap; } DeleteBadTempFiles(); Inet.Deinit(true); pszName = PointToName(asDownloadedPackage); pszExt = PointToExt(pszName); if (!pszName || !*pszName || !pszExt || !*pszExt) { AssertMsg(L"Invalid asDownloadedPackage"); goto wrap; } // Запомнить текущие параметры обновления if (!mp_Set) mp_Set = new ConEmuUpdateSettings; mp_Set->LoadFrom(&gpSet->UpdSet); mb_ManualCallMode = TRUE; // Clear possible last error { MSectionLock SC; SC.Lock(mp_LastErrorSC, TRUE); SafeFree(ms_LastErrorInfo); } ms_NewVersion[0] = 0; if ((lstrcmpni(pszName, pszPackPref, lnPackPref) == 0) && (lstrcmpi(pszExt, L".7z") == 0) && (((pszExt - pszName) - lnPackPref + 1) < sizeof(ms_NewVersion))) { // Check it was NOT installed with "Setupper" if (mp_Set->UpdateDownloadSetup() == 1) { DontEnable de; LPCWSTR pszConfirm = L"ConEmu was installed with setup!\nAre you sure to update installation with 7zip?"; int iBtn = MessageBox(NULL, pszConfirm, ms_DefaultTitle, MB_ICONEXCLAMATION|MB_SETFOREGROUND|MB_SYSTEMMODAL|MB_YESNO|MB_DEFBUTTON2); if (iBtn != IDYES) { goto wrap; } } if (!Check7zipInstalled()) goto wrap; // Error already reported // Forcing usage of 7zip package! mp_Set->isUpdateDownloadSetup = 2; //if (!CanUpdateInstallation()) //{ // // Значит 7zip обломается при попытке распаковки // goto wrap; //} // OK size_t nLen = (pszExt - pszName) - lnPackPref; wmemmove(ms_NewVersion, pszName+lnPackPref, nLen); ms_NewVersion[nLen] = 0; } else if ((lstrcmpni(pszName, pszSetupPref, lnSetupPref) == 0) && (lstrcmpi(pszExt, L".exe") == 0) && (((pszExt - pszName) - lnSetupPref + 1) < sizeof(ms_NewVersion))) { // Must be installed with "Setupper" if (mp_Set->UpdateDownloadSetup() != 1) { MBoxError(L"ConEmu was not installed with setup! Can't update!"); goto wrap; } // OK size_t nLen = (pszExt - pszName) - lnSetupPref; wmemmove(ms_NewVersion, pszName+lnSetupPref, nLen); ms_NewVersion[nLen] = 0; } else { AssertMsg(L"Invalid asDownloadedPackage (2)"); goto wrap; } // Сразу проверим, как нужно будет запускаться bNeedRunElevation = NeedRunElevation(); _wsprintf(ms_CurVersion, SKIPLEN(countof(ms_CurVersion)) L"%02u%02u%02u%s", (MVV_1%100),MVV_2,MVV_3,_T(MVV_4a)); //ms_NewVersion // StartLocalUpdate - запуск обновления из локального пакета mb_InetMode = false; mb_DroppedMode = true; pszLocalPackage = CreateTempFile(mp_Set->szUpdateDownloadPath, PointToName(asDownloadedPackage), hTarget); if (!pszLocalPackage) goto wrap; lbDownloadRc = DownloadFile(asDownloadedPackage, pszLocalPackage, hTarget, nLocalCRC, TRUE); CloseHandle(hTarget); if (!lbDownloadRc) goto wrap; if (mb_RequestTerminate) goto wrap; pszBatchFile = CreateBatchFile(pszLocalPackage); if (!pszBatchFile) goto wrap; if (!QueryConfirmation(us_ConfirmUpdate)) { goto wrap; } Assert(mb_ManualCallMode==TRUE); Assert(mpsz_PendingBatchFile==NULL); mpsz_PendingPackageFile = pszLocalPackage; pszLocalPackage = NULL; mpsz_PendingBatchFile = pszBatchFile; pszBatchFile = NULL; m_UpdateStep = us_ExitAndUpdate; if (gpConEmu) gpConEmu->RequestExitUpdate(); lbExecuteRc = TRUE; wrap: _ASSERTE(mpsz_DeleteIniFile==NULL); _ASSERTE(mpsz_DeletePackageFile==NULL); mpsz_DeletePackageFile = NULL; if (pszLocalPackage) { if (*pszLocalPackage && (!lbDownloadRc || (!lbExecuteRc && !mp_Set->isUpdateLeavePackages))) mpsz_DeletePackageFile = pszLocalPackage; //DeleteFile(pszLocalPackage); else SafeFree(pszLocalPackage); } _ASSERTE(mpsz_DeleteBatchFile==NULL); mpsz_DeleteBatchFile = NULL; if (pszBatchFile) { if (*pszBatchFile && !lbExecuteRc) mpsz_DeleteBatchFile = pszBatchFile; //DeleteFile(pszBatchFile); else SafeFree(pszBatchFile); } if (!lbExecuteRc) { m_UpdateStep = us_NotStarted; mb_DroppedMode = false; } return bRc; }
bool CBackgroundInfo::LoadBackgroundFile(bool abShowErrors) { // Пустой путь - значит БЕЗ обоев if (!*ms_BgImage) { return true; } //_ASSERTE(isMainThread()); _ASSERTE(isMainThread()); bool lRes = false; BY_HANDLE_FILE_INFORMATION inf = {0}; BITMAPFILEHEADER* pBkImgData = NULL; if (wcspbrk(ms_BgImage, L"%\\.") == NULL) { // May be "Solid color" COLORREF clr = (COLORREF)-1; if (GetColorRef(ms_BgImage, &clr)) { pBkImgData = CreateSolidImage(clr, 128, 128); } } if (!pBkImgData) { wchar_t* exPath = ExpandEnvStr(ms_BgImage); if (!exPath || !*exPath) { if (abShowErrors) { wchar_t szError[MAX_PATH*2]; DWORD dwErr = GetLastError(); _wsprintf(szError, SKIPLEN(countof(szError)) L"Can't expand environment strings:\r\n%s\r\nError code=0x%08X\r\nImage loading failed", ms_BgImage, dwErr); MBoxA(szError); } SafeFree(exPath); return false; } pBkImgData = LoadImageEx(exPath, inf); SafeFree(exPath); } if (pBkImgData) { ftBgModified = inf.ftLastWriteTime; nBgModifiedTick = GetTickCount(); //NeedBackgroundUpdate(); //MSectionLock SBG; SBG.Lock(&mcs_BgImgData); SafeFree(mp_BgImgData); mb_IsBackgroundImageValid = true; mp_BgImgData = pBkImgData; lRes = true; } return lRes; }
DWORD CConEmuUpdate::CheckProcInt() { BOOL lbDownloadRc = FALSE, lbExecuteRc = FALSE; LPCWSTR pszUpdateVerLocationSet = mp_Set->UpdateVerLocation(); wchar_t *pszUpdateVerLocation = NULL, *pszLocalPackage = NULL, *pszBatchFile = NULL; bool bTempUpdateVerLocation = false; wchar_t szSection[64], szItem[64]; wchar_t szSourceFull[1024]; wchar_t szTemplFilename[128]; wchar_t *pszSource, *pszEnd, *pszFileName; DWORD nSrcLen, nSrcCRC, nLocalCRC = 0; bool lbSourceLocal; //INT_PTR nShellRc = 0; #ifdef _DEBUG // Чтобы успел сервер проинититься и не ругался под отладчиком... if (!mb_ManualCallMode) Sleep(2500); #endif _ASSERTE(m_UpdateStep==us_NotStarted); m_UpdateStep = us_Check; DeleteBadTempFiles(); //120315 - OK, положим в архив и 64битный гуй //#ifdef _WIN64 //if (mp_Set->UpdateDownloadSetup() == 2) //{ // if (mb_ManualCallMode) // { // ReportError(L"64bit versions of ConEmu may be updated with ConEmuSetup.exe only!", 0); // } // goto wrap; //} //#endif // This implies Inet.Deinit(false) too if (!Inet.Init(this)) { goto wrap; } _wsprintf(ms_CurVersion, SKIPLEN(countof(ms_CurVersion)) L"%02u%02u%02u%s", (MVV_1%100),MVV_2,MVV_3,_T(MVV_4a)); // Загрузить информацию о файлах обновления if (IsLocalFile(pszUpdateVerLocationSet)) { pszUpdateVerLocation = (wchar_t*)pszUpdateVerLocationSet; } else { HANDLE hInfo = NULL; BOOL bInfoRc; DWORD crc; TODO("Было бы хорошо избавиться от *ini-файла* и парсить данные в памяти"); pszUpdateVerLocation = CreateTempFile(mp_Set->szUpdateDownloadPath/*L"%TEMP%"*/, L"ConEmuVersion.ini", hInfo); if (!pszUpdateVerLocation) goto wrap; bTempUpdateVerLocation = true; bInfoRc = DownloadFile(pszUpdateVerLocationSet, pszUpdateVerLocation, hInfo, crc); CloseHandle(hInfo); if (!bInfoRc) { if (!mb_ManualCallMode) { DeleteFile(pszUpdateVerLocation); SafeFree(pszUpdateVerLocation); } goto wrap; } } // Проверить версии _wcscpy_c(szSection, countof(szSection), (mp_Set->isUpdateUseBuilds==1) ? sectionConEmuStable : (mp_Set->isUpdateUseBuilds==3) ? sectionConEmuPreview : sectionConEmuDevel); _wcscpy_c(szItem, countof(szItem), (mp_Set->UpdateDownloadSetup()==1) ? L"location_exe" : L"location_arc"); if (!GetPrivateProfileString(szSection, L"version", L"", ms_NewVersion, countof(ms_NewVersion), pszUpdateVerLocation) || !*ms_NewVersion) { ReportBrokenIni(szSection, L"version", pszUpdateVerLocationSet); goto wrap; } // URL may not contain file name at all, compile it (predefined) _wsprintf(szTemplFilename, SKIPLEN(countof(szTemplFilename)) (mp_Set->UpdateDownloadSetup()==1) ? L"ConEmuSetup.%s.exe" : L"ConEmuPack.%s.7z", ms_NewVersion); if (!GetPrivateProfileString(szSection, szItem, L"", szSourceFull, countof(szSourceFull), pszUpdateVerLocation) || !*szSourceFull) { ReportBrokenIni(szSection, szItem, pszUpdateVerLocationSet); goto wrap; } GetVersionsFromIni(pszUpdateVerLocation, ms_VerOnServer, ms_CurVerInfo); if ((lstrcmpi(ms_NewVersion, ms_CurVersion) <= 0) // Если пользователь отказался от обновления в этом сеансе - не предлагать ту же версию при ежечасных проверках || (!mb_ManualCallMode && (lstrcmp(ms_NewVersion, ms_SkipVersion) == 0))) { // Новых версий нет if (mb_ManualCallMode) { wchar_t szFull[300]; _wsprintf(szFull, SKIPLEN(countof(szFull)) L"Your current ConEmu version is %s\n\n" L"Versions on server\n%s\n\n" L"No newer %s version is available", ms_CurVerInfo, ms_VerOnServer, (mp_Set->isUpdateUseBuilds==1) ? L"stable" : (mp_Set->isUpdateUseBuilds==3) ? L"preview" : L"developer", 0); ReportError(szFull, 0); } if (bTempUpdateVerLocation && pszUpdateVerLocation && *pszUpdateVerLocation) { DeleteFile(pszUpdateVerLocation); SafeFree(pszUpdateVerLocation); } goto wrap; } pszSource = szSourceFull; nSrcLen = wcstoul(pszSource, &pszEnd, 10); if (!nSrcLen || !pszEnd || *pszEnd != L',' || *(pszEnd+1) != L'x') { ReportError(L"Invalid format in version description (size)\n%s", szSourceFull, 0); goto wrap; } mn_PackageSize = nSrcLen; pszSource = pszEnd+2; nSrcCRC = wcstoul(pszSource, &pszEnd, 16); if (!nSrcCRC || !pszEnd || *pszEnd != L',') { ReportError(L"Invalid format in version description (CRC32)\n%s", szSourceFull, 0); goto wrap; } pszSource = pszEnd+1; lbSourceLocal = IsLocalFile(pszSource); if (mb_RequestTerminate) goto wrap; // It returns true, if updating with "exe" installer. if (!Check7zipInstalled()) goto wrap; // Error already reported if (!QueryConfirmation(us_ConfirmDownload, pszSource)) { // Если пользователь отказался от обновления в этом сеансе - не предлагать ту же версию при ежечасных проверках wcscpy_c(ms_SkipVersion, ms_NewVersion); goto wrap; } mn_InternetContentReady = 0; m_UpdateStep = us_Downloading; // May be null, if update package was dropped on ConEmu icon if (gpConEmu && ghWnd) { gpConEmu->UpdateProgress(); } pszFileName = wcsrchr(pszSource, lbSourceLocal ? L'\\' : L'/'); if (!pszFileName) { ReportError(L"Invalid source url\n%s", szSourceFull, 0); goto wrap; } else { // Загрузить пакет обновления pszFileName++; // пропустить слеш HANDLE hTarget = NULL; pszLocalPackage = CreateTempFile(mp_Set->szUpdateDownloadPath, szTemplFilename, hTarget); if (!pszLocalPackage) goto wrap; lbDownloadRc = DownloadFile(pszSource, pszLocalPackage, hTarget, nLocalCRC, TRUE); if (lbDownloadRc) { wchar_t szInfo[2048]; LARGE_INTEGER liSize = {}; if (!GetFileSizeEx(hTarget, &liSize) || liSize.HighPart || liSize.LowPart != nSrcLen) { _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"%s\nRequired size=%u, local size=%u", pszSource, nSrcLen, liSize.LowPart); ReportError(L"Downloaded file does not match\n%s\n%s", pszLocalPackage, szInfo, 0); lbDownloadRc = FALSE; } else if (nLocalCRC != nSrcCRC) { _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Required CRC32=x%08X, local CRC32=x%08X", nSrcCRC, nLocalCRC); ReportError(L"Invalid local file\n%s\n%s", pszLocalPackage, szInfo, 0); lbDownloadRc = FALSE; } } CloseHandle(hTarget); if (!lbDownloadRc) goto wrap; } Inet.Deinit(true); if (mb_RequestTerminate) goto wrap; pszBatchFile = CreateBatchFile(pszLocalPackage); if (!pszBatchFile) goto wrap; /* nShellRc = (INT_PTR)ShellExecute(ghWnd, bNeedRunElevation ? L"runas" : L"open", pszBatchFile, NULL, NULL, SW_SHOWMINIMIZED); if (nShellRc <= 32) { ReportError(L"Failed to start update batch\n%s\nError code=%i", pszBatchFile, (int)nShellRc); goto wrap; } */ if (!QueryConfirmation(us_ConfirmUpdate)) { // Если пользователь отказался от обновления в этом сеансе - не предлагать ту же версию при ежечасных проверках wcscpy_c(ms_SkipVersion, ms_NewVersion); goto wrap; } mpsz_PendingPackageFile = pszLocalPackage; pszLocalPackage = NULL; mpsz_PendingBatchFile = pszBatchFile; pszBatchFile = NULL; m_UpdateStep = us_ExitAndUpdate; if (gpConEmu) gpConEmu->RequestExitUpdate(); lbExecuteRc = TRUE; wrap: _ASSERTE(mpsz_DeleteIniFile==NULL); mpsz_DeleteIniFile = NULL; if (bTempUpdateVerLocation && pszUpdateVerLocation) { if (*pszUpdateVerLocation) mpsz_DeleteIniFile = pszUpdateVerLocation; //DeleteFile(pszUpdateVerLocation); else SafeFree(pszUpdateVerLocation); } _ASSERTE(mpsz_DeletePackageFile==NULL); mpsz_DeletePackageFile = NULL; if (pszLocalPackage) { if (*pszLocalPackage && (!lbDownloadRc || (!lbExecuteRc && !mp_Set->isUpdateLeavePackages))) mpsz_DeletePackageFile = pszLocalPackage; //DeleteFile(pszLocalPackage); else SafeFree(pszLocalPackage); } _ASSERTE(mpsz_DeleteBatchFile==NULL); mpsz_DeleteBatchFile = NULL; if (pszBatchFile) { if (*pszBatchFile && !lbExecuteRc) mpsz_DeleteBatchFile = pszBatchFile; //DeleteFile(pszBatchFile); else SafeFree(pszBatchFile); } if (!lbExecuteRc) m_UpdateStep = us_NotStarted; Inet.Deinit(true); mb_InCheckProcedure = FALSE; return 0; }
// // IDataObject::GetData // HRESULT __stdcall CDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium) { int idx; #ifdef _DEBUG wchar_t szDbg[200]; #endif // // try to match the requested FORMATETC with one of our supported formats // if ((idx = LookupFormatEtc(pFormatEtc)) == -1) { #ifdef _DEBUG _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"!!! CDataObject::LookupFormatEtc(%s) failed\n", GetFormatName(pFormatEtc->cfFormat)); DEBUGSTRDATA(szDbg); #endif return DV_E_FORMATETC; } #ifdef _DEBUG _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"CDataObject::GetData {cfFormat=%s, lindex=%i, tymed=x%02X(%u)})", GetFormatName(pFormatEtc->cfFormat), pFormatEtc->lindex, pFormatEtc->tymed, pFormatEtc->tymed); LPCWSTR pszName = GetFormatName(pFormatEtc->cfFormat, true); DWORD nData = (DWORD)-1; if (lstrcmp(pszName, L"IsShowingLayered")==0 || lstrcmp(pszName, L"IsShowingText")==0 || lstrcmp(pszName, L"DragContext")==0 || lstrcmp(pszName, L"UsingDefaultDragImage")==0 || lstrcmp(pszName, L"DragSourceHelperFlags")==0 || lstrcmp(pszName, L"DragWindow")==0 || lstrcmp(pszName, L"DisableDragText")==0 ) { LPDWORD pdw = (LPDWORD)GlobalLock(m_Data[idx].StgMedium.hGlobal); if (pdw) { nData = *pdw; int nLen = lstrlen(szDbg); _wsprintf(szDbg+nLen, SKIPLEN(countof(szDbg)-nLen) L", Data=x%02X(%u)", nData, nData); } GlobalUnlock(m_Data[idx].StgMedium.hGlobal); } wcscat_c(szDbg, L"\n"); DEBUGSTRDATA(szDbg); #endif HRESULT hr = DV_E_FORMATETC; switch (m_Data[idx].FormatEtc.tymed) { case TYMED_HGLOBAL: //ReleaseStgMedium(pMedium); pMedium->hGlobal = DupMem(m_Data[idx].StgMedium.hGlobal); pMedium->pUnkForRelease = NULL; // m_Data[idx].StgMedium.pUnkForRelease; hr = S_OK; break; case TYMED_ISTREAM: _ASSERTE(pMedium->pstm != m_Data[idx].StgMedium.pstm); //ReleaseStgMedium(pMedium); pMedium->pstm = m_Data[idx].StgMedium.pstm; if (m_Data[idx].StgMedium.pstm) m_Data[idx].StgMedium.pstm->AddRef(); pMedium->pUnkForRelease = m_Data[idx].StgMedium.pUnkForRelease; hr = S_OK; break; case TYMED_ISTORAGE: _ASSERTE(pMedium->pstg != m_Data[idx].StgMedium.pstg); //ReleaseStgMedium(pMedium); pMedium->pstg = m_Data[idx].StgMedium.pstg; if (m_Data[idx].StgMedium.pstg) m_Data[idx].StgMedium.pstg->AddRef(); pMedium->pUnkForRelease = m_Data[idx].StgMedium.pUnkForRelease; hr = S_OK; break; default: AssertMsg(L"Unsupported value in m_Data[idx].FormatEtc.tymed"); } if (hr == S_OK) { // // found a match! transfer the data into the supplied storage-medium // pMedium->tymed = m_Data[idx].FormatEtc.tymed; //Assert(pMedium->pUnkForRelease==NULL && m_Data[idx].StgMedium.pUnkForRelease==NULL); //pMedium->pUnkForRelease = NULL; } else { #ifdef _DEBUG _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"!!! CDataObject::GetData(tymed=%u) failed", m_Data[idx].FormatEtc.tymed); DEBUGSTRDATA(szDbg); //_ASSERTE(FALSE && "Unsupported tymed!"); #endif } return hr; }
CConEmuUpdate::~CConEmuUpdate() { if (mh_CheckThread) { DWORD nWait; if ((nWait = WaitForSingleObject(mh_CheckThread, 0)) == WAIT_TIMEOUT) { RequestTerminate(); nWait = WaitForSingleObject(mh_CheckThread, UPDATETHREADTIMEOUT); } if (nWait != WAIT_OBJECT_0) { TerminateThread(mh_CheckThread, 100); } CloseHandle(mh_CheckThread); mh_CheckThread = NULL; } //if (mh_StopThread) //{ // CloseHandle(mh_StopThread); // mh_StopThread = NULL; //} DeleteBadTempFiles(); Inet.Deinit(true); SafeFree(ms_LastErrorInfo); if (mp_LastErrorSC) { delete mp_LastErrorSC; mp_LastErrorSC = NULL; } if (m_UpdateStep == us_ExitAndUpdate && mpsz_PendingBatchFile) { WaitAllInstances(); wchar_t *pszCmd = lstrdup(L"cmd.exe"); // Мало ли что в ComSpec пользователь засунул... size_t cchParmMax = lstrlen(mpsz_PendingBatchFile)+16; wchar_t *pszParm = (wchar_t*)calloc(cchParmMax,sizeof(*pszParm)); // Обязательно двойное окавычивание. cmd.exe отбрасывает кавычки, // и при наличии разделителей (пробелы, скобки,...) получаем проблемы _wsprintf(pszParm, SKIPLEN(cchParmMax) L"/c \"\"%s\"\"", mpsz_PendingBatchFile); // Наверное на Elevated процесс это не распространится, но для четкости - взведем флажок SetEnvironmentVariable(ENV_CONEMU_INUPDATE, ENV_CONEMU_INUPDATE_YES); // ghWnd уже закрыт INT_PTR nShellRc = (INT_PTR)ShellExecute(NULL, bNeedRunElevation ? L"runas" : L"open", pszCmd, pszParm, NULL, SW_SHOWMINIMIZED); if (nShellRc <= 32) { wchar_t szErrInfo[MAX_PATH*4]; _wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Failed to start update batch\n%s\nError code=%i", mpsz_PendingBatchFile, (int)nShellRc); MessageBoxW(NULL, szErrInfo, L"ConEmu", MB_ICONSTOP|MB_SYSTEMMODAL); DeleteFile(mpsz_PendingBatchFile); if (!(mp_Set && mp_Set->isUpdateLeavePackages)) DeleteFile(mpsz_PendingPackageFile); } SafeFree(pszCmd); SafeFree(pszParm); } SafeFree(mpsz_PendingBatchFile); SafeFree(mpsz_PendingPackageFile); if (mp_Set) { delete mp_Set; mp_Set = NULL; } }
// Вызывается для инициализации из Settings::LoadSettings() HWND CConEmuInside::InsideFindParent() { bool bFirstStep = true; DWORD nParentPID = 0; if (!m_InsideIntegration) { return NULL; } if (mh_InsideParentWND) { if (IsWindow(mh_InsideParentWND)) { if (m_InsideIntegration == ii_Simple) { if (mh_InsideParentRoot == NULL) { // Если еще не искали "корневое" окно HWND hParent = mh_InsideParentWND; while (hParent) { mh_InsideParentRoot = hParent; hParent = GetParent(hParent); } } // В этом режиме занимаем всю клиентскую область _ASSERTE(mh_InsideParentRel==NULL); mh_InsideParentRel = NULL; } _ASSERTE(mh_InsideParentWND!=NULL); goto wrap; } else { if (m_InsideIntegration == ii_Simple) { DisplayLastError(L"Specified window not found"); mh_InsideParentWND = NULL; goto wrap; } _ASSERTE(IsWindow(mh_InsideParentWND)); mh_InsideParentRoot = mh_InsideParentWND = mh_InsideParentRel = NULL; } } _ASSERTE(m_InsideIntegration!=ii_Simple); if (mn_InsideParentPID) { PROCESSENTRY32 pi = {sizeof(pi)}; if ((mn_InsideParentPID == GetCurrentProcessId()) || !GetProcessInfo(mn_InsideParentPID, &pi)) { DisplayLastError(L"Invalid parent process specified"); m_InsideIntegration = ii_None; mh_InsideParentWND = NULL; goto wrap; } nParentPID = mn_InsideParentPID; } else { PROCESSENTRY32 pi = {sizeof(pi)}; if (!GetProcessInfo(GetCurrentProcessId(), &pi) || !pi.th32ParentProcessID) { DisplayLastError(L"GetProcessInfo(GetCurrentProcessId()) failed"); m_InsideIntegration = ii_None; mh_InsideParentWND = NULL; goto wrap; } nParentPID = pi.th32ParentProcessID; } EnumWindows(EnumInsideFindParent, nParentPID); if (!mh_InsideParentRoot) { int nBtn = MsgBox(L"Can't find appropriate parent window!\n\nContinue in normal mode?", MB_ICONSTOP|MB_YESNO|MB_DEFBUTTON2); if (nBtn != IDYES) { mh_InsideParentWND = INSIDE_PARENT_NOT_FOUND; return mh_InsideParentWND; // Закрыться! } // Продолжить в обычном режиме m_InsideIntegration = ii_None; mh_InsideParentWND = NULL; goto wrap; } HWND hExistConEmu; if ((hExistConEmu = InsideFindConEmu(mh_InsideParentRoot)) != NULL) { _ASSERTE(FALSE && "Continue to create tab in existing instance"); // Если в проводнике уже есть ConEmu - открыть в нем новую вкладку gpSetCls->SingleInstanceShowHide = sih_None; LPCWSTR pszCmdLine = GetCommandLine(); LPCWSTR pszCmd = StrStrI(pszCmdLine, L" /cmd "); gpConEmu->RunSingleInstance(hExistConEmu, pszCmd ? (pszCmd + 6) : NULL); mh_InsideParentWND = INSIDE_PARENT_NOT_FOUND; return mh_InsideParentWND; // Закрыться! } // Теперь нужно найти дочерние окна // 1. в которое будем внедряться // 2. по которому будем позиционироваться // 3. для синхронизации текущего пути InsideFindShellView(mh_InsideParentRoot); RepeatCheck: if (!mh_InsideParentWND || (!mh_InsideParentRel && (m_InsideIntegration == ii_Explorer))) { wchar_t szAddMsg[128] = L"", szMsg[1024]; if (bFirstStep) { bFirstStep = false; if (TurnExplorerTipPane(szAddMsg)) { goto RepeatCheck; } } //MessageBox(L"Can't find appropriate shell window!", MB_ICONSTOP); _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"%sCan't find appropriate shell window!\nUnrecognized layout of the Explorer.\n\nContinue in normal mode?", szAddMsg); int nBtn = MsgBox(szMsg, MB_ICONSTOP|MB_YESNO|MB_DEFBUTTON2); if (nBtn != IDYES) { mh_InsideParentWND = INSIDE_PARENT_NOT_FOUND; return mh_InsideParentWND; // Закрыться! } m_InsideIntegration = ii_None; mh_InsideParentRoot = NULL; mh_InsideParentWND = NULL; goto wrap; } wrap: if (!mh_InsideParentWND) { m_InsideIntegration = ii_None; mh_InsideParentRoot = NULL; } else { GetWindowThreadProcessId(mh_InsideParentWND, &mn_InsideParentPID); // Для мониторинга папки GetCurrentDirectory(countof(ms_InsideParentPath), ms_InsideParentPath); int nLen = lstrlen(ms_InsideParentPath); if ((nLen > 3) && (ms_InsideParentPath[nLen-1] == L'\\')) { ms_InsideParentPath[nLen-1] = 0; } } return mh_InsideParentWND; }
wchar_t* CConEmuUpdate::CreateBatchFile(LPCWSTR asPackage) { BOOL lbRc = FALSE; HANDLE hBatch = NULL; wchar_t* pszBatch = NULL; wchar_t* pszCommand = NULL; BOOL lbWrite; DWORD nLen, nWritten; char szOem[4096]; LPCWSTR pszFormat = NULL; size_t cchCmdMax = 0; wchar_t szPID[16]; _wsprintf(szPID, SKIPLEN(countof(szPID)) L"%u", GetCurrentProcessId()); wchar_t szCPU[4]; wcscpy_c(szCPU, WIN3264TEST(L"x86",L"x64")); WARNING("Битность установщика? Если ставим в ProgramFiles64 на Win64"); if (!gpConEmu) { ReportError(L"CreateBatchFile failed, gpConEmu==NULL", 0); goto wrap; } pszBatch = CreateTempFile(mp_Set->szUpdateDownloadPath, L"ConEmuUpdate.cmd", hBatch); if (!pszBatch) goto wrap; #define WRITE_BATCH_A(s) \ nLen = lstrlenA(s); \ lbWrite = WriteFile(hBatch, s, nLen, &nWritten, NULL); \ if (!lbWrite || (nLen != nWritten)) { ReportError(L"WriteBatch failed, code=%u", GetLastError()); goto wrap; } #define WRITE_BATCH_W(s) \ nLen = WideCharToMultiByte(CP_OEMCP, 0, s, -1, szOem, countof(szOem), NULL, NULL); \ if (!nLen) { ReportError(L"WideCharToMultiByte failed, len=%i", lstrlen(s)); goto wrap; } \ WRITE_BATCH_A(szOem); WRITE_BATCH_A("@echo off\r\n"); // "set ConEmuInUpdate=YES" WRITE_BATCH_W(L"\r\nset " ENV_CONEMU_INUPDATE L"=" ENV_CONEMU_INUPDATE_YES L"\r\n"); WRITE_BATCH_A("cd /d \""); WRITE_BATCH_W(gpConEmu->ms_ConEmuExeDir); WRITE_BATCH_A("\\\"\r\necho Current folder\r\ncd\r\necho .\r\n\r\necho Starting update...\r\n"); // Формат. pszFormat = (mp_Set->UpdateDownloadSetup()==1) ? mp_Set->UpdateExeCmdLine() : mp_Set->UpdateArcCmdLine(); // Замена %1 и т.п. for (int s = 0; s < 2; s++) { // На первом шаге - считаем требуемый размер под pszCommand, на втором - формируем команду if (s) { if (!cchCmdMax) { ReportError(L"Invalid %s update command (%s)", (mp_Set->UpdateDownloadSetup()==1) ? L"exe" : L"arc", pszFormat, 0); goto wrap; } pszCommand = (wchar_t*)malloc((cchCmdMax+1)*sizeof(wchar_t)); } wchar_t* pDst = pszCommand; LPCWSTR pszMacro; for (LPCWSTR pSrc = pszFormat; *pSrc; pSrc++) { switch (*pSrc) { case L'%': pSrc++; switch (*pSrc) { case L'%': pszMacro = L"%"; break; // "%1"-archive or setup file, "%2"-ConEmu.exe folder, "%3"-x86/x64, "%4"-ConEmu PID case L'1': pszMacro = asPackage; break; case L'2': pszMacro = gpConEmu->ms_ConEmuExeDir; break; case L'3': pszMacro = szCPU; break; case L'4': pszMacro = szPID; break; default: // Недопустимый управляющий символ, это может быть переменная окружения pszMacro = NULL; pSrc--; if (s) *(pDst++) = L'%'; else cchCmdMax++; } if (pszMacro) { size_t cchLen = _tcslen(pszMacro); if (s) { _wcscpy_c(pDst, cchLen+1, pszMacro); pDst += cchLen; } else { cchCmdMax += cchLen; } } break; default: if (s) *(pDst++) = *pSrc; else cchCmdMax++; } } if (s) *pDst = 0; } // Выполнить команду обновления WRITE_BATCH_A("echo "); WRITE_BATCH_W(pszCommand); WRITE_BATCH_A("\r\ncall "); WRITE_BATCH_W(pszCommand); WRITE_BATCH_A("\r\nif errorlevel 1 goto err\r\n"); // Если юзер просил что-то выполнить после распаковки установки if (mp_Set->szUpdatePostUpdateCmd && *mp_Set->szUpdatePostUpdateCmd) { WRITE_BATCH_A("\r\n"); WRITE_BATCH_W(mp_Set->szUpdatePostUpdateCmd); WRITE_BATCH_A("\r\n"); } // Сброс переменной окружения: "set ConEmuInUpdate=" WRITE_BATCH_W(L"\r\nset " ENV_CONEMU_INUPDATE L"=\r\n"); // Перезапуск ConEmu WRITE_BATCH_A("\r\necho Starting ConEmu...\r\nstart \"ConEmu\" \""); WRITE_BATCH_W(gpConEmu->ms_ConEmuExe); WRITE_BATCH_A("\" "); if (bNeedRunElevation) { WRITE_BATCH_A("/demote /cmd \""); WRITE_BATCH_W(gpConEmu->ms_ConEmuExe); WRITE_BATCH_A("\" "); } if (gpConEmu->mpsz_ConEmuArgs) { WRITE_BATCH_W(gpConEmu->mpsz_ConEmuArgs); } // Fin WRITE_BATCH_A("\r\ngoto fin\r\n"); // Сообщение об ошибке? WRITE_BATCH_A("\r\n:err\r\n"); WRITE_BATCH_A((mp_Set->UpdateDownloadSetup()==1) ? "echo \7Installation failed\7" : "echo \7Extraction failed\7\r\n"); WRITE_BATCH_A("\r\npause\r\n:fin\r\n"); // Грохнуть пакет обновления if (!mp_Set->isUpdateLeavePackages) { WRITE_BATCH_A("del \""); WRITE_BATCH_W(asPackage); WRITE_BATCH_A("\"\r\n"); } // Грохнуть сам батч и позвать "exit" чтобы в консоли // не появлялось "Batch not found" при попытке выполнить следующую строку файла WRITE_BATCH_A("del \"%~0\" & exit\r\n"); //// Для отладки //WRITE_BATCH_A("\r\npause\r\n"); // Succeeded lbRc = TRUE; wrap: SafeFree(pszCommand); if (!lbRc) { SafeFree(pszBatch); } if (hBatch && hBatch != INVALID_HANDLE_VALUE) { CloseHandle(hBatch); } return pszBatch; }
LRESULT CConEmuChild::BackWndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam) { LRESULT result = 0; // Logger MSG msgStr = {hWnd, messg, wParam, lParam}; ConEmuMsgLogger::Log(msgStr, ConEmuMsgLogger::msgBack); if (gpSetCls->isAdvLogging >= 4) { gpConEmu->LogMessage(hWnd, messg, wParam, lParam); } CVConGuard guard; CVirtualConsole* pVCon = NULL; if (messg == WM_CREATE || messg == WM_NCCREATE) { LPCREATESTRUCT lp = (LPCREATESTRUCT)lParam; guard = (CVirtualConsole*)lp->lpCreateParams; pVCon = guard.VCon(); if (pVCon) gVConBkMap.Set(hWnd, pVCon); } else if (hWnd != ghBkInDestroing) { if (!gVConBkMap.Get(hWnd, &pVCon) || !guard.Attach(pVCon)) pVCon = NULL; } if (messg == WM_SYSCHAR) { _ASSERTE(FALSE); // по идее, фокуса тут быть не должно // Чтобы не пищало result = TRUE; goto wrap; } if (!pVCon) { _ASSERTE(pVCon!=NULL || hWnd==ghBkInDestroing); result = DefWindowProc(hWnd, messg, wParam, lParam); goto wrap; } switch (messg) { case WM_SHOWWINDOW: if (wParam) { HWND hView = pVCon->GetView(); SetWindowPos(hView, HWND_TOP, 0, 0, 0,0, SWP_NOSIZE|SWP_NOMOVE); SetWindowPos(hWnd, hView, 0, 0, 0,0, SWP_NOSIZE|SWP_NOMOVE); } break; // DefaultProc case WM_SETFOCUS: // Если в консоли работает "GUI" окно (GUI режим), то фокус нужно отдать туда. { // Фокус должен быть в главном окне! За исключением случая работы в GUI режиме. pVCon->setFocus(); } return 0; case WM_ERASEBKGND: result = 0; break; case WM_PAINT: _ASSERTE(hWnd == pVCon->mh_WndBack); pVCon->OnPaintGaps(); break; case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_MOUSEWHEEL: case WM_ACTIVATE: case WM_ACTIVATEAPP: //case WM_MOUSEACTIVATE: case WM_KILLFOCUS: //case WM_SETFOCUS: case WM_MOUSEMOVE: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_XBUTTONDOWN: case WM_XBUTTONUP: case WM_XBUTTONDBLCLK: case WM_VSCROLL: // Вся обработка в родителе { switch (messg) { case WM_VSCROLL: switch (LOWORD(wParam)) { case SB_THUMBTRACK: case SB_THUMBPOSITION: pVCon->mb_VTracking = TRUE; break; case SB_ENDSCROLL: pVCon->mb_VTracking = FALSE; break; } pVCon->RCon()->OnSetScrollPos(wParam); break; case WM_LBUTTONUP: pVCon->mb_VTracking = FALSE; break; } TODO("Обработка ghWndWork"); HWND hParent = ghWnd; _ASSERTE(GetParent(hWnd)==ghWnd); if (messg >= WM_MOUSEFIRST && messg <= WM_MOUSELAST) { POINT pt = {LOWORD(lParam),HIWORD(lParam)}; MapWindowPoints(hWnd, hParent, &pt, 1); lParam = MAKELONG(pt.x,pt.y); } result = gpConEmu->WndProc(hParent, messg, wParam, lParam); } break; case WM_IME_NOTIFY: break; case WM_INPUTLANGCHANGE: case WM_INPUTLANGCHANGEREQUEST: { #ifdef _DEBUG if (IsDebuggerPresent()) { WCHAR szMsg[128]; _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"InChild %s(CP:%i, HKL:0x%08X)\n", (messg == WM_INPUTLANGCHANGE) ? L"WM_INPUTLANGCHANGE" : L"WM_INPUTLANGCHANGEREQUEST", (DWORD)wParam, (DWORD)lParam); DEBUGSTRLANG(szMsg); } #endif result = DefWindowProc(hWnd, messg, wParam, lParam); } break; #ifdef _DEBUG case WM_WINDOWPOSCHANGING: { WINDOWPOS* pwp = (WINDOWPOS*)lParam; result = DefWindowProc(hWnd, messg, wParam, lParam); } return result; case WM_WINDOWPOSCHANGED: { WINDOWPOS* pwp = (WINDOWPOS*)lParam; result = DefWindowProc(hWnd, messg, wParam, lParam); } break; #endif case WM_SETCURSOR: { gpConEmu->WndProc(hWnd, messg, wParam, lParam); //if (!result) // result = DefWindowProc(hWnd, messg, wParam, lParam); } // If an application processes this message, it should return TRUE to halt further processing or FALSE to continue. break; case WM_SYSCOMMAND: // -- лишние ограничения, похоже result = DefWindowProc(hWnd, messg, wParam, lParam); //if (wParam >= SC_SIZE && wParam <= SC_CONTEXTHELP/*0xF180*/) //{ // // Изменение размеров/максимизация/и т.п. окна консоли - запрещена // _ASSERTE(!(wParam >= SC_SIZE && wParam <= SC_CONTEXTHELP)); //} //else //{ // // По идее, сюда ничего приходить больше не должно // _ASSERTE(FALSE); //} break; case WM_GESTURENOTIFY: case WM_GESTURE: { gpConEmu->ProcessGestureMessage(hWnd, messg, wParam, lParam, result); break; } // case WM_GESTURE, WM_GESTURENOTIFY default: if (pVCon && (messg == pVCon->mn_MsgRestoreChildFocus)) { if (!gpConEmu->CanSetChildFocus()) { // Клик по иконке открывает системное меню //_ASSERTE(FALSE && "Must not get here?"); } else { CRealConsole* pRCon = pVCon->RCon(); if (gpConEmu->isActive(pVCon, false)) { pRCon->GuiWndFocusRestore(); } if (pRCon->GuiWnd()) { pRCon->StoreGuiChildRect(NULL); } } } else { result = DefWindowProc(hWnd, messg, wParam, lParam); } } wrap: return result; }
LRESULT TrayIcon::OnTryIcon(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam) { #ifdef _DEBUG wchar_t szMsg[128]; #endif switch (lParam) { case WM_LBUTTONUP: case NIN_BALLOONUSERCLICK: #ifdef _DEBUG _wsprintf(szMsg, SKIPLEN(countof(szMsg)) (lParam==WM_LBUTTONUP) ? L"TSA: WM_LBUTTONUP(%i,0x%08X)\n" : L"TSA: NIN_BALLOONUSERCLICK(%i,0x%08X)\n", (int)wParam, (DWORD)lParam); DEBUGSTRICON(szMsg); #endif if (gpSet->isQuakeStyle) { SingleInstanceShowHideType sih = sih_ShowHideTSA; if (IsWindowVisible(ghWnd)) { if (gpSet->isAlwaysOnTop || (gpSet->isQuakeStyle == 2)) { sih = sih_HideTSA; } else { // Хм. Тут проблема. Если поверх ConEmu есть какое-то окно, то ConEmu нужно поднять? } } gpConEmu->OnMinimizeRestore(sih); } else Icon.RestoreWindowFromTray(); if (m_MsgSource == tsa_Source_Updater) { m_MsgSource = tsa_Source_None; gpConEmu->CheckUpdates(2); } break; case NIN_BALLOONSHOW: #ifdef _DEBUG _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: NIN_BALLOONSHOW(%i,0x%08X)\n", (int)wParam, (DWORD)lParam); DEBUGSTRICON(szMsg); #endif mn_BalloonShowTick = GetTickCount(); break; case NIN_BALLOONTIMEOUT: { #ifdef _DEBUG _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: NIN_BALLOONTIMEOUT(%i,0x%08X)\n", (int)wParam, (DWORD)lParam); DEBUGSTRICON(szMsg); #endif if (mb_SecondTimeoutMsg || (mn_BalloonShowTick && ((GetTickCount() - mn_BalloonShowTick) > MY_BALLOON_TICK))) { m_MsgSource = tsa_Source_None; Icon.RestoreWindowFromTray(TRUE); } else if (!mb_SecondTimeoutMsg && (mn_BalloonShowTick && ((GetTickCount() - mn_BalloonShowTick) > MY_BALLOON_TICK))) { mb_SecondTimeoutMsg = true; } } break; case WM_RBUTTONUP: { #ifdef _DEBUG _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: WM_RBUTTONUP(%i,0x%08X)\n", (int)wParam, (DWORD)lParam); DEBUGSTRICON(szMsg); #endif POINT mPos; GetCursorPos(&mPos); apiSetForegroundWindow(ghWnd); gpConEmu->ShowSysmenu(mPos.x, mPos.y); PostMessage(hWnd, WM_NULL, 0, 0); } break; #ifdef _DEBUG default: _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: OnTryIcon(uMsg, wParam=%i, lParam=0x%04X)\n", messg, (int)wParam, (DWORD)lParam); DEBUGSTRICON(szMsg); #endif } return 0; }
bool GetAliases(wchar_t* asExeName, wchar_t** rsAliases, LPDWORD rnAliasesSize) { bool lbRc = false; DWORD nAliasRC, nAliasErr, nAliasAErr = 0, nSizeA = 0; _ASSERTE(asExeName && rsAliases && rnAliasesSize); _ASSERTE(*rsAliases == NULL); *rnAliasesSize = GetConsoleAliasesLength(asExeName); if (*rnAliasesSize == 0) { lbRc = true; } else { *rsAliases = (wchar_t*)calloc(*rnAliasesSize+2,1); nAliasRC = GetConsoleAliases(*rsAliases,*rnAliasesSize,asExeName); if (nAliasRC) { lbRc = true; } else { nAliasErr = GetLastError(); if (nAliasErr == ERROR_NOT_ENOUGH_MEMORY) { // Попробовать ANSI функции UINT nCP = CP_OEMCP; char szExeName[MAX_PATH+1]; char *pszAliases = NULL; WideCharToMultiByte(nCP,0,asExeName,-1,szExeName,MAX_PATH+1,0,0); nSizeA = GetConsoleAliasesLengthA(szExeName); if (nSizeA) { pszAliases = (char*)calloc(nSizeA+1,1); nAliasRC = GetConsoleAliasesA(pszAliases,nSizeA,szExeName); if (nAliasRC) { lbRc = true; MultiByteToWideChar(nCP,0,pszAliases,nSizeA,*rsAliases,((*rnAliasesSize)/2)+1); } else { nAliasAErr = GetLastError(); } free(pszAliases); } } if (!nAliasRC) { if ((*rnAliasesSize) < 255) { free(*rsAliases); *rsAliases = (wchar_t*)calloc(128,2); } _wsprintf(*rsAliases, SKIPLEN(127) L"\nConEmuC: GetConsoleAliases failed, ErrCode=0x%08X(0x%08X), AliasesLength=%i(%i)\n\n", nAliasErr, nAliasAErr, *rnAliasesSize, nSizeA); } } } return lbRc; }
int main(int argc, char** argv) { int iRc = 0; HMODULE hConEmu; char szErrInfo[512]; DWORD dwErr, dwOut; typedef int (__stdcall* ConsoleMain2_t)(BOOL abAlternative); ConsoleMain2_t lfConsoleMain2; #if defined(SHOW_STARTED_MSGBOX) if (!IsDebuggerPresent()) { wchar_t szTitle[100]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) WIN3264TEST(L"ConEmuC",L"ConEmuC64") L" Loaded (PID=%i)", GetCurrentProcessId()); const wchar_t* pszCmdLine = GetCommandLineW(); MessageBox(NULL,pszCmdLine,szTitle,0); } #endif // Обязательно, иначе по CtrlC мы свалимся SetConsoleCtrlHandler((PHANDLER_ROUTINE)HandlerRoutine, true); #ifdef _DEBUG UnitTests(); #endif hConEmu = LoadLibrary(WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll")); dwErr = GetLastError(); if (!hConEmu) { _wsprintfA(szErrInfo, SKIPLEN(countof(szErrInfo)) "Can't load library \"%s\", ErrorCode=0x%08X\n", WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll"), dwErr); WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szErrInfo, lstrlenA(szErrInfo), &dwOut, NULL); return CERR_CONEMUHK_NOTFOUND; } // Загрузить функи из ConEmuHk lfConsoleMain2 = (ConsoleMain2_t)GetProcAddress(hConEmu, "ConsoleMain2"); gfHandlerRoutine = (PHANDLER_ROUTINE)GetProcAddress(hConEmu, "HandlerRoutine"); if (!lfConsoleMain2 || !gfHandlerRoutine) { dwErr = GetLastError(); _wsprintfA(szErrInfo, SKIPLEN(countof(szErrInfo)) "Procedure \"%s\" not found in library \"%s\"", lfConsoleMain2 ? "HandlerRoutine" : "ConsoleMain2", WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll")); WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), szErrInfo, lstrlenA(szErrInfo), &dwOut, NULL); FreeLibrary(hConEmu); return CERR_CONSOLEMAIN_NOTFOUND; } // Main dll entry point for Server & ComSpec iRc = lfConsoleMain2(0/*WorkMode*/); // Exiting gfHandlerRoutine = NULL; //FreeLibrary(hConEmu); -- Shutdown Server/Comspec уже выполнен ExitProcess(iRc); return iRc; }
// // Wrapper around WM_SETCONSOLEINFO. We need to create the // necessary section (file-mapping) object in the context of the // process which owns the console, before posting the message // BOOL SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci) { DWORD dwConsoleOwnerPid, dwCurProcId; PVOID ptrView = 0; DWORD dwLastError=0; WCHAR ErrText[255]; // // Retrieve the process which "owns" the console // dwCurProcId = GetCurrentProcessId(); DEBUGTEST(DWORD dwConsoleThreadId =) GetWindowThreadProcessId(hwndConsole, &dwConsoleOwnerPid); // We'll fail, if console was created by other process if (dwConsoleOwnerPid != dwCurProcId) { #ifdef _DEBUG // Wine related PROCESSENTRY32W pi = {}; GetProcessInfo(dwConsoleOwnerPid, &pi); if (lstrcmpi(pi.szExeFile, L"wineconsole.exe")!=0) { wchar_t szDbgMsg[512], szTitle[128]; szDbgMsg[0] = 0; GetModuleFileName(NULL, szDbgMsg, countof(szDbgMsg)); msprintf(szTitle, countof(szTitle), L"%s: PID=%u", PointToName(szDbgMsg), GetCurrentProcessId()); msprintf(szDbgMsg, countof(szDbgMsg), L"GetWindowThreadProcessId()\nPID=%u, TID=%u, %s\n%s", dwConsoleOwnerPid, dwConsoleThreadId, pi.szExeFile, szTitle); MessageBox(NULL, szDbgMsg, szTitle, MB_SYSTEMMODAL); } //_ASSERTE(dwConsoleOwnerPid == dwCurProcId); #endif return FALSE; } // // Create a SECTION object backed by page-file, then map a view of // this section into the owner process so we can write the contents // of the CONSOLE_INFO buffer into it // if (!ghConsoleSection) { ghConsoleSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, gnConsoleSectionSize, 0); if (!ghConsoleSection) { dwLastError = GetLastError(); _wsprintf(ErrText, SKIPLEN(countof(ErrText)) L"Can't CreateFileMapping(ghConsoleSection). ErrCode=%i", dwLastError); MessageBox(NULL, ErrText, L"ConEmu", MB_OK|MB_ICONSTOP|MB_SETFOREGROUND); return FALSE; } _ASSERTE(OnShutdownConsole==NULL || OnShutdownConsole==ShutdownConsole); OnShutdownConsole = ShutdownConsole; } // // Copy our console structure into the section-object // ptrView = MapViewOfFile(ghConsoleSection, FILE_MAP_WRITE|FILE_MAP_READ, 0, 0, gnConsoleSectionSize); if (!ptrView) { dwLastError = GetLastError(); _wsprintf(ErrText, SKIPLEN(countof(ErrText)) L"Can't MapViewOfFile. ErrCode=%i", dwLastError); MessageBox(NULL, ErrText, L"ConEmu", MB_OK|MB_ICONSTOP|MB_SETFOREGROUND); } else { _ASSERTE(pci->Length==sizeof(CONSOLE_INFO)); //2010-09-19 что-то на XP стало окошко мелькать. // при отсылке WM_SETCONSOLEINFO консоль отображается :( BOOL lbWasVisible = IsWindowVisible(hwndConsole); RECT rcOldPos = {0}, rcAllMonRect = {0}; if (!lbWasVisible) { GetWindowRect(hwndConsole, &rcOldPos); // В много-мониторных конфигурациях координаты на некоторых могут быть отрицательными! rcAllMonRect = GetAllMonitorsWorkspace(); pci->AutoPosition = FALSE; pci->WindowPosX = rcAllMonRect.left - 1280; pci->WindowPosY = rcAllMonRect.top - 1024; } memcpy(ptrView, pci, pci->Length); //-V106 UnmapViewOfFile(ptrView); // Send console window the "update" message DEBUGTEST(LRESULT dwConInfoRc =) SendMessage(hwndConsole, WM_SETCONSOLEINFO, (WPARAM)ghConsoleSection, 0); DEBUGTEST(DWORD dwConInfoErr = GetLastError()); if (!lbWasVisible && IsWindowVisible(hwndConsole)) { //DEBUGTEST(Sleep(10)); ShowWindow(hwndConsole, SW_HIDE); //SetWindowPos(hwndConsole, NULL, rcOldPos.left, rcOldPos.top, 0,0, SWP_NOSIZE|SWP_NOZORDER); // -- чтобы на некоторых системах не возникала проблема с позиционированием -> {0,0} // Issue 274: Окно реальной консоли позиционируется в неудобном месте SetWindowPos(hwndConsole, NULL, 0, 0, 0,0, SWP_NOSIZE|SWP_NOZORDER); } } return TRUE; }
BOOL CConEmuChild::ShowView(int nShowCmd) { if (!this || !mh_WndDC) return FALSE; BOOL bRc = FALSE; DWORD nTID = 0, nPID = 0; wchar_t sInfo[200]; // Должно быть создано в главной нити! nTID = GetWindowThreadProcessId(mh_WndDC, &nPID); #ifdef _DEBUG DWORD nMainThreadID = GetWindowThreadProcessId(ghWnd, &nPID); _ASSERTE(nTID==nMainThreadID); #endif // Если это "GUI" режим - могут возникать блокировки из-за дочернего окна CVirtualConsole* pVCon = mp_VCon; _ASSERTE(pVCon!=NULL); CVConGuard guard(pVCon); HWND hChildGUI = pVCon->GuiWnd(); BOOL bGuiVisible = (hChildGUI && nShowCmd) ? pVCon->RCon()->isGuiVisible() : FALSE; DWORD nDcShowCmd = nShowCmd; if (gpSetCls->isAdvLogging) { if (hChildGUI != NULL) _wsprintf(sInfo, SKIPLEN(countof(sInfo)) L"ShowView: Back=x%08X, DC=x%08X, ChildGUI=x%08X, ShowCMD=%u, ChildVisible=%u", (DWORD)mh_WndBack, (DWORD)mh_WndDC, (DWORD)hChildGUI, nShowCmd, bGuiVisible); else _wsprintf(sInfo, SKIPLEN(countof(sInfo)) L"ShowView: Back=x%08X, DC=x%08X, ShowCMD=%u", (DWORD)mh_WndBack, (DWORD)mh_WndDC, nShowCmd); gpConEmu->LogString(sInfo); } if (hChildGUI || (GetCurrentThreadId() != nTID)) { // Только Async, иначе можно получить dead-lock bRc = ShowWindowAsync(mh_WndBack, nShowCmd); if (bGuiVisible && !mp_VCon->RCon()->isGuiForceConView()) nDcShowCmd = SW_HIDE; bRc = ShowWindowAsync(mh_WndDC, nDcShowCmd); } else { bRc = ShowWindow(mh_WndBack, nShowCmd); bRc = ShowWindow(mh_WndDC, nShowCmd); if (nShowCmd) { SetWindowPos(mh_WndDC, HWND_TOP, 0, 0, 0,0, SWP_NOSIZE|SWP_NOMOVE); SetWindowPos(mh_WndBack, mh_WndDC, 0, 0, 0,0, SWP_NOSIZE|SWP_NOMOVE); } } if (nShowCmd && bGuiVisible) { // Если активируется таб с ChildGui if (pVCon->isActive(false)) { PostRestoreChildFocus(); } } return bRc; }
// Warning, напрямую НЕ вызывать. Пользоваться "общей" PostMacro void CPluginW2800::PostMacroApi(const wchar_t* asMacro, INPUT_RECORD* apRec, bool abShowParseErrors) { if (!InfoW2800 || !InfoW2800->AdvControl) return; MacroSendMacroText mcr = {sizeof(MacroSendMacroText)}; //mcr.Flags = 0; // По умолчанию - вывод на экран разрешен bool bEnableOutput = true; while ((asMacro[0] == L'@' || asMacro[0] == L'^') && asMacro[1] && asMacro[1] != L' ') { switch (*asMacro) { case L'@': bEnableOutput = false; break; case L'^': mcr.Flags |= KMFLAGS_NOSENDKEYSTOPLUGINS; break; } asMacro++; } if (bEnableOutput) mcr.Flags |= KMFLAGS_ENABLEOUTPUT; // This macro was not adopted to Lua? _ASSERTE(*asMacro && *asMacro != L'$'); // Вообще говоря, если тут попадается макрос в старом формате - то мы уже ничего не сделаем... // Начиная с Far 3 build 2851 - все макросы переведены на Lua mcr.SequenceText = asMacro; if (apRec) mcr.AKey = *apRec; mcr.Flags |= KMFLAGS_SILENTCHECK; if (!InfoW2800->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, MSSC_CHECK, &mcr)) { if (abShowParseErrors) { wchar_t* pszErrText = NULL; size_t iRcSize = InfoW2800->MacroControl(&guid_ConEmu, MCTL_GETLASTERROR, 0, NULL); MacroParseResult* Result = iRcSize ? (MacroParseResult*)calloc(iRcSize,1) : NULL; if (Result) { Result->StructSize = sizeof(*Result); _ASSERTE(FALSE && "Check MCTL_GETLASTERROR"); InfoW2800->MacroControl(&guid_ConEmu, MCTL_GETLASTERROR, iRcSize, Result); size_t cchMax = (Result->ErrSrc ? lstrlen(Result->ErrSrc) : 0) + lstrlen(asMacro) + 255; pszErrText = (wchar_t*)malloc(cchMax*sizeof(wchar_t)); _wsprintf(pszErrText, SKIPLEN(cchMax) L"Error in Macro. Far %u.%u build %u r%u\n" L"ConEmu plugin %02u%02u%02u%s[%u] {2800}\n" L"Code: %u, Line: %u, Col: %u%s%s\n" L"----------------------------------\n" L"%s", gFarVersion.dwVerMajor, gFarVersion.dwVerMinor, gFarVersion.dwBuild, gFarVersion.Bis ? 1 : 0, MVV_1, MVV_2, MVV_3, _CRT_WIDE(MVV_4a), WIN3264TEST(32,64), Result->ErrCode, (UINT)(int)Result->ErrPos.Y+1, (UINT)(int)Result->ErrPos.X+1, Result->ErrSrc ? L", Hint: " : L"", Result->ErrSrc ? Result->ErrSrc : L"", asMacro); SafeFree(Result); } else { size_t cchMax = lstrlen(asMacro) + 255; pszErrText = (wchar_t*)malloc(cchMax*sizeof(wchar_t)); _wsprintf(pszErrText, SKIPLEN(cchMax) L"Error in Macro. Far %u.%u build %u r%u\n" L"ConEmu plugin %02u%02u%02u%s[%u] {2800}\n" L"----------------------------------\n" L"%s", gFarVersion.dwVerMajor, gFarVersion.dwVerMinor, gFarVersion.dwBuild, gFarVersion.Bis ? 1 : 0, MVV_1, MVV_2, MVV_3, _CRT_WIDE(MVV_4a), WIN3264TEST(32,64), asMacro); } if (pszErrText) { DWORD nTID; HANDLE h = CreateThread(NULL, 0, BackgroundMacroError, pszErrText, 0, &nTID); SafeCloseHandle(h); } } } else { //gFarVersion.dwBuild InfoW2800->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, 0, &mcr); } }
// Main function of this class decodes gesture information // in: // hWnd window handle // wParam message parameter (message-specific) // lParam message parameter (message-specific) bool CGestures::ProcessGestureMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult) { if ((uMsg != WM_GESTURENOTIFY) && (uMsg != WM_GESTURE)) return false; if (!_isGestures) { _ASSERTE(_isGestures); gpConEmu->LogString(L"Gesture message received but not allowed, skipping"); return false; } if (uMsg == WM_GESTURENOTIFY) { // This is the right place to define the list of gestures that this // application will support. By populating GESTURECONFIG structure // and calling SetGestureConfig function. We can choose gestures // that we want to handle in our application. In this app we // decide to handle all gestures. GESTURECONFIG gc[] = { {GID_ZOOM, GC_ZOOM}, {GID_ROTATE, GC_ROTATE}, {GID_PAN, GC_PAN|GC_PAN_WITH_GUTTER|GC_PAN_WITH_INERTIA, GC_PAN_WITH_SINGLE_FINGER_VERTICALLY|GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY }, {GID_PRESSANDTAP, GC_PRESSANDTAP}, {GID_TWOFINGERTAP, GC_TWOFINGERTAP}, }; BOOL bResult = _SetGestureConfig(hWnd, 0, countof(gc), gc, sizeof(GESTURECONFIG)); DWORD dwErr = GetLastError(); if (gpSetCls->isAdvLogging) { wchar_t szNotify[60]; _wsprintf(szNotify, SKIPLEN(countof(szNotify)) L"SetGestureConfig -> %u,%u", bResult, dwErr); gpConEmu->LogString(szNotify); } if (!bResult) { DisplayLastError(L"Error in execution of SetGestureConfig", dwErr); } lResult = ::DefWindowProc(hWnd, WM_GESTURENOTIFY, wParam, lParam); return true; } // Остался только WM_GESTURE Assert(uMsg==WM_GESTURE); // helper variables POINT ptZoomCenter; double k; GESTUREINFO gi = {sizeof(gi)}; // Checking for compiler alignment errors if (gi.cbSize != WIN3264TEST(48,56)) { // Struct member alignment must be 8bytes even on x86 Assert(sizeof(GESTUREINFO)==WIN3264TEST(48,56)); _isGestures = false; return false; } BOOL bResult = _GetGestureInfo((HGESTUREINFO)lParam, &gi); if (!bResult) { //_ASSERT(L"_GetGestureInfo failed!" && 0); DWORD dwErr = GetLastError(); DisplayLastError(L"Error in execution of _GetGestureInfo", dwErr); return FALSE; } #ifdef USE_DUMPGEST bool bLog = (gpSetCls->isAdvLogging >= 2); UNREFERENCED_PARAMETER(bLog); bLog = true; #endif #define DUMPGEST(tp) DumpGesture(tp, gi) //#ifdef USE_DUMPGEST // wchar_t szDump[256]; // #define DUMPGEST(tp) // _wsprintf(szDump, SKIPLEN(countof(szDump)) // L"Gesture(x%08X {%i,%i} %s", // (DWORD)gi.hwndTarget, gi.ptsLocation.x, gi.ptsLocation.y, // tp); // if (gi.dwID==GID_PRESSANDTAP) { // DWORD h = LODWORD(gi.ullArguments); _wsprintf(szDump+_tcslen(szDump), SKIPLEN(32) // L" Dist={%i,%i}", (int)(short)LOWORD(h), (int)(short)HIWORD(h)); } // if (gi.dwID==GID_ROTATE) { // DWORD h = LODWORD(gi.ullArguments); _wsprintf(szDump+_tcslen(szDump), SKIPLEN(32) // L" %i", (int)LOWORD(h)); } // if (gi.dwFlags&GF_BEGIN) wcscat_c(szDump, L" GF_BEGIN"); // if (gi.dwFlags&GF_END) wcscat_c(szDump, L" GF_END"); // if (gi.dwFlags&GF_INERTIA) { wcscat_c(szDump, L" GF_INERTIA"); // DWORD h = HIDWORD(gi.ullArguments); _wsprintf(szDump+_tcslen(szDump), SKIPLEN(32) // L" {%i,%i}", (int)(short)LOWORD(h), (int)(short)HIWORD(h)); } // wcscat_c(szDump, L")\n"); // DEBUGSTR(szDump) //#else //#define DUMPGEST(s) //#endif switch (gi.dwID) { case GID_BEGIN: DUMPGEST(L"GID_BEGIN"); break; case GID_END: DUMPGEST(L"GID_END"); break; case GID_ZOOM: DUMPGEST(L"GID_ZOOM"); if (gi.dwFlags & GF_BEGIN) { _dwArguments = LODWORD(gi.ullArguments); _ptFirst.x = gi.ptsLocation.x; _ptFirst.y = gi.ptsLocation.y; ScreenToClient(hWnd,&_ptFirst); } else { // We read here the second point of the gesture. This is middle point between // fingers in this new position. _ptSecond.x = gi.ptsLocation.x; _ptSecond.y = gi.ptsLocation.y; ScreenToClient(hWnd,&_ptSecond); // We have to calculate zoom center point ptZoomCenter.x = (_ptFirst.x + _ptSecond.x)/2; ptZoomCenter.y = (_ptFirst.y + _ptSecond.y)/2; // The zoom factor is the ratio between the new and the old distance. // The new distance between two fingers is stored in gi.ullArguments // (lower DWORD) and the old distance is stored in _dwArguments. k = (double)(LODWORD(gi.ullArguments))/(double)(_dwArguments); // Now we process zooming in/out of the object ProcessZoom(hWnd, k, ptZoomCenter.x, ptZoomCenter.y); // Now we have to store new information as a starting information // for the next step in this gesture. _ptFirst = _ptSecond; _dwArguments = LODWORD(gi.ullArguments); } break; case GID_PAN: DUMPGEST(L"GID_PAN"); if (gi.dwFlags & GF_BEGIN) { _ptFirst.x = gi.ptsLocation.x; _ptFirst.y = gi.ptsLocation.y; _ptBegin.x = gi.ptsLocation.x; _ptBegin.y = gi.ptsLocation.y; ScreenToClient(hWnd, &_ptFirst); } else { // We read the second point of this gesture. It is a middle point // between fingers in this new position _ptSecond.x = gi.ptsLocation.x; _ptSecond.y = gi.ptsLocation.y; ScreenToClient(hWnd, &_ptSecond); if (!(gi.dwFlags & (GF_END/*|GF_INERTIA*/))) { // We apply move operation of the object if (ProcessMove(hWnd, _ptSecond.x-_ptFirst.x, _ptSecond.y-_ptFirst.y)) { // We have to copy second point into first one to prepare // for the next step of this gesture. _ptFirst = _ptSecond; } } } break; case GID_ROTATE: DUMPGEST(L"GID_ROTATE"); if (gi.dwFlags & GF_BEGIN) { _inRotate = false; _dwArguments = LODWORD(gi.ullArguments); // Запомним начальный угол } else { _ptFirst.x = gi.ptsLocation.x; _ptFirst.y = gi.ptsLocation.y; ScreenToClient(hWnd, &_ptFirst); // Пока угол не станет достаточным для смены таба - игнорируем if (ProcessRotate(hWnd, LODWORD(gi.ullArguments) - _dwArguments, _ptFirst.x,_ptFirst.y, ((gi.dwFlags & GF_END) == GF_END))) { _dwArguments = LODWORD(gi.ullArguments); } } break; case GID_TWOFINGERTAP: DUMPGEST(L"GID_TWOFINGERTAP"); _ptFirst.x = gi.ptsLocation.x; _ptFirst.y = gi.ptsLocation.y; ScreenToClient(hWnd,&_ptFirst); ProcessTwoFingerTap(hWnd, _ptFirst.x, _ptFirst.y, LODWORD(gi.ullArguments)); break; case GID_PRESSANDTAP: DUMPGEST(L"GID_PRESSANDTAP"); if (gi.dwFlags & GF_BEGIN) { _ptFirst.x = gi.ptsLocation.x; _ptFirst.y = gi.ptsLocation.y; ScreenToClient(hWnd,&_ptFirst); DWORD nDelta = LODWORD(gi.ullArguments); short nDeltaX = (short)LOWORD(nDelta); short nDeltaY = (short)HIWORD(nDelta); ProcessPressAndTap(hWnd, _ptFirst.x, _ptFirst.y, nDeltaX, nDeltaY); } break; default: DUMPGEST(L"GID_<UNKNOWN>"); } _CloseGestureInfoHandle((HGESTUREINFO)lParam); return TRUE; }
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); } } }