Example #1
0
int apiGetFullPathName(LPCWSTR lpFileName, CEStr& rsPath)
{
	bool bFound = false;
	wchar_t *pszFilePart, *pszBuffer = NULL;
	wchar_t szFind[MAX_PATH+1];

	DWORD nLen = GetFullPathName(lpFileName, countof(szFind), szFind, &pszFilePart);
	if (nLen)
	{
		if (nLen < countof(szFind))
		{
			bFound = true;
			rsPath.Set(szFind);
		}
		else
		{
			// Too long path, allocate more space
			pszBuffer = (wchar_t*)malloc((++nLen)*sizeof(*pszBuffer));
			if (pszBuffer)
			{
				DWORD nLen2 = GetFullPathName(lpFileName, nLen, pszBuffer, &pszFilePart);
				if (nLen2 && (nLen2 < nLen))
				{
					bFound = true;
					rsPath.Set(pszBuffer);
				}
				free(pszBuffer);
			}
		}
	}

	return bFound ? rsPath.GetLen() : 0;
}
Example #2
0
	// Create the command to show on the Integration settings page
	LPCWSTR CreateCommand(CEStr& rsReady)
	{
		rsReady = L"";

		for (INT_PTR i = 0; i < ourSwitches.size(); i++)
		{
			Switch* ps = ourSwitches[i];
			_ASSERTE(ps && !ps->szSwitch.IsEmpty());
			bool bOpt = !ps->szOpt.IsEmpty();
			bool bQuot = (bOpt && IsQuotationNeeded(ps->szOpt));
			lstrmerge(&rsReady.ms_Val,
				ps->szSwitch,
				bOpt ? L" " : NULL,
				bQuot ? L"\"" : NULL,
				bOpt ? ps->szOpt.c_str() : NULL,
				bQuot ? L"\" " : L" ");
		}

		if (!rsReady.IsEmpty() || bCmdList)
		{
			lstrmerge(&rsReady.ms_Val,
				bCmdList ? L"-runlist " : L"-run ", szCmd);
		}
		else
		{
			rsReady.Set(szCmd);
		}

		return rsReady.c_str(L"");
	};
Example #3
0
bool FileSearchInDir(LPCWSTR asFilePath, CEStr& rsFound)
{
	// Possibilities
	// a) asFilePath does not contain path, only: "far"
	// b) asFilePath contains path, but without extension: "C:\\Program Files\\Far\\Far"

	LPCWSTR pszSearchFile = asFilePath;
	LPCWSTR pszSlash = wcsrchr(asFilePath, L'\\');
	if (pszSlash)
	{
		if ((pszSlash - asFilePath) >= MAX_PATH)
		{
			// No need to continue, this is invalid path to executable
			return false;
		}

		// C:\Far\Far.exe /w /pC:\Far\Plugins\ConEmu;C:\Far\Plugins.My
		if (!IsFilePath(asFilePath, false))
		{
			return false;
		}

		// Do not allow '/' here
		LPCWSTR pszFwd = wcschr(asFilePath, L'/');
		if (pszFwd != NULL)
		{
			return false;
		}
	}

	wchar_t* pszSearchPath = NULL;
	if (pszSlash)
	{
		if ((pszSearchPath = lstrdup(asFilePath)) != NULL)
		{
			pszSearchFile = pszSlash + 1;
			pszSearchPath[pszSearchFile - asFilePath] = 0;
		}
	}

	// Попытаемся найти "по путям" (%PATH%)
	wchar_t *pszFilePart;
	wchar_t szFind[MAX_PATH+1];
	LPCWSTR pszExt = PointToExt(asFilePath);

	DWORD nLen = SearchPath(pszSearchPath, pszSearchFile, pszExt ? NULL : L".exe", countof(szFind), szFind, &pszFilePart);

	SafeFree(pszSearchPath);

	if (nLen && (nLen < countof(szFind)) && FileExists(szFind))
	{
		// asFilePath will be invalid after .Set
		rsFound.Set(szFind);
		return true;
	}

	return false;
}
Example #4
0
		void SetFKey(CEStr& lsSubst, UINT fn)
		{
			if (!Mods)
			{
				msprintf(szSubst, countof(szSubst), L"\033[%u~", fn);
			}
			else
			{
				msprintf(szSubst, countof(szSubst), L"\033[%u;%c~", fn, Mods+L'1');
			}
			lsSubst.Set(szSubst);
		}
Example #5
0
		void SetTilde(CEStr& lsSubst, wchar_t c)
		{
			if (!Mods)
			{
				msprintf(szSubst, countof(szSubst), L"\033[%c~", c);
			}
			else
			{
				msprintf(szSubst, countof(szSubst), L"\033[%c;%c~", c, Mods+L'1');
			}
			lsSubst.Set(szSubst);
		}
Example #6
0
		void SetKey(CEStr& lsSubst, wchar_t c, wchar_t prefix=L'O')
		{
			if (!Mods)
			{
				//wcscpy_c(szSubst, L"\033O*A");
				msprintf(szSubst, countof(szSubst), L"\033%c%c", prefix, c);
			}
			else
			{
				msprintf(szSubst, countof(szSubst), L"\033[1;%c%c", Mods+L'1', c);
			}
			lsSubst.Set(szSubst);
		}
