HWND CConEmuInside::CheckInsideFocus() { if (!isInsideWndSet()) { //_ASSERTE(FALSE && "Inside was not initialized"); return NULL; } wchar_t szInfo[512]; GUITHREADINFO tif = { sizeof(tif) }; HWND hParentWnd = GetParentRoot(); DWORD nTID = GetWindowThreadProcessId(hParentWnd, NULL); if (!GetGUIThreadInfo(nTID, &tif)) { _wsprintf(szInfo, SKIPCOUNT(szInfo) L"GetGUIThreadInfo(%u) failed, code=%u", nTID, GetLastError()); LogString(szInfo); return NULL; } static GUITHREADINFO last_tif = {}; if (memcmp(&last_tif, &tif, sizeof(tif)) != 0) { last_tif = tif; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"ParentInputInfo: flags=x%X Active=x%X Focus=x%X Capture=x%X Menu=x%X MoveSize=x%X Caret=x%X (%i,%i)-(%i,%i)", tif.flags, LODWORD(tif.hwndActive), LODWORD(tif.hwndFocus), LODWORD(tif.hwndCapture), LODWORD(tif.hwndMenuOwner), LODWORD(tif.hwndMoveSize), LODWORD(tif.hwndCaret), LOGRECTCOORDS(tif.rcCaret)); LogString(szInfo); } return tif.hwndFocus; }
HANDLE MySetClipboardData(UINT uFormat, HANDLE hMem) { HANDLE h = SetClipboardData(uFormat, hMem); wchar_t szLog[100]; DWORD dwErr = (h == NULL) ? GetLastError() : 0; if (h != NULL) _wsprintf(szLog, SKIPCOUNT(szLog) L"SetClipboardData(x%04X, x%08X) succeeded", uFormat, (DWORD)(DWORD_PTR)hMem); else _wsprintf(szLog, SKIPCOUNT(szLog) L"SetClipboardData(x%04X, x%08X) failed, code=%u", uFormat, (DWORD)(DWORD_PTR)hMem, dwErr); LogString(szLog); return h; }
void SetCurrentPanelItemW2800(BOOL abLeftPanel, INT_PTR anTopItem, INT_PTR anCurItem) { if (!InfoW2800) return; wchar_t szMacro[200], szTop[65], szCur[65]; FSFW2800->itoa64(anTopItem, szTop, 10); FSFW2800->itoa64(anCurItem, szCur, 10); LPCWSTR pszEsc, pszFn; if (gFarVersion.IsFarLua()) { pszEsc = L"if Area.Search then Keys(\"Esc\") end"; pszFn = L"Plugin.SyncCall"; } else { pszEsc = L"$if (Search) Esc $end"; pszFn = L"callplugin"; } _wsprintf(szMacro, SKIPCOUNT(szMacro) L"%s %s(\"bd454d48-448e-46cc-909d-b6cf789c2d65\",\"%s\",%u,%s,%s)", pszEsc, pszFn, SetCurItem, abLeftPanel, szTop, szCur); MacroSendMacroText mcr = {sizeof(MacroSendMacroText)}; mcr.Flags = KMFLAGS_NOSENDKEYSTOPLUGINS; mcr.SequenceText = szMacro; InfoW2800->MacroControl(&guid_ConEmuTh, MCTL_SENDSTRING, 0, &mcr); }
// For example, mintty is terminated ‘abnormally’. It calls TerminateProcess instead of ExitProcess. BOOL WINAPI OnTerminateProcess(HANDLE hProcess, UINT uExitCode) { //typedef BOOL (WINAPI* OnTerminateProcess_t)(HANDLE hProcess, UINT uExitCode); ORIGINAL_KRNL(TerminateProcess); BOOL lbRc; if (hProcess == GetCurrentProcess()) { #ifdef PRINT_ON_EXITPROCESS_CALLS wchar_t szInfo[80]; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"\n\x1B[1;31;40m::TerminateProcess(%u) called\x1B[m\n", uExitCode); WriteProcessed2(szInfo, lstrlen(szInfo), NULL, wps_Error); #endif gnDllState |= ds_OnTerminateProcess; // We don't need to do proper/full deinitialization, // because the process is to be terminated abnormally DoDllStop(false, ds_OnTerminateProcess); lbRc = F(TerminateProcess)(hProcess, uExitCode); } else { lbRc = F(TerminateProcess)(hProcess, uExitCode); } return lbRc; }
bool MyOpenClipboard(LPCWSTR asAction) { _ASSERTE(gnMyClipboardOpened==0 || gnMyClipboardOpened==1); if (gnMyClipboardOpened > 0) { InterlockedIncrement(&gnMyClipboardOpened); return true; } BOOL lbRc; int iMaxTries = 100; // Open Windows' clipboard while (!(lbRc = OpenClipboard((ghWnd && IsWindow(ghWnd)) ? ghWnd : NULL)) && (iMaxTries-- > 0)) { DWORD dwErr = GetLastError(); wchar_t szCode[32]; _wsprintf(szCode, SKIPCOUNT(szCode) L", Code=%u", dwErr); wchar_t* pszMsg = lstrmerge(L"OpenClipboard failed (", asAction, L")", szCode); LogString(pszMsg); int iBtn = DisplayLastError(pszMsg, dwErr, MB_RETRYCANCEL|MB_ICONSTOP); SafeFree(pszMsg); if (iBtn != IDRETRY) return false; } InterlockedIncrement(&gnMyClipboardOpened); _ASSERTE(gnMyClipboardOpened==1); LogString(L"OpenClipboard succeeded"); return true; }
// ConEmuC -OsVerInfo int OsVerInfo() { OSVERSIONINFOEX osv = {sizeof(osv)}; GetOsVersionInformational((OSVERSIONINFO*)&osv); UINT DBCS = IsDbcs(); UINT HWFS = IsHwFullScreenAvailable(); UINT W5fam = IsWin5family(); UINT WXPSP1 = IsWinXPSP1(); UINT W6 = IsWin6(); UINT W7 = IsWin7(); UINT W10 = IsWin10(); UINT Wx64 = IsWindows64(); UINT WINE = IsWine(); UINT WPE = IsWinPE(); UINT TELNET = isTerminalMode(); wchar_t szInfo[200]; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"OS version information\n" L"%u.%u build %u SP%u.%u suite=x%04X type=%u\n" L"W5fam=%u WXPSP1=%u W6=%u W7=%u W10=%u Wx64=%u\n" L"HWFS=%u DBCS=%u WINE=%u WPE=%u TELNET=%u\n", osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber, osv.wServicePackMajor, osv.wServicePackMinor, osv.wSuiteMask, osv.wProductType, W5fam, WXPSP1, W6, W7, W10, Wx64, HWFS, DBCS, WINE, WPE, TELNET); _wprintf(szInfo); return MAKEWORD(osv.dwMinorVersion, osv.dwMajorVersion); }
void CTabPanelBase::UpdateTabFontInt() { if (!IsTabbarCreated()) return; LOGFONT lf = {}; lf.lfWeight = FW_DONTCARE; lf.lfCharSet = gpSet->nTabFontCharSet; lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS; wcscpy_c(lf.lfFaceName, gpSet->sTabFontFace); gpFontMgr->EvalLogfontSizes(lf, gpSet->nTabFontHeight, 0); wchar_t szInfo[100]; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"Creating tab font name='%s' height=%i", lf.lfFaceName, lf.lfHeight); LogString(szInfo); // CreateFont HFONT hFont = CreateFontIndirect(&lf); // virtual SetTabbarFont(hFont); // Store new Font in member variable if (mh_TabFont) DeleteObject(mh_TabFont); mh_TabFont = hFont; }
void CTaskBar::Taskbar_SetOverlay(HICON ahIcon) { HRESULT hr = mp_TaskBar3 ? mp_TaskBar3->SetOverlayIcon(ghWnd, ahIcon, NULL) : E_FAIL; wchar_t szInfo[100]; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"mp_TaskBar3->SetOverlayIcon(%s) %s code=x%08X", ahIcon?L"ICON":L"NULL", SUCCEEDED(hr)?L"succeeded":L"failed", hr); LogString(szInfo); _ASSERTE(hr==S_OK); UNREFERENCED_PARAMETER(hr); }
LPCWSTR CIconList::GetIconInfoStr(HICON h, wchar_t (&szInfo)[80]) { ICONINFO ii = {}; GetIconInfo(h, &ii); BITMAP bi = {}; GetObject(ii.hbmColor, sizeof(bi), &bi); _wsprintf(szInfo, SKIPCOUNT(szInfo) L"{%ix%i} planes=%u bpp=%u", bi.bmWidth, bi.bmHeight, bi.bmPlanes, bi.bmBitsPixel); SafeDeleteObject(ii.hbmColor); SafeDeleteObject(ii.hbmMask); return szInfo; }
// May be called from "C" programs VOID WINAPI OnExitProcess(UINT uExitCode) { //typedef BOOL (WINAPI* OnExitProcess_t)(UINT uExitCode); ORIGINAL_KRNL(ExitProcess); #if 0 if (gbIsLessProcess) { _ASSERTE(FALSE && "Continue to ExitProcess"); } #endif gnDllState |= ds_OnExitProcess; #ifdef PRINT_ON_EXITPROCESS_CALLS wchar_t szInfo[80]; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"\n\x1B[1;31;40m::ExitProcess(%u) called\x1B[m\n", uExitCode); WriteProcessed(szInfo, lstrlen(szInfo), NULL); #endif // And terminate our threads DoDllStop(false, ds_OnExitProcess); bool bUseForceTerminate; // Issue 1865: Due to possible dead locks in LdrpAcquireLoaderLock() call TerminateProcess bUseForceTerminate = gbHookServerForcedTermination; #ifdef USE_GH_272_WORKAROUND // gh#272: For unknown yet reason existance of nvd3d9wrap.dll (or nvd3d9wrapx.dll on 64-bit) // caused stack overflow with following calls // // nvd3d9wrap!GetNVDisplayW+0x174f // nvd3d9wrap!GetNVDisplayW+0x174f // user32!_UserClientDllInitialize+0x2ca // ntdll!LdrpCallInitRoutine+0x14 // ntdll!LdrShutdownProcess+0x1aa // ntdll!RtlExitUserProcess+0x74 // kernel32!ExitProcessStub+0x12 // CallExit!main+0x47 if (!bUseForceTerminate && GetModuleHandle(WIN3264TEST(L"nvd3d9wrap.dll",L"nvd3d9wrapx.dll"))) { bUseForceTerminate = true; } #endif // USE_GH_272_WORKAROUND if (bUseForceTerminate) { ORIGINAL_KRNL(TerminateProcess); F(TerminateProcess)(GetCurrentProcess(), uExitCode); return; // Assume not to get here } F(ExitProcess)(uExitCode); }
HWND CSetPgBase::CreatePage(ConEmuSetupPages* p, HWND ahParent, UINT anActivateTabMsg, const CDpiForDialog* apParentDpi) { wchar_t szLog[80]; _wsprintf(szLog, SKIPCOUNT(szLog) L"Creating child dialog ID=%u", p->DialogID); LogString(szLog); SafeDelete(p->pPage); p->pPage = p->CreateObj(); p->pPage->InitObject(ahParent, anActivateTabMsg, apParentDpi, p); p->pPage->mp_DynDialog = CDynDialog::ShowDialog(p->DialogID, ahParent, pageOpProc, (LPARAM)p->pPage); p->hPage = p->pPage->Dlg(); return p->hPage; }
void EmergencyShow(HWND hConWnd, int newFontY /*= 0*/, int newFontX /*= 0*/) { if (!hConWnd) hConWnd = GetConsoleWindow(); if (IsWindowVisible(hConWnd)) return; // уже, делать ничего не будем if (!IsWindow(hConWnd)) return; // Invalid HWND wchar_t szMutex[80]; _wsprintf(szMutex, SKIPCOUNT(szMutex) L"ConEmuEmergencyShow:%08X", (DWORD)(DWORD_PTR)hConWnd); HANDLE hMutex = CreateMutex(NULL, FALSE, szMutex); //_ASSERTE(FALSE && "EmergencyShow was called, Continue?"); DWORD dwWaitResult = WaitForSingleObject(hMutex, 5000); if (dwWaitResult == WAIT_OBJECT_0) { if (!IsWindowVisible(hConWnd)) { // Note, this funciton will fail if called from ConEmu plugin // Only servers (ConEmuCD) will be succeeded here SetUserFriendlyFont(hConWnd, newFontY, newFontX); CorrectConsolePos(hConWnd); SetWindowPos(hConWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE); apiShowWindowAsync(hConWnd, SW_SHOWNORMAL); } ReleaseMutex(hMutex); } else { // Invalid mutex operation? Just show the console apiShowWindowAsync(hConWnd, SW_SHOWNORMAL); } if (!IsWindowEnabled(hConWnd)) EnableWindow(hConWnd, true); CloseHandle(hMutex); }
BOOL apiTerminateThreadEx(HANDLE hThread, DWORD dwExitCode, LPCSTR asFile, int anLine) { ConEmuThreadInfo* pThread = NULL; for (INT_PTR c = THREADS_LOG_SIZE; --c >= 0;) { if (g_Threads[c].bActive && (g_Threads[c].hThread == hThread)) { pThread = (g_Threads+c); pThread->nExitCode = dwExitCode; pThread->bTerminated = TRUE; pThread->nEndTick = GetTickCount(); g_TerminatedThreadIdx = c; } } #ifndef __GNUC__ #pragma warning( push ) #pragma warning( disable : 6258 ) #endif BOOL bRc = ::TerminateThread(hThread, dwExitCode); #ifndef __GNUC__ #pragma warning( pop ) #endif if (pThread) { LPCSTR pszName = strrchr(asFile, L'\\'); if (pszName) pszName++; else pszName = asFile; char szKiller[30]; lstrcpynA(szKiller, pszName, countof(szKiller)); _ASSERTE((countof(szKiller)+8) < countof(pThread->sKiller)); _wsprintfA(pThread->sKiller, SKIPCOUNT(pThread->sKiller) "%s:%i", szKiller, anLine); pThread->bActive = FALSE; } else { g_TerminatedThreadIdx = -2; } return bRc; }
MArray<CDpiForDialog::DlgItem>* CDpiForDialog::LoadDialogItems(HWND hDlg) { MArray<DlgItem>* p = new MArray<DlgItem>(); DlgItem i = {hDlg}; if (!GetWindowRect(hDlg, &i.r)) { delete p; return NULL; } OffsetRect(&i.r, -i.r.left, -i.r.top); p->push_back(i); i.h = NULL; while ((i.h = FindWindowEx(hDlg, i.h, NULL, NULL)) != NULL) { if (GetWindowRect(i.h, &i.r) && MapWindowPoints(NULL, hDlg, (LPPOINT)&i.r, 2)) { #ifdef _DEBUG DWORD_PTR ID = GetWindowLong(i.h, GWL_ID); if (ID == cbExtendFonts) { RECT rcMargin = {}; if (Button_GetTextMargin(i.h, &rcMargin)) { wchar_t szLog[100]; _wsprintf(szLog, SKIPCOUNT(szLog) L"CheckBox Rect={%i,%i}-{%i,%i} Margin={%i,%i}-{%i,%i}", LOGRECTCOORDS(i.r), LOGRECTCOORDS(rcMargin)); LogString(szLog); } } #endif p->push_back(i); } } return p; }
// For example, mintty is terminated ‘abnormally’. It calls TerminateProcess instead of ExitProcess. BOOL WINAPI OnTerminateProcess(HANDLE hProcess, UINT uExitCode) { //typedef BOOL (WINAPI* OnTerminateProcess_t)(HANDLE hProcess, UINT uExitCode); ORIGINAL_KRNL(TerminateProcess); BOOL lbRc; if (hProcess == GetCurrentProcess()) { #ifdef PRINT_ON_EXITPROCESS_CALLS wchar_t szInfo[80]; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"\n\x1B[1;31;40m::TerminateProcess(%u) called\x1B[m\n", uExitCode); WriteProcessed(szInfo, lstrlen(szInfo), NULL); #endif gnDllState |= ds_OnTerminateProcess; // We need not to unset hooks (due to process will be force-killed below) // And terminate our threads DoDllStop(false, ds_OnTerminateProcess); } lbRc = F(TerminateProcess)(hProcess, uExitCode); return lbRc; }
int WINAPI OnGetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount) { //typedef int (WINAPI* OnGetWindowTextW_t)(HWND hWnd, LPWSTR lpString, int nMaxCount); ORIGINAL_EX(GetWindowTextW); int iRc = 0; FixHwnd4ConText(hWnd); if (F(GetWindowTextW)) iRc = F(GetWindowTextW)(hWnd, lpString, nMaxCount); #ifdef DEBUG_CON_TITLE wchar_t szPrefix[32]; _wsprintf(szPrefix, SKIPCOUNT(szPrefix) L"GetWindowTextW(x%08X)='", (DWORD)(DWORD_PTR)hWnd); CEStr lsDbg(lstrmerge(szPrefix, lpString, L"'\n")); OutputDebugString(lsDbg); if (gFarMode.cbSize && lpString && gpLastSetConTitle && gpLastSetConTitle->ms_Arg) { int iCmp = lstrcmp(gpLastSetConTitle->ms_Arg, lpString); _ASSERTE((iCmp == 0) && "Console window title was changed outside or was not applied yet"); } #endif return iRc; }
int DoInjectRemote(LPWSTR asCmdArg, bool abDefTermOnly) { gbInShutdown = TRUE; // чтобы не возникло вопросов при выходе gnRunMode = RM_SETHOOK64; LPWSTR pszNext = asCmdArg; LPWSTR pszEnd = NULL; DWORD nRemotePID = wcstoul(pszNext, &pszEnd, 10); wchar_t szStr[16]; wchar_t szTitle[128]; wchar_t szInfo[120]; wchar_t szParentPID[32]; #ifdef SHOW_INJECTREM_MSGBOX wchar_t szDbgMsg[512], szTitle[128]; PROCESSENTRY32 pinf; GetProcessInfo(nRemotePID, &pinf); _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmuCD PID=%u", GetCurrentProcessId()); _wsprintf(szDbgMsg, SKIPLEN(countof(szDbgMsg)) L"Hooking PID=%s {%s}\nConEmuCD PID=%u. Continue with injects?", asCmdArg ? asCmdArg : L"", pinf.szExeFile, GetCurrentProcessId()); if (MessageBoxW(NULL, szDbgMsg, szTitle, MB_SYSTEMMODAL|MB_OKCANCEL) != IDOK) { return CERR_HOOKS_FAILED; } #endif if (nRemotePID) { #if defined(SHOW_ATTACH_MSGBOX) if (!IsDebuggerPresent()) { wchar_t szTitle[100]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"%s PID=%u /INJECT", gsModuleName, gnSelfPID); const wchar_t* pszCmdLine = GetCommandLineW(); MessageBox(NULL,pszCmdLine,szTitle,MB_SYSTEMMODAL); } #endif CEStr lsName, lsPath; { CProcessData processes; processes.GetProcessName(nRemotePID, lsName.GetBuffer(MAX_PATH), MAX_PATH, lsPath.GetBuffer(MAX_PATH*2), MAX_PATH*2, NULL); CEStr lsLog(L"Remote: PID=", _ultow(nRemotePID, szStr, 10), L" Name=`", lsName, L"` Path=`", lsPath, L"`"); LogString(lsLog); } // Go to hook // InjectRemote waits for thread termination DWORD nErrCode = 0; CINFILTRATE_EXIT_CODES iHookRc = InjectRemote(nRemotePID, abDefTermOnly, &nErrCode); _wsprintf(szInfo, SKIPCOUNT(szInfo) L"InjectRemote result: %i (%s)", iHookRc, (iHookRc == CIR_OK) ? L"CIR_OK" : (iHookRc == CIR_AlreadyInjected) ? L"CIR_AlreadyInjected" : L"?"); LogString(szInfo); if (iHookRc == CIR_OK/*0*/ || iHookRc == CIR_AlreadyInjected/*1*/) { return iHookRc ? CERR_HOOKS_WAS_ALREADY_SET : CERR_HOOKS_WAS_SET; } DWORD nSelfPID = GetCurrentProcessId(); PROCESSENTRY32 self = {sizeof(self)}, parent = {sizeof(parent)}; // Not optimal, needs refactoring if (GetProcessInfo(nSelfPID, &self)) GetProcessInfo(self.th32ParentProcessID, &parent); // Ошибку (пока во всяком случае) лучше показать, для отлова возможных проблем //_ASSERTE(iHookRc == 0); -- ассерт не нужен, есть MsgBox _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"%s %s, PID=%u", gsModuleName, gsVersion, nSelfPID); _wsprintf(szInfo, SKIPCOUNT(szInfo) L"Injecting remote FAILED, code=%i:0x%08X\n" L"%s %s, PID=%u\n" L"RemotePID=%u ", iHookRc, nErrCode, gsModuleName, gsVersion, nSelfPID, nRemotePID); _wsprintf(szParentPID, SKIPCOUNT(szParentPID) L"\n" L"ParentPID=%u ", self.th32ParentProcessID); CEStr lsError(lstrmerge( szInfo, lsPath.IsEmpty() ? lsName.IsEmpty() ? L"<Unknown>" : lsName.ms_Val : lsPath.ms_Val, szParentPID, parent.szExeFile)); LogString(lsError); MessageBoxW(NULL, lsError, szTitle, MB_SYSTEMMODAL); } else { //_ASSERTE(pi.hProcess && pi.hThread && pi.dwProcessId && pi.dwThreadId); wchar_t szDbgMsg[512], szTitle[128]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmuC, PID=%u", GetCurrentProcessId()); _wsprintf(szDbgMsg, SKIPLEN(countof(szDbgMsg)) L"ConEmuC.X, PID=%u\nCmdLine parsing FAILED (%u)!\n%s", GetCurrentProcessId(), nRemotePID, asCmdArg); LogString(szDbgMsg); MessageBoxW(NULL, szDbgMsg, szTitle, MB_SYSTEMMODAL); } return CERR_HOOKS_FAILED; }
int CTabBarClass::GetNextTab(bool abForward, bool abAltStyle/*=false*/) { BOOL lbRecentMode = (gpSet->isTabs != 0) && (((abAltStyle == FALSE) ? gpSet->isTabRecent : !gpSet->isTabRecent)); int nNewSel = -1; // We need "visible" position (selected tab from tabbar) // It may differs from actual active tab during switching int nCurSel = GetCurSel(); int nCurCount = GetItemCount(); #ifdef PRINT_RECENT_STACK // Debug method wchar_t szTab[80]; _wsprintf(szTab, SKIPCOUNT(szTab) L"GetNextTab: GetCurSel=%i\n", nCurSel); DEBUGSTRRECENT(szTab); PrintRecentStack(); #endif if (lbRecentMode) { // index in the m_TabStack int idxCur = -1; // service descriptor CTab tabCur(__FILE__,__LINE__); // find m_TabStack's index of the current tab if (m_Tabs.GetTabByIndex(nCurSel, tabCur)) { for (int i = 0; i < m_TabStack.size(); i++) { if (m_TabStack[i] == tabCur.Tab()) { idxCur = i; break; } } } _ASSERTE(idxCur!=-1); nNewSel = GetNextTabHelper(idxCur, abForward, true); // Succeeded? if (nNewSel >= 0) { #ifdef PRINT_RECENT_STACK _wsprintf(szTab, SKIPCOUNT(szTab) L"GetNextTab(true): nNewSel=%i\n", nNewSel); DEBUGSTRRECENT(szTab); #endif return nNewSel; } _ASSERTE(nNewSel >= 0); } // Choose tab straightly nNewSel = GetNextTabHelper(nCurSel, abForward, false); // Succeeded? if (nNewSel >= 0) { #ifdef PRINT_RECENT_STACK _wsprintf(szTab, SKIPCOUNT(szTab) L"GetNextTab(false): nNewSel=%i\n", nNewSel); DEBUGSTRRECENT(szTab); #endif return nNewSel; } if (nNewSel == -1 && nCurCount > 0) { _ASSERTE(FALSE && "One tab must be <active> any time"); } // There is no "another" tab? return -1; }
bool CLngRc::LoadResouces(LPCWSTR asLanguage, LPCWSTR asFile) { bool bOk = false; CEStr lsJsonData; DWORD jsonDataSize = 0, nErrCode = 0; MJsonValue* jsonFile = NULL; MJsonValue jsonSection; DWORD nStartTick = 0, nLoadTick = 0, nFinTick = 0, nDelTick = 0; int iRc; wchar_t szLog[120]; struct { LPCWSTR pszSection; MArray<LngRcItem>* arr; int idDiff; } sections[] = { { L"cmnhints", &m_CmnHints, 0 }, { L"mnuhints", &m_MnuHints, IDM__MIN_MNU_ITEM_ID }, { L"controls", &m_Controls, 0 }, { L"strings", &m_Strings, 0 }, }; iRc = ReadTextFile(asFile, 1<<24 /*16Mb max*/, lsJsonData.ms_Val, jsonDataSize, nErrCode); if (iRc != 0) { // TODO: Log error goto wrap; } nStartTick = GetTickCount(); jsonFile = new MJsonValue(); if (!jsonFile->ParseJson(lsJsonData)) { // TODO: Log error CEStr lsErrMsg = lstrmerge( L"Language resources loading failed!\r\n" L"File: ", asFile, L"\r\n" L"Error: ", jsonFile->GetParseError()); gpConEmu->LogString(lsErrMsg.ms_Val); DisplayLastError(lsErrMsg.ms_Val, (DWORD)-1, MB_ICONSTOP); goto wrap; } nLoadTick = GetTickCount(); // Remember language parameters ms_Lng.Set(asLanguage); ms_l10n.Set(asFile); // Allocate intial array size m_CmnHints.alloc(4096); m_MnuHints.alloc(512); m_Controls.alloc(4096); m_Strings.alloc(lng_NextId); // Process sections for (size_t i = 0; i < countof(sections); i++) { if (jsonFile->getItem(sections[i].pszSection, jsonSection) && (jsonSection.getType() == MJsonValue::json_Object)) bOk |= LoadSection(&jsonSection, *(sections[i].arr), sections[i].idDiff); else Clean(*(sections[i].arr)); } nFinTick = GetTickCount(); wrap: SafeDelete(jsonFile); nDelTick = GetTickCount(); if (bOk) { _wsprintf(szLog, SKIPCOUNT(szLog) L"Language resources duration (ms): Parse: %u; Internal: %u; Delete: %u", (nLoadTick - nStartTick), (nFinTick - nLoadTick), (nDelTick - nFinTick)); gpConEmu->LogString(szLog); } return bOk; }
LRESULT CFrameHolder::OnPaint(HWND hWnd, HDC hdc, UINT uMsg) { if (hdc == NULL) { LRESULT lRc = 0; PAINTSTRUCT ps = {0}; hdc = BeginPaint(hWnd, &ps); if (hdc != NULL) { lRc = OnPaint(hWnd, hdc, uMsg); EndPaint(hWnd, &ps); } else { _ASSERTE(hdc != NULL); } return lRc; } #ifdef _DEBUG RECT rcClientReal = {}; GetClientRect(hWnd, &rcClientReal); MapWindowPoints(hWnd, NULL, (LPPOINT)&rcClientReal, 2); #endif // Если "завис" PostUpdate if (gpConEmu->mp_TabBar->NeedPostUpdate()) gpConEmu->mp_TabBar->Update(); // Go RECT wr, cr; RecalculateFrameSizes(); wr = gpConEmu->GetGuiClientRect(); #ifdef _DEBUG wchar_t szPaint[140]; _wsprintf(szPaint, SKIPCOUNT(szPaint) L"MainClient %s at {%i,%i}-{%i,%i} screen coords, size (%ix%i) calc (%ix%i)", (uMsg == WM_PAINT) ? L"WM_PAINT" : (uMsg == WM_PRINTCLIENT) ? L"WM_PRINTCLIENT" : L"UnknownMsg", LOGRECTCOORDS(rcClientReal), LOGRECTSIZE(rcClientReal), LOGRECTSIZE(wr)); DEBUGSTRPAINT(szPaint); #endif #if defined(CONEMU_TABBAR_EX) #ifdef RED_CLIENT_FILL HBRUSH h = CreateSolidBrush(RGB(255,0,0)); FillRect(hdc, &wr, h); DeleteObject(h); return 0; #endif #endif if (gpSet->isStatusBarShow) { int nHeight = gpSet->StatusBarHeight(); if (nHeight < (wr.bottom - wr.top)) { RECT rcStatus = {wr.left, wr.bottom - nHeight, wr.right, wr.bottom}; gpConEmu->mp_Status->PaintStatus(hdc, &rcStatus); wr.bottom = rcStatus.top; } } cr = wr; DEBUGTEST(FrameDrawStyle dt = gpConEmu->DrawType()); #if defined(CONEMU_TABBAR_EX) RECT tr = {}; if (!gpSet->isTabsInCaption) { _ASSERTE(gpConEmu->GetDwmClientRectTopOffset() == 0); // CheckIt, must be zero if (gpSet->isTabs) { RECT captrect = gpConEmu->CalcRect(CER_TAB, wr, CER_MAINCLIENT); //CalculateCaptionPosition(cr, &captrect); CalculateTabPosition(cr, captrect, &tr); PaintDC dc = {false}; RECT pr = {captrect.left, 0, captrect.right, captrect.bottom}; gpConEmu->BeginBufferedPaint(hdc, pr, dc); gpConEmu->mp_TabBar->PaintTabs(dc, captrect, tr); gpConEmu->EndBufferedPaint(dc, TRUE); } } else if (dt == fdt_Aero || dt == fdt_Win8) { _ASSERTE(gpSet->isTabsInCaption); int nOffset = gpConEmu->GetDwmClientRectTopOffset(); // "Рамка" расширена на клиентскую область, поэтому // нужно зарисовать заголовок черной кистью, иначе идет // искажение цвета для кнопок Min/Max/Close if (gpSet->isTabs) { RECT captrect = gpConEmu->CalcRect(CER_TAB, wr, CER_MAINCLIENT); //CalculateCaptionPosition(cr, &captrect); CalculateTabPosition(cr, captrect, &tr); PaintDC dc = {false}; RECT pr = {captrect.left, 0, captrect.right, captrect.bottom}; gpConEmu->BeginBufferedPaint(hdc, pr, dc); gpConEmu->mp_TabBar->PaintTabs(dc, captrect, tr); gpConEmu->EndBufferedPaint(dc, TRUE); // There is no "Glass" in Win8 mb_WasGlassDraw = IsWindows7 && !IsWindows8; } cr.top += nOffset; } #endif #ifdef _DEBUG int nWidth = (cr.right-cr.left); int nHeight = (cr.bottom-cr.top); #endif WARNING("Пока табы рисуем не сами и ExtendDWM отсутствует - дополнительные изыски с временным DC не нужны"); #if 0 if (!gpSet->isTabsInCaption) { //OnPaintClient(hdc/*, nWidth, nHeight*/); } else // Создадим временный DC, для удобства отрисовки в Glass-режиме и для фикса глюка DWM(?) см.ниже // В принципе, для режима Win2k/XP временный DC можно не создавать, если это будет тормозить { //_ASSERTE(FALSE && "Need to be rewritten"); HDC hdcPaint = CreateCompatibleDC(hdc); HBITMAP hbmp = CreateCompatibleBitmap(hdc, nWidth, nHeight); HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcPaint, hbmp); //OnPaintClient(hdcPaint/*, nWidth, nHeight*/); if ((dt == fdt_Aero) || !(mb_WasGlassDraw && gpConEmu->isZoomed())) { BitBlt(hdc, cr.left, cr.top, nWidth, nHeight, hdcPaint, 0, 0, SRCCOPY); } else { //mb_WasGlassDraw = FALSE; // Какой-то странный глюк DWM. При отключении Glass несколько верхних строк // клиентской области оказываются "разрушенными" - у них остается атрибут "прозрачности" // хотя прозрачность (Glass) уже отключена. В результате эти строки - белесые BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER)}; bi.biWidth = cr.right-cr.left+1; bi.biHeight = GetFrameHeight()+1; bi.biPlanes = 1; bi.biBitCount = 32; COLORREF *pPixels = NULL; HDC hdcTmp = CreateCompatibleDC(hdc); HBITMAP hTmp = CreateDIBSection(hdcTmp, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pPixels, NULL, 0); if (hTmp == NULL) { _ASSERTE(hTmp == NULL); BitBlt(hdc, cr.left, cr.top, nWidth, nHeight, hdcPaint, 0, 0, SRCCOPY); } else { HBITMAP hOldTmp = (HBITMAP)SelectObject(hdcTmp, hTmp); BitBlt(hdcTmp, 0, 0, bi.biWidth, bi.biHeight, hdcPaint, 0, 0, SRCCOPY); int i = 0; for (int y = 0; y < bi.biHeight; y++) { for (int x = 0; x < bi.biWidth; x++) { pPixels[i++] |= 0xFF000000; } } BitBlt(hdc, cr.left, cr.top, bi.biWidth, bi.biHeight, hdcTmp, 0, 0, SRCCOPY); if (nHeight > bi.biHeight) BitBlt(hdc, cr.left, cr.top+bi.biHeight, nWidth, nHeight-bi.biHeight, hdcPaint, 0, bi.biHeight, SRCCOPY); SelectObject(hdcTmp, hOldTmp); DeleteObject(hbmp); } DeleteDC(hdcTmp); } SelectObject(hdcPaint, hOldBmp); DeleteObject(hbmp); DeleteDC(hdcPaint); } #endif return 0; }
BOOL OnPromptBsDeleteWord(bool bForce, bool bBashMargin) { HANDLE hConIn = NULL; if (!IsPromptActionAllowed(bForce, bBashMargin, &hConIn)) { BsDelWordMsg(L"Skipped due to !IsPromptActionAllowed!"); return FALSE; } int iBSCount = 0; BOOL lbWrite = FALSE; DWORD dwLastError = 0; HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi = {}; if (GetConsoleScreenBufferInfo(hConOut, &csbi) && csbi.dwSize.X && csbi.dwSize.Y) { if (csbi.dwCursorPosition.X == 0) { iBSCount = 1; } else { bool bDBCS = false; DWORD nRead = 0; BOOL bReadOk = FALSE; // Если в консоли выбрана DBCS кодировка - там все не просто DWORD nCP = GetConsoleOutputCP(); if (nCP && nCP != CP_UTF7 && nCP != CP_UTF8 && nCP != 1200 && nCP != 1201) { CPINFO cp = {}; if (GetCPInfo(nCP, &cp) && (cp.MaxCharSize > 1)) { bDBCS = true; } } #ifdef _DEBUG wchar_t szDbg[120]; _wsprintf(szDbg, SKIPCOUNT(szDbg) L"CP=%u bDBCS=%u IsDbcs=%u X=%i", nCP, bDBCS, IsDbcs(), csbi.dwCursorPosition.X); BsDelWordMsg(szDbg); #endif int xPos = csbi.dwCursorPosition.X; COORD cr = {0, csbi.dwCursorPosition.Y}; if ((xPos == 0) && (csbi.dwCursorPosition.Y > 0)) { cr.Y--; xPos = csbi.dwSize.X; } COORD cursorFix = {xPos, cr.Y}; wchar_t* pwszLine = (wchar_t*)malloc((csbi.dwSize.X+1)*sizeof(*pwszLine)); if (pwszLine) { pwszLine[csbi.dwSize.X] = 0; // Считать строку if (bDBCS) { CHAR_INFO *pData = (CHAR_INFO*)calloc(csbi.dwSize.X, sizeof(CHAR_INFO)); COORD bufSize = {csbi.dwSize.X, 1}; SMALL_RECT rgn = {0, cr.Y, csbi.dwSize.X-1, cr.Y}; bReadOk = ReadConsoleOutputEx(hConOut, pData, bufSize, rgn, &cursorFix); dwLastError = GetLastError(); _ASSERTE(bReadOk); if (bReadOk) { for (int i = 0; i < csbi.dwSize.X; i++) pwszLine[i] = pData[i].Char.UnicodeChar; nRead = csbi.dwSize.X; xPos = cursorFix.X; } SafeFree(pData); } else { bReadOk = ReadConsoleOutputCharacterW(hConOut, pwszLine, csbi.dwSize.X, cr, &nRead); if (bReadOk && !nRead) bReadOk = FALSE; } if (bReadOk) { // Count chars { if ((int)nRead >= xPos) { int i = xPos - 1; _ASSERTEX(i >= 0); iBSCount = 0; // Only RIGHT brackets here to be sure that `(x86)` will be deleted including left bracket wchar_t cBreaks[] = L"\x20\xA0>])}$.,/\\\""; // Delete all `spaces` first while ((i >= 0) && ((pwszLine[i] == ucSpace) || (pwszLine[i] == ucNoBreakSpace))) iBSCount++, i--; _ASSERTE(cBreaks[0]==ucSpace && cBreaks[1]==ucNoBreakSpace); // delimiters while ((i >= 0) && wcschr(cBreaks+2, pwszLine[i])) iBSCount++, i--; // and all `NON-spaces` while ((i >= 0) && !wcschr(cBreaks, pwszLine[i])) iBSCount++, i--; } } } } // Done, string was processed SafeFree(pwszLine); } } else { BsDelWordMsg(L"GetConsoleScreenBufferInfo failed"); } if (iBSCount > 0) { INPUT_RECORD* pr = (INPUT_RECORD*)calloc((size_t)iBSCount,sizeof(*pr)); if (pr != NULL) { WORD vk = VK_BACK; HKL hkl = GetKeyboardLayout(gReadConsoleInfo.InReadConsoleTID ? gReadConsoleInfo.InReadConsoleTID : gReadConsoleInfo.LastReadConsoleInputTID); WORD sc = MapVirtualKeyEx(vk, 0/*MAPVK_VK_TO_VSC*/, hkl); if (!sc) { _ASSERTEX(sc!=NULL && "Can't determine SC?"); sc = 0x0E; } for (int i = 0; i < iBSCount; i++) { pr[i].EventType = KEY_EVENT; pr[i].Event.KeyEvent.bKeyDown = TRUE; pr[i].Event.KeyEvent.wRepeatCount = 1; pr[i].Event.KeyEvent.wVirtualKeyCode = vk; pr[i].Event.KeyEvent.wVirtualScanCode = sc; pr[i].Event.KeyEvent.uChar.UnicodeChar = vk; // BS pr[i].Event.KeyEvent.dwControlKeyState = 0; } DWORD nWritten = 0; while (iBSCount > 0) { lbWrite = WriteConsoleInputW(hConIn, pr, min(iBSCount,256), &nWritten); if (!lbWrite || !nWritten) break; iBSCount -= nWritten; } free(pr); } } else { BsDelWordMsg(L"Nothing to delete"); } UNREFERENCED_PARAMETER(dwLastError); return FALSE; }
bool CIconList::Initialize() { bool lbOk = true; if (!mh_TabIcons) { int iSysX = GetSystemMetrics(SM_CXSMICON), iSysY = GetSystemMetrics(SM_CYSMICON); int iFontY = gpSetCls->EvalSize(gpSet->nTabFontHeight, esf_Vertical|esf_CanUseUnits|esf_CanUseDpi|esf_CanUseZoom); if (iFontY < 0) iFontY = gpSetCls->EvalFontHeight(gpSet->sTabFontFace, iFontY, gpSet->nTabFontHeight); int iDpyY = gpSetCls->EvalSize(max(16,iSysY), esf_Vertical|esf_CanUseDpi); mn_CxIcon = iSysX; mn_CyIcon = iSysY; if (iFontY > 16) { if (iDpyY <= iFontY) { mn_CxIcon = gpSetCls->EvalSize(max(16,iSysX), esf_Horizontal|esf_CanUseDpi); mn_CyIcon = iDpyY; } else { // Issue 1939: Tab bar height too big since version 150307 int iSizes[] = {20, 24, 28, 32, 40, 48, 60, 64}; iFontY++; // Allow one pixes larger... for (INT_PTR j = countof(iSizes)-1; j >= 0; j--) { if (iFontY >= iSizes[j]) { mn_CyIcon = iSizes[j]; mn_CxIcon = (iSysX * iSizes[j]) / iSysY; break; } } } } wchar_t szLog[100]; _wsprintf(szLog, SKIPCOUNT(szLog) L"Creating IconList for size {%ix%i} SysIcon size is {%ix%i}", mn_CxIcon, mn_CyIcon, iSysX, iSysY); gpConEmu->LogString(szLog); if ((mh_TabIcons = ImageList_Create(mn_CxIcon, mn_CyIcon, ILC_COLOR24|ILC_MASK, 0, 16)) != NULL) { CToolImg img; int nFirstAdd = -1; const int iShieldButtons = 4; if (img.Create(mn_CxIcon, mn_CyIcon, iShieldButtons, GetSysColor(COLOR_BTNFACE))) { if (img.AddButtons(g_hInstance, IDB_SHIELD16, iShieldButtons)) { HBITMAP hShieldUser = img.GetBitmap(); #ifdef _DEBUG BITMAP bmi = {}; GetObject(hShieldUser, sizeof(bmi), &bmi); #ifdef _DEBUG //SaveImageEx(L"T:\\ShieldUser.png", hShieldUser); #endif #endif nFirstAdd = ImageList_AddMasked(mh_TabIcons, hShieldUser, RGB(128,0,0)); } } #ifdef _DEBUG int iCount = ImageList_GetImageCount(mh_TabIcons); _ASSERTE(iCount==4); IMAGEINFO ii = {}; BOOL b; // An application should not call DeleteObject to destroy the bitmaps retrieved by ImageList_GetImageInfo b = ImageList_GetImageInfo(mh_TabIcons, 0, &ii); b = ImageList_GetImageInfo(mh_TabIcons, 1, &ii); #endif if (nFirstAdd >= 0) { mn_AdminIcon = nFirstAdd + ((gOSVer.dwMajorVersion >= 6) ? 0 : 1); } else { lbOk = false; } } else { lbOk = false; } } return lbOk; }
bool TermX::GetSubstitute(const KEY_EVENT_RECORD& k, wchar_t (&szSubst)[16]) { _ASSERTE(szSubst[0] == 0); static UINT F1Codes[24] = { 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23, 24, 25, 26, 28, 29, 31, 32, 33, 34, 42, 43, 44, 45 }; typedef DWORD XTermCtrls; const XTermCtrls xtc_Shift = 1, xtc_Alt = 2, xtc_Ctrl = 4, xtc_None = 0; struct processor { XTermCtrls Mods; void SetKey(wchar_t (&szSubst)[16], wchar_t c) { if (!Mods) { //wcscpy_c(szSubst, L"\033O*A"); msprintf(szSubst, countof(szSubst), L"\033O%c", c); } else { msprintf(szSubst, countof(szSubst), L"\033[1;%c%c", Mods+L'1', c); } } } Processor = {xtc_None}; if (k.dwControlKeyState & (SHIFT_PRESSED)) Processor.Mods |= xtc_Shift; if (k.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) Processor.Mods |= xtc_Alt; if (k.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) Processor.Mods |= xtc_Ctrl; switch (k.wVirtualKeyCode) { case VK_UP: Processor.SetKey(szSubst, L'A'); return true; case VK_DOWN: Processor.SetKey(szSubst, L'B'); return true; case VK_RIGHT: Processor.SetKey(szSubst, L'C'); return true; case VK_LEFT: Processor.SetKey(szSubst, L'D'); return true; case VK_F1: case VK_F2: case VK_F3: case VK_F4: case VK_F5: case VK_F6: case VK_F7: case VK_F8: case VK_F9: case VK_F10: case VK_F11: case VK_F12: case VK_F13: case VK_F14: case VK_F15: case VK_F16: case VK_F17: case VK_F18: case VK_F19: case VK_F20: case VK_F21: case VK_F22: case VK_F23: case VK_F24: // "\033[11;*~" .. L"\033[15;*~", and so on: F1Codes[] _wsprintf(szSubst, SKIPCOUNT(szSubst) L"\033[%u;*~", F1Codes[(k.wVirtualKeyCode-VK_F1)]); return true; case VK_INSERT: wcscpy_c(szSubst, L"\033[2;*~"); return true; case VK_HOME: wcscpy_c(szSubst, L"\033[1;*H"); return true; case VK_END: wcscpy_c(szSubst, L"\033[1;*F"); return true; case VK_PRIOR: wcscpy_c(szSubst, L"\033[5;*~"); return true; case VK_NEXT: wcscpy_c(szSubst, L"\033[6;*~"); return true; case VK_DELETE: wcscpy_c(szSubst, L"\033[3;*~"); // ??? return true; case VK_TAB: if (!(k.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED|LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))) { wcscpy_c(szSubst, (k.dwControlKeyState & SHIFT_PRESSED) ? L"\033[Z" : L"\t"); } return true; /* NumPad with NumLock ON */ case VK_NUMPAD0: case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: case VK_DECIMAL: // VK_OEM_PERIOD}, // Actually, this may be comma case VK_DIVIDE: case VK_MULTIPLY: case VK_SUBTRACT: case VK_ADD: if (k.uChar.UnicodeChar) { // Just a digits '0'..'9' and symbols +-/*. szSubst[0] = k.uChar.UnicodeChar; szSubst[1] = 0; } return true; } // Ctrl+Char? A-->1, ..., J-->10, ... return false; }
// returns count of *lines* were copied to pChar/pAttr // nWidth & nHeight - dimension which VCon want to display UINT CRConData::GetConsoleData(wchar_t* rpChar, CharAttr* rpAttr, UINT anWidth, UINT anHeight, wchar_t wSetChar, CharAttr lcaDef, CharAttr *lcaTable, CharAttr *lcaTableExt, bool bFade, bool bExtendColors, BYTE nExtendColorIdx, bool bExtendFonts) { TODO("Во время ресайза консоль может подглючивать - отдает не то что нужно..."); //_ASSERTE(*con.pConChar!=ucBoxDblVert); UINT nYMax = klMin(anHeight,nHeight); MFileMapping<AnnotationHeader>& TrueMap = mp_RCon->m_TrueColorerMap; const AnnotationInfo *pTrueData = mp_RCon->mp_TrueColorerData; wchar_t *pszDst = rpChar; CharAttr *pcaDst = rpAttr; wchar_t *pszSrc = pConChar; WORD *pnSrc = pConAttr; bool lbIsFar = mp_RCon->isFar(); // Т.к. есть блокировка (csData), то con.pConChar и con.pConAttr // не должны меняться во время выполнения этой функции const wchar_t* const pszSrcStart = pConChar; WORD* const pnSrcStart = pConAttr; size_t nSrcCells = (nWidth * nHeight); Assert(pszSrcStart==pszSrc && pnSrcStart==pnSrc); const AnnotationInfo *pcolSrc = NULL; const AnnotationInfo *pcolEnd = NULL; BOOL bUseColorData = FALSE, bStartUseColorData = FALSE; if (gpSet->isTrueColorer && TrueMap.IsValid() && pTrueData) { pcolSrc = pTrueData; pcolEnd = pTrueData + TrueMap.Ptr()->bufferSize; bUseColorData = TRUE; WARNING("Если far/w - pcolSrc нужно поднять вверх, bStartUseColorData=TRUE, bUseColorData=FALSE"); if (m_sbi.dwSize.Y > (int)nHeight) // con.bBufferHeight { int lnShiftRows = (m_sbi.dwSize.Y - anHeight) - m_sbi.srWindow.Top; if (lnShiftRows > 0) { #ifdef _DEBUG if (nWidth != (m_sbi.srWindow.Right - m_sbi.srWindow.Left + 1)) { _ASSERTE(nWidth == (m_sbi.srWindow.Right - m_sbi.srWindow.Left + 1)); } #endif pcolSrc -= (lnShiftRows * nWidth); DEBUGSTRTRUEMOD(L"TrueMod skipped due to nShiftRows, bStartUseColorData was set"); bUseColorData = FALSE; bStartUseColorData = TRUE; } #ifdef _DEBUG else if (lnShiftRows < 0) { //_ASSERTE(nShiftRows>=0); wchar_t szLog[200]; _wsprintf(szLog, SKIPCOUNT(szLog) L"!!! CRealBuffer::GetConsoleData !!! " L"nShiftRows=%i nWidth=%i nHeight=%i Rect={%i,%i}-{%i,%i} Buf={%i,%i}", lnShiftRows, anWidth, anHeight, m_sbi.srWindow.Left, m_sbi.srWindow.Top, m_sbi.srWindow.Right, m_sbi.srWindow.Bottom, m_sbi.dwSize.X, m_sbi.dwSize.Y); mp_RCon->LogString(szLog); } #endif } } else { DEBUGSTRTRUEMOD(L"TrueMod is not allowed here"); } DWORD cbDstLineSize = anWidth * 2; DWORD cnSrcLineLen = nWidth; DWORD cbSrcLineSize = cnSrcLineLen * 2; #ifdef _DEBUG if (nWidth != m_sbi.dwSize.X) { _ASSERTE(nWidth == m_sbi.dwSize.X); // Scrolling? } #endif DWORD cbLineSize = min(cbDstLineSize,cbSrcLineSize); int nCharsLeft = (anWidth > nWidth) ? (anWidth - nWidth) : 0; //int nY, nX; //120331 - Нехорошо заменять на "черный" с самого начала BYTE attrBackLast = 0; UINT nExtendStartsY = 0; //int nPrevDlgBorder = -1; bool lbStoreBackLast = false; if (bExtendColors) { BYTE FirstBackAttr = lcaTable[(*pnSrc) & 0xFF].nBackIdx; if (FirstBackAttr != nExtendColorIdx) attrBackLast = FirstBackAttr; const CEFAR_INFO_MAPPING* pFarInfo = lbIsFar ? mp_RCon->GetFarInfo() : NULL; if (pFarInfo) { // Если в качестве цвета "расширения" выбран цвет панелей - значит // пользователь просто настроил "другую" палитру для панелей фара. // К сожалению, таким образом нельзя заменить только цвета для элемента под курсором. if (CONBACKCOLOR(pFarInfo->nFarColors[col_PanelText]) != nExtendColorIdx) lbStoreBackLast = true; else attrBackLast = FirstBackAttr; if (pFarInfo->FarInterfaceSettings.AlwaysShowMenuBar || mp_RCon->isEditor() || mp_RCon->isViewer()) nExtendStartsY = 1; // пропустить обработку строки меню } else { lbStoreBackLast = true; } } // Собственно данные for (UINT nY = 0; nY < nYMax; nY++) { if (nY == nExtendStartsY) lcaTable = lcaTableExt; // Текст memmove(pszDst, pszSrc, cbLineSize); if (nCharsLeft > 0) wmemset(pszDst+cnSrcLineLen, wSetChar, nCharsLeft); // Console text colors (Fg,Bg) BYTE PalIndex = MAKECONCOLOR(7,0); // While console is in recreate (shutdown console, startup new root) // it's shown using monochrome (gray on black) bool bForceMono = (mp_RCon->mn_InRecreate != 0); int iTail = cnSrcLineLen; wchar_t* pch = pszDst; for (UINT nX = 0; // Don't forget to advance same pointers at the and if bPair iTail-- > 0; nX++, pnSrc++, pcolSrc++, pch++) { CharAttr& lca = pcaDst[nX]; bool hasTrueColor = false; bool hasFont = false; // If not "mono" we need only lower byte with color indexes if (!bForceMono) { if (((*pnSrc) & COMMON_LVB_REVERSE_VIDEO) && (((*pnSrc) & CHANGED_CONATTR) == COMMON_LVB_REVERSE_VIDEO)) PalIndex = MAKECONCOLOR(CONBACKCOLOR(*pnSrc), CONFORECOLOR(*pnSrc)); // Inverse else PalIndex = ((*pnSrc) & 0xFF); } TODO("OPTIMIZE: lca = lcaTable[PalIndex];"); lca = lcaTable[PalIndex]; TODO("OPTIMIZE: вынести проверку bExtendColors за циклы"); bool bPair = (iTail > 0); ucs32 wwch = ucs32_from_wchar(pch, bPair); _ASSERTE(wwch >= 0); // Colorer & Far - TrueMod TODO("OPTIMIZE: вынести проверку bUseColorData за циклы"); if (bStartUseColorData && !bUseColorData) { // В случае "far /w" буфер цвета может начаться НИЖЕ верхней видимой границы, // если буфер немного прокручен вверх if (pcolSrc >= mp_RCon->mp_TrueColorerData) { DEBUGSTRTRUEMOD(L"TrueMod forced back due bStartUseColorData"); bUseColorData = TRUE; } } if (bUseColorData) { if (pcolSrc >= pcolEnd) { DEBUGSTRTRUEMOD(L"TrueMod stopped - out of buffer"); bUseColorData = FALSE; } else { TODO("OPTIMIZE: доступ к битовым полям тяжело идет..."); if (pcolSrc->fg_valid) { hasTrueColor = true; hasFont = true; lca.nFontIndex = fnt_Normal; //bold/italic/underline will be set below lca.crForeColor = bFade ? gpSet->GetFadeColor(pcolSrc->fg_color) : pcolSrc->fg_color; if (pcolSrc->bk_valid) lca.crBackColor = bFade ? gpSet->GetFadeColor(pcolSrc->bk_color) : pcolSrc->bk_color; } else if (pcolSrc->bk_valid) { hasTrueColor = true; hasFont = true; lca.nFontIndex = fnt_Normal; //bold/italic/underline will be set below lca.crBackColor = bFade ? gpSet->GetFadeColor(pcolSrc->bk_color) : pcolSrc->bk_color; } // nFontIndex: 0 - normal, 1 - bold, 2 - italic, 3 - bold&italic,..., 4 - underline, ... if (pcolSrc->style) { hasFont = true; lca.nFontIndex = pcolSrc->style & fnt_StdFontMask; } } } if (!hasFont && ((*pnSrc) & COMMON_LVB_UNDERSCORE) && ((nX >= ROWID_USED_CELLS) || !((*pnSrc) & (CHANGED_CONATTR & ~COMMON_LVB_UNDERSCORE))) ) { lca.nFontIndex = fnt_Underline; } if (!hasTrueColor && bExtendColors && (nY >= nExtendStartsY)) { if (lca.nBackIdx == nExtendColorIdx) { // Have to change the color to adjacent(?) cell lca.nBackIdx = attrBackLast; // For the background nExtendColorIdx we use upper // palette range for text: 16..31 instead of 0..15 lca.nForeIdx += 0x10; lca.crForeColor = lca.crOrigForeColor = mp_RCon->mp_Palette->m_Colors[lca.nForeIdx]; lca.crBackColor = lca.crOrigBackColor = mp_RCon->mp_Palette->m_Colors[lca.nBackIdx]; } else if (lbStoreBackLast) { // Remember last "normal" background attrBackLast = lca.nBackIdx; } } switch (get_wcwidth(wwch)) { case 0: lca.Flags2 |= CharAttr2_Combining; break; case 2: lca.Flags2 |= CharAttr2_DoubleSpaced; break; } if (bPair) { lca.Flags2 |= CharAttr2_Surrogate; CharAttr& lca2 = pcaDst[nX+1]; lca2 = lca; lca2.Flags2 = (lca.Flags2 & ~(CharAttr2_Combining)) | CharAttr2_NonSpacing; // advance +1 character nX++; pnSrc++; pcolSrc++; pch++; iTail--; } } // Залить остаток (если запрошен больший участок, чем есть консоль for (UINT nX = cnSrcLineLen; nX < anWidth; nX++) { pcaDst[nX] = lcaDef; } // Far2 показывает красный 'A' в правом нижнем углу консоли // Этот ярко красный цвет фона может попасть в Extend Font Colors if (bExtendFonts && ((nY+1) == nYMax) && lbIsFar && (pszDst[anWidth-1] == L'A') && (PalIndex == 0xCF)) { // Вернуть "родной" цвет и шрифт pcaDst[anWidth-1] = lcaTable[PalIndex]; } // Next line pszDst += anWidth; pcaDst += anWidth; pszSrc += cnSrcLineLen; } #ifndef __GNUC__ UNREFERENCED_PARAMETER(pszSrcStart); UNREFERENCED_PARAMETER(pnSrcStart); #endif UNREFERENCED_PARAMETER(nSrcCells); return nYMax; }
//------------------------------------------------------------------------ ///| Parsing the command line |/////////////////////////////////////////// //------------------------------------------------------------------------ // Returns: // true - continue normal startup // false - exit process with iResult code bool CConEmuStart::ParseCommandLine(LPCWSTR pszCmdLine, int& iResult) { bool bRc = false; iResult = 100; _ASSERTE(pszCmdLine!=NULL); opt.cmdLine.Set(pszCmdLine ? pszCmdLine : L""); // pszCmdLine *may* or *may not* start with our executable or full path to our executable LPCWSTR pszTemp = opt.cmdLine; LPCWSTR cmdLineRest = SkipNonPrintable(opt.cmdLine); LPCWSTR pszName, pszArgStart; LPCWSTR psUnknown = NULL; CEStr szArg, szNext; CEStr szExeName, szExeNameOnly; // Set %ConEmuArgs% env var // It may be usefull if we need to restart ConEmu // from batch/script with the same arguments (selfupdate etc.) LPCWSTR pszCopyToEnvStart = NULL; // Have to get our exectuable name and name without extension szExeName.Set(PointToName(gpConEmu->ms_ConEmuExe)); szExeNameOnly.Set(szExeName); wchar_t* pszDot = (wchar_t*)PointToExt(szExeNameOnly.ms_Val); _ASSERTE(pszDot); if (pszDot) *pszDot = 0; // Check the first argument in the command line (most probably it will be our executable path/name) if (NextArg(&pszTemp, szArg) != 0) { _ASSERTE(FALSE && "GetCommandLine() is empty"); // Treat as empty command line, allow to start bRc = true; iResult = 0; goto wrap; } pszName = PointToName(szArg); if ((lstrcmpi(pszName, szExeName) == 0) || (lstrcmpi(pszName, szExeNameOnly) == 0)) { // OK, our executable was specified properly in the command line _ASSERTE(*pszTemp != L' '); cmdLineRest = SkipNonPrintable(pszTemp); } // Must be empty at the moment _ASSERTE(opt.runCommand.IsEmpty()); // Does the command line contain our switches? // Or we need to append all switches to starting shell? if (cmdLineRest && *cmdLineRest) { pszTemp = cmdLineRest; if (NextArg(&pszTemp, szArg) == 0) { if ((*szArg.ms_Val != L'/') && (*szArg.ms_Val != L'-') /*&& !wcschr(szArg.ms_Val, L'/')*/ ) { // Save it for further use opt.runCommand.Set(cmdLineRest); // And do not process it (no switches at all) cmdLineRest = NULL; opt.params = -1; } } } // Let parse the reset szArg.Empty(); szNext.Empty(); // Processing loop begin if (cmdLineRest && *cmdLineRest) { pszCopyToEnvStart = cmdLineRest; opt.cfgSwitches.Set(pszCopyToEnvStart); while (NextArg(&cmdLineRest, szArg, &pszArgStart) == 0) { bool lbNotFound = false; // ':' removed from checks because otherwise it will not warn // on invalid usage of "-new_console:a" for example if (szArg.ms_Val[0] == L'-' && szArg.ms_Val[1] && !wcspbrk(szArg.ms_Val+1, L"\\//|.&<>^")) { // Seems this is to be the "switch" too // Use both notations ('-' and '/') *szArg.ms_Val = L'/'; } LPCWSTR curCommand = szArg.ms_Val; #define NeedNextArg() \ if (NextArg(&cmdLineRest, szNext) != 0) { iResult = 101; goto wrap; } \ curCommand = szNext.ms_Val; if (*curCommand != L'/') { continue; // Try next switch? } else { opt.params++; if (!klstricmp(curCommand, _T("/autosetup"))) { BOOL lbTurnOn = TRUE; NeedNextArg(); if (*curCommand == _T('0')) { lbTurnOn = FALSE; } else { NeedNextArg(); DWORD dwAttr = GetFileAttributes(curCommand); if (dwAttr == (DWORD)-1 || (dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { iResult = 102; goto wrap; } } HKEY hk = NULL; DWORD dw; int nSetupRc = 100; if (0 != RegCreateKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Command Processor"), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dw)) { iResult = 103; goto wrap; } if (lbTurnOn) { size_t cchMax = _tcslen(curCommand); LPCWSTR pszArg1 = NULL; if (*cmdLineRest) { // May be ‘/GHWND=NEW’ or smth else pszArg1 = cmdLineRest; cchMax += _tcslen(pszArg1); } cchMax += 16; // + quotations, spaces and so on wchar_t* pszCmd = (wchar_t*)calloc(cchMax, sizeof(*pszCmd)); _wsprintf(pszCmd, SKIPLEN(cchMax) L"\"%s\"%s%s%s", curCommand, pszArg1 ? L" \"" : L"", pszArg1 ? pszArg1 : L"", pszArg1 ? L"\"" : L""); if (0 == RegSetValueEx(hk, _T("AutoRun"), 0, REG_SZ, (LPBYTE)pszCmd, (DWORD)sizeof(*pszCmd)*(_tcslen(pszCmd)+1))) nSetupRc = 1; free(pszCmd); } else { if (0==RegDeleteValue(hk, _T("AutoRun"))) nSetupRc = 1; } RegCloseKey(hk); // сбросить CreateInNewEnvironment для ConMan ResetConman(); iResult = nSetupRc; goto wrap; } else if (!klstricmp(curCommand, _T("/bypass")) || !klstricmp(curCommand, _T("/apparent")) || !klstricmp(curCommand, _T("/system")) || !klstricmp(curCommand, _T("/interactive")) || !klstricmp(curCommand, _T("/demote"))) { // -bypass // Этот ключик был придуман для прозрачного запуска консоли // в режиме администратора // (т.е. чтобы окно UAC нормально всплывало, но не мелькало консольное окно) // Но не получилось, пока требуются хэндлы процесса, а их не получается // передать в НЕ приподнятый процесс (исходный ConEmu GUI). // -apparent // Same as -bypass, but run the process as SW_SHOWNORMAL // -demote // Запуск процесса (ком.строка после "/demote") в режиме простого юзера, // когда текущий процесс уже запущен "под админом". "Понизить" текущие // привилегии просто так нельзя, поэтому запуск идет через TaskSheduler. // -system // Non-interactive process, started as System account // It's used when starting consoles, our server works fine as non-interactive // -interactive // Used when ConEmu.exe is started under System account, // but we need to give starting process interactive capabilities. _ASSERTE(opt.runCommand.IsEmpty()); pszTemp = cmdLineRest; if ((NextArg(&pszTemp, szNext) == 0) && (szNext.ms_Val[0] == L'-' || szNext.ms_Val[0] == L'/') && (lstrcmpi(szNext.ms_Val+1, L"cmd") == 0)) { opt.runCommand.Set(pszTemp); } else { opt.runCommand.Set(cmdLineRest); } if (opt.runCommand.IsEmpty()) { CEStr lsMsg(L"Invalid cmd line. '", curCommand, L"' exists, command line is empty"); DisplayLastError(lsMsg, -1); goto wrap; } // Information #ifdef _DEBUG STARTUPINFO siOur = {sizeof(siOur)}; GetStartupInfo(&siOur); #endif STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; si.dwFlags = STARTF_USESHOWWINDOW; // Only `-demote` and `-apparent` switches were implemented to start application visible // All others are intended to run our server process, without blinking of course if ((0 == klstricmp(curCommand, _T("/demote"))) || (0 == klstricmp(curCommand, _T("/apparent")))) si.wShowWindow = SW_SHOWNORMAL; else si.wShowWindow = SW_HIDE; wchar_t szCurDir[MAX_PATH+1] = L""; GetCurrentDirectory(countof(szCurDir), szCurDir); BOOL b; DWORD nErr = 0; // if we were started from TaskScheduler, it would be nice to wait a little // to let parent (creator of the scheduler task) know we were started successfully bool bFromScheduler = false; // Log the command to be started { CEStr lsLog( L"Starting process", L": ", curCommand, L" `", opt.runCommand.ms_Val, L"`"); LogString(lsLog); } if (!klstricmp(curCommand, _T("/demote"))) { b = CreateProcessDemoted(opt.runCommand.ms_Val, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, szCurDir, &si, &pi, &nErr); } else if (!klstricmp(curCommand, _T("/system"))) { b = CreateProcessSystem(opt.runCommand.ms_Val, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, szCurDir, &si, &pi); } else if (!klstricmp(curCommand, _T("/interactive"))) { b = CreateProcessInteractive((DWORD)-1, NULL, opt.runCommand.ms_Val, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, szCurDir, &si, &pi, &nErr); bFromScheduler = true; } else // -bypass, -apparent { b = CreateProcess(NULL, opt.runCommand.ms_Val, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); nErr = b ? 0 : GetLastError(); bFromScheduler = true; } // Log the result { CEStr lsLog; wchar_t szExtra[32] = L""; if (b) { if (pi.dwProcessId) _wsprintf(szExtra, SKIPCOUNT(szExtra) L", PID=%u", pi.dwProcessId); lsLog = lstrmerge( L"Process was created successfully", szExtra); } else { _wsprintf(szExtra, SKIPCOUNT(szExtra) L", ErrorCode=%u", nErr); lsLog = lstrmerge( L"Failed to start process", szExtra); } LogString(lsLog); } // If the error was not shown yet if (nErr) DisplayLastError(opt.runCommand, nErr); // if we were started from TaskScheduler, it would be nice to wait a little // to let parent (creator of the scheduler task) know we were started successfully if (bFromScheduler) { LogString(L"Sleeping for 5 seconds"); Sleep(5*1000); } // Success? if (b) { iResult = 0; } // Done, close handles, if they were opened SafeCloseHandle(pi.hProcess); SafeCloseHandle(pi.hThread); goto wrap; } else if (!klstricmp(curCommand, _T("/multi"))) { gpConEmu->AppendExtraArgs(curCommand); gpConEmu->opt.MultiConValue = true; } else if (!klstricmp(curCommand, _T("/nomulti"))) { gpConEmu->AppendExtraArgs(curCommand); gpConEmu->opt.MultiConValue = false; } else if (!klstricmp(curCommand, _T("/visible"))) { gpConEmu->opt.VisValue = true; } else if (!klstricmp(curCommand, _T("/ct")) || !klstricmp(curCommand, _T("/cleartype")) || !klstricmp(curCommand, _T("/ct0")) || !klstricmp(curCommand, _T("/ct1")) || !klstricmp(curCommand, _T("/ct2"))) { switch (curCommand[3]) { case L'0': gpConEmu->opt.ClearTypeVal = NONANTIALIASED_QUALITY; break; case L'1': gpConEmu->opt.ClearTypeVal = ANTIALIASED_QUALITY; break; default: gpConEmu->opt.ClearTypeVal = CLEARTYPE_NATURAL_QUALITY; } } // Interface language else if (!klstricmp(curCommand, _T("/lng"))) { NeedNextArg(); if (!gpConEmu->opt.Language.Exists) { gpConEmu->opt.Language = curCommand; gpConEmu->AppendExtraArgs(L"/lng", curCommand); } } // Optional specific "ConEmu.l10n" else if (!klstricmp(curCommand, _T("/lngfile"))) { NeedNextArg(); if (!gpConEmu->opt.LanguageFile.Exists) { gpConEmu->opt.LanguageFile = curCommand; gpConEmu->AppendExtraArgs(L"/lngfile", curCommand); } } // имя шрифта else if (!klstricmp(curCommand, _T("/font"))) { NeedNextArg(); if (!gpConEmu->opt.FontVal.Exists) { gpConEmu->opt.FontVal = curCommand; gpConEmu->AppendExtraArgs(L"/font", curCommand); } } // Высота шрифта else if (!klstricmp(curCommand, _T("/size"))) { NeedNextArg(); if (!gpConEmu->opt.SizeVal.Exists) { gpConEmu->opt.SizeVal.SetInt(curCommand); } } // ADD fontname; by Mors else if (!klstricmp(curCommand, _T("/fontfile"))) { CESwitch szFile(sw_Str); if (!GetCfgParm(cmdLineRest, szFile, MAX_PATH)) { goto wrap; } gpConEmu->AppendExtraArgs(L"/fontfile", szFile.GetStr()); gpFontMgr->RegisterFont(szFile.GetStr(), TRUE); } // Register all fonts from specified directory else if (!klstricmp(curCommand, _T("/fontdir"))) { CESwitch szDir(sw_Str); if (!GetCfgParm(cmdLineRest, szDir, MAX_PATH)) { goto wrap; } gpConEmu->AppendExtraArgs(L"/fontdir", szDir.GetStr()); gpFontMgr->RegisterFontsDir(szDir.GetStr()); } else if (!klstricmp(curCommand, _T("/fs"))) { gpConEmu->opt.WindowModeVal = wmFullScreen; } else if (!klstricmp(curCommand, _T("/max"))) { gpConEmu->opt.WindowModeVal = wmMaximized; } else if (!klstricmp(curCommand, _T("/min")) || !klstricmp(curCommand, _T("/mintsa")) || !klstricmp(curCommand, _T("/starttsa"))) { gpConEmu->WindowStartMinimized = true; if (klstricmp(curCommand, _T("/min")) != 0) { gpConEmu->WindowStartTsa = true; gpConEmu->WindowStartNoClose = (klstricmp(curCommand, _T("/mintsa")) == 0); } } else if (!klstricmp(curCommand, _T("/tsa")) || !klstricmp(curCommand, _T("/tray"))) { gpConEmu->ForceMinimizeToTray = true; } else if (!klstricmp(curCommand, _T("/detached"))) { gpConEmu->m_StartDetached = crb_On; } else if (!klstricmp(curCommand, _T("/here"))) { gpConEmu->mb_ConEmuHere = true; gpConEmu->StoreWorkDir(); } else if (!klstricmp(curCommand, _T("/update"))) { gpConEmu->opt.AutoUpdateOnStart = true; } else if (!klstricmp(curCommand, _T("/noupdate"))) { // This one has more weight than AutoUpdateOnStart gpConEmu->opt.DisableAutoUpdate = true; } else if (!klstricmp(curCommand, _T("/nokeyhook")) || !klstricmp(curCommand, _T("/nokeyhooks")) || !klstricmp(curCommand, _T("/nokeybhook")) || !klstricmp(curCommand, _T("/nokeybhooks"))) { gpConEmu->DisableKeybHooks = true; } else if (!klstricmp(curCommand, _T("/nocloseconfirm"))) { gpConEmu->DisableCloseConfirm = true; } else if (!klstricmp(curCommand, _T("/nomacro"))) { gpConEmu->DisableAllMacro = true; } else if (!klstricmp(curCommand, _T("/nohotkey")) || !klstricmp(curCommand, _T("/nohotkeys"))) { gpConEmu->DisableAllHotkeys = true; } else if (!klstricmp(curCommand, _T("/nodeftrm")) || !klstricmp(curCommand, _T("/nodefterm"))) { gpConEmu->DisableSetDefTerm = true; } else if (!klstricmp(curCommand, _T("/noregfont")) || !klstricmp(curCommand, _T("/noregfonts"))) { gpConEmu->DisableRegisterFonts = true; } else if (!klstricmp(curCommand, _T("/inside")) || !lstrcmpni(curCommand, _T("/inside="), 8)) { bool bRunAsAdmin = isPressed(VK_SHIFT); bool bSyncDir = false; LPCWSTR pszSyncFmt = NULL; gpConEmu->mb_ConEmuHere = true; gpConEmu->StoreWorkDir(); if (curCommand[7] == _T('=')) { bSyncDir = true; pszSyncFmt = curCommand+8; // \eCD /d %1 - \e - ESC, \b - BS, \n - ENTER, %1 - "dir", %2 - "bash dir" } CConEmuInside::InitInside(bRunAsAdmin, bSyncDir, pszSyncFmt, 0, NULL); } else if (!klstricmp(curCommand, _T("/insidepid"))) { NeedNextArg(); bool bRunAsAdmin = isPressed(VK_SHIFT); wchar_t* pszEnd; // Здесь указывается PID, в который нужно внедриться. DWORD nInsideParentPID = wcstol(curCommand, &pszEnd, 10); if (nInsideParentPID) { CConEmuInside::InitInside(bRunAsAdmin, false, NULL, nInsideParentPID, NULL); } } else if (!klstricmp(curCommand, _T("/insidewnd"))) { NeedNextArg(); if (curCommand[0] == L'0' && (curCommand[1] == L'x' || curCommand[1] == L'X')) curCommand += 2; else if (curCommand[0] == L'x' || curCommand[0] == L'X') curCommand ++; bool bRunAsAdmin = isPressed(VK_SHIFT); wchar_t* pszEnd; // Здесь указывается HWND, в котором нужно создаваться. HWND hParent = (HWND)(DWORD_PTR)wcstoul(curCommand, &pszEnd, 16); if (hParent && IsWindow(hParent)) { CConEmuInside::InitInside(bRunAsAdmin, false, NULL, 0, hParent); } } else if (!klstricmp(curCommand, _T("/icon"))) { NeedNextArg(); if (!gpConEmu->opt.IconPrm.Exists && *curCommand) { gpConEmu->opt.IconPrm = true; gpConEmu->mps_IconPath = ExpandEnvStr(curCommand); } } else if (!klstricmp(curCommand, _T("/dir"))) { NeedNextArg(); if (*curCommand) { // Например, "%USERPROFILE%" wchar_t* pszExpand = NULL; if (wcschr(curCommand, L'%') && ((pszExpand = ExpandEnvStr(curCommand)) != NULL)) { gpConEmu->StoreWorkDir(pszExpand); SafeFree(pszExpand); } else { gpConEmu->StoreWorkDir(curCommand); } } } else if (!klstricmp(curCommand, _T("/updatejumplist"))) { // Copy current Task list to Win7 Jump list (Taskbar icon) gpConEmu->mb_UpdateJumpListOnStartup = true; } else if (!klstricmp(curCommand, L"/log") || !klstricmp(curCommand, L"/log0") || !klstricmp(curCommand, L"/log1") || !klstricmp(curCommand, L"/log2") || !klstricmp(curCommand, L"/log3") || !klstricmp(curCommand, L"/log4")) { if (!klstricmp(curCommand, L"/log") || !klstricmp(curCommand, L"/log0")) gpConEmu->opt.AdvLogging.SetInt(1); else gpConEmu->opt.AdvLogging.SetInt((BYTE)(curCommand[4] - L'0')); // 1..4 // Do create logging service DEBUGSTRSTARTUP(L"Creating log file"); gpConEmu->CreateLog(); } else if (!klstricmp(curCommand, _T("/single")) || !klstricmp(curCommand, _T("/reuse"))) { // "/reuse" switch to be remastered gpConEmu->AppendExtraArgs(curCommand); gpSetCls->SingleInstanceArg = sgl_Enabled; } else if (!klstricmp(curCommand, _T("/nosingle"))) { gpConEmu->AppendExtraArgs(curCommand); gpSetCls->SingleInstanceArg = sgl_Disabled; } else if (!klstricmp(curCommand, _T("/DesktopMode"))) { gpConEmu->opt.DesktopMode = true; } else if (!klstricmp(curCommand, _T("/quake")) || !klstricmp(curCommand, _T("/quakeauto")) || !klstricmp(curCommand, _T("/noquake"))) { if (!klstricmp(curCommand, _T("/quake"))) gpConEmu->opt.QuakeMode = 1; else if (!klstricmp(curCommand, _T("/quakeauto"))) gpConEmu->opt.QuakeMode = 2; else { gpConEmu->opt.QuakeMode = 0; if (gpSetCls->SingleInstanceArg == sgl_Default) gpSetCls->SingleInstanceArg = sgl_Disabled; } } else if (!klstricmp(curCommand, _T("/showhide")) || !klstricmp(curCommand, _T("/showhideTSA"))) { gpSetCls->SingleInstanceArg = sgl_Enabled; gpSetCls->SingleInstanceShowHide = !klstricmp(curCommand, _T("/showhide")) ? sih_ShowMinimize : sih_ShowHideTSA; } else if (!klstricmp(curCommand, _T("/reset")) || !klstricmp(curCommand, _T("/resetdefault")) || !klstricmp(curCommand, _T("/basic"))) { gpConEmu->opt.ResetSettings = true; if (!klstricmp(curCommand, _T("/resetdefault"))) { gpSetCls->isFastSetupDisabled = true; } else if (!klstricmp(curCommand, _T("/basic"))) { gpSetCls->isFastSetupDisabled = true; gpSetCls->isResetBasicSettings = true; } } else if (!klstricmp(curCommand, _T("/nocascade")) || !klstricmp(curCommand, _T("/dontcascade"))) { gpConEmu->AppendExtraArgs(curCommand); gpSetCls->isDontCascade = true; } else if (!klstricmp(curCommand, _T("/WndX")) || !klstricmp(curCommand, _T("/WndY")) || !klstricmp(curCommand, _T("/WndW")) || !klstricmp(curCommand, _T("/WndWidth")) || !klstricmp(curCommand, _T("/WndH")) || !klstricmp(curCommand, _T("/WndHeight"))) { TCHAR ch = curCommand[4]; CharUpperBuff(&ch, 1); CESwitch psz(sw_Str); bool bParm = false; if (!GetCfgParm(cmdLineRest, bParm, psz, 32)) { goto wrap; } gpConEmu->opt.SizePosPrm = true; // Direct X/Y implies /nocascade if (ch == _T('X') || ch == _T('Y')) { // TODO: isDontCascade must be in our opt struct !!! gpSetCls->isDontCascade = true; } switch (ch) { case _T('X'): gpConEmu->opt.sWndX.SetStr(psz.Str, sw_Str); break; case _T('Y'): gpConEmu->opt.sWndY.SetStr(psz.Str, sw_Str); break; case _T('W'): gpConEmu->opt.sWndW.SetStr(psz.Str, sw_Str); break; case _T('H'): gpConEmu->opt.sWndH.SetStr(psz.Str, sw_Str); break; } } else if (!klstricmp(curCommand, _T("/Monitor"))) { CESwitch psz(sw_Str); bool bParm = false; if (!GetCfgParm(cmdLineRest, bParm, psz, 64)) { goto wrap; } if ((gpConEmu->opt.Monitor.Mon = MonitorFromParam(psz.Str)) != NULL) { gpConEmu->opt.Monitor.Exists = true; gpConEmu->opt.Monitor.Type = sw_Int; gpStartEnv->hStartMon = gpConEmu->opt.Monitor.Mon; } } else if (!klstricmp(curCommand, _T("/Buffer")) || !klstricmp(curCommand, _T("/BufferHeight"))) { NeedNextArg(); if (!gpConEmu->opt.BufferHeightVal.Exists) { gpConEmu->opt.BufferHeightVal.SetInt(curCommand); if (gpConEmu->opt.BufferHeightVal.GetInt() < 0) { //setParent = true; -- Maximus5 - нефиг, все ручками gpConEmu->opt.BufferHeightVal = -gpConEmu->opt.BufferHeightVal.GetInt(); } if (gpConEmu->opt.BufferHeightVal.GetInt() < LONGOUTPUTHEIGHT_MIN) gpConEmu->opt.BufferHeightVal = LONGOUTPUTHEIGHT_MIN; else if (gpConEmu->opt.BufferHeightVal.GetInt() > LONGOUTPUTHEIGHT_MAX) gpConEmu->opt.BufferHeightVal = LONGOUTPUTHEIGHT_MAX; } } else if (!klstricmp(curCommand, _T("/Config"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.ConfigVal, 127)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/Palette"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.PaletteVal, MAX_PATH)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/LoadRegistry"))) { gpConEmu->AppendExtraArgs(curCommand); gpConEmu->opt.ForceUseRegistryPrm = true; } else if (!klstricmp(curCommand, _T("/LoadCfgFile")) || !klstricmp(curCommand, _T("/LoadXmlFile"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.LoadCfgFile, MAX_PATH, true)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/SaveCfgFile")) || !klstricmp(curCommand, _T("/SaveXmlFile"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.SaveCfgFile, MAX_PATH, true)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/GuiMacro"))) { // -- выполняется только последний if (!GetCfgParm(cmdLineRest, gpConEmu->opt.ExecGuiMacro, 0x8000, false)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/UpdateSrcSet"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.UpdateSrcSet, MAX_PATH*4, false)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/AnsiLog"))) { // -- используем последний из параметров, если их несколько if (!GetCfgParm(cmdLineRest, gpConEmu->opt.AnsiLogPath, MAX_PATH-40, true)) { goto wrap; } } else if (!klstricmp(curCommand, _T("/SetDefTerm"))) { gpConEmu->opt.SetUpDefaultTerminal = true; } else if (!klstricmp(curCommand, _T("/ZoneId"))) { gpConEmu->opt.FixZoneId = true; } else if (!klstricmp(curCommand, _T("/Exit"))) { gpConEmu->opt.ExitAfterActionPrm = true; } else if (!klstricmp(curCommand, _T("/QuitOnClose"))) { gpConEmu->mb_ForceQuitOnClose = true; } else if (!klstricmp(curCommand, _T("/Title"))) { bool bOk = false; CESwitch pszTitle(sw_Str); if (!GetCfgParm(cmdLineRest, bOk, pszTitle, 127)) { goto wrap; } gpConEmu->SetTitleTemplate(pszTitle.GetStr()); } else if (!klstricmp(curCommand, _T("/FindBugMode"))) { gpConEmu->mb_FindBugMode = true; } else if (!klstricmp(curCommand, _T("/debug")) || !klstricmp(curCommand, _T("/debugw")) || !klstricmp(curCommand, _T("/debugi"))) { // These switches were already processed } else if (!klstricmp(curCommand, _T("/?")) || !klstricmp(curCommand, _T("/h")) || !klstricmp(curCommand, _T("/help"))) { if (gpLng) gpLng->Reload(); ConEmuAbout::OnInfo_About(); iResult = -1; goto wrap; } // Final `-cmd ...` or `-cmdlist ...` else if ( !klstricmp(curCommand, _T("/cmd")) || !klstricmp(curCommand, _T("/cmdlist")) ) { if (opt.cfgSwitches.ms_Val) { _ASSERTE(pszArgStart>pszCopyToEnvStart); _ASSERTE((INT_PTR)(pszArgStart - pszCopyToEnvStart) <= opt.cfgSwitches.GetLen()); opt.cfgSwitches.ms_Val[pszArgStart - pszCopyToEnvStart] = 0; } opt.runCommand.Set(SkipNonPrintable(cmdLineRest)); opt.isScript = (klstricmp(curCommand, L"/cmdlist") == 0); break; } else { // Show error on unknown switch psUnknown = pszArgStart; break; } } // (*curCommand == L'/') // Avoid assertions in NextArg szArg.Empty(); szNext.Empty(); } // while (NextArg(&cmdLineRest, szArg, &pszArgStart) == 0) } // Processing loop end if (psUnknown) { DEBUGSTRSTARTUP(L"Unknown switch, exiting!"); if (gpSet->isLogging()) { // For direct logging we do not use lng resources CEStr lsLog(L"\r\n", L"Unknown switch specified: ", psUnknown, L"\r\n\r\n"); gpConEmu->LogString(lsLog, false, false); } CEStr szNewConWarn; LPCWSTR pszTestSwitch = (psUnknown[0] == L'-' || psUnknown[0] == L'/') ? ((psUnknown[1] == L'-' || psUnknown[1] == L'/') ? (psUnknown+2) : (psUnknown+1)) : psUnknown; if ((lstrcmpni(pszTestSwitch, L"new_console", 11) == 0) || (lstrcmpni(pszTestSwitch, L"cur_console", 11) == 0)) { szNewConWarn = lstrmerge(L"\r\n\r\n", CLngRc::getRsrc(lng_UnknownSwitch4/*"Switch -new_console must be specified *after* /cmd or /cmdlist"*/) ); } CEStr lsMsg( CLngRc::getRsrc(lng_UnknownSwitch1/*"Unknown switch specified:"*/), L"\r\n\r\n", psUnknown, szNewConWarn, L"\r\n\r\n", CLngRc::getRsrc(lng_UnknownSwitch2/*"Visit website to get thorough switches description:"*/), L"\r\n" CEGUIARGSPAGE L"\r\n\r\n", CLngRc::getRsrc(lng_UnknownSwitch3/*"Or run ‘ConEmu.exe -?’ to get the brief."*/) ); MBoxA(lsMsg); goto wrap; } // Set "ConEmuArgs" and "ConEmuArgs2" ProcessConEmuArgsVar(); // Continue normal startup bRc = true; wrap: return bRc; }
// The function exists in both "ConEmuC/ConEmuC.cpp" and "ConEmuCD/Actions.cpp" // Version in "ConEmuC/ConEmuC.cpp" shows arguments from main(int argc, char** argv) // Version in "ConEmuCD/Actions.cpp" perhaps would not be ever called int DoParseArgs(LPCWSTR asCmdLine) { char szLine[80]; char szCLVer[32]; HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi = {}; GetConsoleScreenBufferInfo(hOut, &csbi); struct Highlighter { HANDLE hOut; WORD defAttr; Highlighter(HANDLE ahOut, WORD adefAttr, WORD fore) : hOut(ahOut), defAttr(adefAttr) { SetConsoleTextAttribute(hOut, fore|(defAttr & 0xF0)); }; ~Highlighter() { SetConsoleTextAttribute(hOut, defAttr); }; }; #undef HL #define HL(fore) Highlighter hl(hOut, csbi.wAttributes, fore) #if defined(__GNUC__) lstrcpyn(szCLVer, "GNUC"); #elif defined(_MSC_VER) _wsprintfA(szCLVer, SKIPCOUNT(szCLVer) "VC %u.%u", (int)(_MSC_VER / 100), (int)(_MSC_VER % 100)); #else lstrcpyn(szCLVer, "<Unknown CL>"); #endif _wsprintfA(szLine, SKIPCOUNT(szLine) "main arguments (count %i) {%s}\n", gn_argc, szCLVer); { HL(10); _printf(szLine); } for (int j = 0; j < gn_argc; j++) { if (j >= 999) { HL(12); _printf("*** TOO MANY ARGUMENTS ***\n"); break; } _wsprintfA(szLine, SKIPCOUNT(szLine) " %u: ", j); { HL(2); _printf(szLine); } if (!gp_argv) { HL(12); _printf("*NULL"); } else if (!gp_argv[j]) { HL(12); _printf("<NULL>"); } else { { HL(8); _printf("`"); } { HL(15); _printf(gp_argv[j]); } { HL(8); _printf("`"); } } _printf("\n"); } { HL(10); _printf("Parsing command"); } { HL(8); _printf("\n `"); } { HL(15); _wprintf(asCmdLine); } { HL(8); _printf("`\n"); } int iShellCount = 0; LPWSTR* ppszShl = CommandLineToArgvW(asCmdLine, &iShellCount); int i = 0; CEStr szArg; { HL(10); _printf("ConEmu `NextArg` splitter\n"); } while (NextArg(&asCmdLine, szArg) == 0) { if (szArg.mb_Quoted) DemangleArg(szArg, true); _wsprintfA(szLine, SKIPCOUNT(szLine) " %u: ", ++i); { HL(2); _printf(szLine); } { HL(8); _printf("`"); } { HL(15); _wprintf(szArg); } { HL(8); _printf("`\n"); } } _wsprintfA(szLine, SKIPCOUNT(szLine) " Total arguments parsed: %u\n", i); { HL(8); _printf(szLine); } { HL(10); _printf("Standard shell splitter\n"); } for (int j = 0; j < iShellCount; j++) { _wsprintfA(szLine, SKIPCOUNT(szLine) " %u: ", j); { HL(2); _printf(szLine); } { HL(8); _printf("`"); } { HL(15); _wprintf(ppszShl[j]); } { HL(8); _printf("`\n"); } } _wsprintfA(szLine, SKIPCOUNT(szLine) " Total arguments parsed: %u\n", iShellCount); { HL(8); _printf(szLine); } LocalFree(ppszShl); return i; }
bool CDpiForDialog::SetDialogDPI(const DpiValue& newDpi, LPRECT lprcSuggested /*= NULL*/) { wchar_t szLog[160]; RECT rcClient = {}, rcCurWnd = {}; #ifdef _DEBUG if (gbSkipSetDialogDPI) { GetClientRect(mh_Dlg, &rcClient); GetWindowRect(mh_Dlg, &rcCurWnd); _wsprintf(szLog, SKIPCOUNT(szLog) L"SKIPPED CDpiForDialog::SetDialogDPI x%08X, OldDpi={%i,%i}, NewDpi={%i,%i}, CurSize={%i,%i}, CurClient={%i,%i}", (DWORD)(DWORD_PTR)mh_Dlg, m_CurDpi.Xdpi, m_CurDpi.Ydpi, newDpi.Xdpi, newDpi.Ydpi, (rcCurWnd.right - rcCurWnd.left), (rcCurWnd.bottom - rcCurWnd.top), (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top)); LogString(szLog); return false; } #endif if (mn_InSet > 0) return false; if (newDpi.Ydpi <= 0 || newDpi.Xdpi <= 0) return false; if (m_CurDpi.Ydpi <= 0 || m_CurDpi.Xdpi <= 0) return false; // When overall DPI is very large but new dpi is small // (example: primary mon is 192 high-dpi, new mon is 96 dpi) // Windows goes crazy... HUGE caption, scrollbars, checkbox marks and so on... // So huge difference makes dialog unattractive, let's try to smooth that DpiValue setDpi(newDpi); if (m_InitDpi.Ydpi > MulDiv(setDpi.Ydpi, 144, 96)) { // Increase DPI one step up setDpi.Ydpi = MulDiv(setDpi.Ydpi, 120, 96); setDpi.Xdpi = MulDiv(setDpi.Xdpi, 120, 96); // Log it _wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::SetDialogDPI x%08X forces larger dpi value from {%i,%i} to {%i,%i}", (DWORD)(DWORD_PTR)mh_Dlg, newDpi.Xdpi, newDpi.Ydpi, setDpi.Xdpi, setDpi.Ydpi); LogString(szLog); } if (m_CurDpi.Equals(setDpi)) return false; bool bRc = false; MArray<DlgItem>* p = NULL; DpiValue curDpi(m_CurDpi); HFONT hf = NULL; wchar_t szClass[100]; #ifdef _DEBUG LOGFONT lftest1 = {}, lftest2 = {}; HFONT hftest; int itest1, itest2; #endif // To avoid several nested passes InterlockedIncrement(&mn_InSet); m_CurDpi.SetDpi(setDpi); // Eval mn_CurFontHeight = GetFontSizeForDpi(NULL, m_CurDpi.Ydpi); //(m_CurDpi.Ydpi && m_InitDpi.Ydpi) ? (mn_InitFontHeight * m_CurDpi.Ydpi / m_InitDpi.Ydpi) : -11; mlf_CurFont = mlf_InitFont; mlf_CurFont.lfHeight = mn_CurFontHeight; mlf_CurFont.lfWidth = 0; // Font mapper fault if (mn_CurFontHeight == 0) goto wrap; if (!m_Items.Get(m_CurDpi.Ydpi, &p)) { MArray<DlgItem>* pOrig = NULL; int iOrigDpi = 0; if (!m_Items.GetNext(NULL, &iOrigDpi, &pOrig) || !pOrig || (iOrigDpi <= 0)) goto wrap; int iNewDpi = m_CurDpi.Ydpi; p = new MArray<DlgItem>(); DWORD dwStyle = GetWindowLong(mh_Dlg, GWL_STYLE); DWORD dwStyleEx = GetWindowLong(mh_Dlg, GWL_EXSTYLE); if (!GetClientRect(mh_Dlg, &rcClient) || !GetWindowRect(mh_Dlg, &rcCurWnd)) { delete p; goto wrap; } _ASSERTE(rcClient.left==0 && rcClient.top==0); int calcDlgWidth = rcClient.right * m_CurDpi.Xdpi / curDpi.Xdpi; int calcDlgHeight = rcClient.bottom * m_CurDpi.Ydpi / curDpi.Ydpi; DlgItem i = {mh_Dlg}; // Windows DWM manager do not resize NonClient areas of per-monitor dpi aware applications // So, we can not use AdjustWindowRectEx to determine full window rectangle // Just use current NonClient dimensions i.r.right = calcDlgWidth + ((rcCurWnd.right - rcCurWnd.left) - rcClient.right); i.r.bottom = calcDlgHeight + ((rcCurWnd.bottom - rcCurWnd.top) - rcClient.bottom); // .right and .bottom are width and height of the dialog _ASSERTE(i.r.left==0 && i.r.top==0); p->push_back(i); for (INT_PTR k = 1; k < pOrig->size(); k++) { const DlgItem& iOrig = (*pOrig)[k]; i.h = iOrig.h; i.r.left = iOrig.r.left * iNewDpi / iOrigDpi; i.r.top = iOrig.r.top * iNewDpi / iOrigDpi; i.r.right = iOrig.r.right * iNewDpi / iOrigDpi; i.r.bottom = iOrig.r.bottom * iNewDpi / iOrigDpi; p->push_back(i); } m_Items.Set(iNewDpi, p); } if (p->size() <= 0) { _ASSERTE(FALSE && "No elements"); goto wrap; } else { const DlgItem& di = (*p)[0]; _wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::SetDialogDPI x%08X, OldDpi={%i,%i}, NewDpi={%i,%i}, OldSize={%i,%i}, NewSize={%i,%i}, NewFont=%i", (DWORD)(DWORD_PTR)mh_Dlg, curDpi.Xdpi, curDpi.Ydpi, newDpi.Xdpi, newDpi.Ydpi, (rcCurWnd.right - rcCurWnd.left), (rcCurWnd.bottom - rcCurWnd.top), di.r.right, di.r.bottom, mlf_CurFont.lfHeight); LogString(szLog); } hf = CreateFontIndirect(&mlf_CurFont); if (hf == NULL) { goto wrap; } for (INT_PTR k = p->size() - 1; k >= 1; k--) { const DlgItem& di = (*p)[k]; GetClassName(di.h, szClass, countof(szClass)); DWORD nCtrlID = GetWindowLong(di.h, GWL_ID); DWORD nStyles = GetWindowLong(di.h, GWL_STYLE); bool bResizeCombo = (lstrcmpi(szClass, L"ComboBox") == 0); int iComboFieldHeight = 0, iComboWasHeight = 0; LONG_PTR lFieldHeight = 0, lNewHeight = 0; RECT rcCur = {}; HWND hComboEdit = NULL; RECT rcEdit = {}, rcClient = {}; if (bResizeCombo && (nStyles & CBS_OWNERDRAWFIXED)) { GetWindowRect(di.h, &rcCur); hComboEdit = FindWindowEx(di.h, NULL, L"Edit", NULL); GetClientRect(di.h, &rcClient); GetClientRect(hComboEdit, &rcEdit); iComboWasHeight = (rcCur.bottom - rcCur.top); lFieldHeight = SendMessage(di.h, CB_GETITEMHEIGHT, -1, 0); if (lFieldHeight < iComboWasHeight) { iComboFieldHeight = lFieldHeight; } } int newW = di.r.right - di.r.left; int newH = di.r.bottom - di.r.top; MoveWindow(di.h, di.r.left, di.r.top, newW, newH, FALSE); SendMessage(di.h, WM_SETFONT, (WPARAM)hf, FALSE/*immediately*/); if (bResizeCombo) { if ((nStyles & CBS_OWNERDRAWFIXED) && (iComboWasHeight > 0) && (iComboFieldHeight > 0)) { RECT rcEdit2 = {}, rcClient2 = {}; GetClientRect(di.h, &rcClient2); GetClientRect(hComboEdit, &rcEdit2); lNewHeight = newH*iComboFieldHeight/iComboWasHeight; _wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::Combo height changed - OldHeight=%i, ItemHeight=%i, NewHeight=%i, NewItemHeight=%i", (rcCur.bottom - rcCur.top), lFieldHeight, newH, lNewHeight); LogString(szLog); SendMessage(di.h, CB_SETITEMHEIGHT, -1, lNewHeight); } SendMessage(di.h, CB_SETEDITSEL, 0, MAKELPARAM(-1,0)); } EditIconHint_ResChanged(di.h); InvalidateRect(di.h, NULL, TRUE); #ifdef _DEBUG itest1 = GetObject(hf, sizeof(lftest1), &lftest1); hftest = (HFONT)SendMessage(di.h, WM_GETFONT, 0, 0); itest2 = GetObject(hftest, sizeof(lftest2), &lftest2); #endif } if (p->size() > 0) { const DlgItem& di = (*p)[0]; SendMessage(mh_Dlg, WM_SETFONT, (WPARAM)hf, FALSE); DWORD nWndFlags = SWP_NOZORDER | (lprcSuggested ? 0 : SWP_NOMOVE); SetWindowPos(mh_Dlg, NULL, lprcSuggested ? lprcSuggested->left : 0, lprcSuggested ? lprcSuggested->top : 0, di.r.right, di.r.bottom, nWndFlags); RECT rc = {}; GetClientRect(mh_Dlg, &rc); InvalidateRect(mh_Dlg, NULL, TRUE); RedrawWindow(mh_Dlg, &rc, NULL, /*RDW_ERASE|*/RDW_ALLCHILDREN/*|RDW_INVALIDATE|RDW_UPDATENOW|RDW_INTERNALPAINT*/); } if (mh_CurFont != hf) DeleteObject(mh_CurFont); mh_CurFont = hf; bRc = true; wrap: InterlockedDecrement(&mn_InSet); return bRc; }
wchar_t* CreateCommand(LPCWSTR asSource, LPCWSTR asTarget, UINT& iRc) { wchar_t* pszCommand = NULL; if (!szCmdStringFormat || !*szCmdStringFormat) { wchar_t szConEmuC[MAX_PATH] = L"", *psz; wchar_t szOTimeout[20] = L"", szTimeout[20] = L""; if (mb_OTimeout) _wsprintf(szOTimeout, SKIPCOUNT(szOTimeout) L"%u", mn_OTimeout); if (mb_Timeout) _wsprintf(szTimeout, SKIPCOUNT(szTimeout) L"%u", mn_Timeout); struct _Switches { LPCWSTR pszName, pszValue; } Switches[] = { {L"-login", m_Server.szUser}, {L"-password", m_Server.szPassword}, {L"-proxy", m_Proxy.szProxy}, {L"-proxylogin", m_Proxy.szProxyUser}, {L"-proxypassword", m_Proxy.szProxyPassword}, {L"-async", mb_AsyncMode ? L"Y" : L"N"}, {L"-otimeout", szOTimeout}, {L"-timeout", szTimeout}, }; if (!asSource || !*asSource || !asTarget || !*asTarget) { iRc = E_INVALIDARG; goto wrap; } if (!GetModuleFileName(ghOurModule, szConEmuC, countof(szConEmuC)) || !(psz = wcsrchr(szConEmuC, L'\\'))) { //ReportMessage(dc_LogCallback, L"GetModuleFileName(ghOurModule) failed, code=%u", at_Uint, GetLastError(), at_None); iRc = E_HANDLE; goto wrap; } psz[1] = 0; wcscat_c(szConEmuC, WIN3264TEST(L"ConEmuC.exe",L"ConEmuC64.exe")); /* ConEmuC /download [-login <name> -password <pwd>] [-proxy <address:port> [-proxylogin <name> -proxypassword <pwd>]] [-async Y|N] [-otimeout <ms>] [-timeout <ms>] "full_url_to_file" "local_path_name" */ if (!(pszCommand = lstrmerge(L"\"", szConEmuC, L"\" -download "))) { iRc = E_OUTOFMEMORY; goto wrap; } for (INT_PTR i = 0; i < countof(Switches); i++) { LPCWSTR pszValue = Switches[i].pszValue; if (pszValue && *pszValue && !lstrmerge(&pszCommand, Switches[i].pszName, L" \"", pszValue, L"\" ")) { iRc = E_OUTOFMEMORY; goto wrap; } } if (!lstrmerge(&pszCommand, asSource, L" \"", asTarget, L"\"")) { iRc = E_OUTOFMEMORY; goto wrap; } } else { // Environment string? Expand it wchar_t* pszExp = ExpandEnvStr(szCmdStringFormat); // "curl -L %1 -o %2" // "wget %1 -O %2" LPCWSTR Values[] = {asSource, asTarget}; pszCommand = ExpandMacroValues((pszExp && *pszExp) ? pszExp : szCmdStringFormat, Values, countof(Values)); SafeFree(pszExp); if (!pszCommand) { iRc = E_OUTOFMEMORY; goto wrap; } } wrap: return pszCommand; }