Ejemplo n.º 1
0
void Help()
{
	PrintVersion();

	// See definition in "ConEmuCD/ConsoleHelp.h"
	_wprintf(pConsoleHelp);
	_wprintf(pNewConsoleHelp);
}
Ejemplo n.º 2
0
// ConEmuC -OsVerInfo
int OsVerInfo()
{
	OSVERSIONINFOEX osv = {sizeof(osv)};
	GetOsVersionInformational((OSVERSIONINFO*)&osv);

	UINT DBCS = IsDbcs();
	UINT HWFS = IsHwFullScreenAvailable();
	UINT W5fam = IsWin5family();
	UINT WXPSP1 = IsWinXPSP1();
	UINT W6 = IsWin6();
	UINT W7 = IsWin7();
	UINT W10 = IsWin10();
	UINT Wx64 = IsWindows64();
	UINT WINE = IsWine();
	UINT WPE = IsWinPE();
	UINT TELNET = isTerminalMode();

	wchar_t szInfo[200];
	_wsprintf(szInfo, SKIPCOUNT(szInfo)
		L"OS version information\n"
		L"%u.%u build %u SP%u.%u suite=x%04X type=%u\n"
		L"W5fam=%u WXPSP1=%u W6=%u W7=%u W10=%u Wx64=%u\n"
		L"HWFS=%u DBCS=%u WINE=%u WPE=%u TELNET=%u\n",
		osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber, osv.wServicePackMajor, osv.wServicePackMinor, osv.wSuiteMask, osv.wProductType,
		W5fam, WXPSP1, W6, W7, W10, Wx64, HWFS,
		DBCS, WINE, WPE, TELNET);
	_wprintf(szInfo);

	return MAKEWORD(osv.dwMinorVersion, osv.dwMajorVersion);
}
Ejemplo n.º 3
0
void PrintVersion()
{
	wchar_t szProgInfo[255], szVer[32];
	MultiByteToWideChar(CP_ACP, 0, CONEMUVERS, -1, szVer, countof(szVer));
	_wsprintf(szProgInfo, SKIPLEN(countof(szProgInfo))
		L"ConEmuC build %s %s. " CECOPYRIGHTSTRING_W L"\n",
		szVer, WIN3264TEST(L"x86",L"x64"));
	_wprintf(szProgInfo);
}
Ejemplo n.º 4
0
// gpSrv->dwRootProcess
void WriteMiniDump(DWORD dwProcessId, DWORD dwThreadId, EXCEPTION_RECORD *pExceptionRecord, LPCSTR asConfirmText /*= NULL*/, BOOL bTreeBreak /*= FALSE*/)
{
	MINIDUMP_TYPE dumpType = MiniDumpNormal;
	
	char szTitleA[64];
	_wsprintfA(szTitleA, SKIPLEN(countof(szTitleA)) "ConEmuC Debugging PID=%u, Debugger PID=%u", dwProcessId, GetCurrentProcessId());
	wchar_t szTitle[64];
	_wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmuC Debugging PID=%u, Debugger PID=%u", dwProcessId, GetCurrentProcessId());

	int nBtn = 0;
	
	if (gpSrv->DbgInfo.nDebugDumpProcess == 2 || gpSrv->DbgInfo.nDebugDumpProcess == 3)
		nBtn = (gpSrv->DbgInfo.nDebugDumpProcess == 2) ? IDYES : IDNO;
	else
		nBtn = MessageBoxA(NULL, asConfirmText ? asConfirmText : "Create minidump (<No> - fulldump)?", szTitleA, MB_YESNOCANCEL|MB_SYSTEMMODAL);

	switch (nBtn)
	{
	case IDYES:
		break;
	case IDNO:
		dumpType = MiniDumpWithFullMemory;
		break;
	default:
		return;
	}

	// Т.к. в режиме "ProcessTree" мы пишем пачку дампов - спрашивать тип дампа будем один раз.
	if (gpSrv->DbgInfo.bDebugProcessTree && (gpSrv->DbgInfo.nDebugDumpProcess <= 1))
	{
		gpSrv->DbgInfo.nDebugDumpProcess = (nBtn == IDNO) ? 3 : 2;
	}

	if (bTreeBreak)
	{
		GenerateTreeDebugBreak(dwProcessId);
	}

	bool bDumpSucceeded = false;
	HANDLE hDmpFile = NULL;
	//HMODULE hDbghelp = NULL;
	wchar_t szErrInfo[MAX_PATH*2];

	wchar_t dmpfile[MAX_PATH]; dmpfile[0] = 0;

	typedef BOOL (WINAPI* MiniDumpWriteDump_t)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType,
	        PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
	        PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
	MiniDumpWriteDump_t MiniDumpWriteDump_f = NULL;

	while (GetSaveDumpName(dwProcessId, (dumpType == MiniDumpWithFullMemory), dmpfile, countof(dmpfile)))
	{
		if (hDmpFile != INVALID_HANDLE_VALUE && hDmpFile != NULL)
		{
			CloseHandle(hDmpFile); hDmpFile = NULL;
		}
		
		hDmpFile = CreateFileW(dmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, NULL);

		if (hDmpFile == INVALID_HANDLE_VALUE)
		{
			DWORD nErr = GetLastError();
			_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't create debug dump file\n%s\nErrCode=0x%08X\n\nChoose another name?", dmpfile, nErr);

			if (MessageBoxW(NULL, szErrInfo, szTitle, MB_YESNO|MB_SYSTEMMODAL|MB_ICONSTOP)!=IDYES)
				break;

			continue; // еще раз выбрать
		}

		if (!gpSrv->DbgInfo.hDbghelp)
		{
			gpSrv->DbgInfo.hDbghelp = LoadLibraryW(L"Dbghelp.dll");

			if (gpSrv->DbgInfo.hDbghelp == NULL)
			{
				DWORD nErr = GetLastError();
				_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't load debug library 'Dbghelp.dll'\nErrCode=0x%08X\n\nTry again?", nErr);

				if (MessageBoxW(NULL, szErrInfo, szTitle, MB_YESNO|MB_SYSTEMMODAL|MB_ICONSTOP)!=IDYES)
					break;

				continue; // еще раз выбрать
			}
		}

		if (gpSrv->DbgInfo.MiniDumpWriteDump_f)
		{
			MiniDumpWriteDump_f = (MiniDumpWriteDump_t)gpSrv->DbgInfo.MiniDumpWriteDump_f;
		}
		else if (!MiniDumpWriteDump_f)
		{
			MiniDumpWriteDump_f = (MiniDumpWriteDump_t)GetProcAddress(gpSrv->DbgInfo.hDbghelp, "MiniDumpWriteDump");

			if (!MiniDumpWriteDump_f)
			{
				DWORD nErr = GetLastError();
				_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't locate 'MiniDumpWriteDump' in library 'Dbghelp.dll', ErrCode=%u", nErr);
				MessageBoxW(NULL, szErrInfo, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL);
				break;
			}

			gpSrv->DbgInfo.MiniDumpWriteDump_f = (FARPROC)MiniDumpWriteDump_f;
		}

		if (MiniDumpWriteDump_f)
		{
			MINIDUMP_EXCEPTION_INFORMATION mei = {dwThreadId};
			EXCEPTION_POINTERS ep = {pExceptionRecord};
			ep.ContextRecord = NULL; // Непонятно, откуда его можно взять
			mei.ExceptionPointers = &ep;
			mei.ClientPointers = FALSE;
			PMINIDUMP_EXCEPTION_INFORMATION pmei = NULL; // пока
			_printf("Creating minidump: ");
			_wprintf(dmpfile);
			_printf("...");

			HANDLE hProcess = GetProcessHandleForDebug(dwProcessId);

			BOOL lbDumpRc = MiniDumpWriteDump_f(
			                    hProcess, dwProcessId,
			                    hDmpFile,
			                    dumpType,
			                    pmei,
			                    NULL, NULL);

			if (!lbDumpRc)
			{
				DWORD nErr = GetLastError();
				_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"MiniDumpWriteDump failed.\nErrorCode=0x%08X", nErr);
				_printf("\nFailed, ErrorCode=0x%08X\n", nErr);
				MessageBoxW(NULL, szErrInfo, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL);
			}
			else
			{
				_printf("\nMiniDumpWriteDump succeeded\n");
				bDumpSucceeded = true;
			}

			break;
		}

	} // end while (GetSaveDumpName(dwProcessId, (dumpType == MiniDumpWithFullMemory), dmpfile, countof(dmpfile)))

	if (hDmpFile != INVALID_HANDLE_VALUE && hDmpFile != NULL)
	{
		CloseHandle(hDmpFile);
	}

	//if (hDbghelp)
	//{
	//	FreeLibrary(hDbghelp);
	//}

	//if (hCOMDLG32)
	//{
	//	FreeLibrary(hCOMDLG32);
	//}

	// В Win2k еще не было функции "отцепиться от процесса"
	if (bDumpSucceeded && gpSrv->DbgInfo.nDebugDumpProcess && !gpSrv->DbgInfo.bDebugProcessTree && (gnOsVer >= 0x0501))
	{
		// Дело сделали, закрываемся
		SetTerminateEvent(ste_WriteMiniDump);

		//if (pfnGetConsoleProcessList)
		//{
		//	DWORD nCurCount = 0;
		//	DWORD nConsolePids[128] = {};
		//	nCurCount = pfnGetConsoleProcessList(nConsolePids, countof(nConsolePids));

		//	// Но только если в консоли кроме нас никого нет
		//	if (nCurCount == 0)
		//	{
		//		PostMessage(ghConWnd, WM_CLOSE, 0, 0);
		//	}
		//	else
		//	{
		//		SetTerminateEvent();
		//	}
		//}
	}
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
int main(int argc, char** argv)
{
	gn_argc = argc; gp_argv = argv;

	int iRc = 0;
	HMODULE hConEmu = NULL;
	wchar_t szErrInfo[200];
	DWORD dwErr;
	typedef int (__stdcall* ConsoleMain2_t)(BOOL abAlternative);
	ConsoleMain2_t lfConsoleMain2;

	#ifdef _DEBUG
	HMODULE hConEmuHk = GetModuleHandle(WIN3264TEST(L"ConEmuHk.dll",L"ConEmuHk64.dll"));
	_ASSERTE(hConEmuHk==NULL && "Hooks must not be loaded into ConEmuC[64].exe!");
	#endif

	#if defined(SHOW_STARTED_MSGBOX)
	if (!IsDebuggerPresent())
	{
		wchar_t szTitle[100]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) WIN3264TEST(L"ConEmuC",L"ConEmuC64") L" Loaded (PID=%i)", GetCurrentProcessId());
		const wchar_t* pszCmdLine = GetCommandLineW();
		MessageBox(NULL,pszCmdLine,szTitle,0);
	}
	#endif

	// Обязательно, иначе по CtrlC мы свалимся
	SetConsoleCtrlHandler((PHANDLER_ROUTINE)HandlerRoutine, true);

	#ifdef _DEBUG
	UnitTests();
	#endif

	// Some command we can process internally
	if (ProcessCommandLine(iRc, hConEmu))
	{
		// Done, exiting
		goto wrap;
	}

	// Otherwise - do the full cycle
	if (!hConEmu)
		hConEmu = LoadLibrary(WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll"));
	dwErr = GetLastError();

	if (!hConEmu)
	{
		_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo))
		           L"Can't load library \"%s\", ErrorCode=0x%08X\n",
		           WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll"),
		           dwErr);
		_wprintf(szErrInfo);
		_ASSERTE(FALSE && "LoadLibrary failed");
		iRc = CERR_CONEMUHK_NOTFOUND;
		goto wrap;
	}

	// Загрузить функи из ConEmuHk
	lfConsoleMain2 = (ConsoleMain2_t)GetProcAddress(hConEmu, "ConsoleMain2");
	gfHandlerRoutine = (PHANDLER_ROUTINE)GetProcAddress(hConEmu, "HandlerRoutine");

	if (!lfConsoleMain2 || !gfHandlerRoutine)
	{
		dwErr = GetLastError();
		_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo))
		           L"Procedure \"%s\"  not found in library \"%s\"",
		           lfConsoleMain2 ? L"HandlerRoutine" : L"ConsoleMain2",
		           WIN3264TEST(L"ConEmuCD.dll",L"ConEmuCD64.dll"));
		_wprintf(szErrInfo);
		_ASSERTE(FALSE && "GetProcAddress failed");
		FreeLibrary(hConEmu);
		iRc = CERR_CONSOLEMAIN_NOTFOUND;
		goto wrap;
	}

	// Main dll entry point for Server & ComSpec
	iRc = lfConsoleMain2(0/*WorkMode*/);
	// Exiting
	gfHandlerRoutine = NULL;
	//FreeLibrary(hConEmu); -- Shutdown Server/Comspec уже выполнен
