// Parse switches stored in gpConEmu during initialization (AppendExtraArgs) // These are, for example, `-lngfile`, `-fontdir`, and so on. void ParseStdSwitches() { _ASSERTE(stdSwitches.empty()); CEStr szArg, szNext, lsExta; LPCWSTR psz, pszExtraArgs; pszExtraArgs = gpConEmu->MakeConEmuStartArgs(lsExta); psz = pszExtraArgs; while (psz && *psz) { Switch* ps = GetNextPair(psz); if (!ps) { continue; } if (IsIgnored(ps, GetSkipSwitches())) { SafeDelete(ps); continue; } stdSwitches.push_back(ps); } };
CAttachDlg::AttachMacroRet CAttachDlg::AttachFromMacro(DWORD anPID, bool abAlternative) { MArray<AttachParm> Parms; HWND hFind = NULL; CProcessData ProcessData; while ((hFind = FindWindowEx(NULL, hFind, NULL, NULL)) != NULL) { if (!IsWindowVisible(hFind)) continue; AttachWndInfo Info = {}; if (!GetWindowThreadProcessId(hFind, &Info.nPID) || (Info.nPID != anPID)) continue; if (!CanAttachWindow(hFind, 0, &ProcessData, Info)) continue; AttachParm p = {}; p.hAttachWnd = hFind; p.nPID = Info.nPID; p.nBits = Info.nImageBits; if (lstrcmp(Info.szType, szTypeCon) == 0) p.nType = apt_Console; else if (lstrcmp(Info.szType, szTypeGui) == 0) p.nType = apt_Gui; else continue; p.bAlternativeMode = abAlternative; Parms.push_back(p); } if (Parms.empty()) return amr_WindowNotFound; if (Parms.size() > 1) return amr_Ambiguous; AttachParm Null = {}; Parms.push_back(Null); // Работу делаем в фоновом потоке, чтобы не блокировать главный // (к окну ConEmu должна подцепиться новая вкладка) AttachParm* pParm = Parms.detach(); if (!pParm) return amr_Unexpected; DWORD nTID = 0; HANDLE hThread = apiCreateThread((LPTHREAD_START_ROUTINE)StartAttachThread, pParm, &nTID, "CAttachDlg::StartAttachThread#2"); if (!hThread) { //DWORD dwErr = GetLastError(); //_wsprintf(szItem, SKIPLEN(countof(szItem)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); //DisplayLastError(L"Can't start attach thread", dwErr, 0, szItem); return amr_Unexpected; } // We don't need this handle CloseHandle(hThread); return amr_Success; }
bool CAttachDlg::OnStartAttach() { bool lbRc = false; // Тут нужно получить инфу из списка и дернуть собственно аттач wchar_t szItem[128] = {}; //DWORD nPID = 0, nBits = WIN3264TEST(32,64); //AttachProcessType nType = apt_Unknown; wchar_t *psz; int iSel, iCur; DWORD nTID; HANDLE hThread = NULL; AttachParm *pParm = NULL; MArray<AttachParm> Parms; //HWND hAttachWnd = NULL; ShowWindow(mh_Dlg, SW_HIDE); BOOL bAlternativeMode = (IsDlgButtonChecked(mh_Dlg, IDC_ATTACH_ALT) != 0); iSel = ListView_GetNextItem(mh_List, -1, LVNI_SELECTED); while (iSel >= 0) { iCur = iSel; iSel = ListView_GetNextItem(mh_List, iCur, LVNI_SELECTED); AttachParm L = {NULL, 0, WIN3264TEST(32,64), apt_Unknown, bAlternativeMode}; ListView_GetItemText(mh_List, iCur, alc_PID, szItem, countof(szItem)-1); L.nPID = wcstoul(szItem, &psz, 10); if (L.nPID) { psz = wcschr(szItem, L'['); if (!psz) { _ASSERTE(FALSE && "Process bitness was not detected?"); } else { L.nBits = wcstoul(psz+1, &psz, 10); } } ListView_GetItemText(mh_List, iCur, alc_Type, szItem, countof(szItem)); if (lstrcmp(szItem, szTypeCon) == 0) L.nType = apt_Console; else if (lstrcmp(szItem, szTypeGui) == 0) L.nType = apt_Gui; ListView_GetItemText(mh_List, iCur, alc_HWND, szItem, countof(szItem)); L.hAttachWnd = (szItem[0]==L'0' && szItem[1]==L'x') ? (HWND)(DWORD_PTR)wcstoul(szItem+2, &psz, 16) : NULL; if (!L.nPID || !L.nBits || !L.nType || !L.hAttachWnd) { MBoxAssert(L.nPID && L.nBits && L.nType && L.hAttachWnd); goto wrap; } Parms.push_back(L); } if (Parms.empty()) { goto wrap; } else { AttachParm N = {NULL}; Parms.push_back(N); } //// Чтобы клик от мышки в консоль не провалился //WARNING("Клик от мышки в консоль проваливается"); //gpConEmu->mouse.nSkipEvents[0] = WM_LBUTTONUP; //gpConEmu->mouse.nSkipEvents[1] = 0; //gpConEmu->mouse.nReplaceDblClk = 0; // Все, диалог закрываем, чтобы не мешался Close(); // Работу делаем в фоновом потоке, чтобы не блокировать главный // (к окну ConEmu должна подцепиться новая вкладка) pParm = Parms.detach(); if (!pParm) { _wsprintf(szItem, SKIPLEN(countof(szItem)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); DisplayLastError(L"Parms.detach() failed", -1, 0, szItem); goto wrap; } else { hThread = apiCreateThread((LPTHREAD_START_ROUTINE)StartAttachThread, pParm, &nTID, "CAttachDlg::StartAttachThread#1"); if (!hThread) { DWORD dwErr = GetLastError(); _wsprintf(szItem, SKIPLEN(countof(szItem)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); DisplayLastError(L"Can't start attach thread", dwErr, 0, szItem); } else lbRc = true; } wrap: // We don't need this handle if (hThread) CloseHandle(hThread); return lbRc; }
// Supports MultiLine and SingleLine strings // If there were no key_value or key_value_type is unexpected, DOESN'T touch *value bool SettingsXML::Load(const wchar_t *regName, wchar_t **value) noexcept { bool lbRc = false; SettingsXML::node *pChild = NULL; SettingsXML::node *pNode = NULL; const char *sType; size_t cchMax = 0; CEStrA data; LPCSTR pszData = nullptr; try { if (mp_Key) pChild = FindItem(mp_Key, L"value", regName, false); if (!pChild) return false; sType = GetAttr(pChild, "type"); if (0 == _strcmpi(sType, "multi")) { //<value name="CmdLineHistory" type="multi"> // <line data="C:\Far\Far.exe"/> // <line data="cmd"/> //</value> struct line_info { const char* str; size_t cchSize; }; MArray<line_info> lines; for (pNode = pChild->first_node("line"); pNode; pNode = pNode->next_sibling("line")) { const char* lstr = GetAttr(pNode, "data"); if (!lstr || !*lstr) lstr = " "; // Because of ASCIIZZ we must be sure there were no zero-length string size_t cchSize = strlen(lstr) + 1; cchMax += cchSize; lines.push_back({lstr, cchSize}); } if (!lines.empty()) { // ASCIIZ,ASCIIZ,...,ASCIIZ buffer if (char* buffer = data.getbuffer(cchMax)) { for (INT_PTR i = 0; i < lines.size(); ++i) { const auto& line = lines[i]; strcpy_s(buffer, line.cchSize, line.str); buffer += line.cchSize; } _ASSERTE(cchMax>=1 && data.ms_Val[cchMax-1]==0); pszData = data.c_str(); } } } else if (0 == _strcmpi(sType, "string")) { pszData = GetAttr(pChild, "data"); cchMax = pszData ? (strlen(pszData) + 1) : 0; // ASCIIZ } else { // We don't care about other data types, only strings here } // Data exist? if (pszData) { int cvt_size = MultiByteToWideChar(CP_UTF8, 0, pszData, cchMax, nullptr, 0); if (cvt_size > 0) { // Allocate data for ASCIIZZ (additional zero at the end) if ((*value = (wchar_t*)realloc(*value, (cvt_size + 1) * sizeof(**value)))) { int cvt = MultiByteToWideChar(CP_UTF8, 0, pszData, cchMax, *value, cvt_size+1); _ASSERTE(cvt == cvt_size); if (cvt > 0) { _ASSERTE((*value)[cvt-1] == 0); (*value)[cvt] = 0; // ASCIIZZ lbRc = true; } } } } } catch (rapidxml::parse_error&) { // #XML Log error lbRc = false; } return lbRc; }