BOOL GuiSetForeground(HWND hWnd) { BOOL lbRc = FALSE; if (ghConEmuWndDC) { CESERVER_REQ *pIn = (CESERVER_REQ*)malloc(sizeof(*pIn)), *pOut; if (pIn) { ExecutePrepareCmd(pIn, CECMD_SETFOREGROUND, sizeof(CESERVER_REQ_HDR)+sizeof(u64)); //-V119 DWORD nConEmuPID = ASFW_ANY; GetWindowThreadProcessId(ghConEmuWndDC, &nConEmuPID); AllowSetForegroundWindow(nConEmuPID); pIn->qwData[0] = (u64)hWnd; HWND hConWnd = GetRealConsoleWindow(); pOut = ExecuteGuiCmd(hConWnd, pIn, hConWnd); if (pOut) { if (pOut->hdr.cbSize == (sizeof(CESERVER_REQ_HDR)+sizeof(DWORD))) lbRc = pOut->dwData[0]; ExecuteFreeResult(pOut); } free(pIn); } } return lbRc; }
int WINAPI RegisterPanelView(PanelViewInit *ppvi) { if (!ppvi) { _ASSERTE(ppvi != NULL); return -2; } if (ppvi->cbSize != sizeof(PanelViewInit)) { _ASSERTE(ppvi->cbSize == sizeof(PanelViewInit)); return -2; } PanelViewRegInfo *pp = (ppvi->bLeftPanel) ? &gPanelRegLeft : &gPanelRegRight; if (ppvi->bRegister) { pp->pfnPeekPreCall = ppvi->pfnPeekPreCall.f; pp->pfnPeekPostCall = ppvi->pfnPeekPostCall.f; pp->pfnReadPreCall = ppvi->pfnReadPreCall.f; pp->pfnReadPostCall = ppvi->pfnReadPostCall.f; pp->pfnWriteCall = ppvi->pfnWriteCall.f; } else { pp->pfnPeekPreCall = pp->pfnPeekPostCall = pp->pfnReadPreCall = pp->pfnReadPostCall = NULL; pp->pfnWriteCall = NULL; } pp->bRegister = ppvi->bRegister; CESERVER_REQ In; int nSize = sizeof(CESERVER_REQ_HDR) + sizeof(In.PVI); ExecutePrepareCmd(&In, CECMD_REGPANELVIEW, nSize); In.PVI = *ppvi; CESERVER_REQ* pOut = ExecuteGuiCmd(FarHwnd, &In, FarHwnd); if (!pOut) { pp->pfnPeekPreCall = pp->pfnPeekPostCall = pp->pfnReadPreCall = pp->pfnReadPostCall = NULL; pp->pfnWriteCall = NULL; pp->bRegister = FALSE; return -3; } *ppvi = pOut->PVI; ExecuteFreeResult(pOut); if (ppvi->cbSize == 0) { pp->pfnPeekPreCall = pp->pfnPeekPostCall = pp->pfnReadPreCall = pp->pfnReadPostCall = NULL; pp->pfnWriteCall = NULL; pp->bRegister = FALSE; return -1; } return 0; }
DWORD WINAPI OnGetConsoleAliasesW(LPWSTR AliasBuffer, DWORD AliasBufferLength, LPWSTR ExeName) { //typedef DWORD (WINAPI* OnGetConsoleAliasesW_t)(LPWSTR AliasBuffer, DWORD AliasBufferLength, LPWSTR ExeName); ORIGINALFAST(GetConsoleAliasesW); DWORD nError = 0; DWORD nRc = F(GetConsoleAliasesW)(AliasBuffer,AliasBufferLength,ExeName); if (!nRc) { nError = GetLastError(); // финт ушами if (nError == ERROR_NOT_ENOUGH_MEMORY) // && gdwServerPID) { DWORD nServerPID = gnServerPID; HWND hConWnd = GetRealConsoleWindow(); _ASSERTE(hConWnd == ghConWnd); //MFileMapping<CESERVER_CONSOLE_MAPPING_HDR> ConInfo; //ConInfo.InitName(CECONMAPNAME, (DWORD)hConWnd); //-V205 //CESERVER_CONSOLE_MAPPING_HDR *pInfo = ConInfo.Open(); //if (pInfo // && (pInfo->cbSize >= sizeof(CESERVER_CONSOLE_MAPPING_HDR)) // //&& (pInfo->nProtocolVersion == CESERVER_REQ_VER) // ) //{ // nServerPID = pInfo->nServerPID; // ConInfo.CloseMap(); //} if (nServerPID) { CESERVER_REQ_HDR In; ExecutePrepareCmd(&In, CECMD_GETALIASES, sizeof(CESERVER_REQ_HDR)); CESERVER_REQ* pOut = ExecuteSrvCmd(nServerPID/*gdwServerPID*/, (CESERVER_REQ*)&In, hConWnd); if (pOut) { size_t nData = min(AliasBufferLength,(pOut->hdr.cbSize-sizeof(pOut->hdr))); if (nData) { memmove(AliasBuffer, pOut->Data, nData); nRc = TRUE; } ExecuteFreeResult(pOut); } } } if (!nRc) SetLastError(nError); // вернуть, вдруг какая функция его поменяла } return nRc; }
void ExecutePrepareCmd(CESERVER_REQ* pIn, DWORD nCmd, size_t cbSize) { if (!pIn) return; ExecutePrepareCmd(&(pIn->hdr), nCmd, cbSize); // Обнулить хвост с данными if (cbSize > sizeof(pIn->hdr)) memset(((LPBYTE)&(pIn->hdr))+sizeof(pIn->hdr), 0, cbSize - sizeof(pIn->hdr)); }
int GuiMessageBox(HWND hConEmuWndRoot, LPCWSTR asText, LPCWSTR asTitle, int anBtns) { int nResult = 0; if (hConEmuWndRoot) { HWND hConWnd = myGetConsoleWindow(); CESERVER_REQ *pIn = (CESERVER_REQ*)malloc(sizeof(*pIn)); ExecutePrepareCmd(pIn, CECMD_ASSERT, sizeof(CESERVER_REQ_HDR)+sizeof(MyAssertInfo)); pIn->AssertInfo.nBtns = anBtns; _wcscpyn_c(pIn->AssertInfo.szTitle, countof(pIn->AssertInfo.szTitle), asTitle, countof(pIn->AssertInfo.szTitle)); //-V501 _wcscpyn_c(pIn->AssertInfo.szDebugInfo, countof(pIn->AssertInfo.szDebugInfo), asText, countof(pIn->AssertInfo.szDebugInfo)); //-V501 wchar_t szGuiPipeName[128]; msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", (DWORD)hConEmuWndRoot); //-V205 CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 1000, hConWnd); free(pIn); if (pOut) { if (pOut->hdr.cbSize > sizeof(CESERVER_REQ_HDR)) { nResult = pOut->dwData[0]; } ExecuteFreeResult(pOut); } } else { //_ASSERTE(hConEmuWndRoot!=NULL); // Избежать статической линковки к user32 HMODULE hUser32 = GetModuleHandle(L"User32.dll"); if (hUser32 == NULL) hUser32 = LoadLibrary(L"User32.dll"); typedef int (WINAPI* MessageBoxW_T)(HWND, LPCWSTR, LPCWSTR, UINT); MessageBoxW_T _MessageBoxW = hUser32 ? (MessageBoxW_T)GetProcAddress(hUser32, "MessageBoxW") : NULL; if (_MessageBoxW) { nResult = _MessageBoxW(NULL, asText, asTitle, MB_SYSTEMMODAL|anBtns); } else { #ifdef _DEBUG _CrtDbgBreak(); #endif } } return nResult; }
// export // Активировать текущую консоль в ConEmu int WINAPI ActivateConsole() { CESERVER_REQ In; int nSize = sizeof(CESERVER_REQ_HDR) + sizeof(In.ActivateCon); ExecutePrepareCmd(&In, CECMD_ACTIVATECON, nSize); In.ActivateCon.hConWnd = FarHwnd; CESERVER_REQ* pOut = ExecuteGuiCmd(FarHwnd, &In, FarHwnd); if (!pOut) { return FALSE; } BOOL lbSucceeded = (pOut->ActivateCon.hConWnd == FarHwnd); ExecuteFreeResult(pOut); return lbSucceeded; }
CESERVER_REQ* ExecuteNewCmd(DWORD nCmd, size_t nSize) { _ASSERTE(nSize>=sizeof(CESERVER_REQ_HDR)); CESERVER_REQ* pIn = NULL; if (nSize) { DWORD nErr = GetLastError(); // Обязательно с обнулением выделяемой памяти pIn = (CESERVER_REQ*)calloc(nSize, 1); if (pIn) { ExecutePrepareCmd(pIn, nCmd, nSize); pIn->hdr.nLastError = nErr; } } return pIn; }
void GuiFlashWindow(CEFlashType fType, HWND hWnd, BOOL bInvert, DWORD dwFlags, UINT uCount, DWORD dwTimeout) { if (ghConEmuWndDC) { CESERVER_REQ *pIn = (CESERVER_REQ*)malloc(sizeof(*pIn)), *pOut; if (pIn) { ExecutePrepareCmd(pIn, CECMD_FLASHWINDOW, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_FLASHWINFO)); //-V119 pIn->Flash.fType = fType; pIn->Flash.hWnd = hWnd; pIn->Flash.bInvert = bInvert; pIn->Flash.dwFlags = dwFlags; pIn->Flash.uCount = uCount; pIn->Flash.dwTimeout = dwTimeout; HWND hConWnd = GetRealConsoleWindow(); pOut = ExecuteGuiCmd(hConWnd, pIn, hConWnd); if (pOut) ExecuteFreeResult(pOut); free(pIn); } } }
BOOL ExecuteNewCmd(CESERVER_REQ* &ppCmd, DWORD &pcbCurMaxSize, DWORD nCmd, size_t nSize) { if (!ppCmd || (pcbCurMaxSize < nSize)) { DWORD nErr = GetLastError(); ExecuteFreeResult(ppCmd); ppCmd = ExecuteNewCmd(nCmd, nSize); if (ppCmd != NULL) { // Обмен данными идет и между 32bit & 64bit процессами, размеры __int64 недопустимы _ASSERTE(nSize == (DWORD)nSize); pcbCurMaxSize = (DWORD)nSize; ppCmd->hdr.nLastError = nErr; } } else { ExecutePrepareCmd(ppCmd, nCmd, nSize); } return (ppCmd != NULL); }
// Вызывается ТОЛЬКО в главной нити! 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; } } }
// Returns HWND of ... // aiType==0: Gui console DC window // ==1: Gui Main window // ==2: Console window HWND GetConEmuHWND(int aiType) { //CESERVER_REQ *pIn = NULL; //CESERVER_REQ *pOut = NULL; DWORD nLastErr = GetLastError(); HWND FarHwnd = NULL, ConEmuHwnd = NULL, ConEmuRoot = NULL; size_t cchMax = 128; wchar_t *szGuiPipeName = NULL; FarHwnd = myGetConsoleWindow(); if (!FarHwnd || (aiType == 2)) { goto wrap; //SetLastError(nLastErr); //return NULL; } szGuiPipeName = (wchar_t*)malloc(cchMax*sizeof(*szGuiPipeName)); if (!szGuiPipeName) { _ASSERTE(szGuiPipeName!=NULL); return NULL; } // Сначала пробуем Mapping консоли (вдруг есть?) if (!ConEmuRoot) { // создание этого объекта не позволяет отказаться от CRT (создается __chkstk) //MFileMapping<CESERVER_CONSOLE_MAPPING_HDR> ConMap; //ConMap.InitName(CECONMAPNAME, (DWORD)FarHwnd); //CESERVER_CONSOLE_MAPPING_HDR* p = ConMap.Open(); CESERVER_CONSOLE_MAPPING_HDR* p = NULL; msprintf(szGuiPipeName, cchMax, CECONMAPNAME, (DWORD)FarHwnd); //-V205 #ifdef _DEBUG size_t nSize = sizeof(*p); #endif HANDLE hMapping = OpenFileMapping(FILE_MAP_READ, FALSE, szGuiPipeName); if (hMapping) { DWORD nFlags = FILE_MAP_READ; p = (CESERVER_CONSOLE_MAPPING_HDR*)MapViewOfFile(hMapping, nFlags,0,0,0); } if (p && p->hConEmuRoot && isWindow(p->hConEmuRoot)) { // Успешно ConEmuRoot = p->hConEmuRoot; ConEmuHwnd = p->hConEmuWnd; } if (p) UnmapViewOfFile(p); if (hMapping) CloseHandle(hMapping); } #if 0 // Сервер не мог подцепиться БЕЗ создания мэппинга, поэтому CECMD_GETGUIHWND можно не делать if (!ConEmuRoot) { //BOOL lbRc = FALSE; pIn = (CESERVER_REQ*)calloc(1,sizeof(CESERVER_REQ)); ExecutePrepareCmd(pIn, CECMD_GETGUIHWND, sizeof(CESERVER_REQ_HDR)); //_wsprintf(szGuiPipeName, SKIPLEN(countof(szGuiPipeName)) CEGUIPIPENAME, L".", (DWORD)FarHwnd); msprintf(szGuiPipeName, cchMax, CEGUIPIPENAME, L".", (DWORD)FarHwnd); // Таймаут уменьшим, т.к. на результат не надеемся pOut = ExecuteCmd(szGuiPipeName, pIn, 250, FarHwnd); if (!pOut) { goto wrap; } if (pOut->hdr.cbSize != (sizeof(CESERVER_REQ_HDR)+2*sizeof(DWORD)) || pOut->hdr.nCmd != pIn->hdr.nCmd) { ExecuteFreeResult(pOut); pOut = NULL; goto wrap; } ConEmuRoot = (HWND)pOut->dwData[0]; ConEmuHwnd = (HWND)pOut->dwData[1]; // Сервер не мог подцепиться БЕЗ создания мэппинга, поэтому CECMD_GETGUIHWND не должен был пройти успешно _ASSERTE(ConEmuRoot == NULL); ExecuteFreeResult(pOut); pOut = NULL; } #endif wrap: SetLastError(nLastErr); //if (pIn) // free(pIn); if (szGuiPipeName) free(szGuiPipeName); if (aiType == 2) return FarHwnd; else if (aiType == 0) return ConEmuHwnd; else // aiType == 1 return ConEmuRoot; }
DWORD WINAPI DllStart(LPVOID /*apParm*/) { wchar_t *szModule = (wchar_t*)calloc((MAX_PATH+1),sizeof(wchar_t)); if (!GetModuleFileName(NULL, szModule, MAX_PATH+1)) _wcscpy_c(szModule, MAX_PATH+1, L"GetModuleFileName failed"); const wchar_t* pszName = PointToName(szModule); #if defined(SHOW_EXE_TIMINGS) || defined(SHOW_EXE_MSGBOX) wchar_t szTimingMsg[512]; UNREFERENCED_PARAMETER(szTimingMsg); HANDLE hTimingHandle = GetStdHandle(STD_OUTPUT_HANDLE); if (!lstrcmpi(pszName, SHOW_EXE_MSGBOX_NAME)) { gbShowExeMsgBox = true; } #endif // ******************* begin ********************* print_timings(L"DllStart: InitializeHookedModules"); InitializeHookedModules(); //HANDLE hStartedEvent = (HANDLE)apParm; #if defined(SHOW_EXE_MSGBOX) if (gbShowExeMsgBox) { STARTUPINFO si = {sizeof(si)}; GetStartupInfo(&si); LPCWSTR pszCmd = GetCommandLineW(); // GuiMessageBox еще не прокатит, ничего не инициализировано HMODULE hUser = LoadLibrary(user32); typedef int (WINAPI* MessageBoxW_t)(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); if (hUser) { MessageBoxW_t MsgBox = (MessageBoxW_t)GetProcAddress(hUser, "MessageBoxW"); if (MsgBox) { wchar_t szMsg[128]; lstrcpyn(szMsg, pszName, 96); lstrcat(szMsg, L" loaded!"); wchar_t szTitle[64]; msprintf(szTitle, countof(szTitle), L"ConEmuHk, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); MsgBox(NULL, szMsg, szTitle, MB_SYSTEMMODAL); } FreeLibrary(hUser); } } #endif #ifdef _DEBUG { wchar_t szCpInfo[128]; DWORD nCP = GetConsoleOutputCP(); _wsprintf(szCpInfo, SKIPLEN(countof(szCpInfo)) L"Current Output CP = %u", nCP); print_timings(szCpInfo); } #endif if ((lstrcmpi(pszName, L"powershell.exe") == 0) || (lstrcmpi(pszName, L"powershell") == 0)) { HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (IsOutputHandle(hStdOut)) { gbPowerShellMonitorProgress = true; MY_CONSOLE_SCREEN_BUFFER_INFOEX csbi = {sizeof(csbi)}; if (apiGetConsoleScreenBufferInfoEx(hStdOut, &csbi)) { gnConsolePopupColors = csbi.wPopupAttributes; } else { WARNING("Получить Popup атрибуты из мэппинга"); //gnConsolePopupColors = ...; gnConsolePopupColors = 0; } } } // Поскольку процедура в принципе может быть кем-то перехвачена, сразу найдем адрес // iFindAddress = FindKernelAddress(pi.hProcess, pi.dwProcessId, &fLoadLibrary); //HMODULE hKernel = ::GetModuleHandle(L"kernel32.dll"); //if (hKernel) //{ // gfnLoadLibrary = (UINT_PTR)::GetProcAddress(hKernel, "LoadLibraryW"); // _ASSERTE(gfnLoadLibrary!=NULL); //} //else //{ // _ASSERTE(hKernel!=NULL); // gfnLoadLibrary = NULL; //} if (!GetLoadLibraryAddress()) { _ASSERTE(gfnLoadLibrary!=0); } ghUser32 = GetModuleHandle(user32); if (ghUser32) ghUser32 = LoadLibrary(user32); // если подлинкован - увеличить счетчик WARNING("Попробовать не создавать LocalSecurity при старте"); //#ifndef TESTLINK gpLocalSecurity = LocalSecurity(); //gnMsgActivateCon = RegisterWindowMessage(CONEMUMSG_ACTIVATECON); //#endif //wchar_t szSkipEventName[128]; //msprintf(szSkipEventName, SKIPLEN(countof(szSkipEventName)) CEHOOKDISABLEEVENT, GetCurrentProcessId()); //HANDLE hSkipEvent = OpenEvent(EVENT_ALL_ACCESS , FALSE, szSkipEventName); ////BOOL lbSkipInjects = FALSE; //if (hSkipEvent) //{ // gbSkipInjects = (WaitForSingleObject(hSkipEvent, 0) == WAIT_OBJECT_0); // CloseHandle(hSkipEvent); //} //else //{ // gbSkipInjects = FALSE; //} WARNING("Попробовать не ломиться в мэппинг, а взять все из переменной ConEmuData"); // Открыть мэппинг консоли и попытаться получить HWND GUI, PID сервера, и пр... if (ghConWnd) { print_timings(L"OnConWndChanged"); OnConWndChanged(ghConWnd); //GetConMap(); } if (ghConEmuWnd) { #ifdef SHOW_INJECT_MSGBOX wchar_t* szDbgMsg = (wchar_t*)calloc(1024, sizeof(wchar_t)); wchar_t* szTitle = (wchar_t*)calloc(128, sizeof(wchar_t)); msprintf(szTitle, 1024, L"ConEmuHk, PID=%u", GetCurrentProcessId()); msprintf(szDbgMsg, 128, L"SetAllHooks, ConEmuHk, PID=%u\n%s", GetCurrentProcessId(), szModule); GuiMessageBox(ghConEmuWnd, szDbgMsg, szTitle, MB_SYSTEMMODAL); free(szDbgMsg); free(szTitle); #endif } //if (!gbSkipInjects && ghConWnd) //{ // InitializeConsoleInputSemaphore(); //} print_timings(L"GetImageSubsystem"); // Необходимо определить битность и тип (CUI/GUI) процесса, в который нас загрузили gnImageBits = WIN3264TEST(32,64); gnImageSubsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; // Определим тип (CUI/GUI) GetImageSubsystem(gnImageSubsystem, gnImageBits); // Проверка чего получилось _ASSERTE(gnImageBits==WIN3264TEST(32,64)); _ASSERTE(gnImageSubsystem==IMAGE_SUBSYSTEM_WINDOWS_GUI || gnImageSubsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI); //BOOL lbGuiWindowAttach = FALSE; // Прицепить к ConEmu гуевую программу (notepad, putty, ...) #ifdef USE_PIPE_SERVER _ASSERTEX(gpHookServer==NULL); print_timings(L"gpHookServer"); gpHookServer = (PipeServer<CESERVER_REQ>*)calloc(1,sizeof(*gpHookServer)); if (gpHookServer) { wchar_t szPipeName[128]; msprintf(szPipeName, countof(szPipeName), CEHOOKSPIPENAME, L".", GetCurrentProcessId()); gpHookServer->SetMaxCount(3); gpHookServer->SetOverlapped(true); gpHookServer->SetLoopCommands(false); gpHookServer->SetDummyAnswerSize(sizeof(CESERVER_REQ_HDR)); if (!gpHookServer->StartPipeServer(szPipeName, (LPARAM)gpHookServer, LocalSecurity(), HookServerCommand, HookServerFree, NULL, NULL, HookServerReady)) { _ASSERTEX(FALSE); // Ошибка запуска Pipes? gpHookServer->StopPipeServer(); free(gpHookServer); gpHookServer = NULL; } } else { _ASSERTEX(gpHookServer!=NULL); } #endif WARNING("Попробовать не ломиться в мэппинг, а взять все из переменной ConEmuData"); if (ghConWnd) { print_timings(L"CShellProc"); CShellProc* sp = new CShellProc; if (sp) { if (sp->LoadGuiMapping()) { wchar_t *szExeName = (wchar_t*)calloc((MAX_PATH+1),sizeof(wchar_t)); //BOOL lbDosBoxAllowed = FALSE; if (!GetModuleFileName(NULL, szExeName, MAX_PATH+1)) szExeName[0] = 0; if (sp->GetUseInjects() == 2) { // Можно ли использовать облегченную версию хуков (только для exe-шника)? if (!gbSelfIsRootConsoleProcess && !IsFarExe(szExeName)) { gbHookExecutableOnly = true; } } CESERVER_REQ* pIn = sp->NewCmdOnCreate(eInjectingHooks, L"", szExeName, GetCommandLineW(), NULL, NULL, NULL, NULL, // flags gnImageBits, gnImageSubsystem, GetStdHandle(STD_INPUT_HANDLE), GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE)); if (pIn) { //HWND hConWnd = GetConsoleWindow(); CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd); ExecuteFreeResult(pIn); if (pOut) ExecuteFreeResult(pOut); } free(szExeName); } delete sp; } } else if (gnImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { print_timings(L"IMAGE_SUBSYSTEM_WINDOWS_GUI"); DWORD dwConEmuHwnd = 0; BOOL bAttachExistingWindow = FALSE; wchar_t szVar[64], *psz; ConEmuGuiMapping* GuiMapping = (ConEmuGuiMapping*)calloc(1,sizeof(*GuiMapping)); if (GuiMapping && LoadGuiMapping(gnSelfPID, *GuiMapping)) { gnGuiPID = GuiMapping->nGuiPID; ghConEmuWnd = GuiMapping->hGuiWnd; bAttachExistingWindow = gbAttachGuiClient = TRUE; //ghAttachGuiClient = } SafeFree(GuiMapping); // Если аттачим существующее окно - таб в ConEmu еще не готов if (!bAttachExistingWindow) { if (!dwConEmuHwnd && GetEnvironmentVariable(ENV_CONEMUHWND_VAR_W, szVar, countof(szVar))) { if (szVar[0] == L'0' && szVar[1] == L'x') { dwConEmuHwnd = wcstoul(szVar+2, &psz, 16); if (!user->isWindow((HWND)dwConEmuHwnd)) dwConEmuHwnd = 0; else if (!user->getClassNameW((HWND)dwConEmuHwnd, szVar, countof(szVar))) dwConEmuHwnd = 0; else if (lstrcmp(szVar, VirtualConsoleClassMain) != 0) dwConEmuHwnd = 0; } } if (dwConEmuHwnd) { // Предварительное уведомление ConEmu GUI, что запущено GUI приложение // и оно может "захотеть во вкладку ConEmu". DWORD nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP); CESERVER_REQ *pIn = (CESERVER_REQ*)malloc(nSize); ExecutePrepareCmd(pIn, CECMD_ATTACHGUIAPP, nSize); pIn->AttachGuiApp.nPID = GetCurrentProcessId(); GetModuleFileName(NULL, pIn->AttachGuiApp.sAppFileName, countof(pIn->AttachGuiApp.sAppFileName)); pIn->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(0); wchar_t szGuiPipeName[128]; msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", dwConEmuHwnd); CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 10000, NULL); free(pIn); if (pOut) { if (pOut->hdr.cbSize > sizeof(CESERVER_REQ_HDR)) { if (pOut->AttachGuiApp.nFlags & agaf_Success) { user->allowSetForegroundWindow(pOut->hdr.nSrcPID); // PID ConEmu. _ASSERTEX(gnGuiPID==0 || gnGuiPID==pOut->hdr.nSrcPID); gnGuiPID = pOut->hdr.nSrcPID; //ghConEmuWnd = (HWND)dwConEmuHwnd; _ASSERTE(ghConEmuWnd==NULL || gnGuiPID!=0); _ASSERTE(pOut->AttachGuiApp.hConEmuWnd==(HWND)dwConEmuHwnd); ghConEmuWnd = pOut->AttachGuiApp.hConEmuWnd; ghConEmuWndDC = pOut->AttachGuiApp.hConEmuWndDC; ghConWnd = pOut->AttachGuiApp.hSrvConWnd; _ASSERTE(ghConEmuWndDC && user->isWindow(ghConEmuWndDC)); grcConEmuClient = pOut->AttachGuiApp.rcWindow; gnServerPID = pOut->AttachGuiApp.nPID; if (pOut->AttachGuiApp.hkl) { LONG_PTR hkl = (LONG_PTR)(LONG)pOut->AttachGuiApp.hkl; BOOL lbRc = ActivateKeyboardLayout((HKL)hkl, KLF_SETFORPROCESS) != NULL; UNREFERENCED_PARAMETER(lbRc); } OnConWndChanged(ghConWnd); gbAttachGuiClient = TRUE; } } ExecuteFreeResult(pOut); } } } } //if (!gbSkipInjects) { //gnRunMode = RM_APPLICATION; #ifdef _DEBUG //wchar_t szModule[MAX_PATH+1]; szModule[0] = 0; //GetModuleFileName(NULL, szModule, countof(szModule)); _ASSERTE((gnImageSubsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI) || (lstrcmpi(pszName, L"DosBox.exe")==0) || gbAttachGuiClient); //if (!lstrcmpi(pszName, L"far.exe") || !lstrcmpi(pszName, L"mingw32-make.exe")) //if (!lstrcmpi(pszName, L"as.exe")) // MessageBoxW(NULL, L"as.exe loaded!", L"ConEmuHk", MB_SYSTEMMODAL); //else if (!lstrcmpi(pszName, L"cc1plus.exe")) // MessageBoxW(NULL, L"cc1plus.exe loaded!", L"ConEmuHk", MB_SYSTEMMODAL); //else if (!lstrcmpi(pszName, L"mingw32-make.exe")) // MessageBoxW(NULL, L"mingw32-make.exe loaded!", L"ConEmuHk", MB_SYSTEMMODAL); //if (!lstrcmpi(pszName, L"g++.exe")) // MessageBoxW(NULL, L"g++.exe loaded!", L"ConEmuHk", MB_SYSTEMMODAL); //{ #endif print_timings(L"StartupHooks"); gbHooksWasSet = StartupHooks(ghOurModule); print_timings(L"StartupHooks - done"); #ifdef _DEBUG //} #endif // Если NULL - значит это "Detached" консольный процесс, посылать "Started" в сервер смысла нет if (ghConWnd != NULL) { print_timings(L"SendStarted"); SendStarted(); //#ifdef _DEBUG //// Здесь это приводит к обвалу _chkstk, //// похоже из-за того, что dll-ка загружена НЕ из известных модулей, //// а из специально сформированного блока памяти // -- в одной из функций, под локальные переменные выделялось слишком много памяти // -- переделал в malloc/free, все заработало //TestShellProcessor(); //#endif } } //else //{ // gbHooksWasSet = FALSE; //} //delete sp; /* #ifdef _DEBUG if (!lstrcmpi(pszName, L"mingw32-make.exe")) GuiMessageBox(ghConEmuWnd, L"mingw32-make.exe DllMain finished", L"ConEmuHk", MB_SYSTEMMODAL); #endif */ SafeFree(szModule); //if (hStartedEvent) // SetEvent(hStartedEvent); print_timings(L"DllStart - done"); return 0; }