wrap:
	//-- bottle neck: relatively long deinitialization
	ExitProcess(iRc);
	return iRc;
}
Ejemplo n.º 7
0
// The function exists in both "ConEmuC/ConEmuC.cpp" and "ConEmuCD/Actions.cpp"
// Version in "ConEmuC/ConEmuC.cpp" shows arguments from main(int argc, char** argv)
// Version in "ConEmuCD/Actions.cpp" perhaps would not be ever called
int DoParseArgs(LPCWSTR asCmdLine)
{
	char szLine[80];

	_wsprintfA(szLine, SKIPLEN(countof(szLine)) "main arguments (%i)\n", gn_argc);
	_printf(szLine);
	for (int j = 0; j < gn_argc; j++)
	{
		_wsprintfA(szLine, SKIPLEN(countof(szLine)) "  %u: ", j);
		_printf(szLine);
		if (!gp_argv)
		{
			_printf("*NULL");
		}
		else if (!gp_argv[j])
		{
			_printf("<NULL>");
		}
		else
		{
			_printf("`");
			_printf(gp_argv[j]);
			_printf("`");
		}
		_printf("\n");
	}

	_printf("Parsing command\n  `");
	_wprintf(asCmdLine);
	_printf("`\n");

	int iShellCount = 0;
	LPWSTR* ppszShl = CommandLineToArgvW(asCmdLine, &iShellCount);

	int i = 0;
	CEStr szArg;
	_printf("ConEmu `NextArg` splitter\n");
	while (NextArg(&asCmdLine, szArg) == 0)
	{
		if (szArg.mb_Quoted)
			DemangleArg(szArg, true);
		_wsprintfA(szLine, SKIPLEN(countof(szLine)) "  %u: `", ++i);
		_printf(szLine);
		_wprintf(szArg);
		_printf("`\n");
	}
	_wsprintfA(szLine, SKIPLEN(countof(szLine)) "  Total arguments parsed: %u\n", i);
	_printf(szLine);

	_printf("Standard shell splitter\n");
	for (int j = 0; j < iShellCount; j++)
	{
		_wsprintfA(szLine, SKIPLEN(countof(szLine)) "  %u: `", j);
		_printf(szLine);
		_wprintf(ppszShl[j]);
		_printf("`\n");
	}
	_wsprintfA(szLine, SKIPLEN(countof(szLine)) "  Total arguments parsed: %u\n", iShellCount);
	_printf(szLine);
	LocalFree(ppszShl);

	return i;
}
Ejemplo n.º 8
0
// The function exists in both "ConEmuC/ConEmuC.cpp" and "ConEmuCD/Actions.cpp"
// Version in "ConEmuC/ConEmuC.cpp" shows arguments from main(int argc, char** argv)
// Version in "ConEmuCD/Actions.cpp" perhaps would not be ever called
int DoParseArgs(LPCWSTR asCmdLine)
{
	char szLine[80];
	char szCLVer[32];
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO csbi = {};
	GetConsoleScreenBufferInfo(hOut, &csbi);

	struct Highlighter
	{
		HANDLE hOut;
		WORD defAttr;
		Highlighter(HANDLE ahOut, WORD adefAttr, WORD fore)
			: hOut(ahOut), defAttr(adefAttr)
		{
			SetConsoleTextAttribute(hOut, fore|(defAttr & 0xF0));
		};
		~Highlighter()
		{
			SetConsoleTextAttribute(hOut, defAttr);
		};
	};
	#undef HL
	#define HL(fore) Highlighter hl(hOut, csbi.wAttributes, fore)

	#if defined(__GNUC__)
	lstrcpyn(szCLVer, "GNUC");
	#elif defined(_MSC_VER)
	_wsprintfA(szCLVer, SKIPCOUNT(szCLVer) "VC %u.%u", (int)(_MSC_VER / 100), (int)(_MSC_VER % 100));
	#else
	lstrcpyn(szCLVer, "<Unknown CL>");
	#endif

	_wsprintfA(szLine, SKIPCOUNT(szLine) "main arguments (count %i) {%s}\n", gn_argc, szCLVer);
	{ HL(10); _printf(szLine); }
	for (int j = 0; j < gn_argc; j++)
	{
		if (j >= 999)
		{
			HL(12);
			_printf("*** TOO MANY ARGUMENTS ***\n");
			break;
		}
		_wsprintfA(szLine, SKIPCOUNT(szLine) "  %u: ", j);
		{ HL(2); _printf(szLine); }
		if (!gp_argv)
		{
			HL(12);
			_printf("*NULL");
		}
		else if (!gp_argv[j])
		{
			HL(12);
			_printf("<NULL>");
		}
		else
		{
			{ HL(8); _printf("`"); }
			{ HL(15); _printf(gp_argv[j]); }
			{ HL(8); _printf("`"); }
		}
		_printf("\n");
	}

	{ HL(10); _printf("Parsing command"); }
	{ HL(8); _printf("\n  `"); }
	{ HL(15); _wprintf(asCmdLine); }
	{ HL(8); _printf("`\n"); }

	int iShellCount = 0;
	LPWSTR* ppszShl = CommandLineToArgvW(asCmdLine, &iShellCount);

	int i = 0;
	CEStr szArg;
	{ HL(10); _printf("ConEmu `NextArg` splitter\n"); }
	while (NextArg(&asCmdLine, szArg) == 0)
	{
		if (szArg.mb_Quoted)
			DemangleArg(szArg, true);
		_wsprintfA(szLine, SKIPCOUNT(szLine) "  %u: ", ++i);
		{ HL(2); _printf(szLine); }
		{ HL(8); _printf("`"); }
		{ HL(15); _wprintf(szArg); }
		{ HL(8); _printf("`\n"); }
	}
	_wsprintfA(szLine, SKIPCOUNT(szLine) "  Total arguments parsed: %u\n", i);
	{ HL(8); _printf(szLine); }

	{ HL(10); _printf("Standard shell splitter\n"); }
	for (int j = 0; j < iShellCount; j++)
	{
		_wsprintfA(szLine, SKIPCOUNT(szLine) "  %u: ", j);
		{ HL(2); _printf(szLine); }
		{ HL(8); _printf("`"); }
		{ HL(15); _wprintf(ppszShl[j]); }
		{ HL(8); _printf("`\n"); }
	}
	_wsprintfA(szLine, SKIPCOUNT(szLine) "  Total arguments parsed: %u\n", iShellCount);
	{ HL(8); _printf(szLine); }
	LocalFree(ppszShl);

	return i;
}
Ejemplo n.º 9
0
int ComspecInit()
{
    TODO("Определить код родительского процесса, и если это FAR - запомнить его (для подключения к пайпу плагина)");
    TODO("Размер получить из GUI, если оно есть, иначе - по умолчанию");
    TODO("GUI может скорректировать размер с учетом полосы прокрутки");
    WARNING("CreateFile(CONOUT$) по идее возвращает текущий ScreenBuffer. Можно его самим возвращать в ComspecDone");

    // Правда нужно проверить, что там происходит с ghConOut.Close(),...
    // Размер должен менять сам GUI, через серверный ConEmuC!
#ifdef SHOW_STARTED_MSGBOX
    MessageBox(GetConEmuHWND(2), L"ConEmuC (comspec mode) is about to START", L"ConEmuC.ComSpec", 0);
#endif
    //int nNewBufferHeight = 0;
    //COORD crNewSize = {0,0};
    //SMALL_RECT rNewWindow = gpSrv->sbi.srWindow;
    BOOL lbSbiRc = FALSE;
    gbRootWasFoundInCon = 2; // не добавлять к "Press Enter to close console" - "or wait"
    gbComspecInitCalled = TRUE; // Нельзя вызывать ComspecDone, если не было вызова ComspecInit
    // в режиме ComSpec - запрещено!
    gbAlwaysConfirmExit = FALSE;
    gbAutoDisableConfirmExit = FALSE;
#ifdef _DEBUG
    xf_validate();
    xf_dump_chk();
#endif
    // Это наверное и не нужно, просто для информации...
    lbSbiRc = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &gpSrv->sbi);
