Ejemplo n.º 1
0
void CConEmuInside::InsideUpdateDir()
{
	CVConGuard VCon;

	if (mh_InsideParentPath && IsWindow(mh_InsideParentPath) && (gpConEmu->GetActiveVCon(&VCon) >= 0) && VCon->RCon())
	{
		wchar_t szCurText[512] = {};
		DWORD_PTR lRc = 0;
		if (SendMessageTimeout(mh_InsideParentPath, WM_GETTEXT, countof(szCurText), (LPARAM)szCurText, SMTO_ABORTIFHUNG|SMTO_NORMAL, 300, &lRc))
		{
			if (gnOsVer < 0x600)
			{
				// Если в заголовке нет полного пути
				if (wcschr(szCurText, L'\\') == NULL)
				{
					// Сразу выходим
					return;
				}
			}

			LPCWSTR pszPath = NULL;
			// Если тут уже путь - то префикс не отрезать
			if ((szCurText[0] == L'\\' && szCurText[1] == L'\\' && szCurText[2]) // сетевой путь
				|| (szCurText[0] && szCurText[1] == L':' && szCurText[2] == L'\\' /*&& szCurText[3]*/)) // Путь через букву диска
			{
				pszPath = szCurText;
			}
			else
			{
				// Иначе - отрезать префикс. На английской винде это "Address: D:\dir1\dir2"
				pszPath = wcschr(szCurText, L':');
				if (pszPath)
					pszPath = SkipNonPrintable(pszPath+1);
			}

			// Если успешно - сравниваем с ms_InsideParentPath
			if (pszPath && *pszPath && (lstrcmpi(ms_InsideParentPath, pszPath) != 0))
			{
				int nLen = lstrlen(pszPath);
				if (nLen >= (int)countof(ms_InsideParentPath))
				{
					_ASSERTE((nLen<countof(ms_InsideParentPath)) && "Too long path?");
				}
				else //if (VCon->RCon())
				{
					// Запомнить для сравнения
					lstrcpyn(ms_InsideParentPath, pszPath, countof(ms_InsideParentPath));
					// Подготовить команду для выполнения в Shell
					VCon->RCon()->PostPromptCmd(true, pszPath);
				}
			}
		}
	}
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
CBackgroundInfo* CBackgroundInfo::CreateBackgroundObject(LPCWSTR inPath, bool abShowErrors)
{
	if (inPath && _tcslen(inPath)>=MAX_PATH)
	{
		if (abShowErrors)
			MBoxA(L"Invalid 'BgImagePath' in CBackgroundInfo::CreateBackgroundObject");
		return NULL;
	}

	// Допускается и пустой путь!
	inPath = SkipNonPrintable(inPath);
	if (!inPath)
		inPath = L"";

	CBackgroundInfo* p = NULL;

	for (INT_PTR i = 0; i < g_Backgrounds.size(); i++)
	{
		if (!g_Backgrounds[i])
		{
			_ASSERTE(g_Backgrounds[i]!=NULL);
			continue;
		}
		if (lstrcmpi(g_Backgrounds[i]->BgImage(), inPath) == 0)
		{
			p = g_Backgrounds[i];
			break;
		}
	}

	if (p)
	{
		p->AddRef();
	}
	else
	{
		p = new CBackgroundInfo(inPath);
		if (inPath && *inPath && !p->LoadBackgroundFile(abShowErrors))
		{
			SafeRelease(p);
		}
	}

	return p;
}
Ejemplo n.º 4
0
// Comes from ConEmu's settings (Environment setting page)
void CProcessEnvCmd::AddLines(LPCWSTR asLines, bool bPriority)
{
	LPCWSTR pszLines = asLines;
	CEStr lsLine;
	INT_PTR nBefore = bPriority ? 0 : -1;

	while (0 == NextLine(&pszLines, lsLine))
	{
		// Skip empty lines
		LPCWSTR pszLine = SkipNonPrintable(lsLine);
		if (!pszLine || !*pszLine)
			continue;
		// A comment?
		if ((pszLine[0] == L'#')
			|| ((pszLine[0] == L'/') && (pszLine[1] == L'/'))
			|| ((pszLine[0] == L'-') && (pszLine[1] == L'-'))
			|| (lstrcmpni(pszLine, L"REM ", 4) == 0)
			)
			continue;
		// Process this line
		if (AddCommands(pszLine, NULL, true, nBefore) && bPriority)
			nBefore++;
	}
}
Ejemplo n.º 5
0
int CTabBarClass::PrepareTab(CTab& pTab, CVirtualConsole *apVCon)
{
	int iTabIcon = -1;

	#ifdef _DEBUG
	if (this != gpConEmu->mp_TabBar)
	{
		_ASSERTE(this == gpConEmu->mp_TabBar);
	}
	#endif

	MCHKHEAP
	// get file name
	TCHAR dummy[MAX_PATH*2];
	TCHAR fileName[MAX_PATH+4]; fileName[0] = 0;
	TCHAR szFormat[32];
	TCHAR szEllip[MAX_PATH+1];
	//wchar_t /**tFileName=NULL,*/ *pszNo=NULL, *pszTitle=NULL;
	int nSplit = 0;
	int nMaxLen = 0; //gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */;
	int origLength = 0; //_tcslen(tFileName);

	CRealConsole* pRCon = apVCon ? apVCon->RCon() : NULL;
	bool bIsFar = pRCon ? pRCon->isFar() : false;

	// Far 4040 - new "Desktop" window type has "0" index
	if (apVCon && (pTab->Info.nFarWindowID == 0 || pTab->Type() == fwt_Panels))
	{
		iTabIcon = apVCon->RCon()->GetRootProcessIcon();
	}

	LPCWSTR pszTabName = pRCon->GetTabTitle(pTab);

	if (pTab->Name.Empty() || (pTab->Type() == fwt_Panels))
	{
		//_tcscpy(szFormat, _T("%s"));
		lstrcpyn(szFormat, bIsFar ? gpSet->szTabPanels : gpSet->szTabConsole, countof(szFormat));
		nMaxLen = gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */;

		lstrcpyn(fileName, pszTabName, countof(fileName));

		if (gpSet->pszTabSkipWords && *gpSet->pszTabSkipWords)
		{
			StripWords(fileName, gpSet->pszTabSkipWords);
		}
		origLength = _tcslen(fileName);
		//if (origLength>6) {
		//    // Чтобы в заголовке было что-то вроде "{C:\Program Fil...- Far"
		//    //                              вместо "{C:\Program F...} - Far"
		//	После добавления суффиков к заголовку фара - оно уже влезать не будет в любом случае... Так что если панели - '...' строго ставить в конце
		//    if (lstrcmp(tFileName + origLength - 6, L" - Far") == 0)
		//        nSplit = nMaxLen - 6;
		//}
	}
	else
	{

		LPTSTR tFileName = NULL;
		if (GetFullPathName(pszTabName, countof(dummy), dummy, &tFileName) && tFileName && *tFileName)
			lstrcpyn(fileName, tFileName, countof(fileName));
		else
			lstrcpyn(fileName, pszTabName, countof(fileName));

		if (pTab->Type() == fwt_Editor)
		{
			if (pTab->Flags() & fwt_ModifiedFarWnd)
				lstrcpyn(szFormat, gpSet->szTabEditorModified, countof(szFormat));
			else
				lstrcpyn(szFormat, gpSet->szTabEditor, countof(szFormat));
		}
		else if (pTab->Type() == fwt_Viewer)
		{
			lstrcpyn(szFormat, gpSet->szTabViewer, countof(szFormat));
		}
		else
		{
			_ASSERTE(FALSE && "Must be processed in previous branch");
			lstrcpyn(szFormat, bIsFar ? gpSet->szTabPanels : gpSet->szTabConsole, countof(szFormat));
		}
	}

	// restrict length
	if (!nMaxLen)
		nMaxLen = gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */;

	if (!origLength)
		origLength = _tcslen(fileName);
	if (nMaxLen<15) nMaxLen=15; else if (nMaxLen>=MAX_PATH) nMaxLen=MAX_PATH-1;

	if (origLength > nMaxLen)
	{
		/*_tcsnset(fileName, _T('\0'), MAX_PATH);
		_tcsncat(fileName, tFileName, 10);
		_tcsncat(fileName, _T("..."), 3);
		_tcsncat(fileName, tFileName + origLength - 10, 10);*/
		//if (!nSplit)
		//    nSplit = nMaxLen*2/3;
		//// 2009-09-20 Если в заголовке нет расширения (отсутствует точка)
		//const wchar_t* pszAdmin = gpSet->szAdminTitleSuffix;
		//const wchar_t* pszFrom = tFileName + origLength - (nMaxLen - nSplit);
		//if (!wcschr(pszFrom, L'.') && (*pszAdmin && !wcsstr(tFileName, pszAdmin)))
		//{
		//	// то троеточие ставить в конец, а не середину
		//	nSplit = nMaxLen;
		//}
		// "{C:\Program Files} - Far 2.1283 Administrator x64"
		// После добавления суффиков к заголовку фара - оно уже влезать не будет в любом случае... Так что если панели - '...' строго ставить в конце
		nSplit = nMaxLen;
		_tcsncpy(szEllip, fileName, nSplit); szEllip[nSplit]=0;
		szEllip[nSplit] = L'\x2026' /*"…"*/;
		szEllip[nSplit+1] = 0;
		//_tcscat(szEllip, L"\x2026" /*"…"*/);
		//_tcscat(szEllip, tFileName + origLength - (nMaxLen - nSplit));
		//tFileName = szEllip;
		lstrcpyn(fileName, szEllip, countof(fileName));
	}

	// szFormat различается для Panel/Viewer(*)/Editor(*)
	// Пример: "%i-[%s] *"
	////pszNo = wcsstr(szFormat, L"%i");
	////pszTitle = wcsstr(szFormat, L"%s");
	////if (pszNo == NULL)
	////	_wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, tFileName);
	////else if (pszNo < pszTitle || pszTitle == NULL)
	////	_wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, pTab->Pos, tFileName);
	////else
	////	_wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, tFileName, pTab->Pos);
	//wcscpy(pTab->Name, fileName);
	const TCHAR* pszFmt = szFormat;
	TCHAR* pszDst = dummy;
	TCHAR* pszStart = pszDst;
	TCHAR* pszEnd = dummy + countof(dummy) - 1; // в конце еще нужно зарезервировать место для '\0'

	if (!pszFmt || !*pszFmt)
	{
		pszFmt = _T("%s");
	}
	*pszDst = 0;

	bool bRenamedTab = false;
	if (pTab->Flags() & fwt_Renamed)
	{
		if (wcsstr(pszFmt, L"%s") == NULL)
		{
			if (wcsstr(pszFmt, L"%n") != NULL)
				bRenamedTab = true;
			else
				pszFmt = _T("%s");
		}
	}

	TCHAR szTmp[64];
	CmdArg szArg;
	bool  bAppendAdmin = gpSet->isAdminSuffix() && (pTab->Flags() & fwt_Elevated);

	while (*pszFmt && pszDst < pszEnd)
	{
		if (*pszFmt == _T('%'))
		{
			pszFmt++;
			LPCTSTR pszText = NULL;
			switch (*pszFmt)
			{
				case _T('s'): case _T('S'):
					pszText = fileName;
					break;
				case _T('i'): case _T('I'):
					_wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%i"), pTab->Info.nIndex);
					pszText = szTmp;
					break;
				case _T('p'): case _T('P'):
					if (!apVCon || !apVCon->RCon())
					{
						wcscpy_c(szTmp, _T("?"));
					}
					else
					{
						_wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%u"), apVCon->RCon()->GetActivePID());
					}
					pszText = szTmp;
					break;
				case _T('c'): case _T('C'):
					{
						int iCon = gpConEmu->isVConValid(apVCon);
						if (iCon > 0)
							_wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%u"), iCon);
						else
							wcscpy_c(szTmp, _T("?"));
						pszText = szTmp;
					}
					break;
				case _T('n'): case _T('N'):
					{
						pszText = bRenamedTab ? fileName : pRCon ? pRCon->GetActiveProcessName() : NULL;
						wcscpy_c(szTmp, (pszText && *pszText) ? pszText : L"?");
						pszText = szTmp;
					}
					break;
				case _T('d'): case _T('D'):
					{
						pszText = pRCon ? pRCon->GetConsoleCurDir(szArg) : NULL;
						if (!pszText || !*pszText)
							pszText = L"?";
					}
					break;
				case _T('a'): case _T('A'):
					pszText = bAppendAdmin ? gpSet->szAdminTitleSuffix : NULL;
					bAppendAdmin = false;
					break;
				case _T('%'):
					pszText = L"%";
					break;
				case 0:
					pszFmt--;
					break;
			}
			pszFmt++;
			if (pszText)
			{
				if ((*(pszDst-1) == L' ') && (*pszText == L' '))
					pszText = SkipNonPrintable(pszText);
				while (*pszText && pszDst < pszEnd)
				{
					*(pszDst++) = *(pszText++);
				}
			}
		}
		else if ((pszDst > pszStart) && (*(pszDst-1) == L' ') && (*pszFmt == L' '))
		{
			pszFmt++; // Avoid adding sequential spaces (e.g. if some macros was empty)
		}
		else
		{
			*(pszDst++) = *(pszFmt++);
		}
	}

	// Fin. Append smth else?
	if (bAppendAdmin)
	{
		LPCTSTR pszText = gpSet->szAdminTitleSuffix;
		if (pszText)
		{
			while (*pszText && pszDst < pszEnd)
			{
				*(pszDst++) = *(pszText++);
			}
		}
	}

	*pszDst = 0;

	#ifdef _DEBUG
	if (dummy[0] && *(pszDst-1) == L' ')
		*pszDst = 0;
	#endif

	pTab->SetLabel(dummy);

	MCHKHEAP;

	return iTabIcon;
}
Ejemplo n.º 6
0
BOOL WINAPI OnReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, MY_CONSOLE_READCONSOLE_CONTROL* pInputControl)
{
	//typedef BOOL (WINAPI* OnReadConsoleW_t)(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, MY_CONSOLE_READCONSOLE_CONTROL* pInputControl);
	SUPPRESSORIGINALSHOWCALL;
	ORIGINAL_KRNL(ReadConsoleW);
	BOOL lbRc = FALSE;
	DWORD nErr = GetLastError();
	DWORD nStartTick = GetTickCount(), nEndTick = 0;

	OnReadConsoleStart(true, hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, pInputControl);

	lbRc = F(ReadConsoleW)(hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, pInputControl);
	nErr = GetLastError();
	// Debug purposes
	nEndTick = GetTickCount();

	// gh#465: Terminate Go input with Ctrl-Z
	if (lbRc && lpBuffer && lpNumberOfCharsRead && *lpNumberOfCharsRead
		&& (!pInputControl) // Probably, if application pass this structure it really knows what it's doing
		&& (*lpNumberOfCharsRead <= 3))
	{
		// To avoid checking of the mapping, we check result first
		const wchar_t* pchTest = (const wchar_t*)lpBuffer;
		if ((pchTest[0] == 26 /* Ctrl-Z / ^Z / (char)('Z' - '@') */)
			&& (((*lpNumberOfCharsRead == 3) && (pchTest[1] == '\r') && (pchTest[2] == '\n')) // Expected variant
				|| ((*lpNumberOfCharsRead == 2) && (pchTest[1] == '\n')) // Possible variant?
				))
		{
			if (isProcessCtrlZ())
				*lpNumberOfCharsRead = 0;
		}
	}

	OnReadConsoleEnd(lbRc, true, hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, pInputControl);

	// cd \\server\share\dir\...
	if (gbAllowUncPaths && lpBuffer && lpNumberOfCharsRead && *lpNumberOfCharsRead
		&& (nNumberOfCharsToRead >= *lpNumberOfCharsRead) && (nNumberOfCharsToRead > 6))
	{
		wchar_t* pszCmd = (wchar_t*)lpBuffer;
		// "cd " ?
		if ((pszCmd[0]==L'c' || pszCmd[0]==L'C') && (pszCmd[1]==L'd' || pszCmd[1]==L'D') && pszCmd[2] == L' ')
		{
			pszCmd[*lpNumberOfCharsRead] = 0;
			wchar_t* pszPath = (wchar_t*)SkipNonPrintable(pszCmd+3);
			// Don't worry about local paths, check only network
			if (pszPath[0] == L'\\' && pszPath[1] == L'\\')
			{
				wchar_t* pszEnd;
				if (*pszPath == L'"')
					pszEnd = wcschr(++pszPath, L'"');
				else
					pszEnd = wcspbrk(pszPath, L"\r\n\t&| ");
				if (!pszEnd)
					pszEnd = pszPath + lstrlen(pszPath);
				if ((pszEnd - pszPath) < MAX_PATH)
				{
					wchar_t ch = *pszEnd; *pszEnd = 0;
					BOOL bSet = SetCurrentDirectory(pszPath);
					if (ch) *pszEnd = ch;
					if (bSet)
					{
						if (*pszEnd == L'"') pszEnd++;
						pszEnd = (wchar_t*)SkipNonPrintable(pszEnd);
						if (*pszEnd && wcschr(L"&|", *pszEnd))
						{
							while (*pszEnd && wcschr(L"&|", *pszEnd)) pszEnd++;
							pszEnd = (wchar_t*)SkipNonPrintable(pszEnd);
						}
						// Return anything...
						if (*pszEnd)
						{
							int nLeft = lstrlen(pszEnd);
							memmove(lpBuffer, pszEnd, (nLeft+1)*sizeof(*pszEnd));
						}
						else
						{
							lstrcpyn((wchar_t*)lpBuffer, L"cd\r\n", nNumberOfCharsToRead);

						}
						*lpNumberOfCharsRead = lstrlen((wchar_t*)lpBuffer);
					}
				}
			}
		}
	}

	SetLastError(nErr);

	UNREFERENCED_PARAMETER(nStartTick);
	UNREFERENCED_PARAMETER(nEndTick);
	return lbRc;
}
Ejemplo n.º 7
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;
	CmdArg  szArg, szNext;
	CEStr   szExeName, szExeNameOnly;

	// Set %ConEmuArgs% env var
	// It may be useful 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 (!(pszTemp = NextArg(pszTemp, szArg)))
	{
		_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 ((pszTemp = NextArg(pszTemp, szArg)))
		{
			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;
			}
		}
	}

	struct RunAsAdmin
	{
		static bool Check(LPCWSTR asSwitch)
		{
			bool bRunAsAdmin = false; // isPressed(VK_SHIFT);
			return bRunAsAdmin;
		};
	};


	// Let parse the reset
	szArg.Empty();
	szNext.Empty();

	// Processing loop begin
	if (cmdLineRest && *cmdLineRest)
	{
		pszCopyToEnvStart = cmdLineRest;
		opt.cfgSwitches.Set(pszCopyToEnvStart);

		while ((cmdLineRest = NextArg(cmdLineRest, szArg, &pszArgStart)))
		{
			bool lbNotFound = false;

			TODO("Replace NeedNextArg with GetCfgParm?")
			#define NeedNextArg() \
				if (!(cmdLineRest = NextArg(cmdLineRest, szNext))) { iResult = CERR_CARGUMENT; goto wrap; }


			if (!szArg.IsPossibleSwitch())
			{
				// -- // continue; // Try next switch?

				// Show error on unknown switch
				psUnknown = pszArgStart;
				break;
			}

			// Main processing cycle
			{
				opt.params++;

				if (szArg.IsSwitch(L"-autosetup"))
				{
					BOOL lbTurnOn = TRUE;

					NeedNextArg();

					if (szNext.Compare(L"0") == 0)
					{
						lbTurnOn = FALSE;
					}
					else if (szNext.Compare(L"1") == 0)
					{
						NeedNextArg();

						DWORD dwAttr = GetFileAttributes(szNext);

						if (dwAttr == (DWORD)-1 || (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
						{
							iResult = 102;
							goto wrap;
						}
					}
					else
					{
						iResult = CERR_CARGUMENT;
						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 = szNext.GetLen();
						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));
						swprintf_c(pszCmd, cchMax/*#SECURELEN*/, L"\"%s\"%s%s%s", szNext.ms_Val,
							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 (szArg.OneOfSwitches(L"-bypass", L"-apparent", L"-system:", L"-interactive:", L"-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 ((pszTemp = NextArg(pszTemp, szNext))
						&& szNext.OneOfSwitches(L"-run",L"-cmd"))
					{
						opt.runCommand.Set(pszTemp);
					}
					else
					{
						opt.runCommand.Set(cmdLineRest);
					}

					if (opt.runCommand.IsEmpty())
					{
						CEStr lsMsg(L"Invalid command line. '", szArg, 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 (szArg.OneOfSwitches(L"-demote", L"-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": ", szArg,
							L" `", opt.runCommand.ms_Val, L"`");
						LogString(lsLog);
					}

					if (szArg.IsSwitch(L"-demote"))
					{
						b = CreateProcessDemoted(opt.runCommand.ms_Val, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL,
							szCurDir, &si, &pi, &nErr);
					}
					else if (szArg.IsSwitch(L"-system:"))
					{
						DWORD nSessionID = wcstoul(szArg.ms_Val+wcslen(L"-system:"), NULL, 10);
						b = CreateProcessSystem(nSessionID, opt.runCommand.ms_Val, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL,
							szCurDir, &si, &pi);
					}
					else if (szArg.IsSwitch(L"-interactive:"))
					{
						DWORD nSessionID = wcstoul(szArg.ms_Val+wcslen(L"-interactive:"), NULL, 10);
						b = CreateProcessInteractive(nSessionID, 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)
								swprintf_c(szExtra, L", PID=%u", pi.dwProcessId);
							lsLog = lstrmerge(
								L"Process was created successfully",
								szExtra);
						}
						else
						{
							swprintf_c(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 (szArg.IsSwitch(L"-multi"))
				{
					gpConEmu->AppendExtraArgs(szArg);
					gpConEmu->opt.MultiConValue = true;
				}
				else if (szArg.IsSwitch(L"-NoMulti"))
				{
					gpConEmu->AppendExtraArgs(szArg);
					gpConEmu->opt.MultiConValue = false;
				}
				else if (szArg.IsSwitch(L"-visible"))
				{
					gpConEmu->opt.VisValue = true;
				}
				else if (szArg.OneOfSwitches(L"-ct", L"-cleartype", L"-ct0", L"-ct1", L"-ct2"))
				{
					switch (szArg[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 (szArg.IsSwitch(L"-lng"))
				{
					NeedNextArg();

					if (!gpConEmu->opt.Language.Exists)
					{
						gpConEmu->opt.Language = (LPCWSTR)szNext;
						gpConEmu->AppendExtraArgs(L"-lng", szNext);
					}
				}
				// Optional specific "ConEmu.l10n"
				else if (szArg.IsSwitch(L"-lngfile"))
				{
					NeedNextArg();

					if (!gpConEmu->opt.LanguageFile.Exists)
					{
						gpConEmu->opt.LanguageFile = (LPCWSTR)szNext;
						gpConEmu->AppendExtraArgs(L"-lngfile", szNext);
					}
				}
				// Change font name
				else if (szArg.IsSwitch(L"-Font"))
				{
					NeedNextArg();

					if (!gpConEmu->opt.FontVal.Exists)
					{
						gpConEmu->opt.FontVal = (LPCWSTR)szNext;
						gpConEmu->AppendExtraArgs(L"-font", szNext);
					}
				}
				// Change font height
				else if (szArg.IsSwitch(L"-FontSize") || szArg.IsSwitch(L"-Size"))
				{
					NeedNextArg();

					if (!gpConEmu->opt.SizeVal.Exists)
					{
						gpConEmu->opt.SizeVal.SetInt(szNext);
					}
				}
				// ADD fontname; by Mors
				else if (szArg.IsSwitch(L"-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 (szArg.IsSwitch(L"-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 (szArg.IsSwitch(L"-fs"))
				{
					gpConEmu->opt.WindowModeVal = wmFullScreen;
				}
				else if (szArg.IsSwitch(L"-max"))
				{
					gpConEmu->opt.WindowModeVal = wmMaximized;
				}
				else if (szArg.OneOfSwitches(L"-min", L"-MinTSA", L"-StartTSA"))
				{
					gpConEmu->WindowStartMinimized = true;
					if (!szArg.IsSwitch(L"-min"))
					{
						gpConEmu->WindowStartTsa = true;
						gpConEmu->WindowStartNoClose = szArg.IsSwitch(L"-MinTSA");
					}
				}
				else if (szArg.OneOfSwitches(L"-tsa", L"-tray"))
				{
					gpConEmu->ForceMinimizeToTray = true;
				}
				else if (szArg.IsSwitch(L"-detached"))
				{
					gpConEmu->m_StartDetached = crb_On;
					opt.Detached = true;
				}
				else if (szArg.IsSwitch(L"-NoAutoClose"))
				{
					opt.NoAutoClose = true;
				}
				else if (szArg.IsSwitch(L"-here"))
				{
					gpConEmu->mb_ConEmuHere = true;
					gpConEmu->StoreWorkDir();
				}
				else if (szArg.IsSwitch(L"-update"))
				{
					gpConEmu->opt.AutoUpdateOnStart = true;
				}
				else if (szArg.IsSwitch(L"-NoUpdate"))
				{
					// This one has more weight than AutoUpdateOnStart
					gpConEmu->opt.DisableAutoUpdate = true;
				}
				else if (szArg.IsSwitch(L"-NoHooksWarn"))
				{
					// Don't try to warn users about known problems with third-party detours
					gpConEmu->opt.NoHooksWarn = true;
				}
				else if (szArg.OneOfSwitches(L"-NoKeyHook", L"-NoKeyHooks", L"-NoKeybHook", L"-NoKeybHooks"))
				{
					gpConEmu->DisableKeybHooks = true;
				}
				else if (szArg.IsSwitch(L"-NoCloseConfirm"))
				{
					gpConEmu->DisableCloseConfirm = true;
				}
				else if (szArg.IsSwitch(L"-NoMacro"))
				{
					gpConEmu->DisableAllMacro = true;
				}
				else if (szArg.OneOfSwitches(L"-NoHotkey", L"-NoHotkeys"))
				{
					gpConEmu->DisableAllHotkeys = true;
				}
				else if (szArg.OneOfSwitches(L"-NoDefTrm", L"-NoDefTerm"))
				{
					gpConEmu->DisableSetDefTerm = true;
				}
				else if (szArg.OneOfSwitches(L"-NoRegFont", L"-NoRegFonts"))
				{
					gpConEmu->DisableRegisterFonts = true;
				}
				else if (szArg.OneOfSwitches(L"-inside", L"-inside="))
				{
					bool bRunAsAdmin = RunAsAdmin::Check(szArg.ms_Val);
					bool bSyncDir = false;
					LPCWSTR pszSyncFmt = NULL;

					gpConEmu->mb_ConEmuHere = true;
					gpConEmu->StoreWorkDir();

					// Both `-inside:...` and `-inside=...` are supported
					if (szArg.IsSwitch(L"-inside="))
					{
						bSyncDir = true;
						pszSyncFmt = szArg.ms_Val+8; // \eCD /d %1 - \e - ESC, \b - BS, \n - ENTER, %1 - "dir", %2 - "bash dir"
					}

					CConEmuInside::InitInside(bRunAsAdmin, bSyncDir, pszSyncFmt, 0, NULL);
				}
				else if (szArg.IsSwitch(L"-InsidePID"))
				{
					NeedNextArg();

					bool bRunAsAdmin = RunAsAdmin::Check(szArg.ms_Val);

					wchar_t* pszEnd;
					// Здесь указывается PID, в который нужно внедриться.
					DWORD nInsideParentPID = wcstol(szNext, &pszEnd, 10);
					if (nInsideParentPID)
					{
						CConEmuInside::InitInside(bRunAsAdmin, false, NULL, nInsideParentPID, NULL);
					}
				}
				else if (szArg.IsSwitch(L"-InsideWnd"))
				{
					NeedNextArg();

					LPCWSTR pszHWnd = szNext.ms_Val;

					if (pszHWnd[0] == L'0' && (pszHWnd[1] == L'x' || pszHWnd[1] == L'X'))
						pszHWnd += 2;
					else if (pszHWnd[0] == L'x' || pszHWnd[0] == L'X')
						pszHWnd ++;

					bool bRunAsAdmin = RunAsAdmin::Check(szArg.ms_Val);

					wchar_t* pszEnd;
					// Здесь указывается HWND, в котором нужно создаваться.
					HWND hParent = (HWND)(DWORD_PTR)wcstoul(pszHWnd, &pszEnd, 16);
					if (hParent && IsWindow(hParent))
					{
						CConEmuInside::InitInside(bRunAsAdmin, false, NULL, 0, hParent);
					}
				}
				else if (szArg.IsSwitch(L"-icon"))
				{
					NeedNextArg();

					if (!gpConEmu->opt.IconPrm.Exists && !szNext.IsEmpty())
					{
						gpConEmu->opt.IconPrm = true;
						gpConEmu->mps_IconPath = ExpandEnvStr(szNext);
					}
				}
				else if (szArg.IsSwitch(L"-dir"))
				{
					NeedNextArg();

					if (!szNext.IsEmpty())
					{
						// Например, "%USERPROFILE%"
						CEStr szExpand;
						if (wcschr(szNext, L'%') && ((szExpand = ExpandEnvStr(szNext)) != NULL))
						{
							gpConEmu->StoreWorkDir(szExpand);
						}
						else
						{
							gpConEmu->StoreWorkDir(szNext);
						}
					}
				}
				else if (szArg.IsSwitch(L"-UpdateJumpList"))
				{
					// Copy current Task list to Win7 Jump list (Taskbar icon)
					gpConEmu->mb_UpdateJumpListOnStartup = true;
				}
				else if (szArg.OneOfSwitches(L"-log", L"-log0", L"-log1", L"-log2", L"-log3", L"-log4"))
				{
					if (szArg.OneOfSwitches(L"-log", L"-log0"))
						gpConEmu->opt.AdvLogging.SetInt(1);
					else
						gpConEmu->opt.AdvLogging.SetInt((BYTE)(szArg[4] - L'0')); // 1..4
					// Do create logging service
					DEBUGSTRSTARTUP(L"Creating log file");
					gpConEmu->CreateLog();
				}
				else if (szArg.OneOfSwitches(L"-Single", L"-Reuse"))
				{
					// "/reuse" switch to be remastered
					gpConEmu->AppendExtraArgs(szArg);
					gpSetCls->SingleInstanceArg = sgl_Enabled;
				}
				else if (szArg.IsSwitch(L"-NoSingle"))
				{
					gpConEmu->AppendExtraArgs(szArg);
					gpSetCls->SingleInstanceArg = sgl_Disabled;
				}
				else if (szArg.IsSwitch(L"-DesktopMode"))
				{
					gpConEmu->opt.DesktopMode = true;
				}
				else if (szArg.OneOfSwitches(L"-Quake", L"-QuakeAuto", L"-NoQuake"))
				{
					if (szArg.IsSwitch(L"-Quake"))
						gpConEmu->opt.QuakeMode = 1;
					else if (szArg.IsSwitch(L"-QuakeAuto"))
						gpConEmu->opt.QuakeMode = 2;
					else
					{
						gpConEmu->opt.QuakeMode = 0;
						if (gpSetCls->SingleInstanceArg == sgl_Default)
							gpSetCls->SingleInstanceArg = sgl_Disabled;
					}
				}
				else if (szArg.OneOfSwitches(L"-FrameWidth", L"-Frame"))
				{
					NeedNextArg();

					if (!gpConEmu->opt.FrameWidth.Exists)
						gpConEmu->opt.FrameWidth.SetInt(szNext);
				}
				else if (szArg.OneOfSwitches(L"-ShowHide", L"-ShowHideTSA"))
				{
					gpSetCls->SingleInstanceArg = sgl_Enabled;
					gpSetCls->SingleInstanceShowHide = szArg.IsSwitch(L"-ShowHide")
						? sih_ShowMinimize : sih_ShowHideTSA;
				}
				else if (szArg.OneOfSwitches(L"-Reset", L"-ResetDefault", L"-Basic"))
				{
					gpConEmu->opt.ResetSettings = true;
					if (szArg.IsSwitch(L"-ResetDefault"))
					{
						gpSetCls->isFastSetupDisabled = true;
					}
					else if (szArg.IsSwitch(L"-Basic"))
					{
						gpSetCls->isFastSetupDisabled = true;
						gpSetCls->isResetBasicSettings = true;
					}
				}
				else if (szArg.OneOfSwitches(L"-NoCascade", L"-DontCascade"))
				{
					gpConEmu->AppendExtraArgs(szArg);
					gpSetCls->isDontCascade = true;
				}
				else if (szArg.OneOfSwitches(L"-WndX", L"-WndY", L"-WndW", L"-WndWidth", L"-WndH", L"-WndHeight"))
				{
					wchar_t ch = szArg[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 (szArg.IsSwitch(L"-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 (szArg.IsSwitch(L"-Theme"))
				{
					const wchar_t* kDefaultTheme = L"DarkMode_Explorer";
					bool bParm = false;
					if (!cmdLineRest || (*cmdLineRest == L'-' || *cmdLineRest == L'/')
						|| !GetCfgParm(cmdLineRest, bParm, gpConEmu->opt.WindowTheme, 128))
					{
						gpConEmu->opt.WindowTheme.SetStr(kDefaultTheme);
					}
				}
				else if (szArg.OneOfSwitches(L"-Buffer", L"-BufferHeight"))
				{
					NeedNextArg();

					if (!gpConEmu->opt.BufferHeightVal.Exists)
					{
						gpConEmu->opt.BufferHeightVal.SetInt(szNext);

						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 (szArg.IsSwitch(L"-Config"))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.ConfigVal, 127))
					{
						goto wrap;
					}
				}
				else if (szArg.IsSwitch(L"-Palette"))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.PaletteVal, MAX_PATH))
					{
						goto wrap;
					}
				}
				else if (szArg.IsSwitch(L"-LoadRegistry"))
				{
					gpConEmu->AppendExtraArgs(szArg);
					gpConEmu->opt.ForceUseRegistryPrm = true;
				}
				else if (szArg.OneOfSwitches(L"-LoadCfgFile", L"-LoadXmlFile"))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.LoadCfgFile, MAX_PATH, true))
					{
						goto wrap;
					}
				}
				else if (szArg.OneOfSwitches(L"-SaveCfgFile", L"-SaveXmlFile"))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.SaveCfgFile, MAX_PATH, true))
					{
						goto wrap;
					}
				}
				else if (szArg.IsSwitch(L"-GuiMacro"))
				{
					// -- выполняется только последний
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.ExecGuiMacro, 0x8000, false))
					{
						goto wrap;
					}
				}
				else if (szArg.IsSwitch(L"-UpdateSrcSet"))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.UpdateSrcSet, MAX_PATH*4, false))
					{
						goto wrap;
					}
				}
				else if (szArg.IsSwitch(L"-AnsiLog"))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.AnsiLogPath, MAX_PATH-40, true))
					{
						goto wrap;
					}
				}
				else if (szArg.IsSwitch(L"-SetDefTerm"))
				{
					gpConEmu->opt.SetUpDefaultTerminal = true;
				}
				else if (szArg.IsSwitch(L"-ZoneId"))
				{
					gpConEmu->opt.FixZoneId = true;
				}
				else if (szArg.IsSwitch(L"-Exit"))
				{
					gpConEmu->opt.ExitAfterActionPrm = true;
				}
				else if (szArg.IsSwitch(L"-QuitOnClose"))
				{
					gpConEmu->mb_ForceQuitOnClose = true;
				}
				else if (szArg.IsSwitch(L"-Title"))
				{
					bool bOk = false;
					CESwitch pszTitle(sw_Str);
					if (!GetCfgParm(cmdLineRest, bOk, pszTitle, 127))
					{
						goto wrap;
					}
					gpConEmu->SetTitleTemplate(pszTitle.GetStr());
				}
				else if (szArg.IsSwitch(L"-Settings"))
				{
					gpConEmu->mb_SettingsRequested = true;
				}
				else if (szArg.IsSwitch(L"-FindBugMode"))
				{
					gpConEmu->mb_FindBugMode = true;
				}
				else if (szArg.OneOfSwitches(L"-debug", L"-debugw", L"-debugi"))
				{
					// These switches were already processed
				}
				else if (szArg.OneOfSwitches(L"-?", L"-h", L"-help"))
				{
					if (gpLng) gpLng->Reload();
					ConEmuAbout::OnInfo_About();
					iResult = -1;
					goto wrap;
				}
				// Final `-run ...` or `-runlist ...` (old names `-cmd ...` or `-cmdlist ...`)
				else if (
					szArg.OneOfSwitches(L"-run", L"-runlist", L"-cmd", L"-cmdlist")
					)
				{
					if (opt.cfgSwitches.ms_Val)
					{
						_ASSERTE(pszArgStart>=pszCopyToEnvStart); // If there is only "-run cmd" in arguments
						_ASSERTE((INT_PTR)(pszArgStart - pszCopyToEnvStart) <= opt.cfgSwitches.GetLen());
						opt.cfgSwitches.ms_Val[pszArgStart - pszCopyToEnvStart] = 0;
					}

					opt.runCommand.Set(SkipNonPrintable(cmdLineRest));
					opt.isScript = szArg.OneOfSwitches(L"-runlist", L"-cmdlist");
					break;
				}
				else
				{
					// Show error on unknown switch
					psUnknown = pszArgStart;
					break;
				}
			}
			// Main processing cycle end

			// Avoid assertions in NextArg
			szArg.Empty(); szNext.Empty();
		} // while (NextArg(&cmdLineRest, szArg, &pszArgStart) == 0)
	}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
