// Create the command to show on the Integration settings page LPCWSTR CreateCommand(CEStr& rsReady) { rsReady = L""; for (INT_PTR i = 0; i < ourSwitches.size(); i++) { Switch* ps = ourSwitches[i]; _ASSERTE(ps && !ps->szSwitch.IsEmpty()); bool bOpt = !ps->szOpt.IsEmpty(); bool bQuot = (bOpt && IsQuotationNeeded(ps->szOpt)); lstrmerge(&rsReady.ms_Val, ps->szSwitch, bOpt ? L" " : NULL, bQuot ? L"\"" : NULL, bOpt ? ps->szOpt.c_str() : NULL, bQuot ? L"\" " : L" "); } if (!rsReady.IsEmpty() || bCmdList) { lstrmerge(&rsReady.ms_Val, bCmdList ? L"-runlist " : L"-run ", szCmd); } else { rsReady.Set(szCmd); } return rsReady.c_str(L""); };
int apiGetFullPathName(LPCWSTR lpFileName, CEStr& rsPath) { bool bFound = false; wchar_t *pszFilePart, *pszBuffer = NULL; wchar_t szFind[MAX_PATH+1]; DWORD nLen = GetFullPathName(lpFileName, countof(szFind), szFind, &pszFilePart); if (nLen) { if (nLen < countof(szFind)) { bFound = true; rsPath.Set(szFind); } else { // Too long path, allocate more space pszBuffer = (wchar_t*)malloc((++nLen)*sizeof(*pszBuffer)); if (pszBuffer) { DWORD nLen2 = GetFullPathName(lpFileName, nLen, pszBuffer, &pszFilePart); if (nLen2 && (nLen2 < nLen)) { bFound = true; rsPath.Set(pszBuffer); } free(pszBuffer); } } } return bFound ? rsPath.GetLen() : 0; }
DWORD GetModulePathName(HMODULE hModule, CEStr& lsPathName) { size_t cchMax = MAX_PATH; wchar_t* pszData = lsPathName.GetBuffer(cchMax); if (!pszData) return 0; // Memory allocation error DWORD nRc = GetModuleFileName(hModule, pszData, cchMax); if (!nRc) return 0; // Not enough space? if (nRc == cchMax) { cchMax = 32767; wchar_t* pszData = lsPathName.GetBuffer(cchMax); if (!pszData) return 0; // Memory allocation error nRc = GetModuleFileName(hModule, pszData, cchMax); if (!nRc || (nRc == cchMax)) return 0; } return nRc; }
// Concatenate strings from array and set resource item bool CLngRc::SetResource(MArray<LngRcItem>& arr, int idx, MJsonValue* pJson) { CEStr lsValue; MJsonValue jStr; // [ "Decrease window height ", "(check ‘Resize with arrows’)" ] size_t iCount = pJson->getLength(); for (size_t i = 0; i < iCount; i++) { if (!pJson->getItem(i, jStr) || (jStr.getType() != MJsonValue::json_String)) { _ASSERTE(FALSE && "String format failure"); return false; } lstrmerge(&lsValue.ms_Val, jStr.getString()); } if (lsValue.IsEmpty()) { _ASSERTE(FALSE && "Empty resource string (array)"); return false; } return SetResource(arr, idx, lsValue.ms_Val, true); }
void DebugNeedCmdUnitTests() { BOOL b; struct strTests { LPCWSTR pszCmd; BOOL bNeed; } Tests[] = { {L"\"C:\\windows\\notepad.exe -f \"makefile\" COMMON=\"../../../plugins/common\"\"", FALSE}, {L"\"\"C:\\windows\\notepad.exe -new_console\"\"", FALSE}, {L"\"\"cmd\"\"", FALSE}, {L"cmd /c \"\"C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe\" -?\"", FALSE}, {L"cmd /c \"dir c:\\\"", FALSE}, {L"abc.cmd", TRUE}, // Do not do too many heuristic. If user really needs redirection (for 'root'!) // he must explicitly call "cmd /c ...". With only exception if first exe not found. {L"notepad text & start explorer", FALSE}, }; LPCWSTR psArgs; BOOL bNeedCut, bRootIsCmd, bAlwaysConfirm, bAutoDisable; CEStr szExe; for (INT_PTR i = 0; i < countof(Tests); i++) { szExe.Empty(); RConStartArgs rcs; rcs.pszSpecialCmd = lstrdup(Tests[i].pszCmd); rcs.ProcessNewConArg(); b = IsNeedCmd(TRUE, rcs.pszSpecialCmd, szExe, &psArgs, &bNeedCut, &bRootIsCmd, &bAlwaysConfirm, &bAutoDisable); _ASSERTE(b == Tests[i].bNeed); } }
void DefTermLogString(LPCSTR asMessage, LPCWSTR asLabel /*= NULL*/) { if (!gpDefTerm || !asMessage || !*asMessage) return; INT_PTR iLen = lstrlenA(asMessage); CEStr lsMsg; MultiByteToWideChar(CP_ACP, 0, asMessage, iLen, lsMsg.GetBuffer(iLen), iLen); DefTermLogString(lsMsg.ms_Arg, asLabel); }
Switch* GetNextSwitch(LPCWSTR& rpsz, CEStr& szArg) { LPCWSTR psz = rpsz; CEStr szNext; if ((0 == NextArg(&psz, szNext)) && !szNext.IsPossibleSwitch()) rpsz = psz; else szNext.Clear(); Switch* ps = new Switch(szArg.Detach(), szNext.Detach()); return ps; };
int RegGetStringValue(HKEY hk, LPCWSTR pszSubKey, LPCWSTR pszValueName, CEStr& rszData, DWORD Wow64Flags /*= 0*/) { int iLen = -1; HKEY hkChild = hk; DWORD cbSize = 0; LONG lrc; rszData.Empty(); if (pszSubKey && *pszSubKey) { if (hk == NULL) { lrc = RegGetStringValue(HKEY_CURRENT_USER, pszSubKey, pszValueName, rszData, 0); if (lrc < 0) { bool isWin64 = IsWindows64(); lrc = RegGetStringValue(HKEY_LOCAL_MACHINE, pszSubKey, pszValueName, rszData, isWin64 ? KEY_WOW64_64KEY : 0); if ((lrc < 0) && isWin64) { lrc = RegGetStringValue(HKEY_LOCAL_MACHINE, pszSubKey, pszValueName, rszData, KEY_WOW64_32KEY); } } if (lrc > 0) { return lrc; } } if (0 != (lrc = RegOpenKeyEx(hk, pszSubKey, 0, KEY_READ|Wow64Flags, &hkChild))) hkChild = NULL; } if (hkChild && (0 == (lrc = RegQueryValueEx(hkChild, pszValueName, NULL, NULL, NULL, &cbSize)))) { wchar_t* pszData = rszData.GetBuffer((cbSize>>1)+2); // +wchar_t+1byte (на возможные ошибки хранения данных в реестре) if (pszData) { pszData[cbSize>>1] = 0; // Make sure it will be 0-terminated if (0 == (lrc = RegQueryValueEx(hkChild, pszValueName, NULL, NULL, (LPBYTE)pszData, &cbSize))) { iLen = lstrlen(pszData); } else { rszData.Empty(); } } }
CLogFunction::CLogFunction(const char* asFnName) { const int nLen = MultiByteToWideChar(CP_ACP, 0, asFnName, -1, NULL, 0); const int cchBuf = 80; wchar_t sBuf[cchBuf] = L""; CEStr szTemp; wchar_t *pszBuf = (nLen >= cchBuf) ? szTemp.GetBuffer(nLen + 1) : sBuf; MultiByteToWideChar(CP_ACP, 0, asFnName, -1, pszBuf, nLen+1); DoLogFunction(pszBuf); }
bool FileSearchInDir(LPCWSTR asFilePath, CEStr& rsFound) { // Possibilities // a) asFilePath does not contain path, only: "far" // b) asFilePath contains path, but without extension: "C:\\Program Files\\Far\\Far" LPCWSTR pszSearchFile = asFilePath; LPCWSTR pszSlash = wcsrchr(asFilePath, L'\\'); if (pszSlash) { if ((pszSlash - asFilePath) >= MAX_PATH) { // No need to continue, this is invalid path to executable return false; } // C:\Far\Far.exe /w /pC:\Far\Plugins\ConEmu;C:\Far\Plugins.My if (!IsFilePath(asFilePath, false)) { return false; } // Do not allow '/' here LPCWSTR pszFwd = wcschr(asFilePath, L'/'); if (pszFwd != NULL) { return false; } } wchar_t* pszSearchPath = NULL; if (pszSlash) { if ((pszSearchPath = lstrdup(asFilePath)) != NULL) { pszSearchFile = pszSlash + 1; pszSearchPath[pszSearchFile - asFilePath] = 0; } } // Попытаемся найти "по путям" (%PATH%) wchar_t *pszFilePart; wchar_t szFind[MAX_PATH+1]; LPCWSTR pszExt = PointToExt(asFilePath); DWORD nLen = SearchPath(pszSearchPath, pszSearchFile, pszExt ? NULL : L".exe", countof(szFind), szFind, &pszFilePart); SafeFree(pszSearchPath); if (nLen && (nLen < countof(szFind)) && FileExists(szFind)) { // asFilePath will be invalid after .Set rsFound.Set(szFind); return true; } return false; }
// The function converts UTF-8 to UCS2 (CEStr) and returns pointer to allocated buffer (CEStr) LPCWSTR SettingsXML::utf2wcs(const char* utf8, CEStr& wc) { if (!utf8) { _ASSERTE(utf8 != NULL); wc.Clear(); return NULL; } wc.Empty(); int wcLen = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); if (wcLen > 0) { wcLen = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wc.GetBuffer(wcLen), wcLen); if (wcLen <= 0) wc.Empty(); } return wc.c_str(); }
Switch* GetNextPair(LPCWSTR& rpsz) { LPCWSTR psz = rpsz; CEStr szArg; if (0 != NextArg(&psz, szArg)) { return NULL; } // Invalid switch? or first argument (our executable) if (!szArg.IsPossibleSwitch()) { rpsz = psz; return NULL; } rpsz = psz; return GetNextSwitch(rpsz, szArg); };
void SetFKey(CEStr& lsSubst, UINT fn) { if (!Mods) { msprintf(szSubst, countof(szSubst), L"\033[%u~", fn); } else { msprintf(szSubst, countof(szSubst), L"\033[%u;%c~", fn, Mods+L'1'); } lsSubst.Set(szSubst); }
void SetTilde(CEStr& lsSubst, wchar_t c) { if (!Mods) { msprintf(szSubst, countof(szSubst), L"\033[%c~", c); } else { msprintf(szSubst, countof(szSubst), L"\033[%c;%c~", c, Mods+L'1'); } lsSubst.Set(szSubst); }
void SetKey(CEStr& lsSubst, wchar_t c, wchar_t prefix=L'O') { if (!Mods) { //wcscpy_c(szSubst, L"\033O*A"); msprintf(szSubst, countof(szSubst), L"\033%c%c", prefix, c); } else { msprintf(szSubst, countof(szSubst), L"\033[1;%c%c", Mods+L'1', c); } lsSubst.Set(szSubst); }
int GetDirectory(CEStr& szDir) { int iRc = 0; DWORD nLen, nMax; nMax = GetCurrentDirectory(MAX_PATH, szDir.GetBuffer(MAX_PATH)); if (!nMax) { goto wrap; } else if (nMax > MAX_PATH) { nLen = GetCurrentDirectory(nMax, szDir.GetBuffer(nMax)); if (!nLen || (nLen > nMax)) { goto wrap; } } iRc = lstrlen(szDir); wrap: return iRc; }
// Used for URL wrapped on several lines bool CMatch::GetNextLine(CRConDataGuard& data, int nLine) { // Perhaps not only for "URL"? if (!data.isValid()) return false; ConsoleLinePtr line; if (!data->GetConsoleLine(nLine, line) || line.nLen <= 0 || !line.pChar) return false; // ConsoleLinePtr doesn't contain Z-terminated strings, only RAW characters CEStr add; wchar_t* ptr = add.GetBuffer(line.nLen); if (!ptr) return false; wmemmove(ptr, line.pChar, line.nLen); ptr[line.nLen] = 0; // Append new data if (!lstrmerge(&m_SrcLine.ms_Val, ptr)) return false; mn_SrcLength += line.nLen; return true; }
// 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; }
bool CLngRc::GetResource(MArray<LngRcItem>& arr, int idx, CEStr& lsText) { bool bFound = false; if ((idx >= 0) && (idx < arr.size())) { const LngRcItem& item = arr[idx]; if (item.Processed && (item.Str && *item.Str)) { lsText.Set(item.Str); bFound = true; } } return bFound; }
bool GetLine(CEStr& szLine) { if (!ptrData || !cchUsed) return false; const char* ptrLineEnd = strpbrk(ptrData, "\r\n"); if (!ptrLineEnd) return false; // There is no one completed line yet // Multi-line block? if ((ptrLineEnd[0] == L'\n') && (ptrLineEnd[1] == L' ' || ptrLineEnd[1] == L'\t')) { const char* ptrTestEnd = strpbrk(ptrLineEnd+1, "\r\n"); if (ptrTestEnd) ptrLineEnd = ptrTestEnd; } // \r\n is not expected, but if it happens... const char* ptrNewLine = (ptrLineEnd[0] == '\r' && ptrLineEnd[1] == '\n') ? (ptrLineEnd+2) : (ptrLineEnd+1); // Alloc the buffer size_t cchLen = (ptrLineEnd - ptrData); wchar_t* ptrDst = szLine.GetBuffer(cchLen); if (!ptrDst) { return false; // memory allocation failed } // Return the string MultiByteToWideChar(CP_OEMCP, 0, ptrData, cchLen, ptrDst, cchLen); ptrDst[cchLen] = 0; // Shift the tail _ASSERTE((INT_PTR)cchUsed >= (ptrNewLine - ptrData)); cchUsed -= (ptrNewLine - ptrData); _ASSERTE(cchUsed < cchMax); memmove(ptrData, ptrNewLine, cchUsed); ptrData[cchUsed] = 0; // Succeeded return true; };
LPCWSTR GetDirectory(CEStr& szDir) { DWORD nLen, nMax; nMax = GetCurrentDirectory(MAX_PATH, szDir.GetBuffer(MAX_PATH)); if (!nMax) { szDir.Empty(); goto wrap; } else if (nMax > MAX_PATH) { nLen = GetCurrentDirectory(nMax, szDir.GetBuffer(nMax)); if (!nLen || (nLen > nMax)) { szDir.Empty(); goto wrap; } } wrap: return szDir.IsEmpty() ? NULL : szDir.c_str(); }
bool FileExistsSearch(LPCWSTR asFilePath, CEStr& rsFound, bool abSetPath/*= true*/, bool abRegSearch /*= true*/) { if (!asFilePath || !*asFilePath) { _ASSERTEX(asFilePath && *asFilePath); return false; } if (FileExists(asFilePath)) { return true; } // Развернуть переменные окружения if (wcschr(asFilePath, L'%')) { bool bFound = false; wchar_t* pszExpand = ExpandEnvStr(asFilePath); if (pszExpand && FileExists(pszExpand)) { // asFilePath will be invalid after .Set rsFound.Set(pszExpand); bFound = true; } SafeFree(pszExpand); if (bFound) { return true; } } // Search "Path" if (FileSearchInDir(asFilePath, rsFound)) { return true; } // Только если приложение не нашли "по путям" - пытаемся определить его расположение через [App Paths] // В противном случае, в частности, может быть запущен "far" не из папки с ConEmu, а зарегистрированный // в реестре, если на машине их несколько установлено. #if !defined(CONEMU_MINIMAL) _ASSERTE(gfnSearchAppPaths!=NULL); #endif // В ConEmuHk этот блок не активен, потому что может быть "только" перехват CreateProcess, // а о его параметрах должно заботиться вызывающее (текущее) приложение if (abRegSearch && gfnSearchAppPaths && !wcschr(asFilePath, L'\\')) { // Если в asFilePath НЕ указан путь - искать приложение в реестре, // и там могут быть указаны доп. параметры (пока только добавка в %PATH%) if (gfnSearchAppPaths(asFilePath, rsFound, abSetPath, NULL)) { // Нашли по реестру, возможно обновили %PATH% return true; } } return false; }
void CSetPgDebug::debugLogShell(DWORD nParentPID, CESERVER_REQ_ONCREATEPROCESS* pInfo) { CSetPgDebug* pDbgPg = (CSetPgDebug*)gpSetCls->GetPageObj(thi_Debug); if (!pDbgPg) return; if ((pDbgPg->GetActivityLoggingType() != glt_Processes) && (pDbgPg->GetActivityLoggingType() != glt_Shell)) return; LPCWSTR pszFile = pInfo->wsValue + pInfo->nActionLen; LPCWSTR pszParam = pInfo->wsValue + pInfo->nActionLen+pInfo->nFileLen; DebugLogShellActivity *shl = (DebugLogShellActivity*)calloc(sizeof(DebugLogShellActivity),1); shl->nParentPID = nParentPID; shl->nParentBits = pInfo->nSourceBits; wcscpy_c(shl->szFunction, pInfo->sFunction); shl->pszAction = lstrdup(pInfo->wsValue); shl->pszFile = lstrdup(pszFile); shl->pszParam = lstrdup(pszParam); shl->bDos = (pInfo->nImageBits == 16) && (pInfo->nImageSubsystem == IMAGE_SUBSYSTEM_DOS_EXECUTABLE); shl->nImageBits = pInfo->nImageBits; shl->nImageSubsystem = pInfo->nImageSubsystem; shl->nShellFlags = pInfo->nShellFlags; shl->nCreateFlags = pInfo->nCreateFlags; shl->nStartFlags = pInfo->nStartFlags; shl->nShowCmd = pInfo->nShowCmd; shl->hStdIn = (DWORD)pInfo->hStdIn; shl->hStdOut = (DWORD)pInfo->hStdOut; shl->hStdErr = (DWORD)pInfo->hStdErr; // Append directory and bat/tmp files contents to pszParam { LPCWSTR pszDir = (pInfo->wsValue+pInfo->nActionLen+pInfo->nFileLen+pInfo->nParamLen); LPCWSTR pszAppFile = NULL; wchar_t*& pszParamEx = shl->pszParam; if (pszDir && *pszDir) { CEStr lsDir((pszParamEx && *pszParamEx) ? L"\r\n\r\n" : NULL, L"CD: \"", pszDir, L"\""); lstrmerge(&pszParamEx, lsDir); } if (shl->pszFile) { LPCWSTR pszExt = PointToExt(shl->pszFile); if (pszExt && (!lstrcmpi(pszExt, L".bat") || !lstrcmpi(pszExt, L".cmd"))) debugLogShellText(pszParamEx, (pszAppFile = shl->pszFile)); } if (pszParam && *pszParam) { LPCWSTR pszNext = pszParam; CEStr szArg; while (0 == NextArg(&pszNext, szArg)) { if (!*szArg || (*szArg == L'-') || (*szArg == L'/')) continue; LPCWSTR pszExt = PointToExt(szArg); // Perhaps process *.tmp files too? (used with VC RC compilation?) if (pszExt && (!lstrcmpi(pszExt, L".bat") || !lstrcmpi(pszExt, L".cmd") /*|| !lstrcmpi(pszExt, L".tmp")*/) && (!pszAppFile || (lstrcmpi(szArg, pszAppFile) != 0))) { debugLogShellText(pszParamEx, szArg); } else if (szArg[0] == L'@') { CEStr lsPath; if (IsFilePath(szArg.Mid(1), true)) { // Full path to "arguments file" lsPath.Set(szArg.Mid(1)); } else if ((szArg[1] != L'\\' && szArg[1] != L'/') && (pszDir && *pszDir)) { // Relative path to "arguments file" lsPath = JoinPath(pszDir, szArg.Mid(1)); } if (!lsPath.IsEmpty()) { debugLogShellText(pszParamEx, lsPath); } } } } } // end of "Append directory and bat/tmp files contents to pszParam" PostMessage(pDbgPg->Dlg(), DBGMSG_LOG_ID, DBGMSG_LOG_SHELL_MAGIC, (LPARAM)shl); }
LPCWSTR CRConFiles::GetFileFromConsole(LPCWSTR asSrc, CEStr& szFull) { CEStr szWinPath; LPCWSTR pszWinPath = MakeWinPath(asSrc, mp_RCon ? mp_RCon->GetMntPrefix() : NULL, szWinPath); if (!pszWinPath || !*pszWinPath) { _ASSERTE(pszWinPath && *pszWinPath); return NULL; } if (IsFilePath(pszWinPath, true)) { if (!FileExists(pszWinPath)) // otherwise it will cover directories too return NULL; szFull.Attach(szWinPath.Detach()); } else { CEStr szDir; LPCWSTR pszDir = mp_RCon->GetConsoleCurDir(szDir, true); // We may get empty dir here if we are in "~" subdir if (!pszDir || !*pszDir) { _ASSERTE(pszDir && *pszDir && wcschr(pszDir,L'/')==NULL); return NULL; } // Попытаться просканировать один-два уровеня подпапок bool bFound = FileExistSubDir(pszDir, pszWinPath, 1, szFull); if (!bFound) { // git diffs style, but with backslashes (they are converted already) // "a/src/ConEmu.cpp" and "b/src/ConEmu.cpp" if (pszWinPath[0] && (pszWinPath[1] == L'\\') && wcschr(L"abicwo", pszWinPath[0])) { LPCWSTR pszSlash = pszWinPath; while (!bFound && ((pszSlash = wcschr(pszSlash, L'\\')) != NULL)) { while (*pszSlash == L'\\') pszSlash++; if (!*pszSlash) break; bFound = FileExistSubDir(pszDir, pszSlash, 1, szFull); if (!bFound) { // Try to go to parent folder (useful while browsing git-diff-s) bFound = CheckParentFolders(pszDir, pszSlash, szFull); } } } else { // let's try to check some paths from #include // for example: #include "src/common/Common.h" LPCWSTR pszSlash = pszWinPath; while (*pszSlash == L'\\') pszSlash++; bFound = CheckParentFolders(pszDir, pszSlash, szFull); } } if (!bFound) { // If there is "src" subfolder in the current folder const wchar_t* predefined[] = {L"trunk", L"src", L"source", L"sources", NULL}; for (size_t i = 0; !bFound && predefined[i]; ++i) { CEStr szSrc(JoinPath(pszDir, predefined[i])); if (DirectoryExists(szSrc)) bFound = FileExistSubDir(szSrc, pszWinPath, 1, szFull); } } if (!bFound) { return NULL; } } if (!szFull.IsEmpty()) { // "src\conemu\realconsole.cpp" --> "src\ConEmu\RealConsole.cpp" MakePathProperCase(szFull); } return szFull; }
// Вызывается для инициализации из Settings::LoadSettings() HWND CConEmuInside::InsideFindParent() { bool bFirstStep = true; DWORD nParentPID = 0; PROCESSENTRY32 pi = {sizeof(pi)}; EnumFindParentArg find = {}; if (!m_InsideIntegration) { return NULL; } if (mh_InsideParentWND) { if (IsWindow(mh_InsideParentWND)) { if (m_InsideIntegration == ii_Simple) { // We cover all client area of mh_InsideParentWND in this mode _ASSERTE(mh_InsideParentRel==NULL); mh_InsideParentRel = NULL; } _ASSERTE(mh_InsideParentWND!=NULL); goto wrap; } else { if (m_InsideIntegration == ii_Simple) { DisplayLastError(L"Specified window not found"); SetInsideParentWND(NULL); goto wrap; } _ASSERTE(IsWindow(mh_InsideParentWND)); SetInsideParentWND(mh_InsideParentRel = NULL); } } _ASSERTE(m_InsideIntegration!=ii_Simple); if (mn_InsideParentPID) { if ((mn_InsideParentPID == GetCurrentProcessId()) || !GetProcessInfo(mn_InsideParentPID, &pi)) { DisplayLastError(L"Invalid parent process specified"); m_InsideIntegration = ii_None; SetInsideParentWND(NULL); goto wrap; } nParentPID = mn_InsideParentPID; } else { PROCESSENTRY32 pi = {sizeof(pi)}; if (!GetProcessInfo(GetCurrentProcessId(), &pi) || !pi.th32ParentProcessID) { DisplayLastError(L"GetProcessInfo(GetCurrentProcessId()) failed"); m_InsideIntegration = ii_None; SetInsideParentWND(NULL); goto wrap; } nParentPID = pi.th32ParentProcessID; } // Do window enumeration find.nPID = nParentPID; ::EnumWindows(EnumInsideFindParent, (LPARAM)&find); if (!find.hParentRoot) { int nBtn = MsgBox(L"Can't find appropriate parent window!\n\nContinue in normal mode?", MB_ICONSTOP|MB_YESNO|MB_DEFBUTTON2); if (nBtn != IDYES) { SetInsideParentWND(INSIDE_PARENT_NOT_FOUND); return mh_InsideParentWND; // Закрыться! } // Продолжить в обычном режиме m_InsideIntegration = ii_None; SetInsideParentWND(NULL); goto wrap; } mh_InitialRoot = find.hParentRoot; mn_InsideParentPID = nParentPID; HWND hExistConEmu; if ((hExistConEmu = InsideFindConEmu(find.hParentRoot)) != NULL) { _ASSERTE(FALSE && "Continue to create tab in existing instance"); // Если в проводнике уже есть ConEmu - открыть в нем новую вкладку gpSetCls->SingleInstanceShowHide = sih_None; LPCWSTR pszCmdLine = GetCommandLine(); CEStr lsArg; LPCWSTR pszCmd = pszCmdLine; while (0 == NextArg(&pszCmd, lsArg)) { if (lsArg.OneOfSwitches(L"-runlist",L"-cmdlist")) { pszCmd = NULL; break; } else if (lsArg.OneOfSwitches(L"-run",L"-cmd")) { break; } } gpConEmu->RunSingleInstance(hExistConEmu, (pszCmd && *pszCmd) ? (pszCmd) : NULL); SetInsideParentWND(INSIDE_PARENT_NOT_FOUND); return mh_InsideParentWND; // Закрыться! } // Теперь нужно найти дочерние окна // 1. в которое будем внедряться // 2. по которому будем позиционироваться // 3. для синхронизации текущего пути InsideFindShellView(find.hParentRoot); RepeatCheck: if (!isInsideWndSet() || (!mh_InsideParentRel && (m_InsideIntegration == ii_Explorer))) { wchar_t szAddMsg[128] = L"", szMsg[1024]; if (bFirstStep) { bFirstStep = false; if (TurnExplorerTipPane(szAddMsg)) { goto RepeatCheck; } } _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"%sCan't find appropriate shell window!\nUnrecognized layout of the Explorer.\n\nContinue in normal mode?", szAddMsg); int nBtn = MsgBox(szMsg, MB_ICONSTOP|MB_YESNO|MB_DEFBUTTON2); if (nBtn != IDYES) { SetInsideParentWND(INSIDE_PARENT_NOT_FOUND); return mh_InsideParentWND; // Закрыться! } m_InsideIntegration = ii_None; SetInsideParentWND(NULL); goto wrap; } wrap: if (!isInsideWndSet()) { m_InsideIntegration = ii_None; } else { GetWindowThreadProcessId(mh_InsideParentWND, &mn_InsideParentPID); // Для мониторинга папки GetCurrentDirectory(countof(ms_InsideParentPath), ms_InsideParentPath); int nLen = lstrlen(ms_InsideParentPath); if ((nLen > 3) && (ms_InsideParentPath[nLen-1] == L'\\')) { ms_InsideParentPath[nLen-1] = 0; } } return mh_InsideParentWND; }
// Returns true on changes // bDeQuote: replace two "" with one " // bDeEscape: process special symbols: ^e^[^r^n^t^b bool DemangleArg(CEStr& rsDemangle, bool bDeQuote /*= true*/, bool bDeEscape /*= false*/) { if (rsDemangle.IsEmpty() || !(bDeQuote || bDeEscape)) { return false; // Nothing to do } LPCWSTR pszDemangles = (bDeQuote && bDeEscape) ? L"^\"" : bDeQuote ? L"\"" : L"^"; LPCWSTR pchCap = wcspbrk(rsDemangle, pszDemangles); if (pchCap == NULL) { return false; // Nothing to replace } wchar_t* pszDst = rsDemangle.ms_Val; const wchar_t* pszSrc = rsDemangle.ms_Val; const wchar_t* pszEnd = rsDemangle.ms_Val + rsDemangle.GetLen(); while (pszSrc < pszEnd) { if (bDeQuote && (*pszSrc == L'"')) { *(pszDst++) = *(pszSrc++); if (*pszSrc == L'"') // Expected, but may be missed by user? pszSrc++; } else if (bDeEscape && (*pszSrc == L'^')) { switch (*(++pszSrc)) { case L'^': // Demangle cap *pszDst = L'^'; break; case 0: // Leave single final cap *pszDst = L'^'; continue; case L'r': case L'R': // CR *pszDst = L'\r'; break; case L'n': case L'N': // LF *pszDst = L'\n'; break; case L't': case L'T': // TAB *pszDst = L'\t'; break; case L'a': case L'A': // BELL *pszDst = 7; break; case L'b': case L'B': // BACK *pszDst = L'\b'; break; case L'e': case L'E': case L'[': // ESC *pszDst = 27; break; default: // Unknown ctrl-sequence, bypass *(pszDst++) = *(pszSrc++); continue; } pszDst++; pszSrc++; } else { *(pszDst++) = *(pszSrc++); } } // Was processed? Zero terminate it. *pszDst = 0; return true; }
// 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; }
// Function checks, if we need drop first and last quotation marks // Example: ""7z.exe" /?" // Using cmd.exe rules bool IsNeedDequote(LPCWSTR asCmdLine, bool abFromCmdCK, LPCWSTR* rsEndQuote/*=NULL*/) { if (rsEndQuote) *rsEndQuote = NULL; if (!asCmdLine) return false; bool bDeQu = false; LPCWSTR pszQE, pszSP; if (asCmdLine[0] == L'"') { bDeQu = (asCmdLine[1] == L'"'); // Всегда - нельзя. Иначе парсинг строки запуска некорректно идет // L"\"C:\\ConEmu\\ConEmuC64.exe\" /PARENTFARPID=1 /C \"C:\\GIT\\cmdw\\ad.cmd CE12.sln & ci -m \"Solution debug build properties\"\"" if (!bDeQu) { size_t nLen = lstrlen(asCmdLine); if (abFromCmdCK) { bDeQu = ((asCmdLine[nLen-1] == L'"') && (asCmdLine[nLen-2] == L'"')); } if (!bDeQu && (asCmdLine[nLen-1] == L'"')) { pszSP = wcschr(asCmdLine+1, L' '); pszQE = wcschr(asCmdLine+1, L'"'); if (pszSP && pszQE && (pszSP < pszQE) && ((pszSP - asCmdLine) < MAX_PATH)) { CEStr lsTmp; lsTmp.Set(asCmdLine+1, pszSP-asCmdLine-1); bDeQu = (IsFilePath(lsTmp, true) && IsExecutable(lsTmp)); } } } } if (!bDeQu) return false; // Don't dequote? pszQE = wcsrchr(asCmdLine+2, L'"'); if (!pszQE) return false; #if 0 LPCWSTR pszQ1 = wcschr(asCmdLine+2, L'"'); if (!pszQ1) return false; LPCWSTR pszQE = wcsrchr(pszQ1, L'"'); // Only TWO quotes in asCmdLine? if (pszQE == pszQ1) { // Doesn't contains special symbols? if (!wcspbrk(asCmdLine+1, L"&<>()@^|")) { // Must contains spaces (doubt?) if (wcschr(asCmdLine+1, L' ')) { // Cmd also checks this for executable file name. Skip this check? return false; } } } #endif // Well, we get here _ASSERTE(asCmdLine[0]==L'"' && pszQE && *pszQE==L'"' && !wcschr(pszQE+1,L'"')); // Dequote it! if (rsEndQuote) *rsEndQuote = pszQE; return true; }
bool IsNeedCmd(BOOL bRootCmd, LPCWSTR asCmdLine, CEStr &szExe, LPCWSTR* rsArguments /*= NULL*/, BOOL* rpbNeedCutStartEndQuot /*= NULL*/, BOOL* rpbRootIsCmdExe /*= NULL*/, BOOL* rpbAlwaysConfirmExit /*= NULL*/, BOOL* rpbAutoDisableConfirmExit /*= NULL*/) { bool rbNeedCutStartEndQuot = false; bool rbRootIsCmdExe = true; bool rbAlwaysConfirmExit = false; bool rbAutoDisableConfirmExit = false; wchar_t *pwszEndSpace; if (rsArguments) *rsArguments = NULL; bool lbRc = false; int iRc = 0; BOOL lbFirstWasGot = FALSE; LPCWSTR pwszCopy; int nLastChar; #ifdef _DEBUG CEStr szDbgFirst; #endif if (!asCmdLine || !*asCmdLine) { _ASSERTE(asCmdLine && *asCmdLine); goto wrap; } #ifdef _DEBUG // Это минимальные проверки, собственно к коду - не относятся bool bIsBatch = false; { LPCWSTR psz = asCmdLine; NextArg(&psz, szDbgFirst); psz = PointToExt(szDbgFirst); if (lstrcmpi(psz, L".cmd")==0 || lstrcmpi(psz, L".bat")==0) bIsBatch = true; } #endif if (!szExe.GetBuffer(MAX_PATH)) { _ASSERTE(FALSE && "Failed to allocate MAX_PATH"); lbRc = true; goto wrap; } szExe.Empty(); if (!asCmdLine || *asCmdLine == 0) { _ASSERTE(asCmdLine && *asCmdLine); lbRc = true; goto wrap; } pwszCopy = asCmdLine; // cmd /c ""c:\program files\arc\7z.exe" -?" // да еще и внутри могут быть двойными... // cmd /c "dir c:\" nLastChar = lstrlenW(pwszCopy) - 1; if (pwszCopy[0] == L'"' && pwszCopy[nLastChar] == L'"') { //if (pwszCopy[1] == L'"' && pwszCopy[2]) //{ // pwszCopy ++; // Отбросить первую кавычку в командах типа: ""c:\program files\arc\7z.exe" -?" // if (rbNeedCutStartEndQuot) *rbNeedCutStartEndQuot = TRUE; //} //else // глючила на ""F:\VCProject\FarPlugin\#FAR180\far.exe -new_console"" //if (wcschr(pwszCopy+1, L'"') == (pwszCopy+nLastChar)) { // LPCWSTR pwszTemp = pwszCopy; // // Получим первую команду (исполняемый файл?) // if ((iRc = NextArg(&pwszTemp, szArg)) != 0) { // //Parsing command line failed // lbRc = true; goto wrap; // } // pwszCopy ++; // Отбросить первую кавычку в командах типа: "c:\arc\7z.exe -?" // lbFirstWasGot = TRUE; // if (rbNeedCutStartEndQuot) *rbNeedCutStartEndQuot = TRUE; //} else { // Will be dequoted in 'NextArg' function. Examples // "C:\GCC\msys\bin\make.EXE -f "makefile" COMMON="../../../plugins/common"" // ""F:\VCProject\FarPlugin\#FAR180\far.exe -new_console"" // ""cmd"" // cmd /c ""c:\program files\arc\7z.exe" -?" // да еще и внутри могут быть двойными... // cmd /c "dir c:\" LPCWSTR pwszTemp = pwszCopy; // Получим первую команду (исполняемый файл?) if ((iRc = NextArg(&pwszTemp, szExe)) != 0) { //Parsing command line failed #ifdef WARN_NEED_CMD _ASSERTE(FALSE); #endif lbRc = true; goto wrap; } if (lstrcmpiW(szExe, L"start") == 0) { // Команду start обрабатывает только процессор #ifdef WARN_NEED_CMD _ASSERTE(FALSE); #endif lbRc = true; goto wrap; } LPCWSTR pwszQ = pwszCopy + 1 + lstrlen(szExe); wchar_t* pszExpand = NULL; if (*pwszQ != L'"' && IsExecutable(szExe, &pszExpand)) { pwszCopy ++; // отбрасываем lbFirstWasGot = TRUE; if (pszExpand) { szExe.Set(pszExpand); SafeFree(pszExpand); if (rsArguments) *rsArguments = pwszQ; } rbNeedCutStartEndQuot = true; } } } // Получим первую команду (исполняемый файл?) if (!lbFirstWasGot) { szExe.Empty(); // `start` command must be processed by processor itself if ((lstrcmpni(pwszCopy, L"start", 5) == 0) && (!pwszCopy[5] || isSpace(pwszCopy[5]))) { #ifdef WARN_NEED_CMD _ASSERTE(FALSE); #endif lbRc = true; goto wrap; } // 17.10.2010 - support executable file path without parameters, but with spaces in its path // 22.11.2015 - or some weirdness, like `C:\Program Files\CB/cb_console_runner.exe "C:\sources\app.exe"` LPCWSTR pchEnd = wcschr(pwszCopy, L' '); if (!pchEnd) pchEnd = pwszCopy + lstrlenW(pwszCopy); CEStr szTemp; DWORD nTempSize; while (pchEnd) { szTemp.Set(pwszCopy, (pchEnd - pwszCopy)); _ASSERTE(szTemp[(pchEnd - pwszCopy)] == 0); // If this is a full path without environment variables if (((IsFilePath(szTemp, true) && !wcschr(szTemp, L'%')) // or file/dir may be found via env.var. substitution or searching in %PATH% || FileExistsSearch((LPCWSTR)szTemp, szTemp)) // Than check if it is a FILE (not a directory) && FileExists(szTemp, &nTempSize) && nTempSize) { // OK, it an our executable? if (rsArguments) *rsArguments = pchEnd; szExe.Set(szTemp); break; } _ASSERTE(*pchEnd == 0 || *pchEnd == L' '); if (!*pchEnd) break; // Find next space after nonspace while (*(pchEnd) == L' ') pchEnd++; // If quoted string starts from here - it's supposed to be an argument if (*pchEnd == L'"') { // And we must not get here, because the executable must be already processed above // _ASSERTE(*pchEnd != L'"'); break; } pchEnd = wcschr(pchEnd, L' '); if (!pchEnd) pchEnd = pwszCopy + lstrlenW(pwszCopy); } if (szExe[0] == 0) { if ((iRc = NextArg(&pwszCopy, szExe)) != 0) { //Parsing command line failed #ifdef WARN_NEED_CMD _ASSERTE(FALSE); #endif lbRc = true; goto wrap; } _ASSERTE(lstrcmpiW(szExe, L"start") != 0); // Обработка переменных окружения и поиск в PATH if (FileExistsSearch((LPCWSTR)szExe, szExe)) { if (rsArguments) *rsArguments = pwszCopy; } } } if (!*szExe) { _ASSERTE(szExe[0] != 0); } else { // Если юзеру нужен редирект - то он должен явно указать ком.процессор // Иначе нереально (или достаточно сложно) определить, является ли символ // редиректом, или это просто один из аргументов команды... // "Левые" символы в имени файла (а вот в "первом аргументе" все однозначно) if (wcspbrk(szExe, L"?*<>|")) { rbRootIsCmdExe = TRUE; // запуск через "процессор" lbRc = true; goto wrap; // добавить "cmd.exe" } // если "путь" не указан if (wcschr(szExe, L'\\') == NULL) { bool bHasExt = (wcschr(szExe, L'.') != NULL); // Проверим, может это команда процессора (типа "DIR")? if (!bHasExt) { bool bIsCommand = false; wchar_t* pszUppr = lstrdup(szExe); if (pszUppr) { // избежать линковки на user32.dll //CharUpperBuff(pszUppr, lstrlen(pszUppr)); for (wchar_t* p = pszUppr; *p; p++) { if (*p >= L'a' && *p <= 'z') *p -= 0x20; } const wchar_t* pszFind = gsInternalCommands; while (*pszFind) { if (lstrcmp(pszUppr, pszFind) == 0) { bIsCommand = true; break; } pszFind += lstrlen(pszFind)+1; } free(pszUppr); } if (bIsCommand) { #ifdef WARN_NEED_CMD _ASSERTE(FALSE); #endif rbRootIsCmdExe = TRUE; // запуск через "процессор" lbRc = true; goto wrap; // добавить "cmd.exe" } } // Try to find executable in %PATH% { #ifndef CONEMU_MINIMAL MWow64Disable wow; wow.Disable(); // Disable Wow64 file redirector #endif apiSearchPath(NULL, szExe, bHasExt ? NULL : L".exe", szExe); } } // end: if (wcschr(szExe, L'\\') == NULL) } // Если szExe не содержит путь к файлу - запускаем через cmd // "start "" C:\Utils\Files\Hiew32\hiew32.exe C:\00\Far.exe" if (!IsFilePath(szExe)) { #ifdef WARN_NEED_CMD _ASSERTE(FALSE); #endif rbRootIsCmdExe = TRUE; // запуск через "процессор" lbRc = true; goto wrap; // добавить "cmd.exe" } //pwszCopy = wcsrchr(szArg, L'\\'); if (!pwszCopy) pwszCopy = szArg; else pwszCopy ++; pwszCopy = PointToName(szExe); //2009-08-27 pwszEndSpace = szExe.ms_Val + lstrlenW(szExe) - 1; while ((*pwszEndSpace == L' ') && (pwszEndSpace > szExe)) { *(pwszEndSpace--) = 0; } #ifndef __GNUC__ #pragma warning( push ) #pragma warning(disable : 6400) #endif if (lstrcmpiW(pwszCopy, L"cmd")==0 || lstrcmpiW(pwszCopy, L"cmd.exe")==0 || lstrcmpiW(pwszCopy, L"tcc")==0 || lstrcmpiW(pwszCopy, L"tcc.exe")==0) { rbRootIsCmdExe = TRUE; // уже должен быть выставлен, но проверим rbAlwaysConfirmExit = TRUE; rbAutoDisableConfirmExit = FALSE; _ASSERTE(!bIsBatch); lbRc = false; goto wrap; // уже указан командный процессор, cmd.exe в начало добавлять не нужно } // Issue 1211: Decide not to do weird heuristic. // If user REALLY needs redirection (root command, huh?) // - he must call "cmd /c ..." directly // Если есть одна из команд перенаправления, или слияния - нужен CMD.EXE if (!bRootCmd) { if (wcschr(asCmdLine, L'&') || wcschr(asCmdLine, L'>') || wcschr(asCmdLine, L'<') || wcschr(asCmdLine, L'|') || wcschr(asCmdLine, L'^') // или экранирования ) { #ifdef WARN_NEED_CMD _ASSERTE(FALSE); #endif lbRc = true; goto wrap; } } //if (lstrcmpiW(pwszCopy, L"far")==0 || lstrcmpiW(pwszCopy, L"far.exe")==0) if (IsFarExe(pwszCopy)) { bool bFound = (wcschr(pwszCopy, L'.') != NULL); // Если указали при запуске просто "far" - это может быть батник, расположенный в %PATH% if (!bFound) { CEStr szSearch; if (apiSearchPath(NULL, pwszCopy, L".exe", szSearch)) { if (lstrcmpi(PointToExt(szSearch), L".exe") == 0) bFound = true; } } if (bFound) { rbAutoDisableConfirmExit = TRUE; rbRootIsCmdExe = FALSE; // FAR! _ASSERTE(!bIsBatch); lbRc = false; goto wrap; // уже указан исполняемый файл, cmd.exe в начало добавлять не нужно } } if (IsExecutable(szExe)) { rbRootIsCmdExe = FALSE; // Для других программ - буфер не включаем _ASSERTE(!bIsBatch); lbRc = false; goto wrap; // Запускается конкретная консольная программа. cmd.exe не требуется } //Можно еще Доделать поиски с: SearchPath, GetFullPathName, добавив расширения .exe & .com //хотя фар сам формирует полные пути к командам, так что можно не заморачиваться #ifdef WARN_NEED_CMD _ASSERTE(FALSE); #endif rbRootIsCmdExe = TRUE; #ifndef __GNUC__ #pragma warning( pop ) #endif lbRc = true; wrap: if (rpbNeedCutStartEndQuot) *rpbNeedCutStartEndQuot = rbNeedCutStartEndQuot; if (rpbRootIsCmdExe) *rpbRootIsCmdExe = rbRootIsCmdExe; if (rpbAlwaysConfirmExit) *rpbAlwaysConfirmExit = rbAlwaysConfirmExit; if (rpbAutoDisableConfirmExit) *rpbAutoDisableConfirmExit = rbAutoDisableConfirmExit; return lbRc; }
int CIconList::CreateTabIconInt(LPCWSTR asIconDescr, bool bAdmin, LPCWSTR asWorkDir) { wchar_t* pszExpanded = ExpandEnvStr(asIconDescr); // Need to be created! int iIconIdx = -1; HICON hFileIcon = NULL; CEStr szLoadFile; LPCWSTR lpszExt = NULL; int nIndex = 0; bool bDirChanged = false; if (!szLoadFile.Set(pszExpanded ? pszExpanded : asIconDescr)) { goto wrap; } lpszExt = ParseIconFileIndex(szLoadFile, nIndex); if (asWorkDir && *asWorkDir) { // Executable (or icon) file may be not availbale by %PATH%, let "cd" to it... bDirChanged = gpConEmu->ChangeWorkDir(asWorkDir); } if (!lpszExt) { if (apiSearchPath(NULL, szLoadFile, L".exe", szLoadFile)) { lpszExt = PointToExt(szLoadFile); } if (!lpszExt) goto wrap; } if (lstrcmpi(lpszExt, L".ico") == 0) { hFileIcon = (HICON)LoadImage(0, szLoadFile, IMAGE_ICON, mn_CxIcon, mn_CyIcon, LR_DEFAULTCOLOR|LR_LOADFROMFILE); } else if ((lstrcmpi(lpszExt, L".exe") == 0) || (lstrcmpi(lpszExt, L".dll") == 0)) { HICON hIconLarge = NULL, hIconSmall = NULL; ExtractIconEx(szLoadFile, nIndex, &hIconLarge, &hIconSmall, 1); bool bUseLargeIcon = ((mn_CxIcon > 16) && (hIconLarge != NULL)) || (hIconSmall == NULL); HICON hDestroyIcon = bUseLargeIcon ? hIconSmall : hIconLarge; if (hDestroyIcon) DestroyIcon(hDestroyIcon); hFileIcon = bUseLargeIcon ? hIconLarge : hIconSmall; } else { //TODO: Shell icons for registered files (cmd, bat, sh, pl, py, ...) } if (hFileIcon) { wchar_t szIconInfo[80] = L"", szMergedInfo[80] = L""; GetIconInfoStr(hFileIcon, szIconInfo); if (gpSetCls->isAdvLogging) { CEStr lsLog(lstrmerge(L"Icon `", asIconDescr, L"` was loaded: ", szIconInfo)); gpConEmu->LogString(lsLog); } int iIconIdxAdm = -1; iIconIdx = ImageList_ReplaceIcon(mh_TabIcons, -1, hFileIcon); TabIconCache NewIcon = {lstrdup(asIconDescr), iIconIdx, false}; m_Icons.push_back(NewIcon); if (mn_AdminIcon >= 0) { HIMAGELIST hAdmList = ImageList_Merge(mh_TabIcons, iIconIdx, mh_TabIcons, mn_AdminIcon+2, 0,0); if (hAdmList) { HICON hNewIcon = ImageList_GetIcon(hAdmList, 0, ILD_TRANSPARENT); if (hNewIcon) { CEStr lsLog(lstrmerge(L"Admin icon `", asIconDescr, L"` was created: ", GetIconInfoStr(hNewIcon, szMergedInfo))); gpConEmu->LogString(lsLog); iIconIdxAdm = ImageList_ReplaceIcon(mh_TabIcons, -1, hNewIcon); DestroyIcon(hNewIcon); TabIconCache AdmIcon = {lstrdup(asIconDescr), iIconIdxAdm, true}; m_Icons.push_back(AdmIcon); if (bAdmin && (iIconIdxAdm > 0)) { iIconIdx = iIconIdxAdm; } } else { gpConEmu->LogString(L"GetIcon for admin icon was failed"); } ImageList_Destroy(hAdmList); } else { gpConEmu->LogString(L"Admin icon merging was failed"); } } DestroyIcon(hFileIcon); } wrap: if (bDirChanged) { gpConEmu->ChangeWorkDir(NULL); } SafeFree(pszExpanded); if (gpSetCls->isAdvLogging && (iIconIdx < 0)) { CEStr lsLog(lstrmerge(L"Icon `", asIconDescr, L"` loading was failed")); gpConEmu->LogString(lsLog); } return iIconIdx; }