#ifdef _DEBUG
    DWORD nErrCode = lbSbiRc ? 0 : GetLastError();
    // Процесс запущен с редиректом вывода?
    _ASSERTE(lbSbiRc || (nErrCode == ERROR_INVALID_HANDLE));
#endif

#if 0
    // 111211 - "-new_console" теперь передается в GUI и исполняется в нем
    // Сюда мы попадаем если был ключик -new_console
    // А этом случае нужно завершить ЭТОТ экземпляр и запустить в ConEmu новую вкладку
    if (gpSrv->bNewConsole)
    {
#ifdef _DEBUG
        xf_validate();
        xf_dump_chk();
#endif
        PROCESS_INFORMATION pi;
        memset(&pi, 0, sizeof(pi));
        STARTUPINFOW si;
        memset(&si, 0, sizeof(si));
        si.cb = sizeof(si);
        si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USECOUNTCHARS;
        si.dwXCountChars = gpSrv->sbi.dwSize.X;
        si.dwYCountChars = gpSrv->sbi.dwSize.Y;
        si.wShowWindow = SW_HIDE;
        PRINT_COMSPEC(L"Creating new console for:\n%s\n", gpszRunCmd);
#ifdef _DEBUG
        xf_validate();
        xf_dump_chk();
#endif
        // CREATE_NEW_PROCESS_GROUP - низя, перестает работать Ctrl-C
        // Запускается новый сервер (новая консоль), сюда хуки ставить не надо.
        BOOL lbRc = createProcess(TRUE, NULL, gpszRunCmd, NULL,NULL, TRUE,
                                  NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE,
                                  NULL, NULL, &si, &pi);
        DWORD dwErr = GetLastError();

        if (!lbRc)
        {
            PrintExecuteError(gpszRunCmd, dwErr);
            return CERR_CREATEPROCESS;
        }

#ifdef _DEBUG
        xf_validate();
        xf_dump_chk();
#endif
        //delete psNewCmd; psNewCmd = NULL;
        AllowSetForegroundWindow(pi.dwProcessId);
        PRINT_COMSPEC(L"New console created. PID=%i. Exiting...\n", pi.dwProcessId);
        SafeCloseHandle(pi.hProcess);
        SafeCloseHandle(pi.hThread);
        DisableAutoConfirmExit();
        //gpSrv->nProcessStartTick = GetTickCount() - 2*CHECK_ROOTSTART_TIMEOUT; // менять nProcessStartTick не нужно. проверка только по флажкам
#ifdef _DEBUG
        xf_validate();
        xf_dump_chk();
#endif
        return CERR_RUNNEWCONSOLE;
    }
