Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}
Beispiel #4
0
// 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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
// 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);
}
Beispiel #7
0
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);
}
Beispiel #9
0
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;
}
Beispiel #10
0
// 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);
}
Beispiel #11
0
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;
}
Beispiel #12
0
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);
}
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
// 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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
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;
}
Beispiel #21
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;
}
Beispiel #22
0
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;
}
Beispiel #23
0
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;
}
Beispiel #24
0
// 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;
}
Beispiel #25
0
//------------------------------------------------------------------------
///| 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;
}
Beispiel #26
0
// 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;
}
Beispiel #27
0
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;
}
Beispiel #28
0
	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;
	}