bool CConEmuUpdate::QueryConfirmationInt(LPCWSTR asConfirmInfo) { if (mb_InShowLastError || !gpConEmu) return false; // Если отображается ошибк - не звать bool lbConfirm; if (gpConEmu->isMainThread()) { Assert(!mb_InetMode && mb_ManualCallMode); DontEnable de; int iBtn = MessageBox(NULL, asConfirmInfo, ms_DefaultTitle, MB_ICONQUESTION|MB_SETFOREGROUND|MB_SYSTEMMODAL|MB_YESNO); mb_InShowLastError = false; lbConfirm = (iBtn == IDYES); } else { MSectionLock SC; SC.Lock(mp_LastErrorSC, TRUE); SafeFree(ms_LastErrorInfo); ms_LastErrorInfo = lstrdup(asConfirmInfo); SC.Unlock(); lbConfirm = gpConEmu->ReportUpdateConfirmation(); } return lbConfirm; }
CBackground::~CBackground() { Destroy(); //if (mh_MsImg32) //{ // FreeLibrary(mh_MsImg32); // fAlphaBlend = NULL; //} MSectionLock SC; if (mcs_BkImgData) SC.Lock(mcs_BkImgData, TRUE); SafeFree(mp_BkImgData); mn_BkImgDataMax = 0; SafeFree(mp_BkEmfData); mn_BkImgDataMax = 0; if (mcs_BkImgData) { SC.Unlock(); SafeDelete(mcs_BkImgData); } }
void CConEmuUpdate::ReportErrorInt(wchar_t* asErrorInfo) { if (mb_InShowLastError) return; // Две ошибки сразу не показываем, а то зациклимся MSectionLock SC; SC.Lock(mp_LastErrorSC, TRUE); SafeFree(ms_LastErrorInfo); ms_LastErrorInfo = asErrorInfo; SC.Unlock(); // This will call back ShowLastError if (gpConEmu) gpConEmu->ReportUpdateError(); }
void Store(HKEY hKey, RegKeyType rkt) { if (!hKey || IsPredefined(hKey)) { _ASSERTE(hKey!=NULL); _ASSERTE(!IsPredefined(hKey) || (rkt>=RKT_HKCU && rkt<=RKT_HKLM64)); return; } //mhk_Last = hkSoftware; //WARNING("### Process RegKeyBlocks!"); MSectionLock SC; SC.Lock(&mc_Lock, TRUE, 500); RegKeyInfo* p = FindFreeSlot(); p->hKey = hKey; p->rkt = rkt; mp_LastKey = p; };
void CConEmuUpdate::ShowLastError() { if (ms_LastErrorInfo && *ms_LastErrorInfo) { mb_InShowLastError = true; MSectionLock SC; SC.Lock(mp_LastErrorSC, TRUE); wchar_t* pszError = ms_LastErrorInfo; ms_LastErrorInfo = NULL; SC.Unlock(); MessageBox(pszError, MB_ICONINFORMATION, gpConEmu?gpConEmu->GetDefaultTitle():L"ConEmu Update"); SafeFree(pszError); mb_InShowLastError = false; } }
bool CConEmuUpdate::ShowConfirmation() { bool lbConfirm = false; // May be null, if update package was dropped on ConEmu icon if (gpConEmu && ghWnd) { gpConEmu->UpdateProgress(); } if (ms_LastErrorInfo && *ms_LastErrorInfo) { mb_InShowLastError = true; MSectionLock SC; SC.Lock(mp_LastErrorSC, TRUE); wchar_t* pszConfirm = ms_LastErrorInfo; ms_LastErrorInfo = NULL; SC.Unlock(); DontEnable de; int iBtn = MessageBox(NULL, pszConfirm, ms_DefaultTitle, MB_ICONQUESTION|MB_SETFOREGROUND|MB_SYSTEMMODAL|MB_YESNO); SafeFree(pszConfirm); mb_InShowLastError = false; lbConfirm = (iBtn == IDYES); } else { MBoxAssert(ms_LastErrorInfo && *ms_LastErrorInfo); } if (!lbConfirm) { RequestTerminate(); // May be null, if update package was dropped on ConEmu icon if (gpConEmu && ghWnd) { gpConEmu->UpdateProgress(); } } return lbConfirm; }
BOOL WINAPI PlugServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam) { BOOL lbRc = FALSE; BOOL fSuccess = FALSE; MSectionThread SCT(csTabs); if (pIn->hdr.cbSize < sizeof(CESERVER_REQ_HDR) || /*in.nSize < cbRead ||*/ pIn->hdr.nVersion != CESERVER_REQ_VER) { gpPlugServer->BreakConnection(pInst); return FALSE; } UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR); // Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат switch (pIn->hdr.nCmd) { case 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; } break; } // CMD_LANGCHANGE #if 0 case CMD_DEFFONT: { // исключение - асинхронный, результат не требуется SetConsoleFontSizeTo(FarHwnd, 4, 6); MoveWindow(FarHwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 1); // чтобы убрать возможные полосы прокрутки... break; } CMD_DEFFONT #endif case CMD_REQTABS: case 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 - нужно шаманить Plugin()->ProcessCommand(CMD_CLOSEQSEARCH, TRUE/*bReqMainThread*/, pIn->dwData/*хоть и не нужно?*/); } // Пересылается 2 DWORD BOOL bCmdRc = Plugin()->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); } if (nSetWindowWait == WAIT_TIMEOUT) { gbForceSendTabs = TRUE; DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW timeout !!!\n"); } else { DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW finished\n"); } } if (gpTabs && (nSetWindowWait != WAIT_TIMEOUT)) { //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(); break; } // CMD_REQTABS, CMD_SETWINDOW case 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; break; } // CMD_FARSETCHANGED case CMD_DRAGFROM: { #ifdef _DEBUG BOOL *pbClickNeed = (BOOL*)pIn->Data; COORD *crMouse = (COORD *)(pbClickNeed+1); #endif Plugin()->ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, pIn->Data); CESERVER_REQ* pCmdRet = NULL; Plugin()->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); } break; } // CMD_DRAGFROM case CMD_EMENU: { COORD *crMouse = (COORD *)pIn->Data; #ifdef _DEBUG const wchar_t *pszUserMacro = (wchar_t*)(crMouse+1); #endif DWORD ClickArg[2] = {(DWORD)TRUE, (DWORD)MAKELONG(crMouse->X, crMouse->Y)}; // Выделить файл под курсором DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) begin\n"); BOOL lb1 = Plugin()->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 = Plugin()->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; } break; } // CMD_EMENU case CMD_ACTIVEWNDTYPE: { int nWindowType = -1; //CESERVER_REQ Out; //ExecutePrepareCmd(&Out, CMD_ACTIVEWNDTYPE, sizeof(CESERVER_REQ_HDR)+sizeof(DWORD)); if (gFarVersion.dwVerMajor>=2) nWindowType = Plugin()->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; } break; } // CMD_ACTIVEWNDTYPE case CECMD_ATTACH2GUI: { BOOL bAttached = Plugin()->Attach2Gui(); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = bAttached; } break; } // CECMD_ATTACH2GUI default: { CESERVER_REQ* pCmdRet = NULL; BOOL lbCmd = Plugin()->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); } } // default } // switch (pIn->hdr.nCmd) return lbRc; }
MConHandle::operator const HANDLE() { if (mpp_OutBuffer && *mpp_OutBuffer && (*mpp_OutBuffer != INVALID_HANDLE_VALUE)) { LogHandle(Event::e_GetHandlePtr, *mpp_OutBuffer); return *mpp_OutBuffer; } if (mh_Handle == INVALID_HANDLE_VALUE) { if (mn_StdMode) { mh_Handle = GetStdHandle(mn_StdMode); LogHandle(Event::e_CreateHandleStd, mh_Handle); } else { // Чтобы случайно не открыть хэндл несколько раз в разных потоках MSectionLock CS; CS.Lock(&mcs_Handle, TRUE); // Во время ожидания хэндл мог быт открыт в другом потоке if (mh_Handle == INVALID_HANDLE_VALUE) { mh_Handle = CreateFileW(ms_Name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (mh_Handle != INVALID_HANDLE_VALUE) { mb_OpenFailed = FALSE; } else { mn_LastError = GetLastError(); if (!mb_OpenFailed) { mb_OpenFailed = TRUE; // чтобы ошибка вываливалась только один раз! char szErrMsg[512], szNameA[10], szSelfFull[MAX_PATH]; const char *pszSelf; char *pszDot; if (!GetModuleFileNameA(0,szSelfFull,MAX_PATH)) { pszSelf = "???"; } else { pszSelf = strrchr(szSelfFull, '\\'); if (pszSelf) pszSelf++; else pszSelf = szSelfFull; pszDot = strrchr((char*)pszSelf, '.'); if (pszDot) *pszDot = 0; } WideCharToMultiByte(CP_OEMCP, 0, ms_Name, -1, szNameA, sizeof(szNameA), 0,0); _wsprintfA(szErrMsg, SKIPLEN(countof(szErrMsg)) "%s: CreateFile(%s) failed, ErrCode=0x%08X\n", pszSelf, szNameA, mn_LastError); HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); if (h && h!=INVALID_HANDLE_VALUE) { DWORD dwWritten = 0; WriteFile(h, szErrMsg, lstrlenA(szErrMsg), &dwWritten, 0); } } } LogHandle(Event::e_CreateHandle, mh_Handle); } } } LogHandle(Event::e_GetHandle, mh_Handle); return mh_Handle; };
// Создает (или возвращает уже созданный) HDC (CompatibleDC) для mp_BkImgData bool CBackground::PutPluginBackgroundImage(/*CBackground* pBack,*/ LONG X, LONG Y, LONG Width, LONG Height) { if (!this) return NULL; _ASSERTE(isMainThread()); // Сразу mb_BkImgChanged = FALSE; /*if (mb_BkImgDelete && mp_BkImgData) { free(mp_BkImgData); mp_BkImgData = NULL; mb_BkImgExist = FALSE; return false; }*/ if (!mb_BkImgExist) return false; MSectionLock SC; SC.Lock(mcs_BkImgData, FALSE); if (mb_BkEmfChanged) { // Сразу сброс mb_BkEmfChanged = FALSE; if (!mp_BkEmfData) { _ASSERTE(mp_BkEmfData!=NULL); return false; } // Нужно перекинуть EMF в mp_BkImgData BITMAPINFOHEADER bi = mp_BkEmfData->bi; size_t nBitSize = bi.biWidth*bi.biHeight*sizeof(COLORREF); size_t nWholeSize = sizeof(CESERVER_REQ_SETBACKGROUND)+nBitSize; //-V103 //-V119 if (!mp_BkImgData || (mn_BkImgDataMax < nWholeSize)) { if (mp_BkImgData) free(mp_BkImgData); mp_BkImgData = (CESERVER_REQ_SETBACKGROUND*)malloc(nWholeSize); if (!mp_BkImgData) { _ASSERTE(mp_BkImgData!=NULL); return false; } } *mp_BkImgData = *mp_BkEmfData; mp_BkImgData->bmp.bfType = 0x4D42/*BM*/; mp_BkImgData->bmp.bfSize = nBitSize+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //-V119 // Теперь нужно сформировать DIB и нарисовать в нем EMF HDC hScreen = GetDC(NULL); //RECT rcMeta = {0,0, mn_BkImgWidth, mn_BkImgHeight}; // (in pixels) //RECT rcMetaMM = {0,0, mn_BkImgWidth*10, mn_BkImgHeight*10}; // (in .01-millimeter units) //HDC hdcEmf = CreateEnhMetaFile(NULL, NULL, &rcMetaMM, L"ConEmu\0Far Background\0\0"); //if (!hdcEmf) //{ // _ASSERTE(hdcEmf!=NULL); // return; //} HDC hdcDib = CreateCompatibleDC(hScreen); if (!hdcDib) { _ASSERTE(hdcDib!=NULL); //DeleteEnhMetaFile(hdcEmf); return false; } COLORREF* pBits = NULL; HBITMAP hDib = CreateDIBSection(hScreen, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0); ReleaseDC(NULL, hScreen); hScreen = NULL; if (!hDib || !pBits) { _ASSERTE(hDib && pBits); return false; } HBITMAP hOld = (HBITMAP)SelectObject(hdcDib, hDib); size_t nBitsSize = bi.biWidth*bi.biHeight*sizeof(COLORREF); // Залить черным - по умолчанию #ifdef _DEBUG memset(pBits, 128, nBitSize); #else memset(pBits, 0, nBitsSize); #endif DWORD nEmfBits = mp_BkEmfData->bmp.bfSize - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER); LPBYTE pEmfBits = (LPBYTE)(mp_BkEmfData+1); HENHMETAFILE hdcEmf = SetEnhMetaFileBits(nEmfBits, pEmfBits); RECT rcPlay = {0,0, bi.biWidth, bi.biHeight}; DWORD nPlayErr = 0; if (hdcEmf) { #ifdef _DEBUG ENHMETAHEADER emh = {0}; DWORD PixelsX, PixelsY, MMX, MMY, cx, cy; emh.nSize = sizeof(ENHMETAHEADER); if( GetEnhMetaFileHeader( hdcEmf, sizeof( ENHMETAHEADER ), &emh ) ) { // Get the characteristics of the output device HDC hDC = GetDC(NULL); PixelsX = GetDeviceCaps( hDC, HORZRES ); PixelsY = GetDeviceCaps( hDC, VERTRES ); MMX = GetDeviceCaps( hDC, HORZSIZE ) * 100; MMY = GetDeviceCaps( hDC, VERTSIZE ) * 100; ReleaseDC(NULL, hDC); // Calculate the rect in which to draw the metafile based on the // intended size and the current output device resolution // Remember that the intended size is given in 0.01mm units, so // convert those to device units on the target device cx = (int)((float)(emh.rclFrame.right - emh.rclFrame.left) * PixelsX / (MMX)); cy = (int)((float)(emh.rclFrame.bottom - emh.rclFrame.top) * PixelsY / (MMY)); //pw->PreferredSize.cx = ip.MulDivI32((emh.rclFrame.right - emh.rclFrame.left), PixelsX, MMX); //pw->PreferredSize.cy = ip.MulDivI32((emh.rclFrame.bottom - emh.rclFrame.top), PixelsY, MMY); _ASSERTE(cx>0 && cy>0); //if (pw->PreferredSize.cx < 0) pw->PreferredSize.cx = -pw->PreferredSize.cx; //if (pw->PreferredSize.cy < 0) pw->PreferredSize.cy = -pw->PreferredSize.cy; //rcPlay = MakeRect(emh.rclBounds.left,emh.rclBounds.top,emh.rclBounds.right,emh.rclBounds.bottom); } #endif if (!PlayEnhMetaFile(hdcDib, hdcEmf, &rcPlay)) { nPlayErr = GetLastError(); _ASSERTE(FALSE && (nPlayErr == 0)); } GdiFlush(); memmove(mp_BkImgData+1, pBits, nBitSize); } UNREFERENCED_PARAMETER(nPlayErr); SelectObject(hdcDib, hOld); DeleteObject(hDib); DeleteDC(hdcDib); if (hdcEmf) { DeleteEnhMetaFile(hdcEmf); } else { return false; } } if (!mp_BkImgData) { // Нужен ли тут? Или допустимая ситуация? _ASSERTE(mp_BkImgData!=NULL); return false; } bool lbFade = false; if (gpSet->isFadeInactive && !gpConEmu->isMeForeground(false)) lbFade = true; bool lbRc = FillBackground(&mp_BkImgData->bmp, X, Y, Width, Height, eUpLeft, lbFade); //mb_BkImgChanged = FALSE; 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; }
// Вызывается ТОЛЬКО в главной нити! void CPluginBackground::UpdateBackground() { if (!mn_BgPluginsCount) return; if (!ghConEmuWndDC || !IsWindow(ghConEmuWndDC)) return; if (mb_ThNeedLoad) { LoadThSet(TRUE/*Мы уже в главной нити*/); } //RECT rcClient; GetClientRect(ghConEmuWndDC, &rcClient); struct PaintBackgroundArg Arg = m_Default; Arg.cbSize = sizeof(struct PaintBackgroundArg); //m_Default.dcSizeX = Arg.dcSizeX = rcClient.right+1; //m_Default.dcSizeY = Arg.dcSizeY = rcClient.bottom+1; m_Default.dcSizeX = Arg.dcSizeX = (m_Default.rcConWorkspace.right-m_Default.rcConWorkspace.left+1)*m_Default.MainFont.nFontCellWidth; m_Default.dcSizeY = Arg.dcSizeY = (m_Default.rcConWorkspace.bottom-m_Default.rcConWorkspace.top+1)*m_Default.MainFont.nFontHeight; // ********************************************************************************** // запомнить данные из m_Default в m_Last, но т.к. там есть указатели - move не катит // ********************************************************************************** //memmove(&m_Last, &m_Default, sizeof(m_Last)); m_Last.MainFont = m_Default.MainFont; memmove(m_Last.crPalette, m_Default.crPalette, sizeof(m_Last.crPalette)); m_Last.dcSizeX = m_Default.dcSizeX; m_Last.dcSizeY = m_Default.dcSizeY; m_Last.rcDcLeft = m_Default.rcDcLeft; m_Last.rcDcRight = m_Default.rcDcRight; m_Last.rcConWorkspace = m_Default.rcConWorkspace; m_Last.conCursor = m_Default.conCursor; m_Last.FarInterfaceSettings.Raw = m_Default.FarInterfaceSettings.Raw; m_Last.FarPanelSettings.Raw = m_Default.FarPanelSettings.Raw; memmove(m_Last.nFarColors, m_Default.nFarColors, sizeof(m_Last.nFarColors)); m_Last.bPanelsAllowed = m_Default.bPanelsAllowed; // struct tag_BkPanelInfo m_Last.LeftPanel.bVisible = m_Default.LeftPanel.bVisible; m_Last.LeftPanel.bFocused = m_Default.LeftPanel.bFocused; m_Last.LeftPanel.bPlugin = m_Default.LeftPanel.bPlugin; m_Last.LeftPanel.rcPanelRect = m_Default.LeftPanel.rcPanelRect; m_Last.RightPanel.bVisible = m_Default.RightPanel.bVisible; m_Last.RightPanel.bFocused = m_Default.RightPanel.bFocused; m_Last.RightPanel.bPlugin = m_Default.RightPanel.bPlugin; m_Last.RightPanel.rcPanelRect = m_Default.RightPanel.rcPanelRect; // строки lstrcpyW(m_Last.LeftPanel.szCurDir, m_Default.LeftPanel.szCurDir); lstrcpyW(m_Last.LeftPanel.szFormat, m_Default.LeftPanel.szFormat); lstrcpyW(m_Last.LeftPanel.szHostFile, m_Default.LeftPanel.szHostFile); lstrcpyW(m_Last.RightPanel.szCurDir, m_Default.RightPanel.szCurDir); lstrcpyW(m_Last.RightPanel.szFormat, m_Default.RightPanel.szFormat); lstrcpyW(m_Last.RightPanel.szHostFile, m_Default.RightPanel.szHostFile); // ********************************************************************************** if (m_Default.dcSizeX < 1 || m_Default.dcSizeY < 1) { _ASSERTE(m_Default.dcSizeX >= 1 && m_Default.dcSizeY >= 1); return; } SetDcPanelRect(&Arg.rcDcLeft, &Arg.LeftPanel, &Arg); SetDcPanelRect(&Arg.rcDcRight, &Arg.RightPanel, &Arg); // gpTabs отстает от реальности. Arg.Place = m_Default.Place; //if (!gpTabs) // Arg.Place = pbp_Panels; //else if (gnCurrentWindowType == WTYPE_EDITOR) // Arg.Place = pbp_Editor; //else if (gnCurrentWindowType == WTYPE_VIEWER) // Arg.Place = pbp_Viewer; //else if (Arg.LeftPanel.bVisible || Arg.RightPanel.bVisible) //{ // _ASSERTE(gnCurrentWindowType == WTYPE_PANELS); // Arg.Place = pbp_Panels; //} BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER)}; bi.biWidth = Arg.dcSizeX; bi.biHeight = Arg.dcSizeY; bi.biPlanes = 1; bi.biBitCount = 32; //-V112 bi.biCompression = BI_RGB; //_ASSERTE(Arg.LeftPanel.bVisible || Arg.RightPanel.bVisible); HDC hScreen = GetDC(NULL); RECT rcMeta = {0,0, Arg.dcSizeX, Arg.dcSizeY}; // (in pixels) int iWidthMM = GetDeviceCaps(hScreen, HORZSIZE); if (iWidthMM <= 0) { _ASSERTE(iWidthMM>0); iWidthMM = 1024; } int iHeightMM = GetDeviceCaps(hScreen, VERTSIZE); if (iHeightMM <= 0) { _ASSERTE(iHeightMM>0); iHeightMM = 768; } int iWidthPels = GetDeviceCaps(hScreen, HORZRES); if (iWidthPels <= 0) { _ASSERTE(iWidthPels>0); iWidthPels = 0; } int iHeightPels = GetDeviceCaps(hScreen, VERTRES); if (iHeightPels <= 0) { _ASSERTE(iHeightPels>0); iHeightPels = 0; } RECT rcMetaMM = {0,0, (rcMeta.right * iWidthMM * 100)/iWidthPels, (rcMeta.bottom * iHeightMM * 100)/iHeightPels}; // (in .01-millimeter units) HDC hdc = NULL; HENHMETAFILE hEmf = NULL; COLORREF* pBits = NULL; HBITMAP hDib = NULL, hOld = NULL; #ifdef CREATE_EMF_TEMP_FILES wchar_t szEmfFile[MAX_PATH] = {}; #endif wchar_t *pszEmfFile = NULL; if (SETBACKGROUND_USE_EMF==1) { #ifdef CREATE_EMF_TEMP_FILES GetTempPath(MAX_PATH-32, szEmfFile); int nLen = lstrlen(szEmfFile); if (*szEmfFile && szEmfFile[nLen-1] != L'\\') { szEmfFile[nLen++] = L'\\'; szEmfFile[nLen] = 0; } _wsprintf(szEmfFile+nLen, SKIPLEN(31) L"CeBack%u.emf", GetCurrentProcessId()); pszEmfFile = szEmfFile; #endif hdc = CreateEnhMetaFile(hScreen, pszEmfFile, &rcMetaMM, L"ConEmu\0Far Background\0\0"); if (!hdc) { _ASSERTE(hdc!=NULL); return; } } else { hdc = CreateCompatibleDC(hScreen); if (!hdc) { _ASSERTE(hdc!=NULL); return; } _ASSERTE(pBits = NULL); hDib = CreateDIBSection(hScreen, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0); } ReleaseDC(NULL, hScreen); hScreen = NULL; Arg.hdc = hdc; if (SETBACKGROUND_USE_EMF==1) { HBRUSH hFillBr = CreateSolidBrush ( #ifdef _DEBUG RGB(128,128,0) #else RGB(0,0,0) #endif ); FillRect(hdc, &rcMeta, hFillBr); DeleteObject(hFillBr); } else { if (!hDib || !pBits) { _ASSERTE(hDib && pBits); if (hDib) DeleteObject(hDib); if (hdc) DeleteDC(hdc); return; } hOld = (HBITMAP)SelectObject(hdc, hDib); // Залить черным - по умолчанию #ifdef _DEBUG memset(pBits, 128, bi.biWidth*bi.biHeight*4); //-V112 #else memset(pBits, 0, bi.biWidth*bi.biHeight*4); #endif } // Painting! int nProcessed = 0; MSectionLock SC; SC.Lock(csBgPlugins, TRUE); DWORD nFromLevel = 0, nNextLevel, nSuggested; DWORD dwDrawnPlaces = Arg.Place; while(true) { nNextLevel = nFromLevel; struct RegisterBackgroundArg *p = mp_BgPlugins; for(int i = 0; i < mn_BgPluginsCount; i++, p++) { if (p->Cmd != rbc_Register || !(p->dwPlaces & Arg.Place) || !(p->PaintConEmuBackground)) continue; // пустая, неактивная в данном контексте, или некорректная ячейка // Слои nSuggested = p->dwSuggestedLevel; if (nSuggested < nFromLevel) { continue; // Этот слой уже обработан } else if (nSuggested > nFromLevel) { // Этот слой нужно будет обработать в следующий раз if ((nNextLevel == nFromLevel) || (nSuggested < nNextLevel)) nNextLevel = nSuggested; continue; } // На уровне 0 (заливающий фон) должен быть только один плагин Arg.dwLevel = (nProcessed == 0) ? 0 : (nFromLevel == 0 && nProcessed) ? 1 : nFromLevel; Arg.lParam = mp_BgPlugins[i].lParam; Arg.dwDrawnPlaces = 0; //mp_BgPlugins[i].PaintConEmuBackground(&Arg); UpdateBackground_Exec(mp_BgPlugins+i, &Arg); // Что плагин покрасил (панели/редактор/вьювер считаются покрашенными по умолчанию) dwDrawnPlaces |= Arg.dwDrawnPlaces; // nProcessed++; } if (nNextLevel == nFromLevel) break; // больше слоев нет nFromLevel = nNextLevel; } SC.Unlock(); // Sending background to GUI! if (nProcessed < 1) { // Ситуация возникает при старте ConEmu, когда панелей "еще нет" //_ASSERTE(nProcessed >= 1); if (mb_BgWasSent) { mb_BgWasSent = FALSE; CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_SETBACKGROUND, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SETBACKGROUND)); if (pIn) { pIn->Background.nType = 1; pIn->Background.bEnabled = FALSE; pIn->Background.dwDrawnPlaces = 0; CESERVER_REQ *pOut = ExecuteGuiCmd(FarHwnd, pIn, FarHwnd); if (pOut) { ExecuteFreeResult(pOut); } ExecuteFreeResult(pIn); } } } else // есть "отработавшие" плагины, обновить Background! { GdiFlush(); DWORD nBitSize = 0, nBitsError = 0; if (SETBACKGROUND_USE_EMF==1) { hEmf = CloseEnhMetaFile(hdc); hdc = NULL; nBitSize = GetEnhMetaFileBits(hEmf, 0, NULL); if (nBitSize == 0) { dwDrawnPlaces = 0; nBitsError = GetLastError(); _ASSERTE(nBitSize!=0); if (hEmf) { // В случае ошибки - сразу удаляем DeleteEnhMetaFile(hEmf); hEmf = NULL; } } } else { nBitSize = bi.biWidth*bi.biHeight*sizeof(COLORREF); } DWORD nWholeSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SETBACKGROUND)+nBitSize; //-V103 //-V119 CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_SETBACKGROUND, nWholeSize); if (!pIn) { _ASSERTE(pIn); } else { pIn->Background.nType = 1; pIn->Background.bEnabled = TRUE; pIn->Background.dwDrawnPlaces = dwDrawnPlaces; if (SETBACKGROUND_USE_EMF==1) pIn->Background.bmp.bfType = 0x4645/*EF*/; else pIn->Background.bmp.bfType = 0x4D42/*BM*/; pIn->Background.bmp.bfSize = nBitSize+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //-V119 pIn->Background.bmp.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //-V119 pIn->Background.bi = bi; if (SETBACKGROUND_USE_EMF==1) { LPBYTE pBits = ((LPBYTE)&pIn->Background)+sizeof(pIn->Background); DWORD nBitsRc = (nBitSize && hEmf) ? GetEnhMetaFileBits(hEmf, nBitSize, pBits) : 0; _ASSERTE(nBitsRc == nBitSize); if (!nBitsRc) { _ASSERTE(nBitsRc!=NULL); // Отключить нафиг ExecutePrepareCmd(&pIn->hdr, CECMD_SETBACKGROUND, nWholeSize-nBitSize); pIn->Background.nType = 1; pIn->Background.bEnabled = FALSE; pIn->Background.dwDrawnPlaces = 0; } } else { memmove(((LPBYTE)&pIn->Background)+sizeof(pIn->Background), pBits, bi.biWidth*bi.biHeight*sizeof(COLORREF)); } CESERVER_REQ *pOut = ExecuteGuiCmd(FarHwnd, pIn, FarHwnd); // Вызывается ТОЛЬКО в главной нити _ASSERTE(GetCurrentThreadId() == gnMainThreadId); if (pOut) { mb_BgWasSent = TRUE; // Сбросим флажок "Ошибка уже была показана" if (pOut->BackgroundRet.nResult == esbr_OK) { mb_BgErrorShown = FALSE; } // Показать ошибку, если есть else if ((pOut->BackgroundRet.nResult > esbr_OK) && (pOut->BackgroundRet.nResult <= esbr_LastErrorNo) && (pOut->BackgroundRet.nResult != esbr_ConEmuInShutdown) && !mb_BgErrorShown) { mb_BgErrorShown = TRUE; Plugin()->ShowMessage(CEBkError_ExecFailed+pOut->BackgroundRet.nResult, 0); } ExecuteFreeResult(pOut); } else if (!mb_BgErrorShown) { mb_BgErrorShown = TRUE; Plugin()->ShowMessage(CEBkError_ExecFailed, 0); } ExecuteFreeResult(pIn); } } if (SETBACKGROUND_USE_EMF == 0) { if (hdc && hOld) SelectObject(hdc, hOld); if (hDib) DeleteObject(hDib); if (hdc) DeleteDC(hdc); } else { if (hdc) { hEmf = CloseEnhMetaFile(hdc); hdc = NULL; } if (hEmf) { DeleteEnhMetaFile(hEmf); hEmf = NULL; } } }
int CPluginBackground::RegisterSubplugin(RegisterBackgroundArg *pbk) { if (!pbk) { _ASSERTE(pbk != NULL); return esbr_InvalidArg; } if (!gbBgPluginsAllowed) { _ASSERTE(gbBgPluginsAllowed == TRUE); return esbr_PluginForbidden; } if (pbk->cbSize != sizeof(*pbk)) { _ASSERTE(pbk->cbSize == sizeof(*pbk)); return esbr_InvalidArgSize; } if (pbk->Cmd == rbc_Register) { BOOL lbCheckCallback = CheckCallbackPtr(pbk->hPlugin, 1, (FARPROC*)&pbk->PaintConEmuBackground, TRUE, FALSE, FALSE); if (!lbCheckCallback) { _ASSERTE(lbCheckCallback==TRUE); return esbr_InvalidArgProc; } } MSectionLock SC; SC.Lock(csBgPlugins, TRUE); // Выделение памяти под плагины if (mp_BgPlugins == NULL || (mn_BgPluginsCount == mn_BgPluginsMax)) ReallocItems(16); // go //BOOL lbNeedResort = FALSE; if (pbk->Cmd == rbc_Register) { // Память уже выделена int nFound = -1, nFirstEmpty = -1; for(int i = 0; i < mn_BgPluginsCount; i++) { if (mp_BgPlugins[i].Cmd == rbc_Register && mp_BgPlugins[i].hPlugin == pbk->hPlugin && mp_BgPlugins[i].PaintConEmuBackground == pbk->PaintConEmuBackground && mp_BgPlugins[i].lParam == pbk->lParam) { nFound = i; break; } if (nFirstEmpty == -1 && 0 == (int)mp_BgPlugins[i].Cmd) nFirstEmpty = i; } if (nFound == -1) { if (nFirstEmpty >= 0) nFound = nFirstEmpty; else nFound = mn_BgPluginsCount++; //lbNeedResort = (mn_BgPluginsCount>1); } mp_BgPlugins[nFound] = *pbk; } else if (pbk->Cmd == rbc_Unregister) { for(int i = 0; i < mn_BgPluginsCount; i++) { if (mp_BgPlugins[i].Cmd == rbc_Register && mp_BgPlugins[i].hPlugin == pbk->hPlugin && ((pbk->PaintConEmuBackground == NULL) || (mp_BgPlugins[i].PaintConEmuBackground == pbk->PaintConEmuBackground && mp_BgPlugins[i].lParam == pbk->lParam))) { memset(mp_BgPlugins+i, 0, sizeof(*mp_BgPlugins)); //lbNeedResort = TRUE; } } WARNING("Если количество зарегистрированных плагинов уменьшилось до 0"); // Послать в GUI CECMD_SETBACKGROUND{bEnabled = FALSE} // Проверить, чтобы не было противного мелькания при закрытии FAR } else if (pbk->Cmd == rbc_Redraw) { // просто выставить gbNeedBgActivate } ////TODO: Сортировка //if (lbNeedResort) //{ // WARNING("Сортировка зарегистрированных плагинов - CPluginBackground::RegisterBackground"); //} SC.Unlock(); // Когда активируется MainThread - обновить background mn_ReqActions |= ra_UpdateBackground; gbNeedBgActivate = TRUE; // В фар2 сразу дернем Synchro if (IS_SYNCHRO_ALLOWED) { Plugin()->ExecuteSynchro(); } return esbr_OK; }
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; }
void CConEmuUpdate::StartCheckProcedure(BOOL abShowMessages) { //DWORD nWait = WAIT_OBJECT_0; if (InUpdate() != us_NotStarted) { // Already in update procedure if (m_UpdateStep == us_ExitAndUpdate) { if (gpConEmu) { // Повторно? gpConEmu->RequestExitUpdate(); } } else if (abShowMessages) { MBoxError(L"Checking for updates already started"); } return; } gpSet->UpdSet.dwLastUpdateCheck = GetTickCount(); // Сразу проверим, как нужно будет запускаться bNeedRunElevation = NeedRunElevation(); mb_RequestTerminate = false; //if (!mh_StopThread) // mh_StopThread = CreateEvent(NULL, TRUE/*manual*/, FALSE, NULL); //ResetEvent(mh_StopThread); // Запомнить текущие параметры обновления if (!mp_Set) mp_Set = new ConEmuUpdateSettings; mp_Set->LoadFrom(&gpSet->UpdSet); mb_ManualCallMode = abShowMessages; { MSectionLock SC; SC.Lock(mp_LastErrorSC, TRUE); SafeFree(ms_LastErrorInfo); } wchar_t szReason[128]; if (!mp_Set->UpdatesAllowed(szReason)) { wchar_t szErrMsg[255]; wcscpy_c(szErrMsg, L"Updates are not enabled in ConEmu settings\r\n"); wcscat_c(szErrMsg, szReason); DisplayLastError(szErrMsg, -1); return; } mb_InCheckProcedure = TRUE; mh_CheckThread = CreateThread(NULL, 0, CheckThreadProc, this, 0, &mn_CheckThreadId); if (!mh_CheckThread) { mb_InCheckProcedure = FALSE; DWORD nErrCode = GetLastError(); wchar_t szErrMsg[255]; wcscpy_c(szErrMsg, L"ConEmu automatic update check failed!\r\n"); if (nErrCode == ERROR_ACCESS_DENIED) wcscat_c(szErrMsg, L"Check your antivirus software\r\n"); wcscat_c(szErrMsg, L"\r\nCreateThread(CheckThreadProc) failed\r\n"); DisplayLastError(szErrMsg, nErrCode); return; } // OK }
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; }