#endif

    // Если определена ComSpecC - значит ConEmuC переопределил стандартный ComSpec
    // Вернем его
    wchar_t szComSpec[MAX_PATH+1];
    const wchar_t* pszComSpecName;

    //110202 - comspec более не переопределяется
    //if (GetEnvironmentVariable(L"ComSpecC", szComSpec, MAX_PATH) && szComSpec[0] != 0)
    WARNING("TCC/ComSpec");
    if (GetEnvironmentVariable(L"ComSpec", szComSpec, MAX_PATH) && szComSpec[0] != 0)
    {
        //// Только если это (случайно) не conemuc.exe
        //wchar_t* pwszCopy = (wchar_t*)PointToName(szComSpec); //wcsrchr(szComSpec, L'\\');
        ////if (!pwszCopy) pwszCopy = szComSpec;

        //#pragma warning( push )
        //#pragma warning(disable : 6400)
        //if (lstrcmpiW(pwszCopy, L"ConEmuC")==0 || lstrcmpiW(pwszCopy, L"ConEmuC.exe")==0
        //        /*|| lstrcmpiW(pwszCopy, L"ConEmuC64")==0 || lstrcmpiW(pwszCopy, L"ConEmuC64.exe")==0*/)
        //	szComSpec[0] = 0;
        //#pragma warning( pop )

        //if (szComSpec[0])
        //{
        //	SetEnvironmentVariable(L"ComSpec", szComSpec);
        //	SetEnvironmentVariable(L"ComSpecC", NULL);
        //}

        pszComSpecName = (wchar_t*)PointToName(szComSpec);
    }
    else
    {
        WARNING("TCC/ComSpec");
        pszComSpecName = L"cmd.exe";
    }

    lstrcpyn(gpSrv->szComSpecName, pszComSpecName, countof(gpSrv->szComSpecName));

    if (pszComSpecName)
    {
        wchar_t szSelf[MAX_PATH+1];

        if (GetModuleFileName(NULL, szSelf, MAX_PATH))
        {
            lstrcpyn(gpSrv->szSelfName, (wchar_t*)PointToName(szSelf), countof(gpSrv->szSelfName));

            if (!GetAliases(gpSrv->szSelfName, &gpSrv->pszPreAliases, &gpSrv->nPreAliasSize))
            {
                if (gpSrv->pszPreAliases)
                {
                    _wprintf(gpSrv->pszPreAliases);
                    free(gpSrv->pszPreAliases);
                    gpSrv->pszPreAliases = NULL;
                }
            }
        }
    }

    SendStarted();
    //ConOutCloseHandle()
    return 0;
}
Ejemplo n.º 10
0
void ComspecDone(int aiRc)
{
#ifdef _DEBUG
    xf_dump_chk();
    xf_validate(NULL);
#endif
    //WARNING("Послать в GUI CONEMUCMDSTOPPED");
    LogSize(NULL, 0, "ComspecDone");

    // Это необходимо делать, т.к. при смене буфера (SetConsoleActiveScreenBuffer) приложением,
    // дескриптор нужно закрыть, иначе conhost может не вернуть предыдущий буфер
    //ConOutCloseHandle()

    // Поддержка алиасов
    if (gpSrv->szComSpecName[0] && gpSrv->szSelfName[0])
    {
        // Скопировать алиасы из cmd.exe в conemuc.exe
        wchar_t *pszPostAliases = NULL;
        DWORD nPostAliasSize;
        BOOL lbChanged = (gpSrv->pszPreAliases == NULL);

        if (!GetAliases(gpSrv->szComSpecName, &pszPostAliases, &nPostAliasSize))
        {
            if (pszPostAliases)
                _wprintf(pszPostAliases);
        }
        else
        {
            if (!lbChanged)
            {
                lbChanged = (gpSrv->nPreAliasSize!=nPostAliasSize);
            }

            if (!lbChanged && gpSrv->nPreAliasSize && gpSrv->pszPreAliases && pszPostAliases)
            {
                lbChanged = memcmp(gpSrv->pszPreAliases,pszPostAliases,gpSrv->nPreAliasSize)!=0;
            }

            if (lbChanged)
            {
                xf_dump_chk();

                if (gnMainServerPID)
                {
                    MCHKHEAP;
                    CESERVER_REQ* pIn = ExecuteNewCmd(CECMD_SAVEALIASES,sizeof(CESERVER_REQ_HDR)+nPostAliasSize);

                    if (pIn)
                    {
                        MCHKHEAP;
                        memmove(pIn->Data, pszPostAliases, nPostAliasSize);
                        MCHKHEAP;
                        CESERVER_REQ* pOut = ExecuteSrvCmd(gnMainServerPID, pIn, GetConEmuHWND(2), FALSE, 0, TRUE);
                        MCHKHEAP;

                        if (pOut) ExecuteFreeResult(pOut);

                        ExecuteFreeResult(pIn);
                        MCHKHEAP;
                    }
                }

                xf_dump_chk();
                wchar_t *pszNewName = pszPostAliases, *pszNewTarget, *pszNewLine;

                while (pszNewName && *pszNewName)
                {
                    pszNewLine = pszNewName + lstrlen(pszNewName);
                    pszNewTarget = wcschr(pszNewName, L'=');

                    if (pszNewTarget)
                    {
                        *pszNewTarget = 0;
                        pszNewTarget++;
                    }

                    if (*pszNewTarget == 0) pszNewTarget = NULL;

                    AddConsoleAlias(pszNewName, pszNewTarget, gpSrv->szSelfName);
                    pszNewName = pszNewLine+1;
                }

                xf_dump_chk();
            }
        }

        if (pszPostAliases)
        {
            free(pszPostAliases);
            pszPostAliases = NULL;
        }
    }

    xf_dump_chk();
    //TODO("Уведомить плагин через пайп (если родитель - FAR) что процесс завершен. Плагин должен считать и запомнить содержимое консоли и только потом вернуть управление в ConEmuC!");
    DWORD dwErr1 = 0; //, dwErr2 = 0;
    HANDLE hOut1 = NULL, hOut2 = NULL;
    BOOL lbRc1 = FALSE, lbRc2 = FALSE;
    CONSOLE_SCREEN_BUFFER_INFO sbi1 = {{0,0}}, sbi2 = {{0,0}};

#ifdef _DEBUG
    HWND hWndCon = GetConEmuHWND(2);
#endif

    // Тут нужна реальная, а не скорректированная информация!
    if (!gbNonGuiMode)
    {
        // Если GUI не сможет через сервер вернуть высоту буфера - это нужно сделать нам!
        lbRc1 = GetConsoleScreenBufferInfo(hOut1 = GetStdHandle(STD_OUTPUT_HANDLE), &sbi1);

        if (!lbRc1)
            dwErr1 = GetLastError();

        xf_dump_chk();
    }

    //PRAGMA_ERROR("Размер должен возвращать сам GUI, через серверный ConEmuC!");
#ifdef SHOW_STARTED_MSGBOX
    MessageBox(GetConEmuHWND(2), L"ConEmuC (comspec mode) is about to TERMINATE", L"ConEmuC.ComSpec", 0);
#endif

#ifdef _DEBUG
    xf_dump_chk();
    xf_validate(NULL);
#endif

    if (!gbNonGuiMode && (gpSrv->dwParentFarPID != 0))
    {
        //// Вернуть размер буфера (высота И ширина)
        //if (gpSrv->sbi.dwSize.X && gpSrv->sbi.dwSize.Y) {
        //	SMALL_RECT rc = {0};
        //	SetConsoleSize(0, gpSrv->sbi.dwSize, rc, "ComspecDone");
        //}
        //ConOutCloseHandle()
        CONSOLE_SCREEN_BUFFER_INFO l_csbi = {{0}};
        lbRc2 = GetConsoleScreenBufferInfo(hOut2 = GetStdHandle(STD_OUTPUT_HANDLE), &l_csbi);

        CESERVER_REQ *pOut = SendStopped(&l_csbi);

        if (pOut)
        {
            if (!pOut->StartStopRet.bWasBufferHeight)
            {
                //gpSrv->sbi.dwSize = pIn->StartStop.sbi.dwSize;
                lbRc1 = FALSE; // Консольное приложение самостоятельно сбросило буферный режим. Не дергаться...
            }
            else
            {
                lbRc1 = TRUE;
            }

            ExecuteFreeResult(pOut);
            pOut = NULL;
        }

        if (!gbWasBufferHeight)
        {
            lbRc2 = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi2);

#ifdef _DEBUG
            if (sbi2.dwSize.Y > 200)
            {
                wchar_t szTitle[128];
                _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmuC (PID=%i)", GetCurrentProcessId());
                MessageBox(NULL, L"BufferHeight was not turned OFF", szTitle, MB_SETFOREGROUND|MB_SYSTEMMODAL);
            }
#endif

            if (lbRc1 && lbRc2 && sbi2.dwSize.Y == sbi1.dwSize.Y)
            {
                // GUI не смог вернуть высоту буфера...
                // Это плохо, т.к. фар высоту буфера не меняет и будет сильно глючить на N сотнях строк...
                int nNeedHeight = gpSrv->sbi.dwSize.Y;

                if (nNeedHeight < 10)
                {
                    nNeedHeight = (sbi2.srWindow.Bottom-sbi2.srWindow.Top+1);
                }

                if (sbi2.dwSize.Y != nNeedHeight)
                {
                    _ASSERTE(sbi2.dwSize.Y == nNeedHeight);
                    PRINT_COMSPEC(L"Error: BufferHeight was not changed from %i\n", sbi2.dwSize.Y);
                    SMALL_RECT rc = {0};
                    sbi2.dwSize.Y = nNeedHeight;

                    if (gpLogSize) LogSize(&sbi2.dwSize, 0, ":ComspecDone.RetSize.before");

                    SetConsoleSize(0, sbi2.dwSize, rc, "ComspecDone.Force");

                    if (gpLogSize) LogSize(NULL, 0, ":ComspecDone.RetSize.after");
                }
            }
        }
    }

    if (gpSrv->pszPreAliases) {
        free(gpSrv->pszPreAliases);
        gpSrv->pszPreAliases = NULL;
    }

    //SafeCloseHandle(ghCtrlCEvent);
    //SafeCloseHandle(ghCtrlBreakEvent);
}
Ejemplo n.º 11
0
// gpSrv->dwRootProcess
void WriteMiniDump(DWORD dwProcessId, DWORD dwThreadId, EXCEPTION_RECORD *pExceptionRecord, LPCSTR asConfirmText /*= NULL*/, BOOL bTreeBreak /*= FALSE*/)
{
	// 2 - minidump, 3 - fulldump
	int nConfirmDumpType = ConfirmDumpType(dwProcessId, asConfirmText);
	if (nConfirmDumpType < 2)
	{
		// Отмена
		return;
	}

	MINIDUMP_TYPE dumpType = (nConfirmDumpType == 2) ? MiniDumpNormal : MiniDumpWithFullMemory;

	// Т.к. в режиме "ProcessTree" мы пишем пачку дампов - спрашивать тип дампа будем один раз.
	if (IsDumpMulti() // several processes were attached
		&& (gpSrv->DbgInfo.nDebugDumpProcess <= 1)) // 2 - minidump, 3 - fulldump
	{
		gpSrv->DbgInfo.nDebugDumpProcess = nConfirmDumpType;
	}

	if (bTreeBreak)
	{
		GenerateTreeDebugBreak(dwProcessId);
	}

	bool bDumpSucceeded = false;
	HANDLE hDmpFile = NULL;
	//HMODULE hDbghelp = NULL;
	wchar_t szErrInfo[MAX_PATH*2];

	wchar_t szTitle[64];
	_wsprintf(szTitle, SKIPLEN(countof(szTitle)) CE_CONEMUC_NAME_W L" Debugging PID=%u, Debugger PID=%u", dwProcessId, GetCurrentProcessId());

	wchar_t dmpfile[MAX_PATH] = L""; dmpfile[0] = 0;
	FormatDumpName(dmpfile, countof(dmpfile), dwProcessId, false, (dumpType == MiniDumpWithFullMemory));

	typedef BOOL (WINAPI* MiniDumpWriteDump_t)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType,
	        PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
	        PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
	MiniDumpWriteDump_t MiniDumpWriteDump_f = NULL;

	while (GetSaveDumpName(dwProcessId, (dumpType == MiniDumpWithFullMemory), dmpfile, countof(dmpfile)))
	{
		if (hDmpFile != INVALID_HANDLE_VALUE && hDmpFile != NULL)
		{
			CloseHandle(hDmpFile); hDmpFile = NULL;
		}

		hDmpFile = CreateFileW(dmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, NULL);

		if (hDmpFile == INVALID_HANDLE_VALUE)
		{
			DWORD nErr = GetLastError();
			_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't create debug dump file\n%s\nErrCode=0x%08X\n\nChoose another name?", dmpfile, nErr);

			if (MessageBoxW(NULL, szErrInfo, szTitle, MB_YESNO|MB_SYSTEMMODAL|MB_ICONSTOP)!=IDYES)
				break;

			continue; // еще раз выбрать
		}

		if (!gpSrv->DbgInfo.hDbghelp)
		{
			gpSrv->DbgInfo.hDbghelp = LoadLibraryW(L"Dbghelp.dll");

			if (gpSrv->DbgInfo.hDbghelp == NULL)
			{
				DWORD nErr = GetLastError();
				_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't load debug library 'Dbghelp.dll'\nErrCode=0x%08X\n\nTry again?", nErr);

				if (MessageBoxW(NULL, szErrInfo, szTitle, MB_YESNO|MB_SYSTEMMODAL|MB_ICONSTOP)!=IDYES)
					break;

				continue; // еще раз выбрать
			}
		}

		if (gpSrv->DbgInfo.MiniDumpWriteDump_f)
		{
			MiniDumpWriteDump_f = (MiniDumpWriteDump_t)gpSrv->DbgInfo.MiniDumpWriteDump_f;
		}
		else if (!MiniDumpWriteDump_f)
		{
			MiniDumpWriteDump_f = (MiniDumpWriteDump_t)GetProcAddress(gpSrv->DbgInfo.hDbghelp, "MiniDumpWriteDump");

			if (!MiniDumpWriteDump_f)
			{
				DWORD nErr = GetLastError();
				_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"Can't locate 'MiniDumpWriteDump' in library 'Dbghelp.dll', ErrCode=%u", nErr);
				MessageBoxW(NULL, szErrInfo, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL);
				break;
			}

			gpSrv->DbgInfo.MiniDumpWriteDump_f = (FARPROC)MiniDumpWriteDump_f;
		}

		if (MiniDumpWriteDump_f)
		{
			MINIDUMP_EXCEPTION_INFORMATION mei = {dwThreadId};
			EXCEPTION_POINTERS ep = {pExceptionRecord};
			ep.ContextRecord = NULL; // Непонятно, откуда его можно взять
			mei.ExceptionPointers = &ep;
			mei.ClientPointers = FALSE;
			PMINIDUMP_EXCEPTION_INFORMATION pmei = NULL; // пока
			_printf("Creating minidump: ");
			_wprintf(dmpfile);
			_printf("...");

			HANDLE hProcess = GetProcessHandleForDebug(dwProcessId);

			BOOL lbDumpRc = MiniDumpWriteDump_f(
			                    hProcess, dwProcessId,
			                    hDmpFile,
			                    dumpType,
			                    pmei,
			                    NULL, NULL);

			if (!lbDumpRc)
			{
				DWORD nErr = GetLastError();
				_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"MiniDumpWriteDump failed.\nErrorCode=0x%08X", nErr);
				_printf("\nFailed, ErrorCode=0x%08X\n", nErr);
				MessageBoxW(NULL, szErrInfo, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL);
			}
			else
			{
				int iLeft = (gpSrv->DbgInfo.nWaitTreeBreaks > 0) ? (gpSrv->DbgInfo.nWaitTreeBreaks - 1) : 0;
				_wsprintf(szErrInfo, SKIPLEN(countof(szErrInfo)) L"\nMiniDumpWriteDump succeeded, %i left\n", iLeft);
				bDumpSucceeded = true;
			}

			break;
		}

	} // end while (GetSaveDumpName(dwProcessId, (dumpType == MiniDumpWithFullMemory), dmpfile, countof(dmpfile)))

	if (hDmpFile != INVALID_HANDLE_VALUE && hDmpFile != NULL)
	{
		CloseHandle(hDmpFile);
	}


	// В Win2k еще не было функции "отцепиться от процесса"
	if ((gnOsVer >= 0x0501)
		&& bDumpSucceeded && gpSrv->DbgInfo.bUserRequestDump
		// И все дампы были созданы
		&& (gpSrv->DbgInfo.nWaitTreeBreaks <= 1)
		// И это не ключи /DEBUGEXE или /DEBUGTREE
		&& !gpSrv->DbgInfo.pszDebuggingCmdLine
		)
	{
		// По завершении создания дампов - выйти
		SetTerminateEvent(ste_WriteMiniDump);
	}
}
Ejemplo n.º 12
0
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;
}