Example #7
0
// Returns 0 if succeeded, otherwise the error code
int NextLine(const wchar_t** asLines, CEStr &rsLine, NEXTLINEFLAGS Flags /*= NLF_TRIM_SPACES|NLF_SKIP_EMPTY_LINES*/)
{
	if (!asLines || !*asLines)
		return CERR_CMDLINEEMPTY;

	const wchar_t* psz = *asLines;
	//const wchar_t szSpaces[] = L" \t";
	//const wchar_t szLines[] = L"\r\n";
	//const wchar_t szSpacesLines[] = L" \t\r\n";

	if ((Flags & (NLF_TRIM_SPACES|NLF_SKIP_EMPTY_LINES)) == (NLF_TRIM_SPACES|NLF_SKIP_EMPTY_LINES))
		psz = SkipNonPrintable(psz);
	else if (Flags & NLF_TRIM_SPACES)
		while (*psz == L' ' || *psz == L'\t') psz++;
	else if (Flags & NLF_SKIP_EMPTY_LINES)
		while (*psz == L'\r' || *psz == L'\n') psz++;

	if (!*psz)
	{
		*asLines = psz;
		return CERR_CMDLINEEMPTY;
	}

	const wchar_t* pszEnd = wcspbrk(psz, L"\r\n");
	if (!pszEnd)
	{
		pszEnd = psz + lstrlen(psz);
	}

	const wchar_t* pszTrim = pszEnd;
	if (*pszEnd == L'\r') pszEnd++;
	if (*pszEnd == L'\n') pszEnd++;

	if (Flags & NLF_TRIM_SPACES)
	{
		while ((pszTrim > psz) && ((*(pszTrim-1) == L' ') || (*(pszTrim-1) == L'\t')))
			pszTrim--;
	}

	_ASSERTE(pszTrim >= psz);
	rsLine.Set(psz, pszTrim-psz);
	psz = pszEnd;

	*asLines = psz;
	return 0;
}
Example #8
0
bool CLngRc::GetResource(MArray<LngRcItem>& arr, int idx, CEStr& lsText)
{
	bool bFound = false;

	if ((idx >= 0) && (idx < arr.size()))
	{
		const LngRcItem& item = arr[idx];

		if (item.Processed && (item.Str && *item.Str))
		{
			lsText.Set(item.Str);
			bFound = true;
		}
	}

	return bFound;
}
Example #9
0
bool IsNeedCmd(BOOL bRootCmd, LPCWSTR asCmdLine, CEStr &szExe,
			   LPCWSTR* rsArguments /*= NULL*/, BOOL* rpbNeedCutStartEndQuot /*= NULL*/,
			   BOOL* rpbRootIsCmdExe /*= NULL*/, BOOL* rpbAlwaysConfirmExit /*= NULL*/, BOOL* rpbAutoDisableConfirmExit /*= NULL*/)
{
	bool rbNeedCutStartEndQuot = false;
	bool rbRootIsCmdExe = true;
	bool rbAlwaysConfirmExit = false;
	bool rbAutoDisableConfirmExit = false;

	wchar_t *pwszEndSpace;

	if (rsArguments) *rsArguments = NULL;

	bool lbRc = false;
	int iRc = 0;
	BOOL lbFirstWasGot = FALSE;
	LPCWSTR pwszCopy;
	int nLastChar;
	#ifdef _DEBUG
	CEStr szDbgFirst;
	#endif

	if (!asCmdLine || !*asCmdLine)
	{
		_ASSERTE(asCmdLine && *asCmdLine);
		goto wrap;
	}

	#ifdef _DEBUG
	// Это минимальные проверки, собственно к коду - не относятся
	bool bIsBatch = false;
	{
		LPCWSTR psz = asCmdLine;
		NextArg(&psz, szDbgFirst);
		psz = PointToExt(szDbgFirst);
		if (lstrcmpi(psz, L".cmd")==0 || lstrcmpi(psz, L".bat")==0)
			bIsBatch = true;
	}
	#endif

	if (!szExe.GetBuffer(MAX_PATH))
	{
		_ASSERTE(FALSE && "Failed to allocate MAX_PATH");
		lbRc = true;
		goto wrap;
	}
	szExe.Empty();

	if (!asCmdLine || *asCmdLine == 0)
	{
		_ASSERTE(asCmdLine && *asCmdLine);
		lbRc = true;
		goto wrap;
	}


	pwszCopy = asCmdLine;
	// cmd /c ""c:\program files\arc\7z.exe" -?"   // да еще и внутри могут быть двойными...
	// cmd /c "dir c:\"
	nLastChar = lstrlenW(pwszCopy) - 1;

	if (pwszCopy[0] == L'"' && pwszCopy[nLastChar] == L'"')
	{
		//if (pwszCopy[1] == L'"' && pwszCopy[2])
		//{
		//	pwszCopy ++; // Отбросить первую кавычку в командах типа: ""c:\program files\arc\7z.exe" -?"

		//	if (rbNeedCutStartEndQuot) *rbNeedCutStartEndQuot = TRUE;
		//}
		//else
			// глючила на ""F:\VCProject\FarPlugin\#FAR180\far.exe  -new_console""
			//if (wcschr(pwszCopy+1, L'"') == (pwszCopy+nLastChar)) {
			//	LPCWSTR pwszTemp = pwszCopy;
			//	// Получим первую команду (исполняемый файл?)
			//	if ((iRc = NextArg(&pwszTemp, szArg)) != 0) {
			//		//Parsing command line failed
			//		lbRc = true; goto wrap;
			//	}
			//	pwszCopy ++; // Отбросить первую кавычку в командах типа: "c:\arc\7z.exe -?"
			//	lbFirstWasGot = TRUE;
			//	if (rbNeedCutStartEndQuot) *rbNeedCutStartEndQuot = TRUE;
			//} else
		{
			// Will be dequoted in 'NextArg' function. Examples
			// "C:\GCC\msys\bin\make.EXE -f "makefile" COMMON="../../../plugins/common""
			// ""F:\VCProject\FarPlugin\#FAR180\far.exe  -new_console""
			// ""cmd""
			// cmd /c ""c:\program files\arc\7z.exe" -?"   // да еще и внутри могут быть двойными...
			// cmd /c "dir c:\"

			LPCWSTR pwszTemp = pwszCopy;

			// Получим первую команду (исполняемый файл?)
			if ((iRc = NextArg(&pwszTemp, szExe)) != 0)
			{
				//Parsing command line failed
				#ifdef WARN_NEED_CMD
				_ASSERTE(FALSE);
				#endif
				lbRc = true; goto wrap;
			}

			if (lstrcmpiW(szExe, L"start") == 0)
			{
				// Команду start обрабатывает только процессор
				#ifdef WARN_NEED_CMD
				_ASSERTE(FALSE);
				#endif
				lbRc = true; goto wrap;
			}

			LPCWSTR pwszQ = pwszCopy + 1 + lstrlen(szExe);
			wchar_t* pszExpand = NULL;

			if (*pwszQ != L'"' && IsExecutable(szExe, &pszExpand))
			{
				pwszCopy ++; // отбрасываем
				lbFirstWasGot = TRUE;

				if (pszExpand)
				{
					szExe.Set(pszExpand);
					SafeFree(pszExpand);
					if (rsArguments)
						*rsArguments = pwszQ;
				}

				rbNeedCutStartEndQuot = true;
			}
		}
	}

	// Получим первую команду (исполняемый файл?)
	if (!lbFirstWasGot)
	{
		szExe.Empty();

		// `start` command must be processed by processor itself
		if ((lstrcmpni(pwszCopy, L"start", 5) == 0)
			&& (!pwszCopy[5] || isSpace(pwszCopy[5])))
		{
			#ifdef WARN_NEED_CMD
			_ASSERTE(FALSE);
			#endif
			lbRc = true; goto wrap;
		}

		// 17.10.2010 - support executable file path without parameters, but with spaces in its path
		// 22.11.2015 - or some weirdness, like `C:\Program Files\CB/cb_console_runner.exe "C:\sources\app.exe"`
		LPCWSTR pchEnd = wcschr(pwszCopy, L' ');
		if (!pchEnd)
			pchEnd = pwszCopy + lstrlenW(pwszCopy);

		CEStr szTemp;
		DWORD nTempSize;
		while (pchEnd)
		{
			szTemp.Set(pwszCopy, (pchEnd - pwszCopy));
			_ASSERTE(szTemp[(pchEnd - pwszCopy)] == 0);

			// If this is a full path without environment variables
			if (((IsFilePath(szTemp, true) && !wcschr(szTemp, L'%'))
				// or file/dir may be found via env.var. substitution or searching in %PATH%
				|| FileExistsSearch((LPCWSTR)szTemp, szTemp))
				// Than check if it is a FILE (not a directory)
				&& FileExists(szTemp, &nTempSize) && nTempSize)
			{
				// OK, it an our executable?
				if (rsArguments)
					*rsArguments = pchEnd;
				szExe.Set(szTemp);
				break;
			}

			_ASSERTE(*pchEnd == 0 || *pchEnd == L' ');
			if (!*pchEnd)
				break;
			// Find next space after nonspace
			while (*(pchEnd) == L' ') pchEnd++;
			// If quoted string starts from here - it's supposed to be an argument
			if (*pchEnd == L'"')
			{
				// And we must not get here, because the executable must be already processed above
				// _ASSERTE(*pchEnd != L'"');
				break;
			}
			pchEnd = wcschr(pchEnd, L' ');
			if (!pchEnd)
				pchEnd = pwszCopy + lstrlenW(pwszCopy);
		}

		if (szExe[0] == 0)
		{
			if ((iRc = NextArg(&pwszCopy, szExe)) != 0)
			{
				//Parsing command line failed
				#ifdef WARN_NEED_CMD
				_ASSERTE(FALSE);
				#endif
				lbRc = true; goto wrap;
			}

			_ASSERTE(lstrcmpiW(szExe, L"start") != 0);

			// Обработка переменных окружения и поиск в PATH
			if (FileExistsSearch((LPCWSTR)szExe, szExe))
			{
				if (rsArguments)
					*rsArguments = pwszCopy;
			}
		}
	}

	if (!*szExe)
	{
		_ASSERTE(szExe[0] != 0);
	}
	else
	{
		// Если юзеру нужен редирект - то он должен явно указать ком.процессор
		// Иначе нереально (или достаточно сложно) определить, является ли символ
		// редиректом, или это просто один из аргументов команды...

		// "Левые" символы в имени файла (а вот в "первом аргументе" все однозначно)
		if (wcspbrk(szExe, L"?*<>|"))
		{
			rbRootIsCmdExe = TRUE; // запуск через "процессор"
			lbRc = true; goto wrap; // добавить "cmd.exe"
		}

		// если "путь" не указан
		if (wcschr(szExe, L'\\') == NULL)
		{
			bool bHasExt = (wcschr(szExe, L'.') != NULL);
			// Проверим, может это команда процессора (типа "DIR")?
			if (!bHasExt)
			{
				bool bIsCommand = false;
				wchar_t* pszUppr = lstrdup(szExe);
				if (pszUppr)
				{
					// избежать линковки на user32.dll
					//CharUpperBuff(pszUppr, lstrlen(pszUppr));
					for (wchar_t* p = pszUppr; *p; p++)
					{
						if (*p >= L'a' && *p <= 'z')
							*p -= 0x20;
					}

					const wchar_t* pszFind = gsInternalCommands;
					while (*pszFind)
					{
						if (lstrcmp(pszUppr, pszFind) == 0)
						{
							bIsCommand = true;
							break;
						}
						pszFind += lstrlen(pszFind)+1;
					}
					free(pszUppr);
				}
				if (bIsCommand)
				{
					#ifdef WARN_NEED_CMD
					_ASSERTE(FALSE);
					#endif
					rbRootIsCmdExe = TRUE; // запуск через "процессор"
					lbRc = true; goto wrap; // добавить "cmd.exe"
				}
			}

			// Try to find executable in %PATH%
			{
				#ifndef CONEMU_MINIMAL
				MWow64Disable wow; wow.Disable(); // Disable Wow64 file redirector
				#endif
				apiSearchPath(NULL, szExe, bHasExt ? NULL : L".exe", szExe);
			}
		} // end: if (wcschr(szExe, L'\\') == NULL)
	}

	// Если szExe не содержит путь к файлу - запускаем через cmd
	// "start "" C:\Utils\Files\Hiew32\hiew32.exe C:\00\Far.exe"
	if (!IsFilePath(szExe))
	{
		#ifdef WARN_NEED_CMD
		_ASSERTE(FALSE);
		#endif
		rbRootIsCmdExe = TRUE; // запуск через "процессор"
		lbRc = true; goto wrap; // добавить "cmd.exe"
	}

	//pwszCopy = wcsrchr(szArg, L'\\'); if (!pwszCopy) pwszCopy = szArg; else pwszCopy ++;
	pwszCopy = PointToName(szExe);
	//2009-08-27
	pwszEndSpace = szExe.ms_Val + lstrlenW(szExe) - 1;

	while ((*pwszEndSpace == L' ') && (pwszEndSpace > szExe))
	{
		*(pwszEndSpace--) = 0;
	}

#ifndef __GNUC__
#pragma warning( push )
#pragma warning(disable : 6400)
#endif

	if (lstrcmpiW(pwszCopy, L"cmd")==0 || lstrcmpiW(pwszCopy, L"cmd.exe")==0
		|| lstrcmpiW(pwszCopy, L"tcc")==0 || lstrcmpiW(pwszCopy, L"tcc.exe")==0)
	{
		rbRootIsCmdExe = TRUE; // уже должен быть выставлен, но проверим
		rbAlwaysConfirmExit = TRUE; rbAutoDisableConfirmExit = FALSE;
		_ASSERTE(!bIsBatch);
		lbRc = false; goto wrap; // уже указан командный процессор, cmd.exe в начало добавлять не нужно
	}


	// Issue 1211: Decide not to do weird heuristic.
	//   If user REALLY needs redirection (root command, huh?)
	//   - he must call "cmd /c ..." directly
	// Если есть одна из команд перенаправления, или слияния - нужен CMD.EXE
	if (!bRootCmd)
	{
		if (wcschr(asCmdLine, L'&') ||
			wcschr(asCmdLine, L'>') ||
			wcschr(asCmdLine, L'<') ||
			wcschr(asCmdLine, L'|') ||
			wcschr(asCmdLine, L'^') // или экранирования
			)
		{
			#ifdef WARN_NEED_CMD
			_ASSERTE(FALSE);
			#endif
			lbRc = true; goto wrap;
		}
	}

	//if (lstrcmpiW(pwszCopy, L"far")==0 || lstrcmpiW(pwszCopy, L"far.exe")==0)
	if (IsFarExe(pwszCopy))
	{
		bool bFound = (wcschr(pwszCopy, L'.') != NULL);
		// Если указали при запуске просто "far" - это может быть батник, расположенный в %PATH%
		if (!bFound)
		{
			CEStr szSearch;
			if (apiSearchPath(NULL, pwszCopy, L".exe", szSearch))
			{
				if (lstrcmpi(PointToExt(szSearch), L".exe") == 0)
					bFound = true;
			}
		}

		if (bFound)
		{
			rbAutoDisableConfirmExit = TRUE;
			rbRootIsCmdExe = FALSE; // FAR!
			_ASSERTE(!bIsBatch);
			lbRc = false; goto wrap; // уже указан исполняемый файл, cmd.exe в начало добавлять не нужно
		}
	}

	if (IsExecutable(szExe))
	{
		rbRootIsCmdExe = FALSE; // Для других программ - буфер не включаем
		_ASSERTE(!bIsBatch);
		lbRc = false; goto wrap; // Запускается конкретная консольная программа. cmd.exe не требуется
	}

	//Можно еще Доделать поиски с: SearchPath, GetFullPathName, добавив расширения .exe & .com
	//хотя фар сам формирует полные пути к командам, так что можно не заморачиваться
	#ifdef WARN_NEED_CMD
	_ASSERTE(FALSE);
	#endif
	rbRootIsCmdExe = TRUE;
#ifndef __GNUC__
#pragma warning( pop )
#endif

	lbRc = true;
wrap:
	if (rpbNeedCutStartEndQuot)
		*rpbNeedCutStartEndQuot = rbNeedCutStartEndQuot;
	if (rpbRootIsCmdExe)
		*rpbRootIsCmdExe = rbRootIsCmdExe;
	if (rpbAlwaysConfirmExit)
		*rpbAlwaysConfirmExit = rbAlwaysConfirmExit;
	if (rpbAutoDisableConfirmExit)
		*rpbAutoDisableConfirmExit = rbAutoDisableConfirmExit;
	return lbRc;
}
Example #10
0
// Returns 0 if succeeded, otherwise the error code
int NextArg(const wchar_t** asCmdLine, CEStr &rsArg, const wchar_t** rsArgStart/*=NULL*/)
{
	if (!asCmdLine || !*asCmdLine)
		return CERR_CMDLINEEMPTY;

	#ifdef _DEBUG
	if ((rsArg.mn_TokenNo==0) // first token
		|| ((rsArg.mn_TokenNo>0) && (rsArg.ms_LastTokenEnd==*asCmdLine)
			&& (wcsncmp(*asCmdLine,rsArg.ms_LastTokenSave,countof(rsArg.ms_LastTokenSave)-1))==0))
	{
		// OK, параметры корректны
	}
	else
	{
		_ASSERTE(FALSE && "rsArgs was not resetted before new cycle!");
	}
	#endif

	LPCWSTR psCmdLine = SkipNonPrintable(*asCmdLine), pch = NULL;
	if (!*psCmdLine)
		return CERR_CMDLINEEMPTY;

	// Remote surrounding quotes, in certain cases
	// Example: ""7z.exe" /?"
	// Example: "C:\Windows\system32\cmd.exe" /C ""C:\Python27\python.EXE""
	if ((rsArg.mn_TokenNo == 0) || (rsArg.mn_CmdCall == CEStr::cc_CmdCK))
	{
		if (IsNeedDequote(psCmdLine, (rsArg.mn_CmdCall == CEStr::cc_CmdCK), &rsArg.mpsz_Dequoted))
			psCmdLine++;
		if (rsArg.mn_CmdCall == CEStr::cc_CmdCK)
			rsArg.mn_CmdCall = CEStr::cc_CmdCommand;
	}

	size_t nArgLen = 0;
	bool lbQMode = false;

	// аргумент начинается с "
	if (*psCmdLine == L'"')
	{
		lbQMode = true;
		psCmdLine++;
		// ... /d "\"C:\ConEmu\ConEmuPortable.exe\" /Dir ...
		bool bQuoteEscaped = (psCmdLine[0] == L'\\' && psCmdLine[1] == L'"');
		pch = wcschr(psCmdLine, L'"');
		if (pch && (pch > psCmdLine))
		{
			// To be correctly parsed something like this:
			// reg.exe add "HKCU\MyCo" /ve /t REG_EXPAND_SZ /d "\"C:\ConEmu\ConEmuPortable.exe\" /Dir \"%V\" /cmd \"cmd.exe\" \"-new_console:nC:cmd.exe\" \"-cur_console:d:%V\"" /f
			// But must not fails with ‘simple’ command like (no escapes in "C:\"):
			// /dir "C:\" /icon "cmd.exe" /single

			// Prev version fails while getting strings for -GuiMacro, example:
			// ConEmu.exe -detached -GuiMacro "print(\" echo abc \"); Context;"

			pch = wcspbrk(psCmdLine, L"\\\"");
			while (pch)
			{
				// Escaped quotation?
				if ((*pch == L'\\') && (*(pch+1) == L'"'))
				{
					// It's allowed when:
					// a) at the beginning of the line (handled above, bQuoteEscaped);
					// b) after space, left bracket or colon (-GuiMacro)
					// c) when already was forced by bQuoteEscaped
					if ((
						((((pch - 1) >= psCmdLine) && wcschr(L" (,", *(pch-1)))
							|| (*(pch+2) && !isSpace(*(pch+2)))
						)) || bQuoteEscaped)
					{
						bQuoteEscaped = true;
						pch++; // Point to "
					}
				}
				else if (*pch == L'"')
					break;
				// Next entry AFTER pch
				pch = wcspbrk(pch+1, L"\\\"");
			}
		}

		if (!pch) return CERR_CMDLINE;

		while (pch[1] == L'"' && (!rsArg.mpsz_Dequoted || ((pch+1) < rsArg.mpsz_Dequoted)))
		{
			pch += 2;
			pch = wcschr(pch, L'"');

			if (!pch) return CERR_CMDLINE;
		}

		// Теперь в pch ссылка на последнюю "
	}
	else
	{
		// До конца строки или до первого пробела
		//pch = wcschr(psCmdLine, L' ');
		// 09.06.2009 Maks - обломался на: cmd /c" echo Y "
		pch = psCmdLine;

		// General: Look for spacing of quote
		while (*pch && *pch!=L'"'
			&& *pch!=L' ' && *pch!=L'\t' && *pch!=L'\r' && *pch!=L'\n')
			pch++;

		//if (!pch) pch = psCmdLine + lstrlenW(psCmdLine); // до конца строки
	}

	_ASSERTE(pch >= psCmdLine);
	nArgLen = pch - psCmdLine;

	// Set result arugment
	// Warning: Don't demangle quotes/escapes here, or we'll fail to
	// concatenate environment or smth, losing quotes and others
	if (!rsArg.Set(psCmdLine, nArgLen))
		return CERR_CMDLINE;
	rsArg.mb_Quoted = lbQMode;
	rsArg.mn_TokenNo++;

	if (rsArgStart) *rsArgStart = psCmdLine;

	psCmdLine = pch;
	// Finalize
	if ((*psCmdLine == L'"') && (lbQMode || (rsArg.mpsz_Dequoted == psCmdLine)))
		psCmdLine++; // was pointed to closing quotation mark

	psCmdLine = SkipNonPrintable(psCmdLine);
	// When whole line was dequoted
	if ((*psCmdLine == L'"') && (rsArg.mpsz_Dequoted == psCmdLine))
		psCmdLine++;

	#ifdef _DEBUG
	rsArg.ms_LastTokenEnd = psCmdLine;
	lstrcpyn(rsArg.ms_LastTokenSave, psCmdLine, countof(rsArg.ms_LastTokenSave));
	#endif

	switch (rsArg.mn_CmdCall)
	{
	case CEStr::cc_Undefined:
		// Если это однозначно "ключ" - то на имя файла не проверяем
		if (*rsArg.ms_Val == L'/' || *rsArg.ms_Val == L'-')
		{
			// Это для парсинга (чтобы ассертов не было) параметров из ShellExecute (там cmd.exe указывается в другом аргументе)
			if ((rsArg.mn_TokenNo == 1) && (lstrcmpi(rsArg.ms_Val, L"/C") == 0 || lstrcmpi(rsArg.ms_Val, L"/K") == 0))
				rsArg.mn_CmdCall = CEStr::cc_CmdCK;
		}
		else
		{
			pch = PointToName(rsArg.ms_Val);
			if (pch)
			{
				if ((lstrcmpi(pch, L"cmd") == 0 || lstrcmpi(pch, L"cmd.exe") == 0)
					|| (lstrcmpi(pch, L"ConEmuC") == 0 || lstrcmpi(pch, L"ConEmuC.exe") == 0)
					|| (lstrcmpi(pch, L"ConEmuC64") == 0 || lstrcmpi(pch, L"ConEmuC64.exe") == 0))
				{
					rsArg.mn_CmdCall = CEStr::cc_CmdExeFound;
				}
			}
		}
		break;
	case CEStr::cc_CmdExeFound:
		if (lstrcmpi(rsArg.ms_Val, L"/C") == 0 || lstrcmpi(rsArg.ms_Val, L"/K") == 0)
			rsArg.mn_CmdCall = CEStr::cc_CmdCK;
		else if ((rsArg.ms_Val[0] != L'/') && (rsArg.ms_Val[0] != L'-'))
			rsArg.mn_CmdCall = CEStr::cc_Undefined;
		break;
	}

	*asCmdLine = psCmdLine;
	return 0;
}
Example #11
0
// Function checks, if we need drop first and last quotation marks
// Example: ""7z.exe" /?"
// Using cmd.exe rules
bool IsNeedDequote(LPCWSTR asCmdLine, bool abFromCmdCK, LPCWSTR* rsEndQuote/*=NULL*/)
{
	if (rsEndQuote)
		*rsEndQuote = NULL;

	if (!asCmdLine)
		return false;

	bool bDeQu = false;
	LPCWSTR pszQE, pszSP;
	if (asCmdLine[0] == L'"')
	{
		bDeQu = (asCmdLine[1] == L'"');
		// Всегда - нельзя. Иначе парсинг строки запуска некорректно идет
		// L"\"C:\\ConEmu\\ConEmuC64.exe\"  /PARENTFARPID=1 /C \"C:\\GIT\\cmdw\\ad.cmd CE12.sln & ci -m \"Solution debug build properties\"\""
		if (!bDeQu)
		{
			size_t nLen = lstrlen(asCmdLine);
			if (abFromCmdCK)
			{
				bDeQu = ((asCmdLine[nLen-1] == L'"') && (asCmdLine[nLen-2] == L'"'));
			}
			if (!bDeQu && (asCmdLine[nLen-1] == L'"'))
			{
				pszSP = wcschr(asCmdLine+1, L' ');
				pszQE = wcschr(asCmdLine+1, L'"');
				if (pszSP && pszQE && (pszSP < pszQE)
					&& ((pszSP - asCmdLine) < MAX_PATH))
				{
					CEStr lsTmp;
					lsTmp.Set(asCmdLine+1, pszSP-asCmdLine-1);
					bDeQu = (IsFilePath(lsTmp, true) && IsExecutable(lsTmp));
				}
			}
		}
	}
	if (!bDeQu)
		return false;

	// Don't dequote?
	pszQE = wcsrchr(asCmdLine+2, L'"');
	if (!pszQE)
		return false;

#if 0
	LPCWSTR pszQ1 = wcschr(asCmdLine+2, L'"');
	if (!pszQ1)
		return false;
	LPCWSTR pszQE = wcsrchr(pszQ1, L'"');
	// Only TWO quotes in asCmdLine?
	if (pszQE == pszQ1)
	{
		// Doesn't contains special symbols?
		if (!wcspbrk(asCmdLine+1, L"&<>()@^|"))
		{
			// Must contains spaces (doubt?)
			if (wcschr(asCmdLine+1, L' '))
			{
				// Cmd also checks this for executable file name. Skip this check?
				return false;
			}
		}
	}
#endif

	// Well, we get here
	_ASSERTE(asCmdLine[0]==L'"' && pszQE && *pszQE==L'"' && !wcschr(pszQE+1,L'"'));
	// Dequote it!
	if (rsEndQuote)
		*rsEndQuote = pszQE;
	return true;
}
Example #12
0
void CSetPgDebug::debugLogShell(DWORD nParentPID, CESERVER_REQ_ONCREATEPROCESS* pInfo)
{
	CSetPgDebug* pDbgPg = (CSetPgDebug*)gpSetCls->GetPageObj(thi_Debug);
	if (!pDbgPg)
		return;
	if ((pDbgPg->GetActivityLoggingType() != glt_Processes)
		&& (pDbgPg->GetActivityLoggingType() != glt_Shell))
		return;

	LPCWSTR pszFile = pInfo->wsValue + pInfo->nActionLen;
	LPCWSTR pszParam = pInfo->wsValue + pInfo->nActionLen+pInfo->nFileLen;
	DebugLogShellActivity *shl = (DebugLogShellActivity*)calloc(sizeof(DebugLogShellActivity),1);
	shl->nParentPID = nParentPID;
	shl->nParentBits = pInfo->nSourceBits;
	wcscpy_c(shl->szFunction, pInfo->sFunction);
	shl->pszAction = lstrdup(pInfo->wsValue);
	shl->pszFile   = lstrdup(pszFile);
	shl->pszParam  = lstrdup(pszParam);
	shl->bDos = (pInfo->nImageBits == 16) && (pInfo->nImageSubsystem == IMAGE_SUBSYSTEM_DOS_EXECUTABLE);
	shl->nImageBits = pInfo->nImageBits;
	shl->nImageSubsystem = pInfo->nImageSubsystem;
	shl->nShellFlags = pInfo->nShellFlags;
	shl->nCreateFlags = pInfo->nCreateFlags;
	shl->nStartFlags = pInfo->nStartFlags;
	shl->nShowCmd = pInfo->nShowCmd;
	shl->hStdIn = (DWORD)pInfo->hStdIn;
	shl->hStdOut = (DWORD)pInfo->hStdOut;
	shl->hStdErr = (DWORD)pInfo->hStdErr;

	// Append directory and bat/tmp files contents to pszParam
	{
		LPCWSTR pszDir = (pInfo->wsValue+pInfo->nActionLen+pInfo->nFileLen+pInfo->nParamLen);
		LPCWSTR pszAppFile = NULL;
		wchar_t*& pszParamEx = shl->pszParam;

		if (pszDir && *pszDir)
		{
			CEStr lsDir((pszParamEx && *pszParamEx) ? L"\r\n\r\n" : NULL, L"CD: \"", pszDir, L"\"");
			lstrmerge(&pszParamEx, lsDir);
		}

		if (shl->pszFile)
		{
			LPCWSTR pszExt = PointToExt(shl->pszFile);
			if (pszExt && (!lstrcmpi(pszExt, L".bat") || !lstrcmpi(pszExt, L".cmd")))
				debugLogShellText(pszParamEx, (pszAppFile = shl->pszFile));
		}

		if (pszParam && *pszParam)
		{
			LPCWSTR pszNext = pszParam;
			CEStr szArg;
			while (0 == NextArg(&pszNext, szArg))
			{
				if (!*szArg || (*szArg == L'-') || (*szArg == L'/'))
					continue;
				LPCWSTR pszExt = PointToExt(szArg);

				// Perhaps process *.tmp files too? (used with VC RC compilation?)
				if (pszExt && (!lstrcmpi(pszExt, L".bat") || !lstrcmpi(pszExt, L".cmd") /*|| !lstrcmpi(pszExt, L".tmp")*/)
					&& (!pszAppFile || (lstrcmpi(szArg, pszAppFile) != 0)))
				{
					debugLogShellText(pszParamEx, szArg);
				}
				else if (szArg[0] == L'@')
				{
					CEStr lsPath;

					if (IsFilePath(szArg.Mid(1), true))
					{
						// Full path to "arguments file"
						lsPath.Set(szArg.Mid(1));
					}
					else if ((szArg[1] != L'\\' && szArg[1] != L'/')
						&& (pszDir && *pszDir))
					{
						// Relative path to "arguments file"
						lsPath = JoinPath(pszDir, szArg.Mid(1));
					}

					if (!lsPath.IsEmpty())
					{
						debugLogShellText(pszParamEx, lsPath);
					}
				}
			}
		}
	}
	// end of "Append directory and bat/tmp files contents to pszParam"

	PostMessage(pDbgPg->Dlg(), DBGMSG_LOG_ID, DBGMSG_LOG_SHELL_MAGIC, (LPARAM)shl);
}
Example #13
0
	// pszFull comes from registry's [HKCR\Directory\shell\...\command]
	// Example:
	//	"C:\Tools\ConEmu.exe" -inside -LoadCfgFile "C:\Tools\ConEmu.xml" -FontDir C:\Tools\ConEmu
	//			-lngfile C:\Tools\ConEmu\ConEmu.l10n -lng ru  -dir "%1" -run {cmd} -cur_console:n
	// Strip switches which match current instance startup arguments
	// No sense to show them (e.g. "-lng ru") in the Integration dialog page
	void StripDupSwitches(LPCWSTR pszFull)
	{
		bCmdList = false;
		szCmd = L"";
		szDirSync = L"";
		szConfig = L"";
		ReleaseVectors();

		CEStr szArg, szNext;
		LPCWSTR psz;
		Switch* ps = NULL;

		// First, parse our extra args (passed to current ConEmu.exe)
		ParseStdSwitches();

		// Now parse new switches (command from registry or from field on Integration page)
		// Drop `-dir "..."` (especially from registry) always!

		psz = pszFull;
		while (0 == NextArg(&psz, szArg))
		{
			if (!szArg.IsPossibleSwitch())
				continue;

			if (szArg.OneOfSwitches(L"-inside", L"-here"))
			{
				// Nop
			}
			else if (szArg.IsSwitch(L"-inside:")) // Both "-inside:" and "-inside=" notations are supported
			{
				szDirSync.Set(szArg.Mid(8)); // may be empty!
			}
			else if (szArg.IsSwitch(L"-config"))
			{
				if (0 != NextArg(&psz, szArg))
					break;
				szConfig.Set(szArg);
			}
			else if (szArg.IsSwitch(L"-dir"))
			{
				if (0 != NextArg(&psz, szArg))
					break;
				_ASSERTE(lstrcmpi(szArg, L"%1")==0);
			}
			else if (szArg.OneOfSwitches(L"-Single", L"-NoSingle", L"-ReUse"))
			{
				ps = new Switch(szArg.Detach(), NULL);
				ourSwitches.push_back(ps);
			}
			else if (szArg.OneOfSwitches(L"-run", L"-cmd", L"-runlist", L"-cmdlist"))
			{
				// FIN! LAST SWITCH!
				szCmd.Set(psz);
				bCmdList = szArg.OneOfSwitches(L"-runlist",L"-cmdlist");
				break;
			}
			else if (NULL != (ps = GetNextSwitch(psz, szArg)))
			{
				if (IsIgnored(ps, GetSkipSwitches())
					|| IsIgnored(ps, stdSwitches))
				{
					SafeDelete(ps);
				}
				else
				{
					ourSwitches.push_back(ps);
				}
			}
		}
	};
