bool IsExecutable(LPCWSTR aszFilePathName, wchar_t** rsExpandedVars /*= NULL*/) { #ifndef __GNUC__ #pragma warning( push ) #pragma warning(disable : 6400) #endif wchar_t* pszExpand = NULL; for (int i = 0; i <= 1; i++) { LPCWSTR pwszDot = PointToExt(aszFilePathName); if (pwszDot) // Если указан .exe или .com файл { if (lstrcmpiW(pwszDot, L".exe")==0 || lstrcmpiW(pwszDot, L".com")==0) { if (FileExists(aszFilePathName)) return true; } } if (!i && wcschr(aszFilePathName, L'%')) { pszExpand = ExpandEnvStr(aszFilePathName); if (!pszExpand) break; aszFilePathName = pszExpand; } } if (rsExpandedVars) { *rsExpandedVars = pszExpand; pszExpand = NULL; } else { SafeFree(pszExpand); } return false; }
INT_PTR CRecreateDlg::RecreateDlgProc(HWND hDlg, UINT messg, WPARAM wParam, LPARAM lParam) { #define UM_USER_CONTROLS (WM_USER+121) #define UM_FILL_CMDLIST (WM_USER+122) CRecreateDlg* pDlg = NULL; if (messg == WM_INITDIALOG) { pDlg = (CRecreateDlg*)lParam; pDlg->mh_Dlg = hDlg; SetWindowLongPtr(hDlg, DWLP_USER, lParam); } else { pDlg = (CRecreateDlg*)GetWindowLongPtr(hDlg, DWLP_USER); } if (!pDlg) { return FALSE; } PatchMsgBoxIcon(hDlg, messg, wParam, lParam); switch (messg) { case WM_INITDIALOG: { LRESULT lbRc = FALSE; // Visual SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hClassIcon); SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hClassIconSm); // Set password style (avoid "bars" on some OS) SendDlgItemMessage(hDlg, tRunAsPassword, WM_SETFONT, (LPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), 0); // Add menu items HMENU hSysMenu = GetSystemMenu(hDlg, FALSE); InsertMenu(hSysMenu, 0, MF_BYPOSITION, MF_SEPARATOR, 0); InsertMenu(hSysMenu, 0, MF_BYPOSITION | MF_STRING | MF_ENABLED, ID_RESETCMDHISTORY, L"Clear history..."); InsertMenu(hSysMenu, 0, MF_BYPOSITION | MF_STRING | MF_ENABLED | (gpSet->isSaveCmdHistory ? MF_CHECKED : 0), ID_STORECMDHISTORY, L"Store history"); //#ifdef _DEBUG //SetWindowPos(ghOpWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE); //#endif RConStartArgs* pArgs = pDlg->mp_Args; _ASSERTE(pArgs); // Fill command and task drop down SendMessage(hDlg, UM_FILL_CMDLIST, TRUE, 0); // Set text in command and folder fields SetDlgItemText(hDlg, IDC_RESTART_CMD, pDlg->mpsz_DefCmd ? pDlg->mpsz_DefCmd : pArgs->pszSpecialCmd ? pArgs->pszSpecialCmd : L""); SetDlgItemText(hDlg, IDC_STARTUP_DIR, pDlg->mpsz_DefDir ? pDlg->mpsz_DefDir : pArgs->pszStartupDir ? pArgs->pszStartupDir : gpConEmu->WorkDir()); // Split controls if (pArgs->aRecreate == cra_RecreateTab) { // Hide Split's ShowWindow(GetDlgItem(hDlg, gbRecreateSplit), SW_HIDE); ShowWindow(GetDlgItem(hDlg, rbRecreateSplitNone), SW_HIDE); ShowWindow(GetDlgItem(hDlg, rbRecreateSplit2Right), SW_HIDE); ShowWindow(GetDlgItem(hDlg, rbRecreateSplit2Bottom), SW_HIDE); ShowWindow(GetDlgItem(hDlg, stRecreateSplit), SW_HIDE); ShowWindow(GetDlgItem(hDlg, tRecreateSplit), SW_HIDE); } else { // Fill splits SetDlgItemInt(hDlg, tRecreateSplit, (1000-pArgs->nSplitValue)/10, FALSE); CheckRadioButton(hDlg, rbRecreateSplitNone, rbRecreateSplit2Bottom, rbRecreateSplitNone+pArgs->eSplit); EnableWindow(GetDlgItem(hDlg, tRecreateSplit), (pArgs->eSplit != pArgs->eSplitNone)); EnableWindow(GetDlgItem(hDlg, stRecreateSplit), (pArgs->eSplit != pArgs->eSplitNone)); } // Спрятать флажок "New window" bool bRunInNewWindow_Hidden = (pArgs->aRecreate == cra_EditTab || pArgs->aRecreate == cra_RecreateTab); ShowWindow(GetDlgItem(hDlg, cbRunInNewWindow), bRunInNewWindow_Hidden ? SW_HIDE : SW_SHOWNORMAL); const wchar_t *pszUser = pArgs->pszUserName; const wchar_t *pszDomain = pArgs->pszDomain; bool bResticted = (pArgs->RunAsRestricted == crb_On); int nChecked = rbCurrentUser; DWORD nUserNameLen = countof(pDlg->ms_CurUser); if (!GetUserName(pDlg->ms_CurUser, &nUserNameLen)) pDlg->ms_CurUser[0] = 0; wchar_t szRbCaption[MAX_PATH*3]; lstrcpy(szRbCaption, L"Run as current &user: "******"UPN format" остается в pszUser lstrcpyn(szOtherUser, pszUser, MAX_PATH); wcscat_c(szOtherUser, L"@"); lstrcpyn(szOtherUser+_tcslen(szOtherUser), pszDomain, MAX_PATH); } else { // "Старая" нотация domain\user lstrcpyn(szOtherUser, pszDomain, MAX_PATH); wcscat_c(szOtherUser, L"\\"); lstrcpyn(szOtherUser+_tcslen(szOtherUser), pszUser, MAX_PATH); } } else { lstrcpyn(szOtherUser, pszUser, countof(szOtherUser)); } SetDlgItemText(hDlg, tRunAsPassword, pArgs->szUserPassword); } } SetDlgItemText(hDlg, tRunAsUser, (nChecked == rbAnotherUser) ? szOtherUser : L""); CheckRadioButton(hDlg, rbCurrentUser, rbAnotherUser, nChecked); RecreateDlgProc(hDlg, UM_USER_CONTROLS, 0, 0); if (gOSVer.dwMajorVersion < 6) { // В XP и ниже это просто RunAs - с возможностью ввода имени пользователя и пароля //apiShowWindow(GetDlgItem(hDlg, cbRunAsAdmin), SW_HIDE); SetDlgItemTextA(hDlg, cbRunAsAdmin, "&Run as..."); //GCC hack. иначе не собирается // И уменьшить длину RECT rcBox; GetWindowRect(GetDlgItem(hDlg, cbRunAsAdmin), &rcBox); SetWindowPos(GetDlgItem(hDlg, cbRunAsAdmin), NULL, 0, 0, (rcBox.right-rcBox.left)/2, rcBox.bottom-rcBox.top, SWP_NOMOVE|SWP_NOZORDER); } else if (gpConEmu->mb_IsUacAdmin || (pArgs && (pArgs->RunAsAdministrator == crb_On))) { CheckDlgButton(hDlg, cbRunAsAdmin, BST_CHECKED); if (gpConEmu->mb_IsUacAdmin) // Только в Vista+ если GUI уже запущен под админом { EnableWindow(GetDlgItem(hDlg, cbRunAsAdmin), FALSE); } else if (gOSVer.dwMajorVersion < 6) { RecreateDlgProc(hDlg, WM_COMMAND, cbRunAsAdmin, 0); } } //} SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR)hClassIcon); RECT rcBtnBox = {0}; if (pArgs->aRecreate == cra_RecreateTab) { //GCC hack. иначе не собирается SetDlgItemTextA(hDlg, IDC_RESTART_MSG, "About to restart console"); SendDlgItemMessage(hDlg, IDC_RESTART_ICON, STM_SETICON, (WPARAM)LoadIcon(NULL,IDI_EXCLAMATION), 0); // Выровнять флажок по кнопке GetWindowRect(GetDlgItem(hDlg, IDC_START), &rcBtnBox); lbRc = TRUE; } else { //GCC hack. иначе не собирается SetDlgItemTextA(hDlg, IDC_RESTART_MSG, "Create new console"); // Если ВЫКЛЮЧЕН "Multi consoles in one window" // - Check & Disable "New window" checkbox CheckDlgButton(hDlg, cbRunInNewWindow, (pArgs->aRecreate == cra_CreateWindow || !gpSetCls->IsMulti()) ? BST_CHECKED : BST_UNCHECKED); EnableWindow(GetDlgItem(hDlg, cbRunInNewWindow), gpSetCls->IsMulti()); // SendDlgItemMessage(hDlg, IDC_RESTART_ICON, STM_SETICON, (WPARAM)LoadIcon(NULL,IDI_QUESTION), 0); POINT pt = {0,0}; MapWindowPoints(GetDlgItem(hDlg, IDC_TERMINATE), hDlg, &pt, 1); DestroyWindow(GetDlgItem(hDlg, IDC_TERMINATE)); SetWindowPos(GetDlgItem(hDlg, IDC_START), NULL, pt.x, pt.y, 0,0, SWP_NOSIZE|SWP_NOZORDER); SetDlgItemText(hDlg, IDC_START, (pArgs->aRecreate == cra_EditTab) ? L"&Save" : L"&Start"); DestroyWindow(GetDlgItem(hDlg, IDC_WARNING)); // Выровнять флажок по кнопке GetWindowRect(GetDlgItem(hDlg, IDC_START), &rcBtnBox); } if (rcBtnBox.left) { // Выровнять флажок по кнопке MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtnBox, 2); RECT rcBox; GetWindowRect(GetDlgItem(hDlg, cbRunAsAdmin), &rcBox); POINT pt; pt.x = rcBtnBox.left - (rcBox.right - rcBox.left) - 5; pt.y = rcBtnBox.top + ((rcBtnBox.bottom-rcBtnBox.top) - (rcBox.bottom-rcBox.top))/2; SetWindowPos(GetDlgItem(hDlg, cbRunAsAdmin), NULL, pt.x, pt.y, 0,0, SWP_NOSIZE|SWP_NOZORDER); } // Correct cbRunInNewWindow position if (!bRunInNewWindow_Hidden) { POINT pt = {}; MapWindowPoints(GetDlgItem(hDlg, cbRunAsAdmin), hDlg, &pt, 1); RECT rcBox2; GetWindowRect(GetDlgItem(hDlg, cbRunInNewWindow), &rcBox2); SetWindowPos(GetDlgItem(hDlg, cbRunInNewWindow), NULL, pt.x-(rcBox2.right-rcBox2.left), pt.y, 0,0, SWP_NOSIZE); } // Ensure, it will be "on screen" RECT rect; GetWindowRect(hDlg, &rect); RECT rcCenter = CenterInParent(rect, pDlg->mh_Parent); MoveWindow(hDlg, rcCenter.left, rcCenter.top, rect.right - rect.left, rect.bottom - rect.top, false); // Была отключена обработка CConEmuMain::OnFocus (лишние телодвижения) PostMessage(hDlg, (WM_APP+1), 0,0); // Default focus control if (pArgs->aRecreate == cra_RecreateTab) SetFocus(GetDlgItem(hDlg, IDC_START)); // Win+~ (Recreate tab), Focus on "Restart" button" else if ((pArgs->pszUserName && *pArgs->pszUserName) && !*pArgs->szUserPassword) SetFocus(GetDlgItem(hDlg, tRunAsPassword)); // We need password, all other fields are ready else SetFocus(GetDlgItem(hDlg, IDC_RESTART_CMD)); // Set focus in command-line field return lbRc; } case (WM_APP+1): //TODO: Не совсем корректно, не учитывается предыдущее значение флажка gpConEmu->SetSkipOnFocus(false); return FALSE; case WM_CTLCOLORSTATIC: if (GetDlgItem(hDlg, IDC_WARNING) == (HWND)lParam) { SetTextColor((HDC)wParam, 255); HBRUSH hBrush = GetSysColorBrush(COLOR_3DFACE); SetBkMode((HDC)wParam, TRANSPARENT); return (INT_PTR)hBrush; } break; //case WM_GETICON: // if (wParam==ICON_BIG) // { // /*SetWindowLong(hWnd2, DWL_MSGRESULT, (LRESULT)hClassIcon); // return 1;*/ // } // else // { // SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (LRESULT)hClassIconSm); // return 1; // } // return 0; case UM_FILL_CMDLIST: { RConStartArgs* pArgs = pDlg->mp_Args; _ASSERTE(pArgs); pDlg->AddCommandList(pArgs->pszSpecialCmd); pDlg->AddCommandList(pDlg->mpsz_SysCmd, pArgs->pszSpecialCmd ? -1 : 0); pDlg->AddCommandList(pDlg->mpsz_CurCmd); pDlg->AddCommandList(pDlg->mpsz_DefCmd); // Может быть позван после очистки истории из меню, тогда нет смысла и дергаться if (wParam) { LPCWSTR pszHistory = gpSet->HistoryGet(); if (pszHistory) { while (*pszHistory) { pDlg->AddCommandList(pszHistory); pszHistory += _tcslen(pszHistory)+1; } } } // Tasks int nGroup = 0; const Settings::CommandTasks* pGrp = NULL; while ((pGrp = gpSet->CmdTaskGet(nGroup++))) { pDlg->AddCommandList(pGrp->pszName); } } return 0; case UM_USER_CONTROLS: { if (SendDlgItemMessage(hDlg, rbCurrentUser, BM_GETCHECK, 0, 0)) { EnableWindow(GetDlgItem(hDlg, cbRunAsRestricted), TRUE); //BOOL lbText = SendDlgItemMessage(hDlg, cbRunAsRestricted, BM_GETCHECK, 0, 0) == 0; EnableWindow(GetDlgItem(hDlg, tRunAsUser), FALSE); EnableWindow(GetDlgItem(hDlg, tRunAsPassword), FALSE); } else { if (SendDlgItemMessage(hDlg, tRunAsUser, CB_GETCOUNT, 0, 0) == 0) { DWORD dwLevel = 3, dwEntriesRead = 0, dwTotalEntries = 0, dwResumeHandle = 0; NET_API_STATUS nStatus; USER_INFO_3 *info = NULL; nStatus = ::NetUserEnum(NULL, dwLevel, FILTER_NORMAL_ACCOUNT, (PBYTE*) & info, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, &dwResumeHandle); if (nStatus == NERR_Success) { wchar_t *pszAdmin = NULL, *pszLikeAdmin = NULL, *pszOtherUser = NULL; for (DWORD i = 0; i < dwEntriesRead; ++i) { // usri3_logon_server "\\*" wchar_t * if (!(info[i].usri3_flags & UF_ACCOUNTDISABLE) && info[i].usri3_name && *info[i].usri3_name) { SendDlgItemMessage(hDlg, tRunAsUser, CB_ADDSTRING, 0, (LPARAM)info[i].usri3_name); if (info[i].usri3_priv == 2/*USER_PRIV_ADMIN*/) { if (!pszAdmin && (info[i].usri3_user_id == 500)) pszAdmin = lstrdup(info[i].usri3_name); else if (!pszLikeAdmin && (lstrcmpi(pDlg->ms_CurUser, info[i].usri3_name) != 0)) pszLikeAdmin = lstrdup(info[i].usri3_name); } else if (!pszOtherUser && (info[i].usri3_priv == 1/*USER_PRIV_USER*/) && (lstrcmpi(pDlg->ms_CurUser, info[i].usri3_name) != 0)) { pszOtherUser = lstrdup(info[i].usri3_name); } } } if (GetWindowTextLength(GetDlgItem(hDlg, tRunAsUser)) == 0) { // Try to suggest "Administrator" account SetDlgItemText(hDlg, tRunAsUser, pszAdmin ? pszAdmin : pszLikeAdmin ? pszLikeAdmin : pszOtherUser ? pszOtherUser : pDlg->ms_CurUser); } ::NetApiBufferFree(info); SafeFree(pszAdmin); SafeFree(pszLikeAdmin); } else { // Добавить хотя бы текущего SendDlgItemMessage(hDlg, tRunAsUser, CB_ADDSTRING, 0, (LPARAM)pDlg->ms_CurUser); } } EnableWindow(GetDlgItem(hDlg, cbRunAsRestricted), FALSE); EnableWindow(GetDlgItem(hDlg, tRunAsUser), TRUE); EnableWindow(GetDlgItem(hDlg, tRunAsPassword), TRUE); } if (wParam == rbAnotherUser) SetFocus(GetDlgItem(hDlg, tRunAsUser)); } return 0; case WM_SYSCOMMAND: switch (LOWORD(wParam)) { case ID_RESETCMDHISTORY: // Подтверждение спросит ResetCmdHistory if (gpSetCls->ResetCmdHistory(hDlg)) { wchar_t* pszCmd = GetDlgItemText(hDlg, IDC_RESTART_CMD); SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_RESETCONTENT, 0,0); SendMessage(hDlg, UM_FILL_CMDLIST, FALSE, 0); if (pszCmd) { SetDlgItemText(hDlg, IDC_RESTART_CMD, pszCmd); free(pszCmd); } } SetWindowLongPtr(hDlg, DWLP_MSGRESULT, 0); return 1; case ID_STORECMDHISTORY: if (MsgBox(gpSet->isSaveCmdHistory ? L"Do you want to disable history?" : L"Do you want to enable history?", MB_YESNO|MB_ICONQUESTION, NULL, hDlg) == IDYES) { gpSetCls->SetSaveCmdHistory(!gpSet->isSaveCmdHistory); HMENU hSysMenu = GetSystemMenu(hDlg, FALSE); CheckMenuItem(hSysMenu, ID_STORECMDHISTORY, MF_BYCOMMAND|(gpSet->isSaveCmdHistory ? MF_CHECKED : 0)); } SetWindowLongPtr(hDlg, DWLP_MSGRESULT, 0); return 1; } break; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { switch (LOWORD(wParam)) { case IDC_CHOOSE: { wchar_t *pszFilePath = SelectFile(L"Choose program to run", NULL, hDlg, L"Executables (*.exe)\0*.exe\0All files (*.*)\0*.*\0\0", true, false, false); if (pszFilePath) { SetDlgItemText(hDlg, IDC_RESTART_CMD, pszFilePath); SafeFree(pszFilePath); } return 1; } case IDC_CHOOSE_DIR: { wchar_t* pszDefFolder = GetDlgItemText(hDlg, IDC_STARTUP_DIR); wchar_t* pszFolder = SelectFolder(L"Choose startup directory", pszDefFolder, hDlg, false, false); if (pszFolder) { SetDlgItemText(hDlg, IDC_STARTUP_DIR, pszFolder); SafeFree(pszFolder); } SafeFree(pszDefFolder); return 1; } case cbRunAsAdmin: { // BCM_SETSHIELD = 5644 BOOL bRunAs = SendDlgItemMessage(hDlg, cbRunAsAdmin, BM_GETCHECK, 0, 0); if (gOSVer.dwMajorVersion >= 6) { SendDlgItemMessage(hDlg, IDC_START, 5644/*BCM_SETSHIELD*/, 0, bRunAs && (pDlg->mp_Args->aRecreate != cra_EditTab)); } if (bRunAs) { CheckRadioButton(hDlg, rbCurrentUser, rbAnotherUser, rbCurrentUser); CheckDlgButton(hDlg, cbRunAsRestricted, BST_UNCHECKED); RecreateDlgProc(hDlg, UM_USER_CONTROLS, 0, 0); } return 1; } case rbCurrentUser: case rbAnotherUser: case cbRunAsRestricted: { RecreateDlgProc(hDlg, UM_USER_CONTROLS, LOWORD(wParam), 0); return 1; } case rbRecreateSplitNone: case rbRecreateSplit2Right: case rbRecreateSplit2Bottom: { RConStartArgs* pArgs = pDlg->mp_Args; switch (LOWORD(wParam)) { case rbRecreateSplitNone: pArgs->eSplit = RConStartArgs::eSplitNone; break; case rbRecreateSplit2Right: pArgs->eSplit = RConStartArgs::eSplitHorz; break; case rbRecreateSplit2Bottom: pArgs->eSplit = RConStartArgs::eSplitVert; break; } EnableWindow(GetDlgItem(hDlg, tRecreateSplit), (pArgs->eSplit != pArgs->eSplitNone)); EnableWindow(GetDlgItem(hDlg, stRecreateSplit), (pArgs->eSplit != pArgs->eSplitNone)); if (pArgs->eSplit != pArgs->eSplitNone) SetFocus(GetDlgItem(hDlg, tRecreateSplit)); return 1; } case IDC_START: { RConStartArgs* pArgs = pDlg->mp_Args; _ASSERTE(pArgs); SafeFree(pArgs->pszUserName); SafeFree(pArgs->pszDomain); //SafeFree(pArgs->pszUserPassword); if (SendDlgItemMessage(hDlg, rbAnotherUser, BM_GETCHECK, 0, 0)) { pArgs->RunAsRestricted = crb_Off; pArgs->pszUserName = GetDlgItemText(hDlg, tRunAsUser); if (pArgs->pszUserName) { //pArgs->pszUserPassword = GetDlgItemText(hDlg, tRunAsPassword); // Попытаться проверить правильность введенного пароля и возможность запуска bool bCheckPwd = pArgs->CheckUserToken(GetDlgItem(hDlg, tRunAsPassword)); DWORD nErr = bCheckPwd ? 0 : GetLastError(); if (!bCheckPwd) { DisplayLastError(L"Invalid user name or password was specified!", nErr, MB_ICONSTOP, NULL, hDlg); return 1; } } } else { pArgs->RunAsRestricted = SendDlgItemMessage(hDlg, cbRunAsRestricted, BM_GETCHECK, 0, 0) ? crb_On : crb_Off; } // Vista+ (As Admin...) pArgs->RunAsAdministrator = SendDlgItemMessage(hDlg, cbRunAsAdmin, BM_GETCHECK, 0, 0) ? crb_On : crb_Off; // StartupDir (may be specified as argument) wchar_t* pszDir = GetDlgItemText(hDlg, IDC_STARTUP_DIR); wchar_t* pszExpand = (pszDir && wcschr(pszDir, L'%')) ? ExpandEnvStr(pszDir) : NULL; LPCWSTR pszDirResult = pszExpand ? pszExpand : pszDir; // Another user? We may fail with access denied. Check only for "current user" account if (!pArgs->pszUserName && pszDirResult && *pszDirResult && !DirectoryExists(pszDirResult)) { wchar_t* pszErrInfo = lstrmerge(L"Specified directory does not exists!\n", pszDirResult, L"\n" L"Do you want to choose another directory?\n\n"); DWORD nErr = GetLastError(); int iDirBtn = DisplayLastError(pszErrInfo, nErr, MB_ICONEXCLAMATION|MB_YESNO, NULL, hDlg); if (iDirBtn == IDYES) { SafeFree(pszDir); SafeFree(pszExpand); SafeFree(pszErrInfo); return 1; } // User want to run "as is". Most likely it will fail, but who knows... } SafeFree(pArgs->pszStartupDir); pArgs->pszStartupDir = pszExpand ? pszExpand : pszDir; if (pszExpand) { SafeFree(pszDir) } // Command // pszSpecialCmd мог быть передан аргументом - умолчание для строки ввода SafeFree(pArgs->pszSpecialCmd); // GetDlgItemText выделяет память через calloc pArgs->pszSpecialCmd = GetDlgItemText(hDlg, IDC_RESTART_CMD); if (pArgs->pszSpecialCmd) gpSet->HistoryAdd(pArgs->pszSpecialCmd); if ((pArgs->aRecreate != cra_RecreateTab) && (pArgs->aRecreate != cra_EditTab)) { if (SendDlgItemMessage(hDlg, cbRunInNewWindow, BM_GETCHECK, 0, 0)) pArgs->aRecreate = cra_CreateWindow; else pArgs->aRecreate = cra_CreateTab; } if (((pArgs->aRecreate == cra_CreateTab) || (pArgs->aRecreate == cra_EditTab)) && (pArgs->eSplit != RConStartArgs::eSplitNone)) { BOOL bOk = FALSE; int nPercent = GetDlgItemInt(hDlg, tRecreateSplit, &bOk, FALSE); if (bOk && (nPercent >= 1) && (nPercent <= 99)) { pArgs->nSplitValue = (100-nPercent) * 10; } //pArgs->nSplitPane = 0; Сбрасывать не будем? } pDlg->mn_DlgRc = IDC_START; EndDialog(hDlg, IDC_START); return 1; } case IDC_TERMINATE: pDlg->mn_DlgRc = IDC_TERMINATE; EndDialog(hDlg, IDC_TERMINATE); return 1; case IDCANCEL: pDlg->mn_DlgRc = IDCANCEL; EndDialog(hDlg, IDCANCEL); return 1; } } else if ((HIWORD(wParam) == EN_SETFOCUS) && lParam) { switch (LOWORD(wParam)) { case tRecreateSplit: case tRunAsPassword: PostMessage((HWND)lParam, EM_SETSEL, 0, SendMessage((HWND)lParam, WM_GETTEXTLENGTH, 0,0)); break; } } break; default: return 0; }
// Returns ">0" - when changes was made // 0 - no changes // -1 - error // bForceCurConsole==true, если разбор параметров идет // при запуске Tasks из GUI int RConStartArgs::ProcessNewConArg(bool bForceCurConsole /*= false*/) { NewConsole = crb_Undefined; if (!pszSpecialCmd || !*pszSpecialCmd) { _ASSERTE(pszSpecialCmd && *pszSpecialCmd); return -1; } int nChanges = 0; // 140219 - Остановить обработку, если встретим любой из: ConEmu[.exe], ConEmu64[.exe], ConEmuC[.exe], ConEmuC64[.exe] LPCWSTR pszStopAt = NULL; { LPCWSTR pszTemp = pszSpecialCmd; LPCWSTR pszSave = pszSpecialCmd; LPCWSTR pszName; CmdArg szExe; LPCWSTR pszWords[] = {L"ConEmu", L"ConEmu.exe", L"ConEmu64", L"ConEmu64.exe", L"ConEmuC", L"ConEmuC.exe", L"ConEmuC64", L"ConEmuC64.exe", L"ConEmuPortable.exe", L"ConEmuPortable", NULL}; while (!pszStopAt && (0 == NextArg(&pszTemp, szExe))) { pszName = PointToName(szExe); for (size_t i = 0; pszWords[i]; i++) { if (lstrcmpi(pszName, pszWords[i]) == 0) { pszStopAt = pszSave; break; } } pszSave = pszTemp; } } #if 0 // 140219 - Остановить обработку, если встретим любой из: ConEmu[.exe], ConEmu64[.exe], ConEmuC[.exe], ConEmuC64[.exe] if (!hShlwapi) { hShlwapi = LoadLibrary(L"Shlwapi.dll"); WcsStrI = hShlwapi ? (StrStrI_t)GetProcAddress(hShlwapi, "StrStrIW") : NULL; } #endif // 111211 - здесь может быть передан "-new_console:..." LPCWSTR pszNewCon = L"-new_console"; // 120108 - или "-cur_console:..." для уточнения параметров запуска команд (из фара например) LPCWSTR pszCurCon = L"-cur_console"; int nNewConLen = lstrlen(pszNewCon); _ASSERTE(lstrlen(pszCurCon)==nNewConLen); wchar_t* pszFrom = pszSpecialCmd; bool bStop = false; while (!bStop) { wchar_t* pszSwitch = wcschr(pszFrom, L'-'); if (!pszSwitch) break; // Pre-validation if (((pszSwitch[1] != L'n') && (pszSwitch[1] != L'c')) // -new_... or -cur_... || (((pszSwitch != /* > */ pszFrom) // If it is started from pszFrom - no need to check previous symbols && (*(pszSwitch-1) != L'"') || (((pszSwitch-2) >= pszFrom) && (*(pszSwitch-2) == L'\\'))) // Found: \"-new... && (*(pszSwitch-1) != L' '))) // Prev symbol was space { // НЕ наш аргумент pszSwitch = wcschr(pszSwitch+1, L' '); if (!pszSwitch) break; pszFrom = pszSwitch; continue; } wchar_t* pszFindNew = NULL; wchar_t* pszFind = NULL; wchar_t szTest[12]; lstrcpyn(szTest, pszSwitch+1, countof(szTest)); if (lstrcmp(szTest, L"new_console") == 0) pszFindNew = pszFind = pszSwitch; else if (lstrcmp(szTest, L"cur_console") == 0) pszFind = pszSwitch; else { // НЕ наш аргумент pszSwitch = wcschr(pszSwitch+1, L' '); if (!pszSwitch) break; pszFrom = pszSwitch; continue; } if (!pszFind) break; if (pszStopAt && (pszFind >= pszStopAt)) break; // Проверка валидности _ASSERTE(pszFind >= pszSpecialCmd); if ((pszFind[nNewConLen] != L' ') && (pszFind[nNewConLen] != L':') && (pszFind[nNewConLen] != L'"') && (pszFind[nNewConLen] != 0)) { // НЕ наш аргумент pszFrom = pszFind+nNewConLen; } else { if (pszFindNew) NewConsole = crb_On; // -- не будем пока, мешает. например, при запуске задач //// По умолчанию, принудительно включить "Press Enter or Esc to close console" //if (!bForceCurConsole) // eConfirmation = eConfAlways; bool lbQuot = (*(pszFind-1) == L'"'); bool lbWasQuot = lbQuot; const wchar_t* pszEnd = pszFind+nNewConLen; //wchar_t szNewConArg[MAX_PATH+1]; if (lbQuot) pszFind--; if (*pszEnd == L'"') { pszEnd++; } else if (*pszEnd != L':') { // Конец _ASSERTE(*pszEnd == L' ' || *pszEnd == 0); } else { if (*pszEnd == L':') { pszEnd++; } else { _ASSERTE(*pszEnd == L':'); } // Найти конец аргумента const wchar_t* pszArgEnd = pszEnd; bool lbLocalQuot = false; while (*pszArgEnd) { switch (*pszArgEnd) { case L'^': pszArgEnd++; // Skip control char, goto escaped char break; case L'"': if (*(pszArgEnd+1) == L'"') { pszArgEnd += 2; // Skip qoubled qouble quote continue; } if (!lbQuot) { if (!lbLocalQuot && (*(pszArgEnd-1) == L':')) { lbLocalQuot = true; pszArgEnd++; continue; } if (lbLocalQuot) { if (*(pszArgEnd+1) != L':') goto EndFound; lbLocalQuot = false; pszArgEnd += 2; continue; } } goto EndFound; case L' ': if (!lbQuot && !lbLocalQuot) goto EndFound; break; case 0: goto EndFound; } pszArgEnd++; } EndFound: // Обработка доп.параметров -new_console:xxx bool lbReady = false; while (!lbReady && *pszEnd) { _ASSERTE(pszEnd <= pszArgEnd); wchar_t cOpt = *(pszEnd++); switch (cOpt) { //case L'-': // bStop = true; // следующие "-new_console" - не трогать! // break; case L'"': _ASSERTE(pszEnd > pszArgEnd); lbReady = true; break; case L' ': case 0: lbReady = true; break; case L':': // Just skip ':'. Delimiter between switches: -new_console:c:b:a // Revert stored value to lbQuot. We need to "cut" last double quote in the first two cases // cmd -cur_console:d:"C:\users":t:"My title" "-cur_console:C:C:\cmd.ico" -cur_console:P:"<PowerShell>":a /k ver lbWasQuot = lbQuot; break; case L'b': // b - background, не активировать таб BackgroundTab = crb_On; ForegroungTab = crb_Off; break; case L'f': // f - foreground, активировать таб (аналог ">" в Tasks) ForegroungTab = crb_On; BackgroundTab = crb_Off; break; case L'z': // z - don't use "Default terminal" feature NoDefaultTerm = crb_On; break; case L'a': // a - RunAs shell verb (as admin on Vista+, login/password in WinXP-) RunAsAdministrator = crb_On; break; case L'r': // r - run as restricted user RunAsRestricted = crb_On; break; case L'o': // o - disable "Long output" for next command (Far Manager) LongOutputDisable = crb_On; break; case L'w': // e - enable "Overwrite" mode in console prompt OverwriteMode = crb_On; break; case L'p': if (isDigit(*pszEnd)) { switch (*(pszEnd++)) { case L'0': nPTY = 0; // don't change break; case L'1': nPTY = 1; // enable PTY mode break; case L'2': nPTY = 2; // disable PTY mode (switch to plain $CONIN, $CONOUT, $CONERR) break; default: nPTY = 1; } } else { nPTY = 1; // enable PTY mode } break; case L'i': // i - don't inject ConEmuHk into the starting application InjectsDisable = crb_On; break; case L'N': // N - Force new ConEmu window with Default terminal ForceNewWindow = crb_On; break; case L'h': // "h0" - отключить буфер, "h9999" - включить буфер в 9999 строк { BufHeight = crb_On; if (isDigit(*pszEnd)) { wchar_t* pszDigits = NULL; nBufHeight = wcstoul(pszEnd, &pszDigits, 10); if (pszDigits) pszEnd = pszDigits; } else { nBufHeight = 0; } } // L'h': break; case L'n': // n - отключить "Press Enter or Esc to close console" eConfirmation = eConfNever; break; case L'c': // c - принудительно включить "Press Enter or Esc to close console" eConfirmation = eConfAlways; break; case L'x': // x - Force using dosbox for .bat files ForceDosBox = crb_On; break; case L'I': // I - tell GuiMacro to execute new command inheriting active process state. This is only usage ATM. ForceInherit = crb_On; break; // "Long" code blocks below: 'd', 'u', 's' and so on (in future) case L's': // s[<SplitTab>T][<Percents>](H|V) // Пример: "s3T30H" - разбить 3-ий таб. будет создан новый Pane справа, шириной 30% от 3-го таба. { UINT nTab = 0 /*active*/, nValue = /*пополам*/DefaultSplitValue/10; bool bDisableSplit = false; while (*pszEnd) { if (isDigit(*pszEnd)) { wchar_t* pszDigits = NULL; UINT n = wcstoul(pszEnd, &pszDigits, 10); if (!pszDigits) break; pszEnd = pszDigits; if (*pszDigits == L'T') { nTab = n; } else if ((*pszDigits == L'H') || (*pszDigits == L'V')) { nValue = n; eSplit = (*pszDigits == L'H') ? eSplitHorz : eSplitVert; } else { break; } pszEnd++; } else if (*pszEnd == L'T') { nTab = 0; pszEnd++; } else if ((*pszEnd == L'H') || (*pszEnd == L'V')) { nValue = DefaultSplitValue/10; eSplit = (*pszEnd == L'H') ? eSplitHorz : eSplitVert; pszEnd++; } else if (*pszEnd == L'N') { bDisableSplit = true; pszEnd++; break; } else { break; } } if (bDisableSplit) { eSplit = eSplitNone; nSplitValue = DefaultSplitValue; nSplitPane = 0; } else { if (!eSplit) eSplit = eSplitHorz; // Для удобства, пользователь задает размер НОВОЙ части nSplitValue = 1000-max(1,min(nValue*10,999)); // проценты _ASSERTE(nSplitValue>=1 && nSplitValue<1000); nSplitPane = nTab; } } // L's' break; // Following options (except of single 'u') must be placed on the end of "-new_console:..." // If one needs more that one option - use several "-new_console:..." switches case L'd': // d:<StartupDir>. MUST be last option case L't': // t:<TabName>. MUST be last option case L'u': // u - ConEmu choose user dialog (may be specified in the middle, if it is without ':' - user or pwd) // u:<user> - ConEmu choose user dialog with prefilled user field. MUST be last option // u:<user>:<pwd> - specify user/pwd in args. MUST be last option case L'C': // C:<IconFile>. MUST be last option case L'P': // P:<Palette>. MUST be last option case L'W': // W:<Wallpaper>. MUST be last option { if (cOpt == L'u') { // Show choose user dialog (may be specified in the middle, if it is without ':' - user or pwd) SafeFree(pszUserName); SafeFree(pszDomain); if (szUserPassword[0]) SecureZeroMemory(szUserPassword, sizeof(szUserPassword)); } if (*pszEnd == L':') { pszEnd++; } else { if (cOpt == L'u') { ForceUserDialog = crb_On; break; } } const wchar_t* pszTab = pszEnd; // we need to find end of argument pszEnd = pszArgEnd; // temp buffer wchar_t* lpszTemp = NULL; wchar_t** pptr = NULL; switch (cOpt) { case L'd': pptr = &pszStartupDir; break; case L't': pptr = &pszRenameTab; break; case L'u': pptr = &lpszTemp; break; case L'C': pptr = &pszIconFile; break; case L'P': pptr = &pszPalette; break; case L'W': pptr = &pszWallpaper; break; } if (pszEnd > pszTab) { size_t cchLen = pszEnd - pszTab; SafeFree(*pptr); *pptr = (wchar_t*)malloc((cchLen+1)*sizeof(**pptr)); if (*pptr) { // We need to process escape sequences ("^>" -> ">", "^&" -> "&", etc.) //wmemmove(*pptr, pszTab, cchLen); wchar_t* pD = *pptr; const wchar_t* pS = pszTab; if (lbQuot) { lbLocalQuot = false; } else if (*pS == L'"' && *(pS+1) != L'"') { // Remember, that last processed switch was local-quoted lbWasQuot = true; // This item is local quoted. Example: -new_console:t:"My title" lbLocalQuot = true; pS++; } // There is enough room allocated while (pS < pszEnd) { if ((*pS == L'^') && ((pS + 1) < pszEnd)) { pS++; // Skip control char, goto escaped char } else if (*pS == L'"') { if (((pS + 1) < pszEnd) && (*(pS+1) == L'"')) { pS++; // Skip qoubled qouble quote } else if (lbLocalQuot) { pszEnd = (pS+1); _ASSERTE(*pszEnd==L':' || *pszEnd==L' ' || *pszEnd==0); break; // End of local quoted argument: -new_console:d:"C:\User\super user":t:"My title" } } *(pD++) = *(pS++); } // Terminate with '\0' _ASSERTE(pD <= ((*pptr)+cchLen)); *pD = 0; } // Additional processing switch (cOpt) { case L'd': // Например, "%USERPROFILE%" // TODO("А надо ли разворачивать их тут? Наверное при запуске под другим юзером некорректно? Хотя... все равно до переменных не доберемся"); if (wcschr(pszStartupDir, L'%')) { wchar_t* pszExpand = NULL; if (((pszExpand = ExpandEnvStr(pszStartupDir)) != NULL)) { SafeFree(pszStartupDir); pszStartupDir = pszExpand; } } break; case L'u': if (lpszTemp) { // Split in form: // [Domain\]UserName[:Password] wchar_t* pszPwd = wcschr(lpszTemp, L':'); if (pszPwd) { // Password was specified, dialog prompt is not required ForceUserDialog = crb_Off; *pszPwd = 0; int nPwdLen = lstrlen(pszPwd+1); lstrcpyn(szUserPassword, pszPwd+1, countof(szUserPassword)); if (nPwdLen > 0) SecureZeroMemory(pszPwd+1, nPwdLen); UseEmptyPassword = (nPwdLen == 0) ? crb_On : crb_Off; } else { // Password was NOT specified, dialog prompt IS required ForceUserDialog = crb_On; UseEmptyPassword = crb_Off; } wchar_t* pszSlash = wcschr(lpszTemp, L'\\'); if (pszSlash) { *pszSlash = 0; pszDomain = lstrdup(lpszTemp); pszUserName = lstrdup(pszSlash+1); } else { pszUserName = lstrdup(lpszTemp); } } break; } } SafeFree(lpszTemp); } // L't': break; } } } if (pszEnd > pszFind) { // pszEnd должен указывать на конец -new_console[:...] / -cur_console[:...] // и включать обрамляющую кавычку, если он окавычен if (lbWasQuot) { if (*pszEnd == L'"' && *(pszEnd-1) != L'"') pszEnd++; } else { while (*(pszEnd-1) == L'"') pszEnd--; } // Откусить лишние пробелы, которые стоят ПЕРЕД -new_console[:...] / -cur_console[:...] while (((pszFind - 1) >= pszSpecialCmd) && (*(pszFind-1) == L' ') && (((pszFind - 1) == pszSpecialCmd) || (*(pszFind-2) == L' ') || (/**pszEnd == L'"' ||*/ *pszEnd == 0 || *pszEnd == L' '))) { pszFind--; } // Откусить лишние пробелы ПОСЛЕ -new_console[:...] / -cur_console[:...] если он стоит в НАЧАЛЕ строки! if (pszFind == pszSpecialCmd) { while (*pszEnd == L' ') pszEnd++; } // Здесь нужно подвинуть pszStopAt if (pszStopAt) pszStopAt -= (pszEnd - pszFind); // Удалить из строки запуска обработанный ключ wmemmove(pszFind, pszEnd, (lstrlen(pszEnd)+1)); nChanges++; } else { _ASSERTE(pszEnd > pszFind); *pszFind = 0; nChanges++; } } // if ((((pszFind == pszFrom) ... } // while (!bStop) return nChanges; } // int RConStartArgs::ProcessNewConArg(bool bForceCurConsole /*= false*/)
int CIconList::CreateTabIcon(LPCWSTR asIconDescr, bool bAdmin) { if (!asIconDescr || !*asIconDescr) return GetTabIcon(bAdmin); for (INT_PTR i = 0; i < m_Icons.size(); i++) { const TabIconCache& icn = m_Icons[i]; if ((icn.bAdmin!=FALSE) != bAdmin) continue; if (lstrcmpi(icn.pszIconDescr, asIconDescr) != 0) continue; // Already was created! return icn.nIconIdx; } wchar_t* pszExpanded = ExpandEnvStr(asIconDescr); // Need to be created! int iIconIdx = -1; HICON hFileIcon = NULL; wchar_t szTemp[MAX_PATH]; LPCWSTR pszLoadFile = pszExpanded ? pszExpanded : asIconDescr; LPCWSTR lpszExt = (wchar_t*)PointToExt(pszLoadFile); if (!lpszExt) { LPWSTR pszFile = NULL; if (SearchPath(NULL, pszLoadFile, L".exe", countof(szTemp), szTemp, &pszFile)) { pszLoadFile = szTemp; lpszExt = (wchar_t*)PointToExt(pszLoadFile); } if (!lpszExt) goto wrap; } if (lstrcmpi(lpszExt, L".ico") == 0) { hFileIcon = (HICON)LoadImage(0, pszLoadFile, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_LOADFROMFILE); } else if ((lstrcmpi(lpszExt, L".exe") == 0) || (lstrcmpi(lpszExt, L".dll") == 0)) { //TODO: May be specified index of an icon in the file HICON hIconLarge = NULL; ExtractIconEx(pszLoadFile, 0, &hIconLarge, &hFileIcon, 1); if (hIconLarge) DestroyIcon(hIconLarge); } else { //TODO: Shell icons for registered files (cmd, bat, sh, pl, py, ...) } if (hFileIcon) { int iIconIdxAdm = -1; iIconIdx = ImageList_ReplaceIcon(mh_TabIcons, -1, hFileIcon); TabIconCache NewIcon = {lstrdup(asIconDescr), false, iIconIdx}; m_Icons.push_back(NewIcon); 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) { iIconIdxAdm = ImageList_ReplaceIcon(mh_TabIcons, -1, hNewIcon); DestroyIcon(hNewIcon); TabIconCache AdmIcon = {lstrdup(asIconDescr), true, iIconIdxAdm}; m_Icons.push_back(AdmIcon); if (bAdmin && (iIconIdxAdm > 0)) { iIconIdx = iIconIdxAdm; } } } //TODO: bAdmin!!! DestroyIcon(hFileIcon); } wrap: SafeFree(pszExpanded); return iIconIdx; }
bool GetImageSubsystem(const wchar_t *FileName,DWORD& ImageSubsystem,DWORD& ImageBits/*16/32/64*/,DWORD& FileAttrs) { bool Result = false; ImageSubsystem = IMAGE_SUBSYSTEM_UNKNOWN; ImageBits = 0; FileAttrs = (DWORD)-1; wchar_t* pszExpand = NULL; // Пытаться в UNC? Хотя сам CreateProcess UNC не поддерживает, так что смысла пока нет HANDLE hModuleFile = CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); // Переменные окружения if ((hModuleFile == INVALID_HANDLE_VALUE) && FileName && wcschr(FileName, L'%')) { pszExpand = ExpandEnvStr(FileName); if (pszExpand) { hModuleFile = CreateFile(pszExpand,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); if (hModuleFile != INVALID_HANDLE_VALUE) { FileName = pszExpand; } } } #if 0 // Если не указан путь к файлу - попробовать найти его в %PATH% if (hModuleFile != INVALID_HANDLE_VALUE && FileName && wcschr(FileName, L'\\') == NULL && wcschr(FileName, L'.') != NULL) { DWORD nErrCode = GetLastError(); if (nErrCode) { wchar_t szFind[MAX_PATH], *psz; DWORD nLen = SearchPath(NULL, FileName, NULL, countof(szFind), szFind, &psz); if (nLen && nLen < countof(szFind)) hModuleFile = CreateFile(szFind,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); } } #endif if (hModuleFile != INVALID_HANDLE_VALUE) { BY_HANDLE_FILE_INFORMATION bfi = {0}; IMAGE_DOS_HEADER DOSHeader; DWORD ReadSize; if (GetFileInformationByHandle(hModuleFile, &bfi)) FileAttrs = bfi.dwFileAttributes; // Это это батник - сразу вернуть IMAGE_SUBSYSTEM_BATCH_FILE LPCWSTR pszExt = PointToExt(FileName); if (pszExt && (!lstrcmpi(pszExt, L".cmd") || !lstrcmpiW(pszExt, L".bat") || !lstrcmpiW(pszExt, L".btm") // take command )) { CloseHandle(hModuleFile); ImageSubsystem = IMAGE_SUBSYSTEM_BATCH_FILE; ImageBits = IsWindows64() ? 64 : 32; //-V112 Result = true; goto wrap; } if (ReadFile(hModuleFile,&DOSHeader,sizeof(DOSHeader),&ReadSize,NULL)) { _ASSERTE(IMAGE_DOS_SIGNATURE==0x5A4D); if (DOSHeader.e_magic != IMAGE_DOS_SIGNATURE) { //const wchar_t *pszExt = wcsrchr(FileName, L'.'); if (pszExt && lstrcmpiW(pszExt, L".com") == 0) { ImageSubsystem = IMAGE_SUBSYSTEM_DOS_EXECUTABLE; ImageBits = 16; Result = true; } } else { ImageSubsystem = IMAGE_SUBSYSTEM_DOS_EXECUTABLE; ImageBits = 16; Result = true; if (SetFilePointer(hModuleFile,DOSHeader.e_lfanew,NULL,FILE_BEGIN)) { IMAGE_HEADERS PEHeader; if (ReadFile(hModuleFile,&PEHeader,sizeof(PEHeader),&ReadSize,NULL)) { _ASSERTE(IMAGE_NT_SIGNATURE==0x00004550); if (PEHeader.Signature == IMAGE_NT_SIGNATURE) { switch(PEHeader.OptionalHeader32.Magic) { case IMAGE_NT_OPTIONAL_HDR32_MAGIC: { ImageSubsystem = PEHeader.OptionalHeader32.Subsystem; _ASSERTE((ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) || (ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)); ImageBits = 32; //-V112 } break; case IMAGE_NT_OPTIONAL_HDR64_MAGIC: { ImageSubsystem = PEHeader.OptionalHeader64.Subsystem; _ASSERTE((ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) || (ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)); ImageBits = 64; } break; /*default: { // unknown magic }*/ } } else if ((WORD)PEHeader.Signature == IMAGE_OS2_SIGNATURE) { ImageBits = 32; //-V112 /* NE, хмм... а как определить что оно ГУЕВОЕ? Andrzej Novosiolov <*****@*****.**> AN> ориентироваться по флагу "Target operating system" NE-заголовка AN> (1 байт по смещению 0x36). Если там Windows (значения 2, 4) - подразумеваем AN> GUI, если OS/2 и прочая экзотика (остальные значения) - подразумеваем консоль. */ BYTE ne_exetyp = reinterpret_cast<PIMAGE_OS2_HEADER>(&PEHeader)->ne_exetyp; if (ne_exetyp==2||ne_exetyp==4) //-V112 { ImageSubsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; } else { ImageSubsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; } } /*else { // unknown signature }*/ } /*else { // обломс вышел с чтением следующего заголовка ;-( }*/ } /*else { // видимо улетели куда нить в трубу, т.к. dos_head.e_lfanew указал // слишком в неправдоподное место (например это чистой воды DOS-файл) }*/ } /*else { // это не исполняемый файл - у него нету заголовка MZ, например, NLM-модуль // TODO: здесь можно разбирать POSIX нотацию, например "/usr/bin/sh" }*/ } /*else { // ошибка чтения }*/ CloseHandle(hModuleFile); } /*else { // ошибка открытия }*/ wrap: SafeFree(pszExpand); return Result; }
int CIconList::CreateTabIconInt(LPCWSTR asIconDescr, bool bAdmin, LPCWSTR asWorkDir) { wchar_t* pszExpanded = ExpandEnvStr(asIconDescr); // Need to be created! int iIconIdx = -1; HICON hFileIcon = NULL; wchar_t szTemp[MAX_PATH]; LPCWSTR pszLoadFile = pszExpanded ? pszExpanded : asIconDescr; LPCWSTR lpszExt = (wchar_t*)PointToExt(pszLoadFile); bool bDirChanged = false; if (asWorkDir && *asWorkDir) { // Executable (or icon) file may be not availbale by %PATH%, let "cd" to it... bDirChanged = gpConEmu->ChangeWorkDir(asWorkDir); } if (!lpszExt) { LPWSTR pszFile = NULL; if (SearchPath(NULL, pszLoadFile, L".exe", countof(szTemp), szTemp, &pszFile)) { pszLoadFile = szTemp; lpszExt = (wchar_t*)PointToExt(pszLoadFile); } if (!lpszExt) goto wrap; } if (lstrcmpi(lpszExt, L".ico") == 0) { hFileIcon = (HICON)LoadImage(0, pszLoadFile, IMAGE_ICON, mn_CxIcon, mn_CyIcon, LR_DEFAULTCOLOR|LR_LOADFROMFILE); } else if ((lstrcmpi(lpszExt, L".exe") == 0) || (lstrcmpi(lpszExt, L".dll") == 0)) { //TODO: May be specified index of an icon in the file HICON hIconLarge = NULL, hIconSmall = NULL; ExtractIconEx(pszLoadFile, 0, &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; }
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; }
static INT_PTR Fast_OnInitDialog(HWND hDlg, UINT messg, WPARAM wParam, LPARAM lParam) { SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hClassIcon); SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hClassIconSm); if (gp_DpiAware) { gp_DpiAware->Attach(hDlg, NULL, CDynDialog::GetDlgClass(hDlg)); } RECT rect = {}; if (GetWindowRect(hDlg, &rect)) { CDpiAware::GetCenteredRect(NULL, rect); MoveWindowRect(hDlg, rect); } if (lParam) { SetWindowText(hDlg, (LPCWSTR)lParam); } else { wchar_t szTitle[512]; wcscpy_c(szTitle, gpConEmu->GetDefaultTitle()); wcscat_c(szTitle, L" fast configuration"); SetWindowText(hDlg, szTitle); } // lbStorageLocation SettingsStorage Storage = {}; bool ReadOnly = false; gpSet->GetSettingsType(Storage, ReadOnly); // Same priority as in CConEmuMain::ConEmuXml (reverse order) wchar_t* pszSettingsPlaces[] = { lstrdup(L"HKEY_CURRENT_USER\\Software\\ConEmu"), ExpandEnvStr(L"%APPDATA%\\ConEmu.xml"), ExpandEnvStr(L"%ConEmuBaseDir%\\ConEmu.xml"), ExpandEnvStr(L"%ConEmuDir%\\ConEmu.xml"), NULL }; // Lets find first allowed item int iAllowed = 0; if (lstrcmp(Storage.szType, CONEMU_CONFIGTYPE_XML) == 0) { iAllowed = 1; // XML is used, registry is not allowed if (Storage.pszFile) { if (lstrcmpi(Storage.pszFile, pszSettingsPlaces[1]) == 0) // %APPDATA% iAllowed = 1; // Any other xml has greater priority else if (lstrcmpi(Storage.pszFile, pszSettingsPlaces[2]) == 0) // %ConEmuBaseDir% iAllowed = 2; // Only %ConEmuDir% has greater priority else if (lstrcmpi(Storage.pszFile, pszSettingsPlaces[3]) == 0) // %ConEmuDir% iAllowed = 3; // Most prioritized else { // Directly specified with "/LoadCfgFile ..." SafeFree(pszSettingsPlaces[3]); pszSettingsPlaces[3] = lstrdup(Storage.pszFile); iAllowed = 3; // Most prioritized } } } // Index of the default location (relative to listbox, but not a pszSettingsPlaces) // By default - suggest %APPDATA% or, if possible, %ConEmuDir% // Win2k does not have 'msxml3.dll'/'msxml3r.dll' libraries int iDefault = ((iAllowed == 0) && !IsWin2kEql()) ? (CConEmuUpdate::NeedRunElevation() ? 1 : 3) : 0; // Populate lbStorageLocation while (pszSettingsPlaces[iAllowed]) { SendDlgItemMessage(hDlg, lbStorageLocation, CB_ADDSTRING, 0, (LPARAM)pszSettingsPlaces[iAllowed]); iAllowed++; } SendDlgItemMessage(hDlg, lbStorageLocation, CB_SETCURSEL, iDefault, 0); // Release memory for (int i = 0; pszSettingsPlaces[i]; i++) { SafeFree(pszSettingsPlaces[i]); } // Tasks const CommandTasks* pGrp = NULL; for (int nGroup = 0; (pGrp = gpSet->CmdTaskGet(nGroup)) != NULL; nGroup++) { SendDlgItemMessage(hDlg, lbStartupShellFast, CB_ADDSTRING, 0, (LPARAM)pGrp->pszName); } // Show startup task or shell command line LPCWSTR pszStartup = (gpSet->nStartType == 2) ? gpSet->psStartTasksName : (gpSet->nStartType == 0) ? gpSet->psStartSingleApp : NULL; if (pszStartup && *pszStartup) CSetDlgLists::SelectStringExact(hDlg, lbStartupShellFast, pszStartup); // Palettes (console color sets) const ColorPalette* pPal = NULL; for (int nPal = 0; (pPal = gpSet->PaletteGet(nPal)) != NULL; nPal++) { SendDlgItemMessage(hDlg, lbColorSchemeFast, CB_ADDSTRING, 0, (LPARAM)pPal->pszName); } // Show active (default) palette gp_DefaultPalette = gpSet->PaletteFindCurrent(true); if (gp_DefaultPalette) { CSetDlgLists::SelectStringExact(hDlg, lbColorSchemeFast, gp_DefaultPalette->pszName); } else { _ASSERTE(FALSE && "Current paletted was not defined?"); } // Show its colors in box HWND hChild = GetDlgItem(hDlg, stPalettePreviewFast); if (hChild) gpfn_DefaultColorBoxProc = (WNDPROC)SetWindowLongPtr(hChild, GWLP_WNDPROC, (LONG_PTR)Fast_ColorBoxProc); // Single instance CheckDlgButton(hDlg, cbSingleInstance, gpSetCls->IsSingleInstanceArg()); // Quake style and show/hide key CheckDlgButton(hDlg, cbQuakeFast, gpSet->isQuakeStyle ? BST_CHECKED : BST_UNCHECKED); const ConEmuHotKey* pHK = NULL; if (gpSet->GetHotkeyById(vkMinimizeRestore, &pHK) && pHK) { wchar_t szKey[128] = L""; SetDlgItemText(hDlg, tQuakeKeyFast, pHK->GetHotkeyName(szKey)); ghk_MinMaxKey.SetVkMod(pHK->GetVkMod()); } // Keyhooks required for Win+Number, Win+Arrows, etc. CheckDlgButton(hDlg, cbUseKeyboardHooksFast, gpSet->isKeyboardHooks(true)); // Debug purposes only. ConEmu.exe switch "/nokeyhooks" #ifdef _DEBUG EnableWindow(GetDlgItem(hDlg, cbUseKeyboardHooksFast), !gpConEmu->DisableKeybHooks); #endif // Injects CheckDlgButton(hDlg, cbInjectConEmuHkFast, gpSet->isUseInjects); // Autoupdates if (!gpConEmu->isUpdateAllowed()) { EnableWindow(GetDlgItem(hDlg, cbEnableAutoUpdateFast), FALSE); EnableWindow(GetDlgItem(hDlg, rbAutoUpdateStableFast), FALSE); EnableWindow(GetDlgItem(hDlg, rbAutoUpdatePreviewFast), FALSE); EnableWindow(GetDlgItem(hDlg, rbAutoUpdateDeveloperFast), FALSE); EnableWindow(GetDlgItem(hDlg, stEnableAutoUpdateFast), FALSE); } else { if (gpSet->UpdSet.isUpdateUseBuilds != 0) CheckDlgButton(hDlg, cbEnableAutoUpdateFast, gpSet->UpdSet.isUpdateCheckOnStartup|gpSet->UpdSet.isUpdateCheckHourly); CheckRadioButton(hDlg, rbAutoUpdateStableFast, rbAutoUpdateDeveloperFast, (gpSet->UpdSet.isUpdateUseBuilds == 1) ? rbAutoUpdateStableFast : (gpSet->UpdSet.isUpdateUseBuilds == 3) ? rbAutoUpdatePreviewFast : rbAutoUpdateDeveloperFast); } // Vista - ConIme bugs if (!bCheckIme) { ShowWindow(GetDlgItem(hDlg, gbDisableConImeFast), SW_HIDE); ShowWindow(GetDlgItem(hDlg, cbDisableConImeFast), SW_HIDE); ShowWindow(GetDlgItem(hDlg, stDisableConImeFast1), SW_HIDE); ShowWindow(GetDlgItem(hDlg, stDisableConImeFast2), SW_HIDE); ShowWindow(GetDlgItem(hDlg, stDisableConImeFast3), SW_HIDE); RECT rcGroup, rcBtn, rcWnd; if (GetWindowRect(GetDlgItem(hDlg, gbDisableConImeFast), &rcGroup)) { int nShift = (rcGroup.bottom-rcGroup.top); HWND h = GetDlgItem(hDlg, IDOK); GetWindowRect(h, &rcBtn); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtn, 2); SetWindowPos(h, NULL, rcBtn.left, rcBtn.top - nShift, 0,0, SWP_NOSIZE|SWP_NOZORDER); h = GetDlgItem(hDlg, IDCANCEL); GetWindowRect(h, &rcBtn); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtn, 2); SetWindowPos(h, NULL, rcBtn.left, rcBtn.top - nShift, 0,0, SWP_NOSIZE|SWP_NOZORDER); h = GetDlgItem(hDlg, stHomePage); GetWindowRect(h, &rcBtn); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtn, 2); SetWindowPos(h, NULL, rcBtn.left, rcBtn.top - nShift, 0,0, SWP_NOSIZE|SWP_NOZORDER); SetWindowText(h, gsHomePage); GetWindowRect(hDlg, &rcWnd); MoveWindow(hDlg, rcWnd.left, rcWnd.top+(nShift>>1), rcWnd.right-rcWnd.left, rcWnd.bottom-rcWnd.top-nShift, FALSE); }
void CommandTasks::ParseGuiArgs(RConStartArgs* pArgs) const { if (!pArgs) { _ASSERTE(pArgs!=NULL); return; } LPCWSTR pszArgs = pszGuiArgs, pszOk = pszGuiArgs; CmdArg szArg; while (0 == NextArg(&pszArgs, szArg)) { if (szArg.ms_Arg[0] == L'-') szArg.ms_Arg[0] = L'/'; if (lstrcmpi(szArg, L"/dir") == 0) { if (0 != NextArg(&pszArgs, szArg)) break; if (*szArg) { wchar_t* pszExpand = NULL; // Например, "%USERPROFILE%" if (wcschr(szArg, L'%')) { pszExpand = ExpandEnvStr(szArg); } SafeFree(pArgs->pszStartupDir); pArgs->pszStartupDir = pszExpand ? pszExpand : lstrdup(szArg); } } else if (lstrcmpi(szArg, L"/icon") == 0) { if (0 != NextArg(&pszArgs, szArg)) break; if (*szArg) { wchar_t* pszExpand = NULL; // Например, "%USERPROFILE%" if (wcschr(szArg, L'%')) { pszExpand = ExpandEnvStr(szArg); } SafeFree(pArgs->pszIconFile); pArgs->pszIconFile = pszExpand ? pszExpand : lstrdup(szArg); } } else if (lstrcmpi(szArg, L"/single") == 0) { // Used in the other parts of code } else if (lstrcmpi(szArg, L"/nosingle") == 0) { // Force to run in new ConEmu window pArgs->aRecreate = cra_CreateWindow; } else if (lstrcmpi(szArg, L"/quake") == 0) { // Turn on quake mode in starting console? // Disallowed if current window is already in Quake mode. if (!gpSet->isQuakeStyle) lstrmerge(&pArgs->pszAddGuiArg, L"/quake "); } else if (lstrcmpi(szArg, L"/noquake") == 0) { // Disable quake in starting console lstrmerge(&pArgs->pszAddGuiArg, L"/noquake "); } else { break; } pszOk = pszArgs; } // Errors notification if (pszOk && *pszOk) { wchar_t* pszErr = lstrmerge(L"Unsupported task parameters\r\nTask name: ", pszName, L"\r\nParameters: ", pszOk); MsgBox(pszErr, MB_ICONSTOP); SafeFree(pszErr); } }
// Returns true, if application was found in registry: // [HKCU|HKLM]\Software\Microsoft\Windows\CurrentVersion\App Paths // Also, function may change local process %PATH% variable bool SearchAppPaths(LPCWSTR asFilePath, CmdArg& rsFound, bool abSetPath, CmdArg* rpsPathRestore /*= NULL*/) { if (rpsPathRestore) rpsPathRestore->Empty(); if (!asFilePath || !*asFilePath) return false; LPCWSTR pszSearchFile = PointToName(asFilePath); LPCWSTR pszExt = PointToExt(pszSearchFile); // Lets try find it in "App Paths" // "HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" // "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" LPCWSTR pszRoot = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\"; HKEY hk; LONG lRc; CmdArg lsName; lsName.Attach(lstrmerge(pszRoot, pszSearchFile, pszExt ? NULL : L".exe")); // Seems like 32-bit and 64-bit registry branches are the same now, but just in case - will check both DWORD nWOW[2] = {WIN3264TEST(KEY_WOW64_32KEY,KEY_WOW64_64KEY), WIN3264TEST(KEY_WOW64_64KEY,KEY_WOW64_32KEY)}; for (int i = 0; i < 3; i++) { bool bFound = false; DWORD nFlags = ((i && IsWindows64()) ? nWOW[i-1] : 0); if ((i == 2) && !nFlags) break; // This is 32-bit OS lRc = RegOpenKeyEx(i ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, lsName, 0, KEY_READ|nFlags, &hk); if (lRc != 0) continue; wchar_t szVal[MAX_PATH+1] = L""; DWORD nType, nSize = sizeof(szVal)-sizeof(szVal[0]); lRc = RegQueryValueEx(hk, NULL, NULL, &nType, (LPBYTE)szVal, &nSize); if (lRc == 0) { wchar_t *pszCheck = NULL; if (nType == REG_SZ) { pszCheck = szVal; } else if (nType == REG_EXPAND_SZ) { pszCheck = ExpandEnvStr(szVal); } // May be quoted if (pszCheck) { LPCWSTR pszPath = Unquote(pszCheck, true); if (FileExists(pszPath)) { // asFilePath will be invalid after .Set rsFound.Set(pszPath); bFound = true; if (pszCheck != szVal) free(pszCheck); // The program may require additional "%PATH%". So, if allowed... if (abSetPath) { nSize = 0; lRc = RegQueryValueEx(hk, L"PATH", NULL, &nType, NULL, &nSize); if (lRc == 0 && nSize) { wchar_t* pszCurPath = GetEnvVar(L"PATH"); wchar_t* pszAddPath = (wchar_t*)calloc(nSize+4,1); wchar_t* pszNewPath = NULL; if (pszAddPath) { lRc = RegQueryValueEx(hk, L"PATH", NULL, &nType, (LPBYTE)pszAddPath, &nSize); if (lRc == 0 && *pszAddPath) { // Если в "%PATH%" этого нет (в начале) - принудительно добавить int iCurLen = pszCurPath ? lstrlen(pszCurPath) : 0; int iAddLen = lstrlen(pszAddPath); bool bNeedAdd = true; if ((iCurLen >= iAddLen) && (pszCurPath[iAddLen] == L';' || pszCurPath[iAddLen] == 0)) { wchar_t ch = pszCurPath[iAddLen]; pszCurPath[iAddLen] = 0; if (lstrcmpi(pszCurPath, pszAddPath) == 0) bNeedAdd = false; pszCurPath[iAddLen] = ch; } // Если пути еще нет if (bNeedAdd) { if (rpsPathRestore) { rpsPathRestore->SavePathVar(pszCurPath); } pszNewPath = lstrmerge(pszAddPath, L";", pszCurPath); if (pszNewPath) { SetEnvironmentVariable(L"PATH", pszNewPath); } else { _ASSERTE(pszNewPath!=NULL && "Allocation failed?"); } } } } SafeFree(pszAddPath); SafeFree(pszCurPath); SafeFree(pszNewPath); } } } } } RegCloseKey(hk); if (bFound) return true; } return false; }
static INT_PTR CALLBACK CheckOptionsFastProc(HWND hDlg, UINT messg, WPARAM wParam, LPARAM lParam) { switch (messg) { case WM_SETHOTKEY: gnWndSetHotkey = wParam; break; case WM_INITDIALOG: { SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hClassIcon); SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hClassIconSm); if (gp_DpiAware) { gp_DpiAware->Attach(hDlg, NULL); } RECT rect = {}; if (GetWindowRect(hDlg, &rect)) { CDpiAware::GetCenteredRect(NULL, rect); MoveWindowRect(hDlg, rect); } LRESULT lbRc = FALSE; if (lParam) { SetWindowText(hDlg, (LPCWSTR)lParam); } else { wchar_t szTitle[512]; wcscpy_c(szTitle, gpConEmu->GetDefaultTitle()); wcscat_c(szTitle, L" fast configuration"); SetWindowText(hDlg, szTitle); } // lbStorageLocation SettingsStorage Storage = {}; bool ReadOnly = false; gpSet->GetSettingsType(Storage, ReadOnly); wchar_t* pszSettingsPlaces[] = { lstrdup(L"HKEY_CURRENT_USER\\Software\\ConEmu"), ExpandEnvStr(L"%APPDATA%\\ConEmu.xml"), ExpandEnvStr(L"%ConEmuBaseDir%\\ConEmu.xml"), ExpandEnvStr(L"%ConEmuDir%\\ConEmu.xml"), NULL }; int iAllowed = 0; if (lstrcmp(Storage.szType, CONEMU_CONFIGTYPE_XML) == 0) { iAllowed = 1; // Реестр уже низя if (Storage.pszFile) { if (lstrcmpi(Storage.pszFile, pszSettingsPlaces[1]) == 0) iAllowed = 1; // OK, перебить может любой другой xml else if (lstrcmpi(Storage.pszFile, pszSettingsPlaces[2]) == 0) iAllowed = 2; // "Перебить" может только %APPDATA% else if (lstrcmpi(Storage.pszFile, pszSettingsPlaces[3]) == 0) iAllowed = 3; // Приоритетнее настроек нет else { // Этот xml мог быть указан в "/LoadCfgFile ..." SafeFree(pszSettingsPlaces[3]); pszSettingsPlaces[3] = lstrdup(Storage.pszFile); iAllowed = 3; // Приоритетнее настроек нет } } } while (pszSettingsPlaces[iAllowed]) { SendDlgItemMessage(hDlg, lbStorageLocation, CB_ADDSTRING, 0, (LPARAM)pszSettingsPlaces[iAllowed]); iAllowed++; } SendDlgItemMessage(hDlg, lbStorageLocation, CB_SETCURSEL, 0, 0); for (int i = 0; pszSettingsPlaces[i]; i++) { SafeFree(pszSettingsPlaces[i]); } // continue CheckDlgButton(hDlg, cbSingleInstance, gpSetCls->IsSingleInstanceArg()); CheckDlgButton(hDlg, cbUseKeyboardHooksFast, gpSet->isKeyboardHooks(true)); // Debug purposes only. ConEmu.exe switch "/nokeyhooks" #ifdef _DEBUG EnableWindow(GetDlgItem(hDlg, cbUseKeyboardHooksFast), !gpConEmu->DisableKeybHooks); #endif CheckDlgButton(hDlg, cbInjectConEmuHkFast, gpSet->isUseInjects); if (!gpConEmu->isUpdateAllowed()) { EnableWindow(GetDlgItem(hDlg, cbEnableAutoUpdateFast), FALSE); EnableWindow(GetDlgItem(hDlg, rbAutoUpdateStableFast), FALSE); EnableWindow(GetDlgItem(hDlg, rbAutoUpdatePreviewFast), FALSE); EnableWindow(GetDlgItem(hDlg, rbAutoUpdateDeveloperFast), FALSE); EnableWindow(GetDlgItem(hDlg, stEnableAutoUpdateFast), FALSE); } else { if (gpSet->UpdSet.isUpdateUseBuilds != 0) CheckDlgButton(hDlg, cbEnableAutoUpdateFast, gpSet->UpdSet.isUpdateCheckOnStartup|gpSet->UpdSet.isUpdateCheckHourly); CheckRadioButton(hDlg, rbAutoUpdateStableFast, rbAutoUpdateDeveloperFast, (gpSet->UpdSet.isUpdateUseBuilds == 1) ? rbAutoUpdateStableFast : (gpSet->UpdSet.isUpdateUseBuilds == 3) ? rbAutoUpdatePreviewFast : rbAutoUpdateDeveloperFast); } if (!bCheckIme) { ShowWindow(GetDlgItem(hDlg, gbDisableConImeFast), SW_HIDE); ShowWindow(GetDlgItem(hDlg, cbDisableConImeFast), SW_HIDE); ShowWindow(GetDlgItem(hDlg, stDisableConImeFast1), SW_HIDE); ShowWindow(GetDlgItem(hDlg, stDisableConImeFast2), SW_HIDE); ShowWindow(GetDlgItem(hDlg, stDisableConImeFast3), SW_HIDE); RECT rcGroup, rcBtn, rcWnd; if (GetWindowRect(GetDlgItem(hDlg, gbDisableConImeFast), &rcGroup)) { int nShift = (rcGroup.bottom-rcGroup.top); HWND h = GetDlgItem(hDlg, IDOK); GetWindowRect(h, &rcBtn); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtn, 2); SetWindowPos(h, NULL, rcBtn.left, rcBtn.top - nShift, 0,0, SWP_NOSIZE|SWP_NOZORDER); h = GetDlgItem(hDlg, IDCANCEL); GetWindowRect(h, &rcBtn); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtn, 2); SetWindowPos(h, NULL, rcBtn.left, rcBtn.top - nShift, 0,0, SWP_NOSIZE|SWP_NOZORDER); h = GetDlgItem(hDlg, stHomePage); GetWindowRect(h, &rcBtn); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtn, 2); SetWindowPos(h, NULL, rcBtn.left, rcBtn.top - nShift, 0,0, SWP_NOSIZE|SWP_NOZORDER); GetWindowRect(hDlg, &rcWnd); MoveWindow(hDlg, rcWnd.left, rcWnd.top+(nShift>>1), rcWnd.right-rcWnd.left, rcWnd.bottom-rcWnd.top-nShift, FALSE); } } return lbRc; }
// Returns ">0" - when changes was made // 0 - no changes // -1 - error // bForceCurConsole==true, если разбор параметров идет // при запуске Tasks из GUI int RConStartArgs::ProcessNewConArg(bool bForceCurConsole /*= false*/) { bNewConsole = FALSE; if (!pszSpecialCmd || !*pszSpecialCmd) { _ASSERTE(pszSpecialCmd && *pszSpecialCmd); return -1; } int nChanges = 0; // 120115 - Если первый аргумент - "ConEmu.exe" или "ConEmu64.exe" - не обрабатывать "-cur_console" и "-new_console" { LPCWSTR pszTemp = pszSpecialCmd; CmdArg szExe; if (0 == NextArg(&pszTemp, szExe)) { pszTemp = PointToName(szExe); if (lstrcmpi(pszTemp, L"ConEmu.exe") == 0 || lstrcmpi(pszTemp, L"ConEmu") == 0 || lstrcmpi(pszTemp, L"ConEmu64.exe") == 0 || lstrcmpi(pszTemp, L"ConEmu64") == 0) { return 0; } } } // 111211 - здесь может быть передан "-new_console:..." LPCWSTR pszNewCon = L"-new_console"; // 120108 - или "-cur_console:..." для уточнения параметров запуска команд (из фара например) LPCWSTR pszCurCon = L"-cur_console"; int nNewConLen = lstrlen(pszNewCon); _ASSERTE(lstrlen(pszCurCon)==nNewConLen); bool bStop = false; wchar_t* pszFrom = pszSpecialCmd; while (!bStop) { wchar_t* pszFindNew = wcsstr(pszFrom, pszNewCon); wchar_t* pszFind = pszFindNew ? pszFindNew : wcsstr(pszFrom, pszCurCon); if (pszFindNew) bNewConsole = TRUE; else if (!pszFind) break; // Проверка валидности _ASSERTE(pszFind >= pszSpecialCmd); if (!(((pszFind == pszFrom) || (*(pszFind-1) == L'"') || (*(pszFind-1) == L' ')) // начало аргумента && (pszFind[nNewConLen] == L' ' || pszFind[nNewConLen] == L':' || pszFind[nNewConLen] == L'"' || pszFind[nNewConLen] == 0))) { // НЕ наш аргумент pszFrom = pszFind+nNewConLen; } else { // -- не будем пока, мешает. например, при запуске задач //// По умолчанию, принудительно включить "Press Enter or Esc to close console" //if (!bForceCurConsole) // eConfirmation = eConfAlways; bool lbQuot = (*(pszFind-1) == L'"'); const wchar_t* pszEnd = pszFind+nNewConLen; //wchar_t szNewConArg[MAX_PATH+1]; if (lbQuot) pszFind--; if (*pszEnd == L'"') { pszEnd++; } else if (*pszEnd != L':') { // Конец _ASSERTE(*pszEnd == L' ' || *pszEnd == 0); } else { if (*pszEnd == L':') { pszEnd++; } else { _ASSERTE(*pszEnd == L':'); } // Найти конец аргумента const wchar_t* pszArgEnd = pszEnd; while (*pszArgEnd) { switch (*pszArgEnd) { case L'^': pszArgEnd++; // Skip control char, goto escaped char break; case L'"': if (*(pszArgEnd+1) == L'"') pszArgEnd++; // Skip qoubled qouble quote else goto EndFound; break; case L' ': if (!lbQuot) goto EndFound; break; case 0: goto EndFound; } pszArgEnd++; } EndFound: // Обработка доп.параметров -new_console:xxx bool lbReady = false; while (!lbReady && *pszEnd) { wchar_t cOpt = *(pszEnd++); switch (cOpt) { //case L'-': // bStop = true; // следующие "-new_console" - не трогать! // break; case L'"': case L' ': case 0: lbReady = true; break; case L'b': // b - background, не активировать таб bBackgroundTab = TRUE; bForegroungTab = FALSE; break; case L'f': // f - foreground, активировать таб (аналог ">" в Tasks) bForegroungTab = TRUE; bBackgroundTab = FALSE; break; case L'z': // z - don't use "Default terminal" feature bNoDefaultTerm = TRUE; break; case L'a': // a - RunAs shell verb (as admin on Vista+, login/password in WinXP-) bRunAsAdministrator = TRUE; break; case L'r': // r - run as restricted user bRunAsRestricted = TRUE; break; case L'o': // o - disable "Long output" for next command (Far Manager) bLongOutputDisable = TRUE; break; case L'w': // e - enable "Overwrite" mode in console prompt bOverwriteMode = TRUE; break; case L'p': if (isDigit(*pszEnd)) { switch (*(pszEnd++)) { case L'0': nPTY = 0; // don't change break; case L'1': nPTY = 1; // enable PTY mode break; case L'2': nPTY = 2; // disable PTY mode (switch to plain $CONIN, $CONOUT, $CONERR) break; default: nPTY = 1; } } else { nPTY = 1; // enable PTY mode } break; case L'i': // i - don't inject ConEmuHk into the starting application bInjectsDisable = TRUE; break; case L'h': // "h0" - отключить буфер, "h9999" - включить буфер в 9999 строк { bBufHeight = TRUE; if (isDigit(*pszEnd)) { wchar_t* pszDigits = NULL; nBufHeight = wcstoul(pszEnd, &pszDigits, 10); if (pszDigits) pszEnd = pszDigits; } else { nBufHeight = 0; } } // L'h': break; case L'n': // n - отключить "Press Enter or Esc to close console" eConfirmation = eConfNever; break; case L'c': // c - принудительно включить "Press Enter or Esc to close console" eConfirmation = eConfAlways; break; case L'x': // x - Force using dosbox for .bat files bForceDosBox = TRUE; break; case L'I': // I - tell GuiMacro to execute new command inheriting active process state. This is only usage ATM. bForceInherit = TRUE; break; // "Long" code blocks below: 'd', 'u', 's' and so on (in future) case L's': // s[<SplitTab>T][<Percents>](H|V) // Пример: "s3T30H" - разбить 3-ий таб. будет создан новый Pane справа, шириной 30% от 3-го таба. { UINT nTab = 0 /*active*/, nValue = /*пополам*/DefaultSplitValue/10; bool bDisableSplit = false; while (*pszEnd) { if (isDigit(*pszEnd)) { wchar_t* pszDigits = NULL; UINT n = wcstoul(pszEnd, &pszDigits, 10); if (!pszDigits) break; pszEnd = pszDigits; if (*pszDigits == L'T') { nTab = n; } else if ((*pszDigits == L'H') || (*pszDigits == L'V')) { nValue = n; eSplit = (*pszDigits == L'H') ? eSplitHorz : eSplitVert; } else { break; } pszEnd++; } else if (*pszEnd == L'T') { nTab = 0; pszEnd++; } else if ((*pszEnd == L'H') || (*pszEnd == L'V')) { nValue = DefaultSplitValue/10; eSplit = (*pszEnd == L'H') ? eSplitHorz : eSplitVert; pszEnd++; } else if (*pszEnd == L'N') { bDisableSplit = true; pszEnd++; break; } else { break; } } if (bDisableSplit) { eSplit = eSplitNone; nSplitValue = DefaultSplitValue; nSplitPane = 0; } else { if (!eSplit) eSplit = eSplitHorz; // Для удобства, пользователь задает размер НОВОЙ части nSplitValue = 1000-max(1,min(nValue*10,999)); // проценты _ASSERTE(nSplitValue>=1 && nSplitValue<1000); nSplitPane = nTab; } } // L's' break; // Following options (except of single 'u') must be placed on the end of "-new_console:..." // If one needs more that one option - use several "-new_console:..." switches case L'd': // d:<StartupDir>. MUST be last option case L't': // t:<TabName>. MUST be last option case L'u': // u - ConEmu choose user dialog (may be specified in the middle, if it is without ':' - user or pwd) // u:<user> - ConEmu choose user dialog with prefilled user field. MUST be last option // u:<user>:<pwd> - specify user/pwd in args. MUST be last option case L'C': // C:<IconFile>. MUST be last option case L'P': // P:<Palette>. MUST be last option case L'W': // W:<Wallpaper>. MUST be last option { if (cOpt == L'u') { // Show choose user dialog (may be specified in the middle, if it is without ':' - user or pwd) SafeFree(pszUserName); SafeFree(pszDomain); if (szUserPassword[0]) SecureZeroMemory(szUserPassword, sizeof(szUserPassword)); } if (*pszEnd == L':') { pszEnd++; } else { if (cOpt == L'u') { bForceUserDialog = TRUE; break; } } const wchar_t* pszTab = pszEnd; // we need to find end of argument pszEnd = pszArgEnd; // temp buffer wchar_t* lpszTemp = NULL; if (pszEnd > pszTab) { wchar_t** pptr = NULL; switch (cOpt) { case L'd': pptr = &pszStartupDir; break; case L't': pptr = &pszRenameTab; break; case L'u': pptr = &lpszTemp; break; case L'C': pptr = &pszIconFile; break; case L'P': pptr = &pszPalette; break; case L'W': pptr = &pszWallpaper; break; } size_t cchLen = pszEnd - pszTab; SafeFree(*pptr); *pptr = (wchar_t*)malloc((cchLen+1)*sizeof(**pptr)); if (*pptr) { // We need to process escape sequences ("^>" -> ">", "^&" -> "&", etc.) //wmemmove(*pptr, pszTab, cchLen); wchar_t* pD = *pptr; const wchar_t* pS = pszTab; // There is enough room allocated while (pS < pszEnd) { if ((*pS == L'^') && ((pS + 1) < pszEnd)) pS++; // Skip control char, goto escaped char else if ((*pS == L'"') && ((pS + 1) < pszEnd) && (*(pS+1) == L'"')) pS++; // Skip qoubled qouble quote *(pD++) = *(pS++); } // Terminate with '\0' _ASSERTE(pD <= ((*pptr)+cchLen)); *pD = 0; } // Additional processing switch (cOpt) { case L'd': // Например, "%USERPROFILE%" // TODO("А надо ли разворачивать их тут? Наверное при запуске под другим юзером некорректно? Хотя... все равно до переменных не доберемся"); if (wcschr(pszStartupDir, L'%')) { wchar_t* pszExpand = NULL; if (((pszExpand = ExpandEnvStr(pszStartupDir)) != NULL)) { SafeFree(pszStartupDir); pszStartupDir = pszExpand; } } break; case L'u': if (lpszTemp) { // Split in form: // [Domain\]UserName[:Password] wchar_t* pszPwd = wcschr(lpszTemp, L':'); if (pszPwd) { // Password was specified, dialog prompt is not required bForceUserDialog = FALSE; *pszPwd = 0; int nPwdLen = lstrlen(pszPwd+1); lstrcpyn(szUserPassword, pszPwd+1, countof(szUserPassword)); if (nPwdLen > 0) SecureZeroMemory(pszPwd+1, nPwdLen); bUseEmptyPassword = (nPwdLen == 0); } else { // Password was NOT specified, dialog prompt IS required bForceUserDialog = TRUE; bUseEmptyPassword = FALSE; } wchar_t* pszSlash = wcschr(lpszTemp, L'\\'); if (pszSlash) { *pszSlash = 0; pszDomain = lstrdup(lpszTemp); pszUserName = lstrdup(pszSlash+1); } else { pszUserName = lstrdup(lpszTemp); } } break; } } SafeFree(lpszTemp); } // L't': break; } } } if (pszEnd > pszFind) { // pszEnd должен указывать на конец -new_console[:...] / -cur_console[:...] // и включать обрамляющую кавычку, если он окавычен if (lbQuot) { if (*pszEnd == L'"' && *(pszEnd-1) != L'"') pszEnd++; } else { while (*(pszEnd-1) == L'"') pszEnd--; } // Откусить лишние пробелы, которые стоят ПЕРЕД -new_console[:...] / -cur_console[:...] while (((pszFind - 1) > pszSpecialCmd) && (*(pszFind-1) == L' ') && ((*(pszFind-2) == L' ') || (/**pszEnd == L'"' ||*/ *pszEnd == 0 || *pszEnd == L' '))) { pszFind--; } wmemmove(pszFind, pszEnd, (lstrlen(pszEnd)+1)); nChanges++; } else { _ASSERTE(pszEnd > pszFind); *pszFind = 0; nChanges++; } } // if ((((pszFind == pszFrom) ... } // while (!bStop) return nChanges; } // int RConStartArgs::ProcessNewConArg(bool bForceCurConsole /*= false*/)
//------------------------------------------------------------------------ ///| 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; }
// Returns ">0" - when changes was made // 0 - no changes // -1 - error // bForceCurConsole==true, если разбор параметров идет // при запуске Tasks из GUI int RConStartArgs::ProcessNewConArg(bool bForceCurConsole /*= false*/) { bNewConsole = FALSE; if (!pszSpecialCmd || !*pszSpecialCmd) { _ASSERTE(pszSpecialCmd && *pszSpecialCmd); return -1; } int nChanges = 0; // 120115 - Если первый аргумент - "ConEmu.exe" или "ConEmu64.exe" - не обрабатывать "-cur_console" и "-new_console" { LPCWSTR pszTemp = pszSpecialCmd; wchar_t szExe[MAX_PATH+1]; if (0 == NextArg(&pszTemp, szExe)) { pszTemp = PointToName(szExe); if (lstrcmpi(pszTemp, L"ConEmu.exe") == 0 || lstrcmpi(pszTemp, L"ConEmu") == 0 || lstrcmpi(pszTemp, L"ConEmu64.exe") == 0 || lstrcmpi(pszTemp, L"ConEmu64") == 0) { return 0; } } } // 111211 - здесь может быть передан "-new_console:..." LPCWSTR pszNewCon = L"-new_console"; // 120108 - или "-cur_console:..." для уточнения параметров запуска команд (из фара например) LPCWSTR pszCurCon = L"-cur_console"; int nNewConLen = lstrlen(pszNewCon); _ASSERTE(lstrlen(pszCurCon)==nNewConLen); bool bStop = false; while (!bStop) { wchar_t* pszFindNew = wcsstr(pszSpecialCmd, pszNewCon); wchar_t* pszFind = pszFindNew ? pszFindNew : wcsstr(pszSpecialCmd, pszCurCon); if (pszFindNew) bNewConsole = TRUE; else if (!pszFind) break; // Проверка валидности _ASSERTE(pszFind >= pszSpecialCmd); if (((pszFind == pszSpecialCmd) || (*(pszFind-1) == L'"') || (*(pszFind-1) == L' ')) // начало аргумента && (pszFind[nNewConLen] == L' ' || pszFind[nNewConLen] == L':' || pszFind[nNewConLen] == L'"' || pszFind[nNewConLen] == 0)) { // -- не будем пока, мешает. например, при запуске задач //// По умолчанию, принудительно включить "Press Enter or Esc to close console" //if (!bForceCurConsole) // eConfirmation = eConfAlways; bool lbQuot = (*(pszFind-1) == L'"'); const wchar_t* pszEnd = pszFind+nNewConLen; //wchar_t szNewConArg[MAX_PATH+1]; if (lbQuot) pszFind--; if (*pszEnd == L'"') { pszEnd++; } else if (*pszEnd != L':') { // Конец _ASSERTE(*pszEnd == L' ' || *pszEnd == 0); } else { if (*pszEnd == L':') { pszEnd++; } else { _ASSERTE(*pszEnd == L':'); } // Обработка доп.параметров -new_console:xxx bool lbReady = false; while (!lbReady && *pszEnd) { switch (*(pszEnd++)) { //case L'-': // bStop = true; // следующие "-new_console" - не трогать! // break; case L'"': case L' ': case 0: lbReady = true; break; case L'b': // b - background, не активировать таб bBackgroundTab = TRUE; break; case L'z': // z - don't use "Default terminal" feature bNoDefaultTerm = TRUE; break; case L'a': // a - RunAs shell verb (as admin on Vista+, login/password in WinXP-) bRunAsAdministrator = TRUE; break; case L'r': // r - run as restricted user bRunAsRestricted = TRUE; break; case L'o': // o - disable "Long output" for next command (Far Manager) bLongOutputDisable = TRUE; break; case L'w': // e - enable "Overwrite" mode in console prompt bOverwriteMode = TRUE; break; case L'p': if (isDigit(*pszEnd)) { switch (*(pszEnd++)) { case L'0': nPTY = 0; // don't change break; case L'1': nPTY = 1; // enable PTY mode break; case L'2': nPTY = 2; // disable PTY mode (switch to plain $CONIN, $CONOUT, $CONERR) break; default: nPTY = 1; } } else { nPTY = 1; // enable PTY mode } break; case L'i': // i - don't inject ConEmuHk into the starting application bInjectsDisable = TRUE; break; case L'h': // "h0" - отключить буфер, "h9999" - включить буфер в 9999 строк { bBufHeight = TRUE; if (isDigit(*pszEnd)) { wchar_t* pszDigits = NULL; nBufHeight = wcstoul(pszEnd, &pszDigits, 10); if (pszDigits) pszEnd = pszDigits; } else { nBufHeight = 0; } } // L'h': break; case L'n': // n - отключить "Press Enter or Esc to close console" eConfirmation = eConfNever; break; case L'c': // c - принудительно включить "Press Enter or Esc to close console" eConfirmation = eConfAlways; break; case L'x': // x - Force using dosbox for .bat files bForceDosBox = TRUE; break; // "Long" code blocks below: 'd', 'u', 's' and so on (in future) case L'd': // d:<StartupDir>. MUST be last options { if (*pszEnd == L':') pszEnd++; const wchar_t* pszDir = pszEnd; while ((*pszEnd) && (lbQuot || *pszEnd != L' ') && (*pszEnd != L'"')) pszEnd++; if (pszEnd > pszDir) { size_t cchLen = pszEnd - pszDir; SafeFree(pszStartupDir); pszStartupDir = (wchar_t*)malloc((cchLen+1)*sizeof(*pszStartupDir)); if (pszStartupDir) { wmemmove(pszStartupDir, pszDir, cchLen); pszStartupDir[cchLen] = 0; // Например, "%USERPROFILE%" if (wcschr(pszStartupDir, L'%')) { wchar_t* pszExpand = NULL; if (((pszExpand = ExpandEnvStr(pszStartupDir)) != NULL)) { SafeFree(pszStartupDir); pszStartupDir = pszExpand; } } } } } // L'd': break; case L't': // t:<TabName>. MUST be last options { if (*pszEnd == L':') pszEnd++; const wchar_t* pszTab = pszEnd; while ((*pszEnd) && (lbQuot || *pszEnd != L' ') && (*pszEnd != L'"')) pszEnd++; if (pszEnd > pszTab) { size_t cchLen = pszEnd - pszTab; SafeFree(pszRenameTab); pszRenameTab = (wchar_t*)malloc((cchLen+1)*sizeof(*pszRenameTab)); if (pszRenameTab) { wmemmove(pszRenameTab, pszTab, cchLen); pszRenameTab[cchLen] = 0; } } } // L't': break; case L's': // s[<SplitTab>T][<Percents>](H|V) // Пример: "s3T30H" - разбить 3-ий таб. будет создан новый Pane справа, шириной 30% от 3-го таба. { UINT nTab = 0 /*active*/, nValue = /*пополам*/DefaultSplitValue/10; bool bDisableSplit = false; while (*pszEnd) { if (isDigit(*pszEnd)) { wchar_t* pszDigits = NULL; UINT n = wcstoul(pszEnd, &pszDigits, 10); if (!pszDigits) break; pszEnd = pszDigits; if (*pszDigits == L'T') { nTab = n; } else if ((*pszDigits == L'H') || (*pszDigits == L'V')) { nValue = n; eSplit = (*pszDigits == L'H') ? eSplitHorz : eSplitVert; } else { break; } pszEnd++; } else if (*pszEnd == L'T') { nTab = 0; pszEnd++; } else if ((*pszEnd == L'H') || (*pszEnd == L'V')) { nValue = DefaultSplitValue/10; eSplit = (*pszEnd == L'H') ? eSplitHorz : eSplitVert; pszEnd++; } else if (*pszEnd == L'N') { bDisableSplit = true; pszEnd++; break; } else { break; } } if (bDisableSplit) { eSplit = eSplitNone; nSplitValue = DefaultSplitValue; nSplitPane = 0; } else { if (!eSplit) eSplit = eSplitHorz; // Для удобства, пользователь задает размер НОВОЙ части nSplitValue = 1000-max(1,min(nValue*10,999)); // проценты _ASSERTE(nSplitValue>=1 && nSplitValue<1000); nSplitPane = nTab; } } // L's' break; case L'u': { // u - ConEmu choose user dialog // u:<user>:<pwd> - specify user/pwd in args. MUST be last option lbReady = true; // последняя опция SafeFree(pszUserName); SafeFree(pszDomain); if (szUserPassword[0]) SecureZeroMemory(szUserPassword, sizeof(szUserPassword)); if (*pszEnd == L':') { pszEnd++; wchar_t szUser[MAX_PATH], *p = szUser, *p2 = szUser+countof(szUser)-1; while (*pszEnd && (p < p2)) { if ((*pszEnd == 0) || (*pszEnd == L':') || (*pszEnd == L'"')) { break; } //else if (*pszEnd == L'"' && *(pszEnd+1) == L'"') //{ // *(p++) = L'"'; pszEnd += 2; //} else if (*pszEnd == L'^') { pszEnd++; *(p++) = *(pszEnd++); } else { *(p++) = *(pszEnd++); } } *p = 0; wchar_t* pszSlash = wcschr(szUser, L'\\'); if (pszSlash) { *pszSlash = 0; pszDomain = lstrdup(szUser); pszUserName = lstrdup(pszSlash+1); } else { pszUserName = lstrdup(szUser); } if (*pszEnd == L':') { pszEnd++; //lstrcpyn(szUserPassword, pszPwd, countof(szUserPassword)); p = szUserPassword; p2 = szUserPassword+countof(szUserPassword)-1; while (*pszEnd && (p < p2)) { if ((*pszEnd == 0) || (*pszEnd == L':') || (*pszEnd == L'"')) { break; } else if (*pszEnd == L'^') { pszEnd++; *(p++) = *(pszEnd++); } else { *(p++) = *(pszEnd++); } } *p = 0; } } else { bForceUserDialog = TRUE; } } // L'u' break; } } } if (pszEnd > pszFind) { // pszEnd должен указывать на конец -new_console[:...] / -cur_console[:...] // и включать обрамляющую кавычку, если он окавычен if (lbQuot) { if (*pszEnd == L'"' && *(pszEnd-1) != L'"') pszEnd++; } else { while (*(pszEnd-1) == L'"') pszEnd--; } // Откусить лишние пробелы, которые стоят ПЕРЕД -new_console[:...] / -cur_console[:...] while (((pszFind - 1) > pszSpecialCmd) && (*(pszFind-1) == L' ') && ((*(pszFind-2) == L' ') || (/**pszEnd == L'"' ||*/ *pszEnd == 0 || *pszEnd == L' '))) { pszFind--; } wmemmove(pszFind, pszEnd, (lstrlen(pszEnd)+1)); nChanges++; } else { _ASSERTE(pszEnd > pszFind); *pszFind = 0; nChanges++; } } } return nChanges; }
bool CBackgroundInfo::LoadBackgroundFile(bool abShowErrors) { // Пустой путь - значит БЕЗ обоев if (!*ms_BgImage) { return true; } //_ASSERTE(isMainThread()); _ASSERTE(isMainThread()); bool lRes = false; BY_HANDLE_FILE_INFORMATION inf = {0}; BITMAPFILEHEADER* pBkImgData = NULL; if (wcspbrk(ms_BgImage, L"%\\.") == NULL) { // May be "Solid color" COLORREF clr = (COLORREF)-1; if (GetColorRef(ms_BgImage, &clr)) { pBkImgData = CreateSolidImage(clr, 128, 128); } } if (!pBkImgData) { wchar_t* exPath = ExpandEnvStr(ms_BgImage); if (!exPath || !*exPath) { if (abShowErrors) { wchar_t szError[MAX_PATH*2]; DWORD dwErr = GetLastError(); _wsprintf(szError, SKIPLEN(countof(szError)) L"Can't expand environment strings:\r\n%s\r\nError code=0x%08X\r\nImage loading failed", ms_BgImage, dwErr); MBoxA(szError); } SafeFree(exPath); return false; } pBkImgData = LoadImageEx(exPath, inf); SafeFree(exPath); } if (pBkImgData) { ftBgModified = inf.ftLastWriteTime; nBgModifiedTick = GetTickCount(); //NeedBackgroundUpdate(); //MSectionLock SBG; SBG.Lock(&mcs_BgImgData); SafeFree(mp_BgImgData); mb_IsBackgroundImageValid = true; mp_BgImgData = pBkImgData; lRes = true; } return lRes; }
// 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; }
INT_PTR CRecreateDlg::OnButtonClicked(HWND hDlg, UINT messg, WPARAM wParam, LPARAM lParam) { switch (LOWORD(wParam)) { case IDC_CHOOSE: { wchar_t *pszFilePath = SelectFile(L"Choose program to run", NULL, NULL, hDlg, L"Executables (*.exe)\0*.exe\0All files (*.*)\0*.*\0\0", sff_AutoQuote); if (pszFilePath) { SetDlgItemText(hDlg, IDC_RESTART_CMD, pszFilePath); SafeFree(pszFilePath); } return TRUE; } // case IDC_CHOOSE: case IDC_CHOOSE_DIR: { wchar_t* pszDefFolder = GetDlgItemTextPtr(hDlg, IDC_STARTUP_DIR); wchar_t* pszFolder = SelectFolder(L"Choose startup directory", pszDefFolder, hDlg, sff_Default); if (pszFolder) { SetDlgItemText(hDlg, IDC_STARTUP_DIR, pszFolder); SafeFree(pszFolder); } SafeFree(pszDefFolder); return TRUE; } // case IDC_CHOOSE_DIR: case cbRunAsAdmin: { // BCM_SETSHIELD = 5644 BOOL bRunAs = SendDlgItemMessage(hDlg, cbRunAsAdmin, BM_GETCHECK, 0, 0); if (gOSVer.dwMajorVersion >= 6) { SendDlgItemMessage(hDlg, IDC_START, 5644/*BCM_SETSHIELD*/, 0, bRunAs && (mp_Args->aRecreate != cra_EditTab)); } if (bRunAs) { CheckRadioButton(hDlg, rbCurrentUser, rbAnotherUser, rbCurrentUser); CheckDlgButton(hDlg, cbRunAsRestricted, BST_UNCHECKED); RecreateDlgProc(hDlg, UM_USER_CONTROLS, 0, 0); } return TRUE; } // case cbRunAsAdmin: case rbCurrentUser: case rbAnotherUser: case cbRunAsRestricted: { RecreateDlgProc(hDlg, UM_USER_CONTROLS, LOWORD(wParam), 0); return TRUE; } case rbRecreateSplitNone: case rbRecreateSplit2Right: case rbRecreateSplit2Bottom: { RConStartArgs* pArgs = mp_Args; switch (LOWORD(wParam)) { case rbRecreateSplitNone: pArgs->eSplit = RConStartArgs::eSplitNone; break; case rbRecreateSplit2Right: pArgs->eSplit = RConStartArgs::eSplitHorz; break; case rbRecreateSplit2Bottom: pArgs->eSplit = RConStartArgs::eSplitVert; break; } EnableWindow(GetDlgItem(hDlg, tRecreateSplit), (pArgs->eSplit != pArgs->eSplitNone)); EnableWindow(GetDlgItem(hDlg, stRecreateSplit), (pArgs->eSplit != pArgs->eSplitNone)); if (pArgs->eSplit != pArgs->eSplitNone) SetFocus(GetDlgItem(hDlg, tRecreateSplit)); return TRUE; } // case rbRecreateSplitXXX case IDC_START: { RConStartArgs* pArgs = mp_Args; _ASSERTE(pArgs); SafeFree(pArgs->pszUserName); SafeFree(pArgs->pszDomain); //SafeFree(pArgs->pszUserPassword); if (SendDlgItemMessage(hDlg, rbAnotherUser, BM_GETCHECK, 0, 0)) { pArgs->RunAsRestricted = crb_Off; pArgs->pszUserName = GetDlgItemTextPtr(hDlg, tRunAsUser); if (pArgs->pszUserName) { //pArgs->pszUserPassword = GetDlgItemText(hDlg, tRunAsPassword); // Попытаться проверить правильность введенного пароля и возможность запуска bool bCheckPwd = pArgs->CheckUserToken(GetDlgItem(hDlg, tRunAsPassword)); DWORD nErr = bCheckPwd ? 0 : GetLastError(); if (!bCheckPwd) { DisplayLastError(L"Invalid user name or password was specified!", nErr, MB_ICONSTOP, NULL, hDlg); return 1; } } } else { pArgs->RunAsRestricted = SendDlgItemMessage(hDlg, cbRunAsRestricted, BM_GETCHECK, 0, 0) ? crb_On : crb_Off; } // Vista+ (As Admin...) pArgs->RunAsAdministrator = SendDlgItemMessage(hDlg, cbRunAsAdmin, BM_GETCHECK, 0, 0) ? crb_On : crb_Off; // StartupDir (may be specified as argument) wchar_t* pszDir = GetDlgItemTextPtr(hDlg, IDC_STARTUP_DIR); wchar_t* pszExpand = (pszDir && wcschr(pszDir, L'%')) ? ExpandEnvStr(pszDir) : NULL; LPCWSTR pszDirResult = pszExpand ? pszExpand : pszDir; // Another user? We may fail with access denied. Check only for "current user" account if (!pArgs->pszUserName && pszDirResult && *pszDirResult && !DirectoryExists(pszDirResult)) { wchar_t* pszErrInfo = lstrmerge(L"Specified directory does not exists!\n", pszDirResult, L"\n" L"Do you want to choose another directory?\n\n"); DWORD nErr = GetLastError(); int iDirBtn = DisplayLastError(pszErrInfo, nErr, MB_ICONEXCLAMATION|MB_YESNO, NULL, hDlg); if (iDirBtn == IDYES) { SafeFree(pszDir); SafeFree(pszExpand); SafeFree(pszErrInfo); return 1; } // User want to run "as is". Most likely it will fail, but who knows... } SafeFree(pArgs->pszStartupDir); pArgs->pszStartupDir = pszExpand ? pszExpand : pszDir; if (pszExpand) { SafeFree(pszDir) } // Command // pszSpecialCmd мог быть передан аргументом - умолчание для строки ввода SafeFree(pArgs->pszSpecialCmd); // GetDlgItemText выделяет память через calloc pArgs->pszSpecialCmd = GetDlgItemTextPtr(hDlg, IDC_RESTART_CMD); if (pArgs->pszSpecialCmd) gpSet->HistoryAdd(pArgs->pszSpecialCmd); if ((pArgs->aRecreate != cra_RecreateTab) && (pArgs->aRecreate != cra_EditTab)) { if (SendDlgItemMessage(hDlg, cbRunInNewWindow, BM_GETCHECK, 0, 0)) pArgs->aRecreate = cra_CreateWindow; else pArgs->aRecreate = cra_CreateTab; } if (((pArgs->aRecreate == cra_CreateTab) || (pArgs->aRecreate == cra_EditTab)) && (pArgs->eSplit != RConStartArgs::eSplitNone)) { BOOL bOk = FALSE; int nPercent = GetDlgItemInt(hDlg, tRecreateSplit, &bOk, FALSE); if (bOk && (nPercent >= 1) && (nPercent <= 99)) { pArgs->nSplitValue = (100-nPercent) * 10; } //pArgs->nSplitPane = 0; Сбрасывать не будем? } mn_DlgRc = IDC_START; EndDialog(hDlg, IDC_START); return TRUE; } // case IDC_START: case IDC_TERMINATE: mn_DlgRc = IDC_TERMINATE; EndDialog(hDlg, IDC_TERMINATE); return TRUE; case IDCANCEL: mn_DlgRc = IDCANCEL; EndDialog(hDlg, IDCANCEL); return TRUE; } return FALSE; }
wchar_t* CreateCommand(LPCWSTR asSource, LPCWSTR asTarget, UINT& iRc) { wchar_t* pszCommand = NULL; if (!szCmdStringFormat || !*szCmdStringFormat) { wchar_t szConEmuC[MAX_PATH] = L"", *psz; wchar_t szOTimeout[20] = L"", szTimeout[20] = L""; if (mb_OTimeout) _wsprintf(szOTimeout, SKIPCOUNT(szOTimeout) L"%u", mn_OTimeout); if (mb_Timeout) _wsprintf(szTimeout, SKIPCOUNT(szTimeout) L"%u", mn_Timeout); struct _Switches { LPCWSTR pszName, pszValue; } Switches[] = { {L"-login", m_Server.szUser}, {L"-password", m_Server.szPassword}, {L"-proxy", m_Proxy.szProxy}, {L"-proxylogin", m_Proxy.szProxyUser}, {L"-proxypassword", m_Proxy.szProxyPassword}, {L"-async", mb_AsyncMode ? L"Y" : L"N"}, {L"-otimeout", szOTimeout}, {L"-timeout", szTimeout}, }; if (!asSource || !*asSource || !asTarget || !*asTarget) { iRc = E_INVALIDARG; goto wrap; } if (!GetModuleFileName(ghOurModule, szConEmuC, countof(szConEmuC)) || !(psz = wcsrchr(szConEmuC, L'\\'))) { //ReportMessage(dc_LogCallback, L"GetModuleFileName(ghOurModule) failed, code=%u", at_Uint, GetLastError(), at_None); iRc = E_HANDLE; goto wrap; } psz[1] = 0; wcscat_c(szConEmuC, WIN3264TEST(L"ConEmuC.exe",L"ConEmuC64.exe")); /* ConEmuC /download [-login <name> -password <pwd>] [-proxy <address:port> [-proxylogin <name> -proxypassword <pwd>]] [-async Y|N] [-otimeout <ms>] [-timeout <ms>] "full_url_to_file" "local_path_name" */ if (!(pszCommand = lstrmerge(L"\"", szConEmuC, L"\" -download "))) { iRc = E_OUTOFMEMORY; goto wrap; } for (INT_PTR i = 0; i < countof(Switches); i++) { LPCWSTR pszValue = Switches[i].pszValue; if (pszValue && *pszValue && !lstrmerge(&pszCommand, Switches[i].pszName, L" \"", pszValue, L"\" ")) { iRc = E_OUTOFMEMORY; goto wrap; } } if (!lstrmerge(&pszCommand, asSource, L" \"", asTarget, L"\"")) { iRc = E_OUTOFMEMORY; goto wrap; } } else { // Environment string? Expand it wchar_t* pszExp = ExpandEnvStr(szCmdStringFormat); // "curl -L %1 -o %2" // "wget %1 -O %2" LPCWSTR Values[] = {asSource, asTarget}; pszCommand = ExpandMacroValues((pszExp && *pszExp) ? pszExp : szCmdStringFormat, Values, countof(Values)); SafeFree(pszExp); if (!pszCommand) { iRc = E_OUTOFMEMORY; goto wrap; } } wrap: return pszCommand; }
//------------------------------------------------------------------------ ///| 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) }
INT_PTR CRecreateDlg::RecreateDlgProc(HWND hDlg, UINT messg, WPARAM wParam, LPARAM lParam) { #define UM_USER_CONTROLS (WM_USER+121) #define UM_FILL_CMDLIST (WM_USER+122) CRecreateDlg* pDlg = NULL; if (messg == WM_INITDIALOG) { pDlg = (CRecreateDlg*)lParam; pDlg->mh_Dlg = hDlg; SetWindowLongPtr(hDlg, DWLP_USER, lParam); } else { pDlg = (CRecreateDlg*)GetWindowLongPtr(hDlg, DWLP_USER); } if (!pDlg) { return FALSE; } switch (messg) { case WM_INITDIALOG: { LRESULT lbRc = FALSE; SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hClassIcon); SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hClassIconSm); HMENU hSysMenu = GetSystemMenu(hDlg, FALSE); InsertMenu(hSysMenu, 0, MF_BYPOSITION, MF_SEPARATOR, 0); InsertMenu(hSysMenu, 0, MF_BYPOSITION | MF_STRING | MF_ENABLED | ((GetWindowLong(ghOpWnd,GWL_EXSTYLE)&WS_EX_TOPMOST) ? MF_CHECKED : 0), ID_RESETCMDHISTORY, _T("Reset command history...")); SendDlgItemMessage(hDlg, tRunAsPassword, WM_SETFONT, (LPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), 0); //#ifdef _DEBUG //SetWindowPos(ghOpWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE); //#endif SendMessage(hDlg, UM_FILL_CMDLIST, TRUE, 0); RConStartArgs* pArgs = pDlg->mp_Args; _ASSERTE(pArgs); LPCWSTR pszCmd = pArgs->pszSpecialCmd ? pArgs->pszSpecialCmd : gpConEmu->ActiveCon()->RCon()->GetCmd(); //int nId = SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_FINDSTRINGEXACT, -1, (LPARAM)pszCmd); //if (nId < 0) SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_INSERTSTRING, 0, (LPARAM)pszCmd); LPCWSTR pszSystem = gpSet->GetCmd(); //if (pszSystem != pszCmd && (pszSystem && pszCmd && (lstrcmpi(pszSystem, pszCmd) != 0))) //{ // nId = SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_FINDSTRINGEXACT, -1, (LPARAM)pszSystem); // if (nId < 0) SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_INSERTSTRING, pArgs->pszSpecialCmd ? -1 : 0, (LPARAM)pszSystem); //} //LPCWSTR pszHistory = gpSet->HistoryGet(); //if (pszHistory) //{ // while (*pszHistory) // { // nId = SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_FINDSTRINGEXACT, -1, (LPARAM)pszHistory); // if (nId < 0) // SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_INSERTSTRING, -1, (LPARAM)pszHistory); // pszHistory += _tcslen(pszHistory)+1; // } //} ////// Обновить группы команд ////gpSet->LoadCmdTasks(NULL); //int nGroup = 0; //const Settings::CommandTasks* pGrp = NULL; //while ((pGrp = gpSet->CmdTaskGet(nGroup++))) //{ // nId = SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_FINDSTRINGEXACT, -1, (LPARAM)pGrp->pszName); // if (nId < 0) // SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_INSERTSTRING, -1, (LPARAM)pGrp->pszName); //} if (pArgs->aRecreate == cra_RecreateTab) { SetDlgItemText(hDlg, IDC_RESTART_CMD, pszCmd); SetDlgItemText(hDlg, IDC_STARTUP_DIR, gpConEmu->ActiveCon()->RCon()->GetDir()); } else { SetDlgItemText(hDlg, IDC_RESTART_CMD, pArgs->pszSpecialCmd ? pArgs->pszSpecialCmd : pszSystem); SetDlgItemText(hDlg, IDC_STARTUP_DIR, pArgs->pszStartupDir ? pArgs->pszStartupDir : L""); } //EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_DIR), FALSE); //#ifndef _DEBUG //EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_DIR), FALSE); //#endif const wchar_t *pszUser, *pszDomain; BOOL bResticted; int nChecked = rbCurrentUser; wchar_t szCurUser[MAX_PATH*2+1]; DWORD nUserNameLen = countof(szCurUser); if (!GetUserName(szCurUser, &nUserNameLen)) szCurUser[0] = 0; wchar_t szRbCaption[MAX_PATH*3]; lstrcpy(szRbCaption, L"Run as current &user: "******"UPN format" остается в pszUser lstrcpyn(szCurUser, pszUser, MAX_PATH); wcscat_c(szCurUser, L"@"); lstrcpyn(szCurUser+_tcslen(szCurUser), pszDomain, MAX_PATH); } else { // "Старая" нотация domain\user lstrcpyn(szCurUser, pszDomain, MAX_PATH); wcscat_c(szCurUser, L"\\"); lstrcpyn(szCurUser+_tcslen(szCurUser), pszUser, MAX_PATH); } } else { lstrcpyn(szCurUser, pszUser, countof(szCurUser)); } SetDlgItemText(hDlg, tRunAsPassword, L""); } } SetDlgItemText(hDlg, tRunAsUser, szCurUser); CheckRadioButton(hDlg, rbCurrentUser, rbAnotherUser, nChecked); RecreateDlgProc(hDlg, UM_USER_CONTROLS, 0, 0); if (gOSVer.dwMajorVersion < 6) { // В XP и ниже это просто RunAs - с возможностью ввода имени пользователя и пароля //apiShowWindow(GetDlgItem(hDlg, cbRunAsAdmin), SW_HIDE); SetDlgItemTextA(hDlg, cbRunAsAdmin, "&Run as..."); //GCC hack. иначе не собирается // И уменьшить длину RECT rcBox; GetWindowRect(GetDlgItem(hDlg, cbRunAsAdmin), &rcBox); SetWindowPos(GetDlgItem(hDlg, cbRunAsAdmin), NULL, 0, 0, (rcBox.right-rcBox.left)/2, rcBox.bottom-rcBox.top, SWP_NOMOVE|SWP_NOZORDER); } else if (gpConEmu->mb_IsUacAdmin || (pArgs && pArgs->bRunAsAdministrator)) { CheckDlgButton(hDlg, cbRunAsAdmin, BST_CHECKED); if (gpConEmu->mb_IsUacAdmin) // Только в Vista+ если GUI уже запущен под админом { EnableWindow(GetDlgItem(hDlg, cbRunAsAdmin), FALSE); } else if (gOSVer.dwMajorVersion < 6) { RecreateDlgProc(hDlg, WM_COMMAND, cbRunAsAdmin, 0); } } //} SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR)hClassIcon); RECT rcBtnBox = {0}; if (pArgs->aRecreate == cra_RecreateTab) { //GCC hack. иначе не собирается SetDlgItemTextA(hDlg, IDC_RESTART_MSG, "About to recreate console"); SendDlgItemMessage(hDlg, IDC_RESTART_ICON, STM_SETICON, (WPARAM)LoadIcon(NULL,IDI_EXCLAMATION), 0); // Выровнять флажок по кнопке GetWindowRect(GetDlgItem(hDlg, IDC_START), &rcBtnBox); // Спрятать флажок "New window" ShowWindow(GetDlgItem(hDlg, cbRunInNewWindow), SW_HIDE); lbRc = TRUE; } else { //GCC hack. иначе не собирается SetDlgItemTextA(hDlg, IDC_RESTART_MSG, "Create new console"); CheckDlgButton(hDlg, cbRunInNewWindow, (pArgs->aRecreate == cra_CreateWindow) ? BST_CHECKED : BST_UNCHECKED); //if (pArgs->aRecreate == cra_CreateWindow) //{ // SetWindowText(hDlg, L"ConEmu - Create new window"); // //GCC hack. иначе не собирается // SetDlgItemTextA(hDlg, IDC_RESTART_MSG, "Create new window"); //} //else //{ // //GCC hack. иначе не собирается // SetDlgItemTextA(hDlg, IDC_RESTART_MSG, "Create new console"); //} SendDlgItemMessage(hDlg, IDC_RESTART_ICON, STM_SETICON, (WPARAM)LoadIcon(NULL,IDI_QUESTION), 0); POINT pt = {0,0}; MapWindowPoints(GetDlgItem(hDlg, IDC_TERMINATE), hDlg, &pt, 1); DestroyWindow(GetDlgItem(hDlg, IDC_TERMINATE)); SetWindowPos(GetDlgItem(hDlg, IDC_START), NULL, pt.x, pt.y, 0,0, SWP_NOSIZE|SWP_NOZORDER); SetDlgItemText(hDlg, IDC_START, L"&Start"); DestroyWindow(GetDlgItem(hDlg, IDC_WARNING)); // Выровнять флажок по кнопке GetWindowRect(GetDlgItem(hDlg, IDC_START), &rcBtnBox); SetFocus(GetDlgItem(hDlg, IDC_RESTART_CMD)); } if (rcBtnBox.left) { // Выровнять флажок по кнопке MapWindowPoints(NULL, hDlg, (LPPOINT)&rcBtnBox, 2); RECT rcBox; GetWindowRect(GetDlgItem(hDlg, cbRunAsAdmin), &rcBox); POINT pt; pt.x = rcBtnBox.left - (rcBox.right - rcBox.left) - 5; pt.y = rcBtnBox.top + ((rcBtnBox.bottom-rcBtnBox.top) - (rcBox.bottom-rcBox.top))/2; SetWindowPos(GetDlgItem(hDlg, cbRunAsAdmin), NULL, pt.x, pt.y, 0,0, SWP_NOSIZE|SWP_NOZORDER); SetFocus(GetDlgItem(hDlg, IDC_RESTART_CMD)); } if (pArgs->aRecreate != cra_RecreateTab) { POINT pt = {}; MapWindowPoints(GetDlgItem(hDlg, cbRunAsAdmin), hDlg, &pt, 1); RECT rcBox2; GetWindowRect(GetDlgItem(hDlg, cbRunInNewWindow), &rcBox2); SetWindowPos(GetDlgItem(hDlg, cbRunInNewWindow), NULL, pt.x-(rcBox2.right-rcBox2.left), pt.y, 0,0, SWP_NOSIZE); } RECT rect; GetWindowRect(hDlg, &rect); RECT rcParent; GetWindowRect(ghWnd, &rcParent); MoveWindow(hDlg, (rcParent.left+rcParent.right-rect.right+rect.left)/2, (rcParent.top+rcParent.bottom-rect.bottom+rect.top)/2, rect.right - rect.left, rect.bottom - rect.top, false); PostMessage(hDlg, (WM_APP+1), 0,0); return lbRc; } case (WM_APP+1): gpConEmu->SetSkipOnFocus(FALSE); return FALSE; case WM_CTLCOLORSTATIC: if (GetDlgItem(hDlg, IDC_WARNING) == (HWND)lParam) { SetTextColor((HDC)wParam, 255); HBRUSH hBrush = GetSysColorBrush(COLOR_3DFACE); SetBkMode((HDC)wParam, TRANSPARENT); return (INT_PTR)hBrush; } break; //case WM_GETICON: // if (wParam==ICON_BIG) // { // /*SetWindowLong(hWnd2, DWL_MSGRESULT, (LRESULT)hClassIcon); // return 1;*/ // } // else // { // SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (LRESULT)hClassIconSm); // return 1; // } // return 0; case UM_FILL_CMDLIST: { RConStartArgs* pArgs = pDlg->mp_Args; _ASSERTE(pArgs); LPCWSTR pszCmd = pArgs->pszSpecialCmd ? pArgs->pszSpecialCmd : gpConEmu->ActiveCon()->RCon()->GetCmd(); int nId = SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_FINDSTRINGEXACT, -1, (LPARAM)pszCmd); if (nId < 0) SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_INSERTSTRING, 0, (LPARAM)pszCmd); LPCWSTR pszSystem = gpSet->GetCmd(); if (pszSystem != pszCmd && (pszSystem && pszCmd && (lstrcmpi(pszSystem, pszCmd) != 0))) { nId = SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_FINDSTRINGEXACT, -1, (LPARAM)pszSystem); if (nId < 0) SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_INSERTSTRING, pArgs->pszSpecialCmd ? -1 : 0, (LPARAM)pszSystem); } if (wParam) { LPCWSTR pszHistory = gpSet->HistoryGet(); if (pszHistory) { while (*pszHistory) { nId = SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_FINDSTRINGEXACT, -1, (LPARAM)pszHistory); if (nId < 0) SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_INSERTSTRING, -1, (LPARAM)pszHistory); pszHistory += _tcslen(pszHistory)+1; } } } //// Обновить группы команд //gpSet->LoadCmdTasks(NULL); int nGroup = 0; const Settings::CommandTasks* pGrp = NULL; while ((pGrp = gpSet->CmdTaskGet(nGroup++))) { nId = SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_FINDSTRINGEXACT, -1, (LPARAM)pGrp->pszName); if (nId < 0) SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_INSERTSTRING, -1, (LPARAM)pGrp->pszName); } } return 0; case UM_USER_CONTROLS: { if (SendDlgItemMessage(hDlg, rbCurrentUser, BM_GETCHECK, 0, 0)) { EnableWindow(GetDlgItem(hDlg, cbRunAsRestricted), TRUE); //BOOL lbText = SendDlgItemMessage(hDlg, cbRunAsRestricted, BM_GETCHECK, 0, 0) == 0; EnableWindow(GetDlgItem(hDlg, tRunAsUser), FALSE); EnableWindow(GetDlgItem(hDlg, tRunAsPassword), FALSE); } else { if (SendDlgItemMessage(hDlg, tRunAsUser, CB_GETCOUNT, 0, 0) == 0) { DWORD dwLevel = 3, dwEntriesRead = 0, dwTotalEntries = 0, dwResumeHandle = 0; NET_API_STATUS nStatus; USER_INFO_3 *info = NULL; nStatus = ::NetUserEnum(NULL, dwLevel, FILTER_NORMAL_ACCOUNT, (PBYTE*) & info, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, &dwResumeHandle); if (nStatus == NERR_Success) { for(DWORD i = 0; i < dwEntriesRead; ++i) { // usri3_logon_server "\\*" wchar_t * if ((info[i].usri3_flags & UF_ACCOUNTDISABLE) == 0) SendDlgItemMessage(hDlg, tRunAsUser, CB_ADDSTRING, 0, (LPARAM)info[i].usri3_name); } ::NetApiBufferFree(info); } else { // Добавить хотя бы текущего wchar_t szCurUser[MAX_PATH]; if (GetWindowText(GetDlgItem(hDlg, tRunAsUser), szCurUser, countof(szCurUser))) SendDlgItemMessage(hDlg, tRunAsUser, CB_ADDSTRING, 0, (LPARAM)szCurUser); } } EnableWindow(GetDlgItem(hDlg, cbRunAsRestricted), FALSE); EnableWindow(GetDlgItem(hDlg, tRunAsUser), TRUE); EnableWindow(GetDlgItem(hDlg, tRunAsPassword), TRUE); } if (wParam == rbAnotherUser) SetFocus(GetDlgItem(hDlg, tRunAsUser)); } return 0; case WM_SYSCOMMAND: if (LOWORD(wParam) == ID_RESETCMDHISTORY) { if (IDYES == MessageBox(hDlg, L"Clear command history?", gpConEmu->GetDefaultTitle(), MB_ICONEXCLAMATION|MB_YESNO|MB_DEFBUTTON2)) { gpSet->HistoryReset(); wchar_t* pszCmd = GetDlgItemText(hDlg, IDC_RESTART_CMD); SendDlgItemMessage(hDlg, IDC_RESTART_CMD, CB_RESETCONTENT, 0,0); SendMessage(hDlg, UM_FILL_CMDLIST, FALSE, 0); if (pszCmd) { SetDlgItemText(hDlg, IDC_RESTART_CMD, pszCmd); free(pszCmd); } } SetWindowLongPtr(hDlg, DWLP_MSGRESULT, 0); return 1; } break; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { switch(LOWORD(wParam)) { case IDC_CHOOSE: { wchar_t *pszFilePath = NULL; int nLen = MAX_PATH*2; pszFilePath = (wchar_t*)calloc(nLen+3,2); // +2*'"'+\0 if (!pszFilePath) return 1; OPENFILENAME ofn; memset(&ofn,0,sizeof(ofn)); ofn.lStructSize=sizeof(ofn); ofn.hwndOwner = hDlg; ofn.lpstrFilter = _T("Executables (*.exe)\0*.exe\0\0"); ofn.nFilterIndex = 1; ofn.lpstrFile = pszFilePath+1; ofn.nMaxFile = nLen; ofn.lpstrTitle = _T("Choose program to run"); ofn.Flags = OFN_ENABLESIZING|OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST|OFN_EXPLORER|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST; if (GetOpenFileName(&ofn)) { LPCWSTR pszNewText = pszFilePath + 1; if (wcschr(pszFilePath, L' ')) { pszFilePath[0] = L'"'; _wcscat_c(pszFilePath, nLen+3, L"\""); pszNewText = pszFilePath; } SetDlgItemText(hDlg, IDC_RESTART_CMD, pszNewText); } SafeFree(pszFilePath); return 1; } case IDC_CHOOSE_DIR: { BROWSEINFO bi = {ghWnd}; wchar_t szFolder[MAX_PATH+1] = {0}; GetDlgItemText(hDlg, IDC_STARTUP_DIR, szFolder, countof(szFolder)); bi.pszDisplayName = szFolder; wchar_t szTitle[100]; bi.lpszTitle = wcscpy(szTitle, L"Choose startup directory"); bi.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS | BIF_VALIDATE; bi.lpfn = BrowseCallbackProc; bi.lParam = (LPARAM)szFolder; LPITEMIDLIST pRc = SHBrowseForFolder(&bi); if (pRc) { if (SHGetPathFromIDList(pRc, szFolder)) { SetDlgItemText(hDlg, IDC_STARTUP_DIR, szFolder); } CoTaskMemFree(pRc); } return 1; } case cbRunAsAdmin: { // BCM_SETSHIELD = 5644 BOOL bRunAs = SendDlgItemMessage(hDlg, cbRunAsAdmin, BM_GETCHECK, 0, 0); if (gOSVer.dwMajorVersion >= 6) { SendDlgItemMessage(hDlg, IDC_START, 5644/*BCM_SETSHIELD*/, 0, bRunAs); } if (bRunAs) { CheckRadioButton(hDlg, rbCurrentUser, rbAnotherUser, rbCurrentUser); CheckDlgButton(hDlg, cbRunAsRestricted, BST_UNCHECKED); RecreateDlgProc(hDlg, UM_USER_CONTROLS, 0, 0); } return 1; } case rbCurrentUser: case rbAnotherUser: case cbRunAsRestricted: { RecreateDlgProc(hDlg, UM_USER_CONTROLS, LOWORD(wParam), 0); return 1; } case IDC_START: { RConStartArgs* pArgs = pDlg->mp_Args; _ASSERTE(pArgs); SafeFree(pArgs->pszUserName); SafeFree(pArgs->pszDomain); //SafeFree(pArgs->pszUserPassword); if (SendDlgItemMessage(hDlg, rbAnotherUser, BM_GETCHECK, 0, 0)) { pArgs->bRunAsRestricted = FALSE; pArgs->pszUserName = GetDlgItemText(hDlg, tRunAsUser); if (pArgs->pszUserName) { //pArgs->pszUserPassword = GetDlgItemText(hDlg, tRunAsPassword); // Попытаться проверить правильность введенного пароля и возможность запуска if (!pArgs->CheckUserToken(GetDlgItem(hDlg, tRunAsPassword))) return 1; } } else { pArgs->bRunAsRestricted = SendDlgItemMessage(hDlg, cbRunAsRestricted, BM_GETCHECK, 0, 0); } // Command // pszSpecialCmd мог быть передан аргументом - умолчание для строки ввода SafeFree(pArgs->pszSpecialCmd); // GetDlgItemText выделяет память через calloc pArgs->pszSpecialCmd = GetDlgItemText(hDlg, IDC_RESTART_CMD); if (pArgs->pszSpecialCmd) gpSet->HistoryAdd(pArgs->pszSpecialCmd); // StartupDir (может быть передан аргументом) SafeFree(pArgs->pszStartupDir); wchar_t* pszDir = GetDlgItemText(hDlg, IDC_STARTUP_DIR); wchar_t* pszExpand = (pszDir && wcschr(pszDir, L'%')) ? ExpandEnvStr(pszDir) : NULL; pArgs->pszStartupDir = pszExpand ? pszExpand : pszDir; if (pszExpand) { SafeFree(pszDir) } // Vista+ (As Admin...) pArgs->bRunAsAdministrator = SendDlgItemMessage(hDlg, cbRunAsAdmin, BM_GETCHECK, 0, 0); if (pArgs->aRecreate != cra_RecreateTab) { if (SendDlgItemMessage(hDlg, cbRunInNewWindow, BM_GETCHECK, 0, 0)) pArgs->aRecreate = cra_CreateWindow; else pArgs->aRecreate = cra_CreateTab; } pDlg->mn_DlgRc = IDC_START; EndDialog(hDlg, IDC_START); return 1; } case IDC_TERMINATE: pDlg->mn_DlgRc = IDC_TERMINATE; EndDialog(hDlg, IDC_TERMINATE); return 1; case IDCANCEL: pDlg->mn_DlgRc = IDCANCEL; EndDialog(hDlg, IDCANCEL); return 1; } } break; default: return 0; } return 0; }
void CLngRc::Reload(bool bForce /*= false*/) { bool bChanged = bForce; bool bExists = false; CEStr lsNewLng, lsNewFile; // TODO: There would be gpSet member in future lsNewLng.Set(gpConEmu->opt.Language.GetStr()); // Language was requested? if (!lsNewLng.IsEmpty()) { if (ms_Lng.IsEmpty() || (0 != wcscmp(lsNewLng, ms_Lng))) { bChanged = true; } // We need a file if (gpConEmu->opt.LanguageFile.Exists) { // It may contain environment variables lsNewFile = ExpandEnvStr(gpConEmu->opt.LanguageFile.GetStr()); if (lsNewFile.IsEmpty()) lsNewFile.Set(gpConEmu->opt.LanguageFile.GetStr()); // Check if the file exists bExists = FileExists(lsNewFile); } else { lsNewFile = JoinPath(gpConEmu->ms_ConEmuExeDir, gsResourceFileName); if (!(bExists = FileExists(lsNewFile))) { lsNewFile = JoinPath(gpConEmu->ms_ConEmuBaseDir, gsResourceFileName); bExists = FileExists(lsNewFile); } } // File name was changed? if ((bExists == ms_l10n.IsEmpty()) || (bExists && (ms_l10n.IsEmpty() || (0 != wcscmp(lsNewFile, ms_l10n))) ) ) { bChanged = true; } } else if (!ms_Lng.IsEmpty()) { bChanged = true; } // Check if we have to reload data if (bChanged) { if (!bExists || !LoadResouces(lsNewLng, lsNewFile)) { ms_Lng.Empty(); ms_l10n.Empty(); Clean(m_CmnHints); Clean(m_MnuHints); Clean(m_Controls); } } }
int CIconList::CreateTabIconInt(LPCWSTR asIconDescr, bool bAdmin, LPCWSTR asWorkDir) { wchar_t* pszExpanded = ExpandEnvStr(asIconDescr); // Need to be created! int iIconIdx = -1; HICON hFileIcon = NULL; wchar_t szTemp[MAX_PATH]; LPCWSTR pszLoadFile = pszExpanded ? pszExpanded : asIconDescr; LPCWSTR lpszExt = (wchar_t*)PointToExt(pszLoadFile); bool bDirChanged = false; if (asWorkDir && *asWorkDir) { // Executable (or icon) file may be not availbale by %PATH%, let "cd" to it... bDirChanged = gpConEmu->ChangeWorkDir(asWorkDir); } if (!lpszExt) { LPWSTR pszFile = NULL; if (SearchPath(NULL, pszLoadFile, L".exe", countof(szTemp), szTemp, &pszFile)) { pszLoadFile = szTemp; lpszExt = (wchar_t*)PointToExt(pszLoadFile); } if (!lpszExt) goto wrap; } if (lstrcmpi(lpszExt, L".ico") == 0) { hFileIcon = (HICON)LoadImage(0, pszLoadFile, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_LOADFROMFILE); } else if ((lstrcmpi(lpszExt, L".exe") == 0) || (lstrcmpi(lpszExt, L".dll") == 0)) { //TODO: May be specified index of an icon in the file HICON hIconLarge = NULL; ExtractIconEx(pszLoadFile, 0, &hIconLarge, &hFileIcon, 1); if (hIconLarge) DestroyIcon(hIconLarge); } else { //TODO: Shell icons for registered files (cmd, bat, sh, pl, py, ...) } if (hFileIcon) { int iIconIdxAdm = -1; iIconIdx = ImageList_ReplaceIcon(mh_TabIcons, -1, hFileIcon); TabIconCache NewIcon = {lstrdup(asIconDescr), false, iIconIdx}; m_Icons.push_back(NewIcon); 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) { iIconIdxAdm = ImageList_ReplaceIcon(mh_TabIcons, -1, hNewIcon); DestroyIcon(hNewIcon); TabIconCache AdmIcon = {lstrdup(asIconDescr), true, iIconIdxAdm}; m_Icons.push_back(AdmIcon); if (bAdmin && (iIconIdxAdm > 0)) { iIconIdx = iIconIdxAdm; } } } //TODO: bAdmin!!! DestroyIcon(hFileIcon); } wrap: if (bDirChanged) { gpConEmu->ChangeWorkDir(NULL); } SafeFree(pszExpanded); return iIconIdx; }