int GuiMessageBox(HWND hConEmuWndRoot, LPCWSTR asText, LPCWSTR asTitle, int anBtns) { int nResult = 0; if (hConEmuWndRoot) { HWND hConWnd = myGetConsoleWindow(); CESERVER_REQ *pIn = (CESERVER_REQ*)malloc(sizeof(*pIn)); ExecutePrepareCmd(pIn, CECMD_ASSERT, sizeof(CESERVER_REQ_HDR)+sizeof(MyAssertInfo)); pIn->AssertInfo.nBtns = anBtns; _wcscpyn_c(pIn->AssertInfo.szTitle, countof(pIn->AssertInfo.szTitle), asTitle, countof(pIn->AssertInfo.szTitle)); //-V501 _wcscpyn_c(pIn->AssertInfo.szDebugInfo, countof(pIn->AssertInfo.szDebugInfo), asText, countof(pIn->AssertInfo.szDebugInfo)); //-V501 wchar_t szGuiPipeName[128]; msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", (DWORD)hConEmuWndRoot); //-V205 CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 1000, hConWnd); free(pIn); if (pOut) { if (pOut->hdr.cbSize > sizeof(CESERVER_REQ_HDR)) { nResult = pOut->dwData[0]; } ExecuteFreeResult(pOut); } } else { //_ASSERTE(hConEmuWndRoot!=NULL); // Избежать статической линковки к user32 HMODULE hUser32 = GetModuleHandle(L"User32.dll"); if (hUser32 == NULL) hUser32 = LoadLibrary(L"User32.dll"); typedef int (WINAPI* MessageBoxW_T)(HWND, LPCWSTR, LPCWSTR, UINT); MessageBoxW_T _MessageBoxW = hUser32 ? (MessageBoxW_T)GetProcAddress(hUser32, "MessageBoxW") : NULL; if (_MessageBoxW) { nResult = _MessageBoxW(NULL, asText, asTitle, MB_SYSTEMMODAL|anBtns); } else { #ifdef _DEBUG _CrtDbgBreak(); #endif } } return nResult; }
LPCWSTR CmdArg::Set(LPCWSTR asNewValue, INT_PTR anChars /*= -1*/) { if (asNewValue) { INT_PTR nNewLen = (anChars == -1) ? lstrlen(asNewValue) : anChars; if (nNewLen <= 0) { //_ASSERTE(FALSE && "Check, if caller really need to set empty string???"); if (GetBuffer(1)) ms_Arg[0] = 0; } else if (GetBuffer(nNewLen)) { _ASSERTE(mn_MaxLen > nNewLen); // Must be set in GetBuffer _wcscpyn_c(ms_Arg, mn_MaxLen, asNewValue, nNewLen); } } else { Empty(); } return ms_Arg; }
wchar_t* GetShortFileNameEx(LPCWSTR asLong, BOOL abFavorLength/*=TRUE*/) { if (!asLong) return NULL; int nSrcLen = lstrlenW(asLong); //-V303 wchar_t* pszLong = lstrdup(asLong); int nMaxLen = nSrcLen + MAX_PATH; // "короткое" имя может более MAX_PATH wchar_t* pszShort = (wchar_t*)calloc(nMaxLen, sizeof(wchar_t)); //-V106 wchar_t* pszResult = NULL; wchar_t* pszSrc = pszLong; //wchar_t* pszDst = pszShort; wchar_t* pszSlash; wchar_t* szName = (wchar_t*)malloc((MAX_PATH+1)*sizeof(wchar_t)); bool lbNetwork = false; int nLen, nCurLen = 0; if (!pszLong || !pszShort || !szName) goto wrap; // Если путь сетевой (или UNC?) пропустить префиксы/серверы if (pszSrc[0] == L'\\' && pszSrc[1] == '\\') { // пропуск первых двух слешей pszSrc += 2; // формат "диска" не поддерживаем \\.\Drive\... if (pszSrc[0] == L'.' && pszSrc[1] == L'\\') goto wrap; // UNC if (pszSrc[0] == L'?' && pszSrc[1] == L'\\') { pszSrc += 2; if (pszSrc[0] == L'U' && pszSrc[1] == L'N' && pszSrc[2] == L'C' && pszSrc[3] == L'\\') { // UNC\Server\share\... pszSrc += 4; //-V112 lbNetwork = true; } // иначе - ожидается диск } // Network (\\Server\\Share\...) else { lbNetwork = true; } } if (pszSrc[0] == 0) goto wrap; if (lbNetwork) { pszSlash = wcschr(pszSrc, L'\\'); if (!pszSlash) goto wrap; pszSlash = wcschr(pszSlash+1, L'\\'); if (!pszSlash) goto wrap; pszShort[0] = L'\\'; pszShort[1] = L'\\'; pszShort[2] = 0; _wcscatn_c(pszShort, nMaxLen, pszSrc, (pszSlash-pszSrc+1)); // память выделяется calloc! //-V303 //-V104 } else { // <Drive>:\path... if (pszSrc[1] != L':') goto wrap; if (pszSrc[2] != L'\\' && pszSrc[2] != 0) goto wrap; pszSlash = pszSrc + 2; _wcscatn_c(pszShort, nMaxLen, pszSrc, (pszSlash-pszSrc+1)); // память выделяется calloc! } nCurLen = lstrlenW(pszShort); while (pszSlash && (*pszSlash == L'\\')) { pszSrc = pszSlash; pszSlash = wcschr(pszSrc+1, L'\\'); if (pszSlash) *pszSlash = 0; if (!GetShortFileName(pszLong, MAX_PATH+1, szName, abFavorLength)) goto wrap; nLen = lstrlenW(szName); if ((nLen + nCurLen) >= nMaxLen) goto wrap; //pszShort[nCurLen++] = L'\\'; pszShort[nCurLen] = 0; _wcscpyn_c(pszShort+nCurLen, nMaxLen-nCurLen, szName, nLen); nCurLen += nLen; if (pszSlash) { *pszSlash = L'\\'; pszShort[nCurLen++] = L'\\'; // память выделяется calloc! } } nLen = lstrlenW(pszShort); if ((nLen > 0) && (pszShort[nLen-1] == L'\\')) pszShort[--nLen] = 0; if (nLen <= MAX_PATH) { pszResult = pszShort; pszShort = NULL; goto wrap; } wrap: if (szName) free(szName); if (pszShort) free(pszShort); if (pszLong) free(pszLong); return pszResult; }
DWORD WINAPI DebugThread(LPVOID lpvParam) { DWORD nWait = WAIT_TIMEOUT; //DWORD nExternalExitCode = -1; wchar_t szInfo[1024]; if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; if (gpSrv->DbgInfo.bDebugProcessTree) { SetEnvironmentVariable(ENV_CONEMU_BLOCKCHILDDEBUGGERS_W, ENV_CONEMU_BLOCKCHILDDEBUGGERS_YES); } if (!CreateProcess(NULL, gpSrv->DbgInfo.pszDebuggingCmdLine, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE| DEBUG_PROCESS | (gpSrv->DbgInfo.bDebugProcessTree ? 0 : DEBUG_ONLY_THIS_PROCESS), NULL, NULL, &si, &pi)) { DWORD dwErr = GetLastError(); wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(gpSrv->dwRootProcess, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start debugging process. ErrCode=0x%08X\n", dwErr); lstrcpyn(szInfo+lstrlen(szInfo), gpSrv->DbgInfo.pszDebuggingCmdLine, 400); wcscat_c(szInfo, L"\n"); _wprintf(szInfo); return CERR_CANTSTARTDEBUGGER; } gpSrv->hRootProcess = pi.hProcess; gpSrv->hRootThread = pi.hThread; gpSrv->dwRootProcess = pi.dwProcessId; gpSrv->dwRootThread = pi.dwThreadId; gpSrv->dwRootStartTime = GetTickCount(); } /* ************************* */ int iDbgIdx = 0, iAttachedCount = 0; while (true) { HANDLE hDbgProcess = NULL; DWORD nDbgProcessID = 0; bool bFirstPID = ((iDbgIdx++) == 0); if (bFirstPID) { hDbgProcess = gpSrv->hRootProcess; nDbgProcessID = gpSrv->dwRootProcess; } else { // Взять из pDebugAttachProcesses if (!gpSrv->DbgInfo.pDebugAttachProcesses) break; if (!gpSrv->DbgInfo.pDebugAttachProcesses->pop_back(nDbgProcessID)) break; hDbgProcess = GetProcessHandleForDebug(nDbgProcessID); if (!hDbgProcess) { _ASSERTE(hDbgProcess!=NULL && "Can't open debugging process handle"); continue; } } _ASSERTE(hDbgProcess!=NULL && "Process handle must be opened"); // Битность отладчика должна соответствовать битности приложения! if (IsWindows64()) { int nBits = GetProcessBits(nDbgProcessID, hDbgProcess); if ((nBits == 32 || nBits == 64) && (nBits != WIN3264TEST(32,64))) { if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { _printf("Bitness of ConEmuC and debugging program does not match\n"); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } wchar_t szExe[MAX_PATH+16]; wchar_t szCmdLine[MAX_PATH*2]; if (GetModuleFileName(NULL, szExe, countof(szExe)-16)) { wchar_t* pszName = (wchar_t*)PointToName(szExe); _wcscpy_c(pszName, 16, (nBits == 32) ? L"ConEmuC.exe" : L"ConEmuC64.exe"); _wsprintf(szCmdLine, SKIPLEN(countof(szCmdLine)) L"\"%s\" /DEBUGPID=%u %s", szExe, nDbgProcessID, (gpSrv->DbgInfo.nDebugDumpProcess == 1) ? L"/DUMP" : (gpSrv->DbgInfo.nDebugDumpProcess == 2) ? L"/MINIDUMP" : (gpSrv->DbgInfo.nDebugDumpProcess == 3) ? L"/FULLDUMP" : L""); STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; if (CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { // Ждать НЕ будем, сразу на выход //HANDLE hEvents[2] = {pi.hProcess, ghExitQueryEvent}; //nWait = WaitForMultipleObjects(countof(hEvents), hEvents, FALSE, INFINITE); //if (nWait == WAIT_OBJECT_0) //{ // //GetExitCodeProcess(pi.hProcess, &nExternalExitCode); // nExternalExitCode = 0; //} //CloseHandle(pi.hProcess); //CloseHandle(pi.hThread); //if (nExternalExitCode == 0) //{ // goto done; //} // Может там еще процессы в списке на дамп? continue; } else { DWORD dwErr = GetLastError(); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start external debugger '%s'. ErrCode=0x%08X\n", szCmdLine, dwErr); _wprintf(szInfo); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } } wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(nDbgProcessID, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Bits are incompatible. Can't debug '%s' PID=%i\n", szProc[0] ? szProc : L"not found", nDbgProcessID); _wprintf(szInfo); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } } if (gpSrv->DbgInfo.pszDebuggingCmdLine == NULL) { if (!DebugActiveProcess(nDbgProcessID)) { DWORD dwErr = GetLastError(); wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(nDbgProcessID, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't attach debugger to '%s' PID=%i. ErrCode=0x%08X\n", szProc[0] ? szProc : L"not found", nDbgProcessID, dwErr); _wprintf(szInfo); return CERR_CANTSTARTDEBUGGER; } } iAttachedCount++; } if (iAttachedCount == 0) { return CERR_CANTSTARTDEBUGGER; } /* **************** */ // Дополнительная инициализация, чтобы закрытие дебагера (наш процесс) не привело // к закрытию "отлаживаемой" программы pfnDebugActiveProcessStop = (FDebugActiveProcessStop)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugActiveProcessStop"); pfnDebugSetProcessKillOnExit = (FDebugSetProcessKillOnExit)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugSetProcessKillOnExit"); if (pfnDebugSetProcessKillOnExit) pfnDebugSetProcessKillOnExit(FALSE/*KillOnExit*/); gpSrv->DbgInfo.bDebuggerActive = TRUE; PrintDebugInfo(); SetEvent(gpSrv->DbgInfo.hDebugReady); while (nWait == WAIT_TIMEOUT) { ProcessDebugEvent(); if (ghExitQueryEvent) nWait = WaitForSingleObject(ghExitQueryEvent, 0); } //done: gbRootAliveLess10sec = FALSE; gbInShutdown = TRUE; gbAlwaysConfirmExit = FALSE; _ASSERTE(gbTerminateOnCtrlBreak==FALSE); if (!nExitQueryPlace) nExitQueryPlace = 12+(nExitPlaceStep); SetTerminateEvent(ste_DebugThread); return 0; }
bool FindImageSubsystem(const wchar_t *Module, /*wchar_t* pstrDest,*/ DWORD& ImageSubsystem, DWORD& ImageBits, DWORD& FileAttrs) { if (!Module || !*Module) return false; bool Result = false; //ImageSubsystem = IMAGE_SUBSYSTEM_UNKNOWN; // Исключения нас не интересуют - команда уже сформирована и отдана в CreateProcess! //// нулевой проход - смотрим исключения //// Берем "исключения" из реестра, которые должны исполняться директом, //// например, некоторые внутренние команды ком. процессора. //string strExcludeCmds; //GetRegKey(strSystemExecutor,L"ExcludeCmds",strExcludeCmds,L""); //UserDefinedList ExcludeCmdsList; //ExcludeCmdsList.Set(strExcludeCmds); //while (!ExcludeCmdsList.IsEmpty()) //{ // if (!StrCmpI(Module,ExcludeCmdsList.GetNext())) // { // ImageSubsystem=IMAGE_SUBSYSTEM_WINDOWS_CUI; // Result=true; // break; // } //} //string strFullName=Module; LPCWSTR ModuleExt = PointToExt(Module); wchar_t *strPathExt/*[32767]*/ = NULL; //(L".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WSH"); wchar_t *strPathEnv/*[32767]*/ = NULL; wchar_t *strExpand/*[32767]*/ = NULL; wchar_t *strTmpName/*[32767]*/ = NULL; wchar_t *pszFilePart = NULL; DWORD nPathExtLen = 0; LPCWSTR pszPathExtEnd = NULL; LPWSTR Ext = NULL; typedef LONG (WINAPI *RegOpenKeyExW_t)(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); RegOpenKeyExW_t _RegOpenKeyEx = NULL; typedef LONG (WINAPI *RegQueryValueExW_t)(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); RegQueryValueExW_t _RegQueryValueEx = NULL; typedef LONG (WINAPI *RegCloseKey_t)(HKEY hKey); RegCloseKey_t _RegCloseKey = NULL; HMODULE hAdvApi = NULL; int cchstrPathExt = 32767; strPathExt = (wchar_t*)malloc(cchstrPathExt*sizeof(wchar_t)); *strPathExt = 0; int cchstrPathEnv = 32767; strPathEnv = (wchar_t*)malloc(cchstrPathEnv*sizeof(wchar_t)); *strPathEnv = 0; int cchstrExpand = 32767; strExpand = (wchar_t*)malloc(cchstrExpand*sizeof(wchar_t)); *strExpand = 0; int cchstrTmpName = 32767; strTmpName = (wchar_t*)malloc(cchstrTmpName*sizeof(wchar_t)); *strTmpName = 0; nPathExtLen = GetEnvironmentVariable(L"PATHEXT", strPathExt, cchstrPathExt-2); if (!nPathExtLen) { _wcscpy_c(strPathExt, cchstrPathExt, L".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WSH"); nPathExtLen = lstrlen(strPathExt); } pszPathExtEnd = strPathExt+nPathExtLen; // Разбить на токены strPathExt[nPathExtLen] = strPathExt[nPathExtLen+1] = 0; Ext = wcschr(strPathExt, L';'); while (Ext) { *Ext = 0; Ext = wcschr(Ext+1, L';'); } TODO("Проверить на превышение длин строк"); // первый проход - в текущем каталоге LPWSTR pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; _wcscpyn_c(strTmpName, cchstrTmpName, Module, cchstrTmpName); //-V501 if (!ModuleExt) { if (!*Ext) continue; _wcscatn_c(strTmpName, cchstrTmpName, Ext, cchstrTmpName); } if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits/*16/32/64*/, FileAttrs)) { Result = true; goto wrap; } if (ModuleExt) { break; } } // второй проход - по правилам SearchPath // поиск по переменной PATH if (GetEnvironmentVariable(L"PATH", strPathEnv, cchstrPathEnv)) { LPWSTR pszPathEnvEnd = strPathEnv + lstrlen(strPathEnv); LPWSTR pszPathCur = strPathEnv; while (pszPathCur && (pszPathCur < pszPathEnvEnd)) { LPWSTR Path = pszPathCur; LPWSTR pszPathNext = wcschr(pszPathCur, L';'); if (pszPathNext) { *pszPathNext = 0; pszPathCur = pszPathNext+1; } else { pszPathCur = pszPathEnvEnd; } if (!*Path) continue; pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; if (SearchPath(Path, Module, Ext, cchstrTmpName, strTmpName, &pszFilePart)) { if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } } } pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; if (SearchPath(NULL, Module, Ext, cchstrTmpName, strTmpName, &pszFilePart)) { if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } // третий проход - лезем в реестр в "App Paths" if (!wcschr(Module, L'\\')) { hAdvApi = LoadLibrary(L"AdvApi32.dll"); if (!hAdvApi) goto wrap; _RegOpenKeyEx = (RegOpenKeyExW_t)GetProcAddress(hAdvApi, "RegOpenKeyExW"); _RegQueryValueEx = (RegQueryValueExW_t)GetProcAddress(hAdvApi, "RegQueryValueExW"); _RegCloseKey = (RegCloseKey_t)GetProcAddress(hAdvApi, "RegCloseKey"); if (!_RegOpenKeyEx || !_RegQueryValueEx || !_RegCloseKey) goto wrap; LPCWSTR RegPath = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\"; // В строке Module заменить исполняемый модуль на полный путь, который // берется из SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths // Сначала смотрим в HKCU, затем - в HKLM HKEY RootFindKey[] = {HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_LOCAL_MACHINE}; BOOL lbAddExt = FALSE; pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { if (!lbAddExt) { Ext = NULL; lbAddExt = TRUE; } else { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; } _wcscpy_c(strTmpName, cchstrTmpName, RegPath); _wcscatn_c(strTmpName, cchstrTmpName, Module, cchstrTmpName); if (Ext) _wcscatn_c(strTmpName, cchstrTmpName, Ext, cchstrTmpName); DWORD samDesired = KEY_QUERY_VALUE; DWORD RedirectionFlag = 0; // App Paths key is shared in Windows 7 and above OSVERSIONINFO osv = {sizeof(OSVERSIONINFO)}; GetVersionEx(&osv); if (osv.dwMajorVersion < 6 || (osv.dwMajorVersion == 6 && osv.dwMinorVersion < 1)) { #ifdef _WIN64 RedirectionFlag = KEY_WOW64_32KEY; #else RedirectionFlag = IsWindows64() ? KEY_WOW64_64KEY : 0; #endif } for (size_t i = 0; i < countof(RootFindKey); i++) { if (i == (countof(RootFindKey)-1)) { if (RedirectionFlag) samDesired |= RedirectionFlag; else break; } HKEY hKey; if (_RegOpenKeyEx(RootFindKey[i], strTmpName, 0, samDesired, &hKey) == ERROR_SUCCESS) { DWORD nType = 0, nSize = sizeof(strTmpName)-2; int RegResult = _RegQueryValueEx(hKey, L"", NULL, &nType, (LPBYTE)strTmpName, &nSize); _RegCloseKey(hKey); if ((RegResult == ERROR_SUCCESS) && (nType == REG_SZ || nType == REG_EXPAND_SZ || nType == REG_MULTI_SZ)) { strTmpName[(nSize >> 1)+1] = 0; if (!ExpandEnvironmentStrings(strTmpName, strExpand, cchstrExpand)) _wcscpy_c(strExpand, cchstrExpand, strTmpName); if (GetImageSubsystem(Unquote(strExpand), ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } }
DWORD WINAPI DebugThread(LPVOID lpvParam) { DWORD nWait = WAIT_TIMEOUT; wchar_t szInfo[1024]; wchar_t szPID[20]; int iAttachedCount = 0; CEStr szOtherBitPids, szOtherDebugCmd; // Дополнительная инициализация, чтобы закрытие дебагера (наш процесс) не привело // к закрытию "отлаживаемой" программы pfnDebugActiveProcessStop = (FDebugActiveProcessStop)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugActiveProcessStop"); pfnDebugSetProcessKillOnExit = (FDebugSetProcessKillOnExit)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugSetProcessKillOnExit"); // Affect GetProcessHandleForDebug gpSrv->DbgInfo.bDebuggerActive = TRUE; // If dump was requested if (gpSrv->DbgInfo.nDebugDumpProcess) { gpSrv->DbgInfo.bUserRequestDump = TRUE; } // "/DEBUGEXE" or "/DEBUGTREE" if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; if (gpSrv->DbgInfo.bDebugProcessTree) { SetEnvironmentVariable(ENV_CONEMU_BLOCKCHILDDEBUGGERS_W, ENV_CONEMU_BLOCKCHILDDEBUGGERS_YES); } if (!CreateProcess(NULL, gpSrv->DbgInfo.pszDebuggingCmdLine, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE| DEBUG_PROCESS | (gpSrv->DbgInfo.bDebugProcessTree ? 0 : DEBUG_ONLY_THIS_PROCESS), NULL, NULL, &si, &pi)) { DWORD dwErr = GetLastError(); wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(gpSrv->dwRootProcess, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start debugging process. ErrCode=0x%08X\n", dwErr); CEStr lsInfo(lstrmerge(szInfo, gpSrv->DbgInfo.pszDebuggingCmdLine, L"\n")); _wprintf(lsInfo); return CERR_CANTSTARTDEBUGGER; } gpSrv->hRootProcess = pi.hProcess; gpSrv->hRootThread = pi.hThread; gpSrv->dwRootProcess = pi.dwProcessId; gpSrv->dwRootThread = pi.dwThreadId; gpSrv->dwRootStartTime = GetTickCount(); // Let's know that at least one process is debugging iAttachedCount++; } /* ************************* */ int iDbgIdx = 0; bool bSetKillOnExit = true; while (true) { HANDLE hDbgProcess = NULL; DWORD nDbgProcessID = 0; if ((iDbgIdx++) == 0) { hDbgProcess = gpSrv->hRootProcess; nDbgProcessID = gpSrv->dwRootProcess; } else { // Взять из pDebugAttachProcesses if (!gpSrv->DbgInfo.pDebugAttachProcesses) break; if (!gpSrv->DbgInfo.pDebugAttachProcesses->pop_back(nDbgProcessID)) break; hDbgProcess = GetProcessHandleForDebug(nDbgProcessID); if (!hDbgProcess) { _ASSERTE(hDbgProcess!=NULL && "Can't open debugging process handle"); continue; } } _ASSERTE(hDbgProcess!=NULL && "Process handle must be opened"); // Битность отладчика должна соответствовать битности приложения! if (IsWindows64()) { int nBits = GetProcessBits(nDbgProcessID, hDbgProcess); if ((nBits == 32 || nBits == 64) && (nBits != WIN3264TEST(32,64))) { // If /DEBUGEXE or /DEBUGTREE was used if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { _printf("Bitness of ConEmuC and debugging program does not match\n"); continue; } // Добавить процесс в список для запуска альтернативного дебаггера соотвествующей битности // Force trailing "," even if only one PID specified ( --> bDebugMultiProcess = TRUE) lstrmerge(&szOtherBitPids.ms_Arg, _itow(nDbgProcessID, szPID, 10), L","); // Может там еще процессы в списке на дамп? continue; } } if (gpSrv->DbgInfo.pszDebuggingCmdLine == NULL) { if (DebugActiveProcess(nDbgProcessID)) { iAttachedCount++; } else { DWORD dwErr = GetLastError(); wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(nDbgProcessID, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't attach debugger to '%s' PID=%i. ErrCode=0x%08X\n", szProc[0] ? szProc : L"not found", nDbgProcessID, dwErr); _wprintf(szInfo); // Может другие подцепить получится? continue; } } // To avoid debugged processes killing if (bSetKillOnExit && pfnDebugSetProcessKillOnExit) { // affects all current and future debuggees connected to the calling thread if (pfnDebugSetProcessKillOnExit(FALSE/*KillOnExit*/)) { bSetKillOnExit = false; } } } // Different bitness, need to start appropriate debugger if (szOtherBitPids.ms_Arg && *szOtherBitPids.ms_Arg) { wchar_t szExe[MAX_PATH+5], *pszName; if (!GetModuleFileName(NULL, szExe, MAX_PATH)) { _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"GetModuleFileName(NULL) failed. ErrCode=0x%08X\n", GetLastError()); _wprintf(szInfo); } else if (!(pszName = (wchar_t*)PointToName(szExe))) { _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"GetModuleFileName(NULL) returns invalid path\n%s\n", szExe); _wprintf(szInfo); } else { *pszName = 0; // Reverted to current bitness wcscat_c(szExe, WIN3264TEST(L"ConEmuC64.exe", L"ConEmuC.exe")); szOtherDebugCmd.Attach(lstrmerge(L"\"", szExe, L"\" " L"/DEBUGPID=", szOtherBitPids.ms_Arg, (gpSrv->DbgInfo.nDebugDumpProcess == 1) ? L" /DUMP" : (gpSrv->DbgInfo.nDebugDumpProcess == 2) ? L" /MINIDUMP" : (gpSrv->DbgInfo.nDebugDumpProcess == 3) ? L" /FULLDUMP" : L"")); STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; if (CreateProcess(NULL, szOtherDebugCmd.ms_Arg, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { // Ждать не будем } else { DWORD dwErr = GetLastError(); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start external debugger, ErrCode=0x%08X\n", dwErr); CEStr lsInfo(lstrmerge(szInfo, szOtherDebugCmd, L"\n")); _wprintf(lsInfo); } } } //_ASSERTE(FALSE && "Continue to dump"); // If neither /DEBUG[EXE|TREE] nor /DEBUGPID was not succeeded if (iAttachedCount == 0) { gpSrv->DbgInfo.bDebuggerActive = FALSE; return CERR_CANTSTARTDEBUGGER; } else if (iAttachedCount > 1) { _ASSERTE(gpSrv->DbgInfo.bDebugMultiProcess && "Already must be set from arguments parser"); gpSrv->DbgInfo.bDebugMultiProcess = TRUE; } if (gpSrv->DbgInfo.bUserRequestDump) { gpSrv->DbgInfo.nWaitTreeBreaks = iAttachedCount; } /* **************** */ // To avoid debugged processes killing (JIC, must be called already) if (bSetKillOnExit && pfnDebugSetProcessKillOnExit) { // affects all current and future debuggees connected to the calling thread if (pfnDebugSetProcessKillOnExit(FALSE/*KillOnExit*/)) { bSetKillOnExit = false; } } PrintDebugInfo(); SetEvent(gpSrv->DbgInfo.hDebugReady); while (nWait == WAIT_TIMEOUT) { ProcessDebugEvent(); if (ghExitQueryEvent) nWait = WaitForSingleObject(ghExitQueryEvent, 0); } //done: gbRootAliveLess10sec = FALSE; gbInShutdown = TRUE; gbAlwaysConfirmExit = FALSE; _ASSERTE(gbTerminateOnCtrlBreak==FALSE); if (!nExitQueryPlace) nExitQueryPlace = 12+(nExitPlaceStep); SetTerminateEvent(ste_DebugThread); return 0; }