Example #14
0
bool TermX::GetSubstitute(const KEY_EVENT_RECORD& k, CEStr& lsSubst)
{
	_ASSERTE(lsSubst.IsEmpty());

	// Bypass AltGr+keys to console intact
	if ((k.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_ALT_PRESSED)) == (LEFT_CTRL_PRESSED|RIGHT_ALT_PRESSED))
	{
		if (k.uChar.UnicodeChar)
		{
			wchar_t szData[3] = {k.uChar.UnicodeChar};
			if (LastDeadCharVK == k.wVirtualKeyCode)
				szData[1] = k.uChar.UnicodeChar;
			lsSubst.Set(szData);
			LastDeadCharVK = 0;
		}
		else
		{
			LastDeadCharVK = k.wVirtualKeyCode;
			lsSubst.Clear();
		}
		return true;
	}

	wchar_t szSubst[16] = L"";

	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
	};
	static wchar_t F1F4Codes[] = {L'P', L'Q', L'R', L'S'};

	static wchar_t ArrowCodes[] = {L'F', L'H', L'D', L'A', L'C', L'B'};

	typedef DWORD XTermCtrls;
	const XTermCtrls
		xtc_Shift = 1,
		xtc_Alt   = 2,
		xtc_Ctrl  = 4,
		xtc_None  = 0;
	struct processor
	{
		XTermCtrls Mods;
		wchar_t szSubst[16];

		void SetKey(CEStr& lsSubst, wchar_t c, wchar_t prefix=L'O')
		{
			if (!Mods)
			{
				//wcscpy_c(szSubst, L"\033O*A");
				msprintf(szSubst, countof(szSubst), L"\033%c%c", prefix, c);
			}
			else
			{
				msprintf(szSubst, countof(szSubst), L"\033[1;%c%c", Mods+L'1', c);
			}
			lsSubst.Set(szSubst);
		}

		void SetFKey(CEStr& lsSubst, UINT fn)
		{
			if (!Mods)
			{
				msprintf(szSubst, countof(szSubst), L"\033[%u~", fn);
			}
			else
			{
				msprintf(szSubst, countof(szSubst), L"\033[%u;%c~", fn, Mods+L'1');
			}
			lsSubst.Set(szSubst);
		}

		void SetTilde(CEStr& lsSubst, wchar_t c)
		{
			if (!Mods)
			{
				msprintf(szSubst, countof(szSubst), L"\033[%c~", c);
			}
			else
			{
				msprintf(szSubst, countof(szSubst), L"\033[%c;%c~", c, Mods+L'1');
			}
			lsSubst.Set(szSubst);
		}
	} 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_END:  case VK_HOME:  case VK_LEFT:
	case VK_UP:   case VK_RIGHT: case VK_DOWN:
		Processor.SetKey(lsSubst, ArrowCodes[(k.wVirtualKeyCode-VK_END)], AppCursorKeys ? L'O' : L'[');
		return true;

	case VK_F1: case VK_F2: case VK_F3: case VK_F4:
		Processor.SetKey(lsSubst, F1F4Codes[(k.wVirtualKeyCode-VK_F1)]);
		return true;
	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[]
		Processor.SetFKey(lsSubst, F1Codes[(k.wVirtualKeyCode-VK_F1)]);
		return true;

	case VK_INSERT:
		Processor.SetTilde(lsSubst, L'2');
		return true;
	case VK_PRIOR:
		Processor.SetTilde(lsSubst, L'5');
		return true;
	case VK_NEXT:
		Processor.SetTilde(lsSubst, L'6');
		return true;
	case VK_DELETE:
		Processor.SetTilde(lsSubst, L'3');
		return true;
	case VK_BACK:
		if ((Processor.Mods & xtc_Alt)) szSubst[0] = 0x1B;
		szSubst[(Processor.Mods == xtc_Alt) ? 1 : 0] = ((Processor.Mods & (xtc_Ctrl|xtc_Alt)) == (xtc_Ctrl|xtc_Alt)) ? 0x9F
			: (Processor.Mods & xtc_Ctrl) ? X_CTRL('_')/*0x1F*/ : X_CDEL/*0x7F*/;
		szSubst[(Processor.Mods == xtc_Alt) ? 2 : 1] = 0;
		lsSubst.Set(szSubst);
		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");
		}
		lsSubst.Set(szSubst);
		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;
		}
		lsSubst.Set(szSubst);
		return true;
	}

	// Alt+Char
	if ((Processor.Mods & xtc_Alt) && k.uChar.UnicodeChar
		// connector/gh#4: AltGr+Char
		&& (((k.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED|LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
				!= (LEFT_CTRL_PRESSED|RIGHT_ALT_PRESSED))
		// or just a Alt+Char
			|| !(Processor.Mods & xtc_Ctrl))
		)
	{
		szSubst[0] = L'\033'; szSubst[1] = k.uChar.UnicodeChar; szSubst[2] = 0;
		lsSubst.Set(szSubst);
		return true;
	}

	// Ctrl+Char: A-->1, ..., J-->10, ...
	if (Processor.Mods & (xtc_Alt | xtc_Ctrl))
	{
		wchar_t key_char = k.uChar.UnicodeChar;
		if (!key_char)
		{
			switch (k.wVirtualKeyCode)
			{
			case VK_OEM_2:
				key_char = L'?'; break; // Ctrl+/ -> \x1F
			case VK_OEM_3:
				key_char = L'~'; break;
			case VK_OEM_4:
				key_char = L'['; break;
			case VK_OEM_5:
				key_char = L'\\'; break;
			case VK_OEM_6:
				key_char = L']'; break;
			case VK_OEM_COMMA:
				key_char = L','; break;
			case VK_OEM_PERIOD:
				key_char = L'.'; break;
			case VK_OEM_MINUS:
				key_char = L'-'; break;
			case VK_OEM_PLUS:
				key_char = L'='; break;
			default:
				if (k.wVirtualKeyCode >= L'0' && k.wVirtualKeyCode <= L'9')
					key_char = k.wVirtualKeyCode;
				else if (k.wVirtualKeyCode >= L'A' && k.wVirtualKeyCode <= L'Z')
					key_char = k.wVirtualKeyCode;
			}
		}


		if (key_char)
		{
			szSubst[0] = szSubst[1] = szSubst[2] = szSubst[3] = 0;
			if ((Processor.Mods == xtc_Ctrl) && (key_char == L'2' || key_char == L' '))
			{
				// Must send '\x00' but it's not a valid ASCIIZ string, have to be processed in connector
				return false;
			}
			else if (key_char >= L'A' && key_char <= L'Z')
			{
				if (Processor.Mods == xtc_Ctrl)
				{
					// In vt220: If XOFF support is enabled, then CTRL-S is a "hold screen" local function and CTRL-Q is an "unhold screen" local function.
					szSubst[0] = (wchar_t)(1 + (key_char - L'A'));
				}
				else if ((Processor.Mods == (xtc_Ctrl|xtc_Alt))
					|| (Processor.Mods == (xtc_Ctrl|xtc_Alt|xtc_Shift)))
				{
					szSubst[0] = 0x1B;
					szSubst[1] = (wchar_t)(1 + (key_char - L'A'));
				}
				// doesn't work, "showkey -a" receives "<x1B><xC3><x82><x01>"
				//else if (Processor.Mods == (xtc_Ctrl|xtc_Alt|xtc_Shift))
				//{
				//	szSubst[0] = 0x1B; szSubst[1] = 0xC2;
				//	szSubst[2] = (wchar_t)(1 + (key_char - L'A'));
				//}
			}
			else if ((Processor.Mods == xtc_Ctrl) && (key_char == L'1' || key_char == L'9' || key_char == L'0'))
			{
				// Strangely Ctrl+1, Ctrl+9, Ctrl+0 generate only 1, 9 and 0.
				szSubst[0] = key_char;
			}
			else if ((Processor.Mods == xtc_Ctrl) && (key_char >= L'3' && key_char <= L'7'))
			{
				szSubst[0] = (wchar_t)(0x1B + (key_char - L'3'));
			}
			else switch (key_char)
			{
			case L',':
				szSubst[0] = 0x2C; break;
			//	Processor.SetKey(lsSubst, L'l'); break;
			case L'.':
				szSubst[0] = 0x2E; break;
			//	Processor.SetKey(lsSubst, L'n'); break;
			//case L'-':
			//	Processor.SetKey(lsSubst, L'm'); break;
			//case L'0':
			//	Processor.SetKey(lsSubst, L'p'); break;
			//case L'1':
			//	Processor.SetKey(lsSubst, L'q'); break;
			// case L'2': // processed above
			//case L'3':
			//	Processor.SetKey(lsSubst, L's'); break;
			//case L'4':
			//	Processor.SetKey(lsSubst, L't'); break;
			//case L'5':
			//	Processor.SetKey(lsSubst, L'u'); break;
			//case L'6':
			case L'~':
				szSubst[0] = 0x1E;
				break;
			//case L'7':
			//	Processor.SetKey(lsSubst, L'w'); break;
			case L'8':
				szSubst[0] = 0x1B;
				if ((Processor.Mods == (xtc_Ctrl|xtc_Alt)) || (Processor.Mods == (xtc_Ctrl|xtc_Alt|xtc_Shift)))
					szSubst[1] = 0x7F;
				else
					szSubst[0] = 0x7F;
				break;
				//Processor.SetKey(lsSubst, L'x'); break;
			//case L'9':
			//	Processor.SetKey(lsSubst, L'y'); break;
			//case L'=':
			//	Processor.SetKey(lsSubst, L'X'); break;
			case L'[':
			case L'\\':
			case L']':
			{
				wchar_t c = (key_char == L'[') ? 0x1B : (key_char == L'\\') ? 0x1C : 0x1D;
				szSubst[0] = 0x1B;
				if (Processor.Mods == xtc_Alt)
					szSubst[1] = 0x40 + c;
				else if ((Processor.Mods == (xtc_Ctrl|xtc_Alt)) || (Processor.Mods == (xtc_Ctrl|xtc_Alt|xtc_Shift)))
					szSubst[1] = c;
				else
					szSubst[0] = c;
				break;
			}
			case L'?':
				if (!(Processor.Mods & xtc_Alt))
					szSubst[0] = (Processor.Mods & xtc_Shift) ? 0x7F : 0x1F;
				else
				{
					szSubst[0] = 0x1B; szSubst[1] = (Processor.Mods & xtc_Shift) ? 0x3F : 0x2F;
				}
				break;
			}
			if (szSubst[0])
			{
				lsSubst.Set(szSubst);
				return true;
			}
		}
	}

	return false;
}
Example #15
0
bool TermX::GetSubstitute(const MOUSE_EVENT_RECORD& m, TermMouseMode MouseMode, CEStr& lsSubst)
{
	_ASSERTE(lsSubst.IsEmpty());

	if (!MouseMode)
	{
		lsSubst.Clear();
		return false;
	}

	wchar_t szSubst[16] = L"";

	// Deprecated. Mouse events mimic xterm behavior now.
	#if 0
	// http://conemu.github.io/en/VimXterm.html#Vim-scrolling-using-mouse-Wheel
	// https://github.com/Maximus5/ConEmu/issues/1007
	if ((m.dwEventFlags & MOUSE_WHEELED)
		&& (MouseMode & tmm_VIM))
	{
		// If the high word of the dwButtonState member contains
		// a positive value, the wheel was rotated forward, away from the user.
		// Otherwise, the wheel was rotated backward, toward the user.
		short dir = (short)HIWORD(m.dwButtonState);

		// Ctrl/Alt/Shift
		DWORD mods = (m.dwControlKeyState & (LEFT_ALT_PRESSED|LEFT_CTRL_PRESSED|RIGHT_ALT_PRESSED|RIGHT_CTRL_PRESSED|SHIFT_PRESSED));

		if (mods == 0)
		{
			if (dir <= 0)
				wcscpy_c(szSubst, L"\033[62~"); // <MouseDown>
			else
				wcscpy_c(szSubst, L"\033[63~"); // <MouseUp>
		}
		else if (mods == SHIFT_PRESSED)
		{
			if (dir <= 0)
				wcscpy_c(szSubst, L"\033[64~"); // <S-MouseDown>
			else
				wcscpy_c(szSubst, L"\033[65~"); // <S-MouseUp>
		}
		else
			return false;
		lsSubst.Set(szSubst);
		return true;
	}
	#endif

	if ((m.dwEventFlags & MOUSE_WHEELED)
		&& (MouseMode & tmm_SCROLL))
	{
		KEY_EVENT_RECORD k = {TRUE, 1};
		short dir = (short)HIWORD(m.dwButtonState);
		DWORD mods = (m.dwControlKeyState & (LEFT_ALT_PRESSED|LEFT_CTRL_PRESSED|RIGHT_ALT_PRESSED|RIGHT_CTRL_PRESSED|SHIFT_PRESSED));
		UINT nCount = 1;
		if (mods == 0)
		{
			k.wVirtualKeyCode = (dir > 0) ? VK_UP : VK_DOWN;
			nCount = gpConEmu->mouse.GetWheelScrollLines();
		}
		else if (mods == SHIFT_PRESSED)
		{
			k.wVirtualKeyCode = (dir > 0) ? VK_PRIOR : VK_NEXT;
		}
		else
			return false;
		CEStr lsPart;
		if (!GetSubstitute(k, lsPart) || lsPart.IsEmpty())
			return false;
		if (nCount > 1)
		{
			INT_PTR l = lsPart.GetLen();
			wchar_t* ptr = lsSubst.GetBuffer(l*nCount);
			for (UINT i = 1; i <= nCount; ++i, ptr += l)
				wcscpy_s(ptr, l+1, lsPart);
		}
		else
		{
			lsSubst.Attach(lsPart.Detach());
		}
		return true;
	}
	if (!(MouseMode & ~(tmm_VIM|tmm_SCROLL)))
		return false;


	BYTE NewBtns = (m.dwButtonState & 0x1F);
	if ((NewBtns != MouseButtons)
		|| ((m.dwEventFlags & MOUSE_WHEELED) && HIWORD(m.dwButtonState))
		|| ((LastMousePos != m.dwMousePosition)
			&& ((MouseMode & tmm_ANY)
				|| ((MouseMode & tmm_BTN) && NewBtns)))
		)
	{
		// #XTERM_MOUSE Unfortunately, szSubst is too short to pass "missed" coordinates
		// Like we do for Far events, MouseMove with RBtn pressed in tmm_ANY|tmm_BTN
		// modes would send all intermediate coordinates between two events

		BYTE code; bool released = false;
		if (NewBtns & FROM_LEFT_1ST_BUTTON_PRESSED)
			code = 0; // MB1 pressed
		else if (NewBtns & FROM_LEFT_2ND_BUTTON_PRESSED)
			code = 1; // MB2 pressed
		else if (NewBtns & RIGHTMOST_BUTTON_PRESSED)
			code = 2; // MB3 pressed
		else if (NewBtns & FROM_LEFT_3RD_BUTTON_PRESSED)
			code = 64; // MB4 pressed
		else if (NewBtns & FROM_LEFT_4TH_BUTTON_PRESSED)
			code = 64 + 1; // MB5 pressed
		else if (m.dwEventFlags & MOUSE_WHEELED)
		{
			// #XTERM_MOUSE Post multiple events if dir contains multiple notches
			short dir = (short)HIWORD(m.dwButtonState);
			if (dir > 0)
				code = 64; // MB4
			else if (dir < 0)
				code = 64 + 1; // MB5
		}
		else
		{
			released = true;
			code = 3;
		}

		if (m.dwControlKeyState & SHIFT_PRESSED)
			code |= 4;
		if (m.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
			code |= 8;
		if (m.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
			code |= 16;

		if ((m.dwEventFlags & MOUSE_MOVED)
			&& (MouseMode & (tmm_BTN|tmm_ANY)))
			code |= 32;

		// (1,1) is upper left character position
		SHORT coord[] = {std::max<SHORT>(0, m.dwMousePosition.X) + 1,
			std::max<SHORT>(0, m.dwMousePosition.Y) + 1};

		if (MouseMode & tmm_XTERM)
		{
			msprintf(szSubst, countof(szSubst), L"\033[<%u;%u;%u%c",
				code, coord[0], coord[1], released ? 'm' : 'M');
		}
		else if (MouseMode & tmm_URXVT)
		{
			msprintf(szSubst, countof(szSubst), L"\033[%u;%u;%uM", code + 0x20, coord[0], coord[1]);
		}
		else
		{
			wcscpy_c(szSubst, L"\033[M");
			size_t i = wcslen(szSubst);
			szSubst[i++] = code + 32;

			// And coords. Must be in "screen" coordinate space
			for (size_t s = 0; s < 2; ++s)
			{
				// (1,1) is upper left character position
				if (!(MouseMode & tmm_UTF8))
					szSubst[i++] = std::min<unsigned>(255, coord[s] + 32);
				else if (coord[s] < 0x80)
					szSubst[i++] = coord[s];
				else if (coord[s] < 0x800)
				{
					// xterm #262: positions from 96 to 2015 are encoded as a two-byte UTF-8 sequence
					szSubst[i++] = 0xC0 + (coord[s] >> 6);
					szSubst[i++] = 0x80 + (coord[s] & 0x3F);
				}
				else
				{
					// #XTERM_MOUSE Xterm reports out-of-range positions as a NUL byte.
					szSubst[i++] = 1; // It's impossible to post NUL byte ATM
				}
			}
Example #16
0
bool FileExistsSearch(LPCWSTR asFilePath, CEStr& rsFound, bool abSetPath/*= true*/, bool abRegSearch /*= true*/)
{
	if (!asFilePath || !*asFilePath)
	{
		_ASSERTEX(asFilePath && *asFilePath);
		return false;
	}

	if (FileExists(asFilePath))
	{
		return true;
	}

	// Развернуть переменные окружения
	if (wcschr(asFilePath, L'%'))
	{
		bool bFound = false;
		wchar_t* pszExpand = ExpandEnvStr(asFilePath);
		if (pszExpand && FileExists(pszExpand))
		{
			// asFilePath will be invalid after .Set
			rsFound.Set(pszExpand);
			bFound = true;
		}
		SafeFree(pszExpand);

		if (bFound)
		{
			return true;
		}
	}

	// Search "Path"
	if (FileSearchInDir(asFilePath, rsFound))
	{
		return true;
	}

	// Только если приложение не нашли "по путям" - пытаемся определить его расположение через [App Paths]
	// В противном случае, в частности, может быть запущен "far" не из папки с ConEmu, а зарегистрированный
	// в реестре, если на машине их несколько установлено.

	#if !defined(CONEMU_MINIMAL)
	_ASSERTE(gfnSearchAppPaths!=NULL);
	#endif

	// В ConEmuHk этот блок не активен, потому что может быть "только" перехват CreateProcess,
	// а о его параметрах должно заботиться вызывающее (текущее) приложение
	if (abRegSearch && gfnSearchAppPaths && !wcschr(asFilePath, L'\\'))
	{
		// Если в asFilePath НЕ указан путь - искать приложение в реестре,
		// и там могут быть указаны доп. параметры (пока только добавка в %PATH%)
		if (gfnSearchAppPaths(asFilePath, rsFound, abSetPath, NULL))
		{
			// Нашли по реестру, возможно обновили %PATH%
			return true;
		}
	}

	return false;
}
Example #17
0
int CIconList::CreateTabIconInt(LPCWSTR asIconDescr, bool bAdmin, LPCWSTR asWorkDir)
{
	wchar_t* pszExpanded = ExpandEnvStr(asIconDescr);

	// Need to be created!
	int iIconIdx = -1;
	HICON hFileIcon = NULL;
	CEStr szLoadFile;
	LPCWSTR lpszExt = NULL;
	int nIndex = 0;
	bool bDirChanged = false;

	if (!szLoadFile.Set(pszExpanded ? pszExpanded : asIconDescr))
	{
		goto wrap;
	}

	lpszExt = ParseIconFileIndex(szLoadFile, nIndex);

	if (asWorkDir && *asWorkDir)
	{
		// Executable (or icon) file may be not availbale by %PATH%, let "cd" to it...
		bDirChanged = gpConEmu->ChangeWorkDir(asWorkDir);
	}

	if (!lpszExt)
	{
		if (apiSearchPath(NULL, szLoadFile, L".exe", szLoadFile))
		{
			lpszExt = PointToExt(szLoadFile);
		}

		if (!lpszExt)
			goto wrap;
	}

	if (lstrcmpi(lpszExt, L".ico") == 0)
	{
		hFileIcon = (HICON)LoadImage(0, szLoadFile, IMAGE_ICON, mn_CxIcon, mn_CyIcon, LR_DEFAULTCOLOR|LR_LOADFROMFILE);
	}
	else if ((lstrcmpi(lpszExt, L".exe") == 0) || (lstrcmpi(lpszExt, L".dll") == 0))
	{
		HICON hIconLarge = NULL, hIconSmall = NULL;
		ExtractIconEx(szLoadFile, nIndex, &hIconLarge, &hIconSmall, 1);
		bool bUseLargeIcon = ((mn_CxIcon > 16) && (hIconLarge != NULL)) || (hIconSmall == NULL);
		HICON hDestroyIcon = bUseLargeIcon ? hIconSmall : hIconLarge;
		if (hDestroyIcon) DestroyIcon(hDestroyIcon);
		hFileIcon = bUseLargeIcon ? hIconLarge : hIconSmall;
	}
	else
	{
		//TODO: Shell icons for registered files (cmd, bat, sh, pl, py, ...)
	}

	if (hFileIcon)
	{
		wchar_t szIconInfo[80] = L"", szMergedInfo[80] = L"";
		GetIconInfoStr(hFileIcon, szIconInfo);

		if (gpSetCls->isAdvLogging)
		{
			CEStr lsLog(lstrmerge(L"Icon `", asIconDescr, L"` was loaded: ", szIconInfo));
			gpConEmu->LogString(lsLog);
		}

		int iIconIdxAdm = -1;
		iIconIdx = ImageList_ReplaceIcon(mh_TabIcons, -1, hFileIcon);

		TabIconCache NewIcon = {lstrdup(asIconDescr), iIconIdx, false};
		m_Icons.push_back(NewIcon);

		if (mn_AdminIcon >= 0)
		{
			HIMAGELIST hAdmList = ImageList_Merge(mh_TabIcons, iIconIdx, mh_TabIcons, mn_AdminIcon+2, 0,0);
			if (hAdmList)
			{
				HICON hNewIcon = ImageList_GetIcon(hAdmList, 0, ILD_TRANSPARENT);
				if (hNewIcon)
				{
					CEStr lsLog(lstrmerge(L"Admin icon `", asIconDescr, L"` was created: ", GetIconInfoStr(hNewIcon, szMergedInfo)));
					gpConEmu->LogString(lsLog);

					iIconIdxAdm = ImageList_ReplaceIcon(mh_TabIcons, -1, hNewIcon);
					DestroyIcon(hNewIcon);

					TabIconCache AdmIcon = {lstrdup(asIconDescr), iIconIdxAdm, true};
					m_Icons.push_back(AdmIcon);

					if (bAdmin && (iIconIdxAdm > 0))
					{
						iIconIdx = iIconIdxAdm;
					}
				}
				else
				{
					gpConEmu->LogString(L"GetIcon for admin icon was failed");
				}
				ImageList_Destroy(hAdmList);
			}
			else
			{
				gpConEmu->LogString(L"Admin icon merging was failed");
			}
		}

		DestroyIcon(hFileIcon);
	}

wrap:
	if (bDirChanged)
	{
		gpConEmu->ChangeWorkDir(NULL);
	}
	SafeFree(pszExpanded);
	if (gpSetCls->isAdvLogging && (iIconIdx < 0))
	{
		CEStr lsLog(lstrmerge(L"Icon `", asIconDescr, L"` loading was failed"));
		gpConEmu->LogString(lsLog);
	}
	return iIconIdx;
}
Example #18
0
INT_PTR CRecreateDlg::OnInitDialog(HWND hDlg, UINT messg, WPARAM wParam, LPARAM lParam)
{
	LRESULT lbRc = FALSE;

	gpConEmu->OnOurDialogOpened();

	CDynDialog::LocalizeDialog(hDlg);

	// Visual
	SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hClassIcon);
	SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hClassIconSm);

	// Set password style (avoid "bars" on some OS)
	SendDlgItemMessage(hDlg, tRunAsPassword, WM_SETFONT, (LPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), 0);

	// Add menu items
	HMENU hSysMenu = GetSystemMenu(hDlg, FALSE);
	InsertMenu(hSysMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
	InsertMenu(hSysMenu, 0, MF_BYPOSITION | MF_STRING | MF_ENABLED,
				ID_RESETCMDHISTORY, L"Clear history...");
	InsertMenu(hSysMenu, 0, MF_BYPOSITION | MF_STRING | MF_ENABLED
				| (gpSet->isSaveCmdHistory ? MF_CHECKED : 0),
				ID_STORECMDHISTORY, L"Store history");

	//#ifdef _DEBUG
	//SetWindowPos(ghOpWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
	//#endif

	RConStartArgsEx* pArgs = mp_Args;
	_ASSERTE(pArgs);

	// Fill command and task drop down
	SendMessage(hDlg, UM_FILL_CMDLIST, TRUE, 0);

	// Set text in command and folder fields
	{
	LPCWSTR pszSetCmd = mpsz_DefCmd ? mpsz_DefCmd : pArgs->pszSpecialCmd ? pArgs->pszSpecialCmd : L"";
	CEStr lsTempCmd, lsAppend;
	if (!mpsz_DefCmd && pArgs)
	{
		RConStartArgsEx tempArgs;
		tempArgs.AssignFrom(pArgs);
		tempArgs.CleanSecure();
		tempArgs.RunAsSystem = pArgs->RunAsSystem;
		tempArgs.eSplit = RConStartArgsEx::eSplitNone;
		SafeFree(tempArgs.pszSpecialCmd);
		SafeFree(tempArgs.pszStartupDir);
		tempArgs.NewConsole = pArgs->NewConsole;
		lsAppend = tempArgs.CreateCommandLine();
		if (!lsAppend.IsEmpty())
		{
			lsTempCmd = lstrmerge(pszSetCmd, ((lsAppend[0] == L' ') ? NULL : L" "), lsAppend);
			pszSetCmd = lsTempCmd.ms_Val;
		}
	}
	SetDlgItemText(hDlg, IDC_RESTART_CMD, pszSetCmd);
	// TODO: gh-959: enable autocorrection of cbRunAsAdmin by IDC_RESTART_CMD task contents (first line)
	}

	// "%CD%" was specified as startup dir? In Task parameters for example...
	CEStr lsStartDir;
	if (pArgs->pszStartupDir
		&& (lstrcmpi(pArgs->pszStartupDir, L"%CD%") == 0))
	{
		lsStartDir.Set(ms_RConCurDir);
	}
	// Suggest default ConEmu working directory otherwise (unless it's a cra_RecreateTab)
	if (lsStartDir.IsEmpty())
	{
		lsStartDir.Set(gpConEmu->WorkDir());
	}

	// Current directory, startup directory, ConEmu startup directory, and may be startup directory history in the future
	AddDirectoryList(mpsz_DefDir ? mpsz_DefDir : lsStartDir.ms_Val);
	AddDirectoryList(ms_RConCurDir);
	AddDirectoryList(ms_RConStartDir);
	AddDirectoryList(gpConEmu->WorkDir());
	LPCWSTR pszShowDir;
	if ((pArgs->aRecreate == cra_RecreateTab) && !ms_RConCurDir.IsEmpty())
		pszShowDir = ms_RConCurDir;
	else
		pszShowDir = mpsz_DefDir ? mpsz_DefDir : lsStartDir.ms_Val;
	SetDlgItemText(hDlg, IDC_STARTUP_DIR, pszShowDir);

	// Split controls
	if (pArgs->aRecreate == cra_RecreateTab)
	{
		// Hide Split's
		ShowWindow(GetDlgItem(hDlg, gbRecreateSplit), SW_HIDE);
		ShowWindow(GetDlgItem(hDlg, rbRecreateSplitNone), SW_HIDE);
		ShowWindow(GetDlgItem(hDlg, rbRecreateSplit2Right), SW_HIDE);
		ShowWindow(GetDlgItem(hDlg, rbRecreateSplit2Bottom), SW_HIDE);
		ShowWindow(GetDlgItem(hDlg, stRecreateSplit), SW_HIDE);
		ShowWindow(GetDlgItem(hDlg, tRecreateSplit), SW_HIDE);
	}
	else
	{
		// Fill splits
		SetDlgItemInt(hDlg, tRecreateSplit, (1000-pArgs->nSplitValue)/10, FALSE);
		CheckRadioButton(hDlg, rbRecreateSplitNone, rbRecreateSplit2Bottom, rbRecreateSplitNone+pArgs->eSplit);
		EnableWindow(GetDlgItem(hDlg, tRecreateSplit), (pArgs->eSplit != pArgs->eSplitNone));
		EnableWindow(GetDlgItem(hDlg, stRecreateSplit), (pArgs->eSplit != pArgs->eSplitNone));
	}

	// Спрятать флажок "New window"
	bool bRunInNewWindow_Hidden = (pArgs->aRecreate == cra_EditTab || pArgs->aRecreate == cra_RecreateTab);
	ShowWindow(GetDlgItem(hDlg, cbRunInNewWindow), bRunInNewWindow_Hidden ? SW_HIDE : SW_SHOWNORMAL);


	const wchar_t *pszUser = pArgs->pszUserName;
	const wchar_t *pszDomain = pArgs->pszDomain;
	bool bResticted = (pArgs->RunAsRestricted == crb_On);
	int nChecked = rbCurrentUser;
	int nNetOnly = cbRunAsNetOnly;
	DWORD nUserNameLen = countof(ms_CurUser);

	if (!GetUserName(ms_CurUser, &nUserNameLen))
		ms_CurUser[0] = 0;

	wchar_t szRbCaption[MAX_PATH*3];
	lstrcpy(szRbCaption, L"Run as current &user: "******"UPN format" остается в pszUser
					lstrcpyn(szOtherUser, pszUser, MAX_PATH);
					wcscat_c(szOtherUser, L"@");
					lstrcpyn(szOtherUser+_tcslen(szOtherUser), pszDomain, MAX_PATH);
				}
				else
				{
					// "Старая" нотация domain\user
					lstrcpyn(szOtherUser, pszDomain, MAX_PATH);
					wcscat_c(szOtherUser, L"\\");
					lstrcpyn(szOtherUser+_tcslen(szOtherUser), pszUser, MAX_PATH);
				}
			}
			else
			{
				lstrcpyn(szOtherUser, pszUser, countof(szOtherUser));
			}

			SetDlgItemText(hDlg, tRunAsPassword, pArgs->szUserPassword);
			EnableWindow(GetDlgItem(hDlg, cbRunAsNetOnly), TRUE);
		}
	}

	SetDlgItemText(hDlg, tRunAsUser, (nChecked == rbAnotherUser) ? szOtherUser : L"");
	CheckRadioButton(hDlg, rbCurrentUser, rbAnotherUser, nChecked);
	RecreateDlgProc(hDlg, UM_USER_CONTROLS, 0, 0);

	if (gOSVer.dwMajorVersion < 6)
	{
		// В XP и ниже это просто RunAs - с возможностью ввода имени пользователя и пароля
		//apiShowWindow(GetDlgItem(hDlg, cbRunAsAdmin), SW_HIDE);
		SetDlgItemTextA(hDlg, cbRunAsAdmin, "&Run as..."); //GCC hack. иначе не собирается
		// И уменьшить длину
		RECT rcBox; GetWindowRect(GetDlgItem(hDlg, cbRunAsAdmin), &rcBox);
		SetWindowPos(GetDlgItem(hDlg, cbRunAsAdmin), NULL, 0, 0, (rcBox.right-rcBox.left)/2, rcBox.bottom-rcBox.top,
				        SWP_NOMOVE|SWP_NOZORDER);
	}
	else if (gpConEmu->mb_IsUacAdmin || (pArgs && (pArgs->RunAsAdministrator == crb_On)))
	{
		CheckDlgButton(hDlg, cbRunAsAdmin, BST_CHECKED);

		if (gpConEmu->mb_IsUacAdmin)  // Только в Vista+ если GUI уже запущен под админом
		{
			EnableWindow(GetDlgItem(hDlg, cbRunAsAdmin), FALSE);
		}
		else //if (gOSVer.dwMajorVersion < 6)
		{
			RecreateDlgProc(hDlg, WM_COMMAND, cbRunAsAdmin, 0);
		}
	}

	//}
	SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR)hClassIcon);

	if (pArgs->aRecreate == cra_RecreateTab)
	{
		SetWindowText(hDlg, CLngRc::getRsrc(lng_DlgRestartConsole/*"Restart console"*/));
		SendDlgItemMessage(hDlg, IDC_RESTART_ICON, STM_SETICON, (WPARAM)LoadIcon(NULL,IDI_EXCLAMATION), 0);
		lbRc = TRUE;
	}
	else
	{
		SetWindowText(hDlg, CLngRc::getRsrc(lng_DlgCreateNewConsole/*"Create new console"*/));

		// If we disallowed to create "Multiple consoles in one window"
		// - Check & Disable "New window" checkbox
		bool bForceNewWindow = (!gpSetCls->IsMulti() && gpConEmu->isVConExists(0));
		CheckDlgButton(hDlg, cbRunInNewWindow, (pArgs->aRecreate == cra_CreateWindow || bForceNewWindow) ? BST_CHECKED : BST_UNCHECKED);
		EnableWindow(GetDlgItem(hDlg, cbRunInNewWindow), !bForceNewWindow);

		//
		SendDlgItemMessage(hDlg, IDC_RESTART_ICON, STM_SETICON, (WPARAM)LoadIcon(NULL,IDI_QUESTION), 0);
		POINT pt = {0,0};
		MapWindowPoints(GetDlgItem(hDlg, IDC_TERMINATE), hDlg, &pt, 1);
		DestroyWindow(GetDlgItem(hDlg, IDC_TERMINATE));
		SetWindowPos(GetDlgItem(hDlg, IDC_START), NULL, pt.x, pt.y, 0,0, SWP_NOSIZE|SWP_NOZORDER);
		SetDlgItemText(hDlg, IDC_START, (pArgs->aRecreate == cra_EditTab) ? L"&Save" : L"&Start");
		DestroyWindow(GetDlgItem(hDlg, IDC_WARNING));
	}

	// Align "New window" and "Run as administrator" checkboxes
	{
		RECT rcBox = {}; GetWindowRect(GetDlgItem(hDlg, cbRunAsAdmin), &rcBox);
		MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBox, 2);
		const int chk_height = (rcBox.bottom - rcBox.top);

		POINT pt = {rcBox.left};
		if (!bRunInNewWindow_Hidden)
		{
			RECT rcIcoBox = {}; GetWindowRect(GetDlgItem(hDlg, IDC_RESTART_ICON), &rcIcoBox);
			MapWindowPoints(NULL, hDlg, (LPPOINT)&rcIcoBox, 2);
			const int ico_height = (rcIcoBox.bottom - rcIcoBox.top);
			const int h2 = (chk_height * 5) / 2;
			pt.y = rcIcoBox.top + (ico_height - h2)/2;
			SetWindowPos(GetDlgItem(hDlg, cbRunInNewWindow), NULL, pt.x, pt.y, 0,0, SWP_NOSIZE|SWP_NOZORDER);
			pt.y += (h2 - chk_height);
		}
		else
		{
			RECT rcBtnBox = {}; GetWindowRect(GetDlgItem(hDlg, IDC_START), &rcBtnBox);
			MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtnBox, 2);
			const int btn_height = (rcBtnBox.bottom - rcBtnBox.top);
			pt.y = rcBtnBox.top + (btn_height - chk_height)/2;
		}
		SetWindowPos(GetDlgItem(hDlg, cbRunAsAdmin), NULL, pt.x, pt.y, 0,0, SWP_NOSIZE|SWP_NOZORDER);
	}

	// Dpi aware processing at the end of sequence
	// because we done some manual control reposition
	if (mp_DpiAware)
	{
		mp_DpiAware->Attach(hDlg, ghWnd, CDynDialog::GetDlgClass(hDlg));
	}

	// Ensure, it will be "on screen"
	RECT rect; GetWindowRect(hDlg, &rect);
	RECT rcCenter = CenterInParent(rect, mh_Parent);
	MoveWindow(hDlg, rcCenter.left, rcCenter.top,
			    rect.right - rect.left, rect.bottom - rect.top, false);


	// Была отключена обработка CConEmuMain::OnFocus (лишние телодвижения)
	PostMessage(hDlg, (WM_APP+1), 0,0);


	// Default focus control
	if (pArgs->aRecreate == cra_RecreateTab)
		SetFocus(GetDlgItem(hDlg, IDC_START)); // Win+~ (Recreate tab), Focus on "Restart" button"
	else if ((pArgs->pszUserName && *pArgs->pszUserName) && !*pArgs->szUserPassword)
		SetFocus(GetDlgItem(hDlg, tRunAsPassword)); // We need password, all other fields are ready
	else
		SetFocus(GetDlgItem(hDlg, IDC_RESTART_CMD)); // Set focus in command-line field

	return lbRc;
}