// Called from OnShellExecCmdLine
HRESULT OurShellExecCmdLine(HWND hwnd, LPCWSTR pwszCommand, LPCWSTR pwszStartDir, bool bRunAsAdmin, bool bForce)
{
	HRESULT hr = E_UNEXPECTED;
	BOOL bShell = FALSE;

	CEStr lsLog = lstrmerge(L"OnShellExecCmdLine", bRunAsAdmin ? L"(RunAs): " : L": ", pwszCommand);
	DefTermLogString(lsLog);

	// Bad thing, ShellExecuteEx needs File&Parm, but we get both in pwszCommand
	CmdArg szExe;
	LPCWSTR pszFile = pwszCommand;
	LPCWSTR pszParm = pwszCommand;
	if (NextArg(&pszParm, szExe) == 0)
	{
		pszFile = szExe; pszParm = SkipNonPrintable(pszParm);
	}
	else
	{
		// Failed
		pszFile = pwszCommand; pszParm = NULL;
	}

	if (!bForce)
	{
		DWORD nCheckSybsystem1 = 0, nCheckBits1 = 0;
		if (!FindImageSubsystem(pszFile, nCheckSybsystem1, nCheckBits1))
		{
			hr = (HRESULT)-1;
			DefTermLogString(L"OnShellExecCmdLine: FindImageSubsystem failed");
			goto wrap;
		}
		if (nCheckSybsystem1 != IMAGE_SUBSYSTEM_WINDOWS_CUI)
		{
			hr = (HRESULT)-1;
			DefTermLogString(L"OnShellExecCmdLine: !=IMAGE_SUBSYSTEM_WINDOWS_CUI");
			goto wrap;
		}
	}

	// "Run as admin" was requested?
	if (bRunAsAdmin)
	{
		SHELLEXECUTEINFO sei = {sizeof(sei), 0, hwnd, L"runas", pszFile, pszParm, pwszStartDir, SW_SHOWNORMAL};
		bShell = OnShellExecuteExW(&sei);
	}
	else
	{
		wchar_t* pwCommand = lstrdup(pwszCommand);
		DWORD nCreateFlags = CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT|CREATE_DEFAULT_ERROR_MODE;
		STARTUPINFO si = {sizeof(si)};
		PROCESS_INFORMATION pi = {};
		bShell = OnCreateProcessW(NULL, pwCommand, NULL, NULL, FALSE, nCreateFlags, NULL, pwszStartDir, &si, &pi);
		if (bShell)
		{
			CloseHandle(pi.hProcess);
			CloseHandle(pi.hThread);
		}
	}

	hr = bShell ? S_OK : HRESULT_FROM_WIN32(GetLastError());
wrap:
	return hr;
}
Ejemplo n.º 10
0
BOOL WINAPI OnReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, MY_CONSOLE_READCONSOLE_CONTROL* pInputControl)
{
	//typedef BOOL (WINAPI* OnReadConsoleW_t)(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, MY_CONSOLE_READCONSOLE_CONTROL* pInputControl);
	SUPPRESSORIGINALSHOWCALL;
	ORIGINAL_KRNL(ReadConsoleW);
	BOOL lbRc = FALSE;
	DWORD nErr = GetLastError();
	DWORD nStartTick = GetTickCount(), nEndTick = 0;

	OnReadConsoleStart(true, hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, pInputControl);

	lbRc = F(ReadConsoleW)(hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, pInputControl);
	nErr = GetLastError();
	// Debug purposes
	nEndTick = GetTickCount();

	OnReadConsoleEnd(lbRc, true, hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, pInputControl);

	// cd \\server\share\dir\...
	if (gbAllowUncPaths && lpBuffer && lpNumberOfCharsRead && *lpNumberOfCharsRead
		&& (nNumberOfCharsToRead >= *lpNumberOfCharsRead) && (nNumberOfCharsToRead > 6))
	{
		wchar_t* pszCmd = (wchar_t*)lpBuffer;
		// "cd " ?
		if ((pszCmd[0]==L'c' || pszCmd[0]==L'C') && (pszCmd[1]==L'd' || pszCmd[1]==L'D') && pszCmd[2] == L' ')
		{
			pszCmd[*lpNumberOfCharsRead] = 0;
			wchar_t* pszPath = (wchar_t*)SkipNonPrintable(pszCmd+3);
			// Don't worry about local paths, check only network
			if (pszPath[0] == L'\\' && pszPath[1] == L'\\')
			{
				wchar_t* pszEnd;
				if (*pszPath == L'"')
					pszEnd = wcschr(++pszPath, L'"');
				else
					pszEnd = wcspbrk(pszPath, L"\r\n\t&| ");
				if (!pszEnd)
					pszEnd = pszPath + lstrlen(pszPath);
				if ((pszEnd - pszPath) < MAX_PATH)
				{
					wchar_t ch = *pszEnd; *pszEnd = 0;
					BOOL bSet = SetCurrentDirectory(pszPath);
					if (ch) *pszEnd = ch;
					if (bSet)
					{
						if (*pszEnd == L'"') pszEnd++;
						pszEnd = (wchar_t*)SkipNonPrintable(pszEnd);
						if (*pszEnd && wcschr(L"&|", *pszEnd))
						{
							while (*pszEnd && wcschr(L"&|", *pszEnd)) pszEnd++;
							pszEnd = (wchar_t*)SkipNonPrintable(pszEnd);
						}
						// Return anything...
						if (*pszEnd)
						{
							int nLeft = lstrlen(pszEnd);
							memmove(lpBuffer, pszEnd, (nLeft+1)*sizeof(*pszEnd));
						}
						else
						{
							lstrcpyn((wchar_t*)lpBuffer, L"cd\r\n", nNumberOfCharsToRead);

						}
						*lpNumberOfCharsRead = lstrlen((wchar_t*)lpBuffer);
					}
				}
			}
		}
	}

	SetLastError(nErr);

	UNREFERENCED_PARAMETER(nStartTick);
	UNREFERENCED_PARAMETER(nEndTick);
	return lbRc;
}
Ejemplo n.º 11
0
// Return true if "SetEnvironmentVariable" was processed
// if (bDoSet==false) - just skip all "set" commands
// Supported commands:
//  set abc=val
//  "set PATH=C:\Program Files;%PATH%"
//  chcp [utf8|ansi|oem|<cp_no>]
//  title "Console init title"
bool ProcessSetEnvCmd(LPCWSTR& asCmdLine, bool bDoSet, CmdArg* rpsTitle /*= NULL*/)
{
	LPCWSTR lsCmdLine = asCmdLine;
	bool bEnvChanged = false;
	CmdArg lsSet, lsAmp;

	// Example: "set PATH=C:\Program Files;%PATH%" & set abc=def & cmd
	while (NextArg(&lsCmdLine, lsSet) == 0)
	{
		bool bTokenOk = false;
		wchar_t* lsNameVal = NULL;

		// It may contains only "set" if was not quoted
		if (lstrcmpi(lsSet, L"set") == 0)
		{
			// Now we shell get in lsSet "abc=def" token
			if ((NextArg(&lsCmdLine, lsSet) == 0) && (wcschr(lsSet, L'=') > lsSet.ms_Arg))
			{
				lsNameVal = lsSet.ms_Arg;
			}
		}
		// Or full "set PATH=C:\Program Files;%PATH%" command (without quotes ATM)
		else if (lstrcmpni(lsSet, L"set ", 4) == 0)
		{
			LPCWSTR psz = SkipNonPrintable(lsSet.ms_Arg+4);
			if (wcschr(psz, L'=') > psz)
			{
				lsNameVal = (wchar_t*)psz;
			}
		}
		// Process "chcp <cp>" too
		else if (lstrcmpi(lsSet, L"chcp") == 0)
		{
			if (NextArg(&lsCmdLine, lsSet) == 0)
			{
				UINT nCP = GetCpFromString(lsSet);

				if (nCP > 0 && nCP <= 0xFFFF)
				{
					bTokenOk = true;
					_ASSERTE(lsNameVal == NULL);
					// Ask to be changed?
					if (bDoSet)
					{
						//Issue 60: BUGBUG: На некоторых системых (Win2k3, WinXP) SetConsoleCP (и иже с ними) просто зависают
						DWORD nTID;
						HANDLE hThread = CreateThread(NULL, 0, OurSetConsoleCPThread, (LPVOID)nCP, 0, &nTID);
						if (hThread)
						{
							DWORD nWait = WaitForSingleObject(hThread, 1000);
							if (nWait == WAIT_TIMEOUT)
							{
								TerminateThread(hThread,100);
							}
							CloseHandle(hThread);
						}
					}
				}
			}
		}
		// Change title without need of cmd.exe
		else if (lstrcmpi(lsSet, L"title") == 0)
		{
			if (NextArg(&lsCmdLine, lsSet) == 0)
			{
				bTokenOk = true;
				_ASSERTE(lsNameVal == NULL);
				// Ask to be changed?
				if (rpsTitle)
					rpsTitle->Set(lsSet);
			}
		}

		// Well, known command was detected. What is next?
		if (lsNameVal || bTokenOk)
		{
			lsAmp.GetPosFrom(lsSet);
			if (NextArg(&lsCmdLine, lsAmp) != 0)
			{
				// End of command? Use may call only "set" without following app? Run simple "cmd" in that case
				_ASSERTE(lsCmdLine!=NULL && *lsCmdLine==0);
				bTokenOk = true; // And process SetEnvironmentVariable
			}
			else
			{
				if (lstrcmp(lsAmp, L"&") == 0)
				{
					// Only simple conveyer is supported!
					bTokenOk = true; // And process SetEnvironmentVariable
				}
				// Update last pointer (debug and asserts purposes)
				lsSet.GetPosFrom(lsAmp);
			}
		}

		if (!bTokenOk)
		{
			break; // Stop processing command line
		}
		else if (lsNameVal)
		{
			// And split name/value
			_ASSERTE(lsNameVal!=NULL);

			wchar_t* pszEq = wcschr(lsNameVal, L'=');
			if (!pszEq)
			{
				_ASSERTE(pszEq!=NULL);
				break;
			}

			if (bDoSet)
			{
				*(pszEq++) = 0;
				// Expand value
				wchar_t* pszExpanded = ExpandEnvStr(pszEq);
				LPCWSTR pszSet = pszExpanded ? pszExpanded : pszEq;
				SetEnvironmentVariable(lsNameVal, (pszSet && *pszSet) ? pszSet : NULL);
				SafeFree(pszExpanded);
			}

			bEnvChanged = true;
		}

		// Remember processed position
		asCmdLine = lsCmdLine;

	} // end of "while (NextArg(&lsCmdLine, lsSet) == 0)"

	// Fin
	if (!asCmdLine || !*asCmdLine)
	{
		static wchar_t szSimple[] = L"cmd";
		asCmdLine = szSimple;
	}

	return bEnvChanged;
}
Ejemplo n.º 12
0
// Load current value of "HKCU\Software\Microsoft\Command Processor" : "AutoRun"
// (bClear==true) - remove from it our "... Cmd_Autorun.cmd ..." part
wchar_t* CSetPgComspec::LoadAutorunValue(HKEY hkCmd, bool bClear)
{
	size_t cchCmdMax = 65535;
	wchar_t *pszCmd = (wchar_t*)malloc(cchCmdMax*sizeof(*pszCmd));
	if (!pszCmd)
	{
		_ASSERTE(pszCmd!=NULL);
		return NULL;
	}

	_ASSERTE(hkCmd!=NULL);
	//HKEY hkCmd = NULL;
	//if (0 == RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Command Processor", 0, KEY_READ, &hkCmd))

	DWORD cbMax = (cchCmdMax-2) * sizeof(*pszCmd);
	if (0 == RegQueryValueEx(hkCmd, L"AutoRun", NULL, NULL, (LPBYTE)pszCmd, &cbMax))
	{
		pszCmd[cbMax>>1] = 0;

		if (bClear && *pszCmd)
		{
			// Просили почистить от "... Cmd_Autorun.cmd ..."
			wchar_t* pszFind = StrStrI(pszCmd, L"\\ConEmu\\Cmd_Autorun.cmd");
			if (pszFind)
			{
				// "... Cmd_Autorun.cmd ..." found, need to find possible start and end of our part ('&' separated)
				wchar_t* pszStart = pszFind;
				while ((pszStart > pszCmd) && (*(pszStart-1) != L'&'))
					pszStart--;

				const wchar_t* pszEnd = wcschr(pszFind, L'&');
				if (!pszEnd)
				{
					pszEnd = pszFind + _tcslen(pszFind);
				}
				else
				{
					while (*pszEnd == L'&')
						pszEnd++;
				}

				// Ok, There are another commands?
				if ((pszStart > pszCmd) || *pszEnd)
				{
					// Possibilities
					if (!*pszEnd)
					{
						// app1.exe && Cmd_Autorun.cmd
						while ((pszStart > pszCmd) && ((*(pszStart-1) == L'&') || (*(pszStart-1) == L' ')))
							pszStart--;
						_ASSERTE(pszStart > pszCmd); // Command to left is empty?
						*pszStart = 0; // just trim
					}
					else
					{
						// app1.exe && Cmd_Autorun.cmd & app2.exe
						// app1.exe & Cmd_Autorun.cmd && app2.exe
						// Cmd_Autorun.cmd & app2.exe
						if (pszStart == pszCmd)
						{
							pszEnd = SkipNonPrintable(pszEnd);
						}
						size_t cchLeft = _tcslen(pszEnd)+1;
						// move command (from right) to the 'Cmd_Autorun.cmd' place
						memmove(pszStart, pszEnd, cchLeft*sizeof(wchar_t));
					}
				}
				else
				{
					// No, we are alone
					*pszCmd = 0;
				}
			}
		}

		// Skip spaces?
		LPCWSTR pszChar = SkipNonPrintable(pszCmd);
		if (!pszChar || !*pszChar)
		{
			*pszCmd = 0;
		}
	}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
void CSetPgIntegr::RegisterShell(LPCWSTR asName, LPCWSTR asMode, LPCWSTR asConfig, LPCWSTR asCmd, LPCWSTR asIcon)
{
	if (!asName || !*asName)
		asName = L"ConEmu";

	if (!asCmd || !*asCmd)
		asCmd = CONEMU_HERE_CMD;

	asCmd = SkipNonPrintable(asCmd);

	#ifdef _DEBUG
	CEStr szMode(asMode);
	_ASSERTE(szMode.IsSwitch(L"-here") || szMode.IsSwitch(L"-inside") || szMode.IsSwitch(L"-inside:"));
	#endif

	CEStr lsExta;
	LPCWSTR pszExtraArgs = gpConEmu->MakeConEmuStartArgs(lsExta, asConfig);

	size_t cchMax = _tcslen(gpConEmu->ms_ConEmuExe)
		+ (asMode ? (_tcslen(asMode) + 3) : 0)
		+ (pszExtraArgs ? (_tcslen(pszExtraArgs) + 1) : 0)
		+ _tcslen(asCmd) + 32;
	wchar_t* pszCmd = (wchar_t*)malloc(cchMax*sizeof(*pszCmd));
	if (!pszCmd)
		return;

	//[HKEY_CURRENT_USER\Software\Classes\*\shell\ConEmu inside]
	//"Icon"="C:\\Program Files\\ConEmu\\ConEmu.exe,1"

	//[HKEY_CURRENT_USER\Software\Classes\*\shell\ConEmu inside\command]
	//@="C:\\Program Files\\ConEmu\\ConEmu.exe /inside /config shell /cmd {powershell} -cur_console:n"

	//[HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\ConEmu inside]
	//"Icon"="C:\\Program Files\\ConEmu\\ConEmu.exe,1"

	//[HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\ConEmu inside\command]
	//@="C:\\Program Files\\ConEmu\\ConEmu.exe /inside /config shell /cmd {powershell} -cur_console:n"

	//[HKEY_CURRENT_USER\Software\Classes\Directory\shell\ConEmu inside]
	//"Icon"="C:\\Program Files\\ConEmu\\ConEmu.exe,1"

	//[HKEY_CURRENT_USER\Software\Classes\Directory\shell\ConEmu inside\command]
	//@="C:\\Program Files\\ConEmu\\ConEmu.exe /inside /config shell /dir \"%1\" /cmd {powershell} -cur_console:n"

	//[HKEY_CURRENT_USER\Software\Classes\Drive\shell\ConEmu inside]
	//"Icon"="C:\\Program Files\\ConEmu\\ConEmu.exe,1"

	//[HKEY_CURRENT_USER\Software\Classes\Drive\shell\ConEmu inside\command]
	//@="C:\\Program Files\\ConEmu\\ConEmu.exe /inside /config shell /dir \"%1\" /cmd {powershell} -cur_console:n"

	int iSucceeded = 0;
	bool bHasLibraries = IsWindows7;

	for (int i = 1; i <= 6; i++)
	{
		_wcscpy_c(pszCmd, cchMax, L"\"");
		_wcscat_c(pszCmd, cchMax, gpConEmu->ms_ConEmuExe);
		_wcscat_c(pszCmd, cchMax, L"\" ");

		// `-here`, `-inside` or `-inside:cd ...`
		if (asMode && *asMode)
		{
			bool bQ = IsQuotationNeeded(asMode);
			if (bQ) _wcscat_c(pszCmd, cchMax, L"\"");
			_wcscat_c(pszCmd, cchMax, asMode);
			_wcscat_c(pszCmd, cchMax, bQ ? L"\" " : L" ");
		}

		// -FontDir, -LoadCfgFile, -Config, etc.
		if (pszExtraArgs && *pszExtraArgs)
		{
			_wcscat_c(pszCmd, cchMax, pszExtraArgs);
			_wcscat_c(pszCmd, cchMax, L" ");
		}

		LPCWSTR pszRoot = NULL;
		switch (i)
		{
		case 1:
			pszRoot = L"Software\\Classes\\*\\shell";
			break;
		case 2:
			pszRoot = L"Software\\Classes\\Directory\\Background\\shell";
			break;
		case 3:
			if (!bHasLibraries)
				continue;
			pszRoot = L"Software\\Classes\\LibraryFolder\\Background\\shell";
			break;
		case 4:
			pszRoot = L"Software\\Classes\\Directory\\shell";
			_wcscat_c(pszCmd, cchMax, L"-dir \"%1\" ");
			break;
		case 5:
			pszRoot = L"Software\\Classes\\Drive\\shell";
			_wcscat_c(pszCmd, cchMax, L"-dir \"%1\" ");
			break;
		case 6:
			// Issue 1191: ConEmu was launched instead of explorer from taskbar pinned library icon
			continue;
			//if (!bHasLibraries)
			//	continue;
			//pszRoot = L"Software\\Classes\\LibraryFolder\\shell";
			//_wcscat_c(pszCmd, cchMax, L"-dir \"%1\" ");
			//break;
		}

		bool bCmdKeyExist = false;

		if (*asCmd == L'/')
		{
			CEStr lsArg;
			LPCWSTR pszTemp = asCmd;
			while (0 == NextArg(&pszTemp, lsArg))
			{
				if (lsArg.OneOfSwitches(L"-run",L"-runlist",L"-cmd",L"-cmdlist"))
				{
					bCmdKeyExist = true; break;
				}
			}

		}

		if (!bCmdKeyExist)
			_wcscat_c(pszCmd, cchMax, L"-run ");
		_wcscat_c(pszCmd, cchMax, asCmd);

		HKEY hkRoot;
		if (0 == RegCreateKeyEx(HKEY_CURRENT_USER, pszRoot, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkRoot, NULL))
		{
			HKEY hkConEmu;
			if (0 == RegCreateKeyEx(hkRoot, asName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkConEmu, NULL))
			{
				// Если задана "иконка"
				if (asIcon)
					RegSetValueEx(hkConEmu, L"Icon", 0, REG_SZ, (LPBYTE)asIcon, (lstrlen(asIcon)+1)*sizeof(*asIcon));
				else
					RegDeleteValue(hkConEmu, L"Icon");

				// Команда
				HKEY hkCmd;
				if (0 == RegCreateKeyEx(hkConEmu, L"command", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkCmd, NULL))
				{
					if (0 == RegSetValueEx(hkCmd, NULL, 0, REG_SZ, (LPBYTE)pszCmd, (lstrlen(pszCmd)+1)*sizeof(*pszCmd)))
						iSucceeded++;
					RegCloseKey(hkCmd);
				}

				RegCloseKey(hkConEmu);
			}
			RegCloseKey(hkRoot);
		}
	}

	free(pszCmd);
}
Ejemplo n.º 15
0
// May comes from Task or ConEmu's -run switch
// or from Setting\Environment page where one line is a single command (bAlone == true)
bool CProcessEnvCmd::AddCommands(LPCWSTR asCommands, LPCWSTR* ppszEnd/*= NULL*/, bool bAlone /*= false*/, INT_PTR anBefore /*= -1*/)
{
	bool bNew = false;
	LPCWSTR lsCmdLine = asCommands;
	CEStr lsSet, lsAmp, lsCmd;

	if (ppszEnd)
		*ppszEnd = asCommands;

	// Example: "set PATH=C:\Program Files;%PATH%" & set abc=def & cmd
	while (NextArg(&lsCmdLine, lsSet) == 0)
	{
		bool bTokenOk = false;
		wchar_t* lsNameVal = NULL;

		// It may contains only "set" or "alias" if was not quoted
		if ((lstrcmpi(lsSet, L"set") == 0) || (lstrcmpi(lsSet, L"alias") == 0))
		{
			lsCmd.Set(lsSet);

			_ASSERTE(*lsCmdLine != L' ');

			// Now we shell get in lsSet "abc=def" token
			// Or to simplify usage, the rest of line is supported too,
			// so user may type in our Settings\Environment:
			//   set V1=From Settings
			// instead of
			//   set "V1=From Settings"
			bool bProcessed = false;
			if ((*lsCmdLine != L'"') || bAlone)
			{
				LPCWSTR pszAmp = bAlone ? NULL : wcschr(lsCmdLine, L'&');
				if (!pszAmp) // No ampersand or bAlone? Use var value as the rest of line
					pszAmp = lsCmdLine + lstrlen(lsCmdLine);
				// Set tail pointer
				LPCWSTR pszValEnd = pszAmp;
				// Trim trailing spaces (only \x20)
				while ((pszValEnd > lsCmdLine) && (*(pszValEnd-1) == L' '))
					pszValEnd--;
				// Trim possible leading/trailing quotes
				if (bAlone && (*lsCmdLine == L'"'))
				{
					lsCmdLine++;
					if (((pszValEnd-1) > lsCmdLine) && (*(pszValEnd-1) == L'"'))
					{
						_ASSERTE(*pszValEnd == 0);
						pszValEnd--;
					}
				}
				// OK, return it
				lsSet.Empty(); // to avoid debug asserts
				lsSet.Set(lsCmdLine, pszValEnd - lsCmdLine);
				lsCmdLine = SkipNonPrintable(pszAmp); // Leave possible '&' at pointer
				bProcessed = true;
			}
			// OK, lets get token like "name=var value"
			if (!bProcessed)
			{
				bProcessed = (NextArg(&lsCmdLine, lsSet) == 0);
			}
			if (bProcessed && (wcschr(lsSet, L'=') > lsSet.ms_Val))
			{
				lsNameVal = lsSet.ms_Val;
			}
		}
		// Or full "set PATH=C:\Program Files;%PATH%" command (without quotes ATM)
		else if (lstrcmpni(lsSet, L"set ", 4) == 0)
		{
			lsCmd = L"set";
			LPCWSTR psz = SkipNonPrintable(lsSet.ms_Val+4);
			if (wcschr(psz, L'=') > psz)
			{
				lsNameVal = (wchar_t*)psz;
			}
		}
		// Support "alias token=value" too
		else if (lstrcmpni(lsSet, L"alias ", 6) == 0)
		{
			lsCmd = L"alias";
			LPCWSTR psz = SkipNonPrintable(lsSet.ms_Val+6);
			if (wcschr(psz, L'=') > psz)
			{
				lsNameVal = (wchar_t*)psz;
			}
		}
		// Process "chcp <cp>" too
		else if (lstrcmpi(lsSet, L"chcp") == 0)
		{
			lsCmd = L"chcp";
			if (NextArg(&lsCmdLine, lsSet) == 0)
			{
				UINT nCP = GetCpFromString(lsSet);
				if (nCP > 0 && nCP <= 0xFFFF)
				{
					bTokenOk = true;
					_ASSERTE(lsNameVal == NULL);
					if (mp_CmdChCp)
					{
						SafeFree(mp_CmdChCp->pszName);
						mp_CmdChCp->pszName = lstrdup(lsSet);
					}
					else
					{
						bNew |= (NULL != Add(lsCmd, lsSet, NULL, anBefore));
					}
				}
			}
		}
		// Change title without need of cmd.exe
		else if (lstrcmpi(lsSet, L"title") == 0)
		{
			lsCmd = L"title";
			if (NextArg(&lsCmdLine, lsSet) == 0)
			{
				bTokenOk = true;
				_ASSERTE(lsNameVal == NULL);
				if (mp_CmdTitle)
				{
					SafeFree(mp_CmdTitle->pszName);
					mp_CmdTitle->pszName = lstrdup(lsSet);
				}
				else
				{
					bNew |= (NULL != Add(lsCmd, lsSet, NULL, anBefore));
				}
			}
		}
		// Echo the "text" before console starts
		// Type the "text file" before console starts
		else if ((lstrcmpi(lsSet, L"echo") == 0) || (lstrcmpi(lsSet, L"type") == 0))
		{
			lsCmd.Set(lsSet);
			// echo [-r] [-n] [-x] [-b] "String to echo"
			// type [-b] [-CP] "Path to text file to echo"
			CEStr lsSwitches;
			while (*lsCmdLine == L'-')
			{
				if (NextArg(&lsCmdLine, lsSet) != 0)
					break;
				lstrmerge(&lsSwitches.ms_Val, lsSwitches.IsEmpty() ? NULL : L" ", lsSet.ms_Val);
			}
			// Rest arguments are expected to be processed text or file
			CEStr lsAdd;
			while (NextArg(&lsCmdLine, lsSet) == 0)
			{
				bTokenOk = true;
				lstrmerge(&lsAdd.ms_Val,
					lsAdd.IsEmpty() ? NULL : L" ",
					lsSet.mb_Quoted ? L"\"" : NULL,
					lsSet.ms_Val,
					lsSet.mb_Quoted ? L"\"" : NULL);
				lsCmdLine = SkipNonPrintable(lsCmdLine);
				if (!*lsCmdLine || (*lsCmdLine == L'&') || (*lsCmdLine == L'|'))
					break;

			}
			if (!lsAdd.IsEmpty())
			{
				bNew |= (NULL != Add(lsCmd, lsSwitches, lsAdd, anBefore));
			}
		}
		else
		{
			lsCmd.Empty();
		}

		// Well, known command was detected. What is next?
		if (lsNameVal || bTokenOk)
		{
			lsAmp.GetPosFrom(lsSet);
			if (NextArg(&lsCmdLine, lsAmp) != 0)
			{
				// End of command? Use may call only "set" without following app? Run simple "cmd" in that case
				_ASSERTE(lsCmdLine!=NULL && *lsCmdLine==0);
				bTokenOk = true; // And process SetEnvironmentVariable
			}
			else
			{
				if (lstrcmp(lsAmp, L"&") == 0)
				{
					// Only simple conveyer is supported!
					bTokenOk = true; // And process SetEnvironmentVariable
				}
				// Update last pointer (debug and asserts purposes)
				lsSet.GetPosFrom(lsAmp);
			}
		}

		if (!bTokenOk)
		{
			break; // Stop processing command line
		}
		else if (lsNameVal)
		{
			// And split name/value
			_ASSERTE(lsNameVal!=NULL);

			wchar_t* pszEq = wcschr(lsNameVal, L'=');
			if (!pszEq)
			{
				_ASSERTE(pszEq!=NULL);
				break;
			}

			*(pszEq++) = 0;

			bNew |= (NULL != Add(lsCmd, lsNameVal, pszEq ? pszEq : L"", anBefore));
		}

		// Remember processed position
		if (ppszEnd)
		{
			*ppszEnd = lsCmdLine;
		}
	} // end of "while (NextArg(&lsCmdLine, lsSet) == 0)"

	// Fin
	if (ppszEnd && (!*ppszEnd || !**ppszEnd))
	{
		static wchar_t szSimple[] = L"cmd";
		*ppszEnd = szSimple;
	}

	return bNew;
}