示例#1
0
DWORD WINAPI OnGetConsoleAliasesW(LPWSTR AliasBuffer, DWORD AliasBufferLength, LPWSTR ExeName)
{
	//typedef DWORD (WINAPI* OnGetConsoleAliasesW_t)(LPWSTR AliasBuffer, DWORD AliasBufferLength, LPWSTR ExeName);
	ORIGINALFAST(GetConsoleAliasesW);
	DWORD nError = 0;
	DWORD nRc = F(GetConsoleAliasesW)(AliasBuffer,AliasBufferLength,ExeName);

	if (!nRc)
	{
		nError = GetLastError();

		// финт ушами
		if (nError == ERROR_NOT_ENOUGH_MEMORY) // && gdwServerPID)
		{
			DWORD nServerPID = gnServerPID;
			HWND hConWnd = GetRealConsoleWindow();
			_ASSERTE(hConWnd == ghConWnd);

			//MFileMapping<CESERVER_CONSOLE_MAPPING_HDR> ConInfo;
			//ConInfo.InitName(CECONMAPNAME, (DWORD)hConWnd); //-V205
			//CESERVER_CONSOLE_MAPPING_HDR *pInfo = ConInfo.Open();
			//if (pInfo
			//	&& (pInfo->cbSize >= sizeof(CESERVER_CONSOLE_MAPPING_HDR))
			//	//&& (pInfo->nProtocolVersion == CESERVER_REQ_VER)
			//	)
			//{
			//	nServerPID = pInfo->nServerPID;
			//	ConInfo.CloseMap();
			//}

			if (nServerPID)
			{
				CESERVER_REQ_HDR In;
				ExecutePrepareCmd(&In, CECMD_GETALIASES, sizeof(CESERVER_REQ_HDR));
				CESERVER_REQ* pOut = ExecuteSrvCmd(nServerPID/*gdwServerPID*/, (CESERVER_REQ*)&In, hConWnd);

				if (pOut)
				{
					size_t nData = min(AliasBufferLength,(pOut->hdr.cbSize-sizeof(pOut->hdr)));

					if (nData)
					{
						memmove(AliasBuffer, pOut->Data, nData);
						nRc = TRUE;
					}

					ExecuteFreeResult(pOut);
				}
			}
		}

		if (!nRc)
			SetLastError(nError); // вернуть, вдруг какая функция его поменяла
	}

	return nRc;
}
示例#2
0
文件: Entry.cpp 项目: alexlav/conemu
void SendStopped()
{
	if (gbNonGuiMode || !gnServerPID)
		return;
	
	CESERVER_REQ *pIn = NULL, *pOut = NULL;
	size_t nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOP);
	pIn = ExecuteNewCmd(CECMD_CMDSTARTSTOP,nSize);

	if (pIn)
	{
		pIn->StartStop.nStarted = sst_AppStop;

		if (!GetModuleFileName(NULL, pIn->StartStop.sModuleName, countof(pIn->StartStop.sModuleName)))
			pIn->StartStop.sModuleName[0] = 0;

		pIn->StartStop.hWnd = ghConWnd;
		pIn->StartStop.dwPID = gnSelfPID;
		pIn->StartStop.nSubSystem = gnImageSubsystem;
		pIn->StartStop.bWasBufferHeight = gbWasBufferHeight;
		pIn->StartStop.nOtherPID = gnPrevAltServerPID;

		HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

		// НЕ MyGet..., а то можем заблокироваться...
		// ghConOut может быть NULL, если ошибка произошла во время разбора аргументов
		GetConsoleScreenBufferInfo(hOut, &pIn->StartStop.sbi);

		pIn->StartStop.crMaxSize = MyGetLargestConsoleWindowSize(hOut);

		pOut = ExecuteSrvCmd(gnServerPID, pIn, ghConWnd, TRUE/*bAsyncNoResult*/);

		ExecuteFreeResult(pIn); pIn = NULL;
		
		if (pOut)
		{
			ExecuteFreeResult(pOut);
			pOut = NULL;
		}
	}
}
示例#3
0
// Do the attach procedure for the requested process
bool CAttachDlg::StartAttach(HWND ahAttachWnd, DWORD anPID, DWORD anBits, AttachProcessType anType, BOOL abAltMode)
{
	bool lbRc = false;
	wchar_t szPipe[MAX_PATH];
	PROCESS_INFORMATION pi = {};
	STARTUPINFO si = {sizeof(si)};
	SHELLEXECUTEINFO sei = {sizeof(sei)};
	CESERVER_REQ *pIn = NULL, *pOut = NULL;
	HANDLE hPipeTest = NULL;
	HANDLE hPluginTest = NULL;
	HANDLE hProcTest = NULL;
	DWORD nErrCode = 0;
	bool lbCreate;
	CESERVER_CONSOLE_MAPPING_HDR srv;
	DWORD nWrapperWait = -1;
	DWORD nWrapperResult = -1;

	if (!ahAttachWnd || !anPID || !anBits || !anType)
	{
		MBoxAssert(ahAttachWnd && anPID && anBits && anType);
		goto wrap;
	}

	if (gpSetCls->isAdvLogging)
	{
		wchar_t szInfo[128];
		_wsprintf(szInfo, SKIPLEN(countof(szInfo))
			L"CAttachDlg::StartAttach HWND=x%08X, PID=%u, Bits%u, Type=%u, AltMode=%u",
			(DWORD)(DWORD_PTR)ahAttachWnd, anPID, anBits, (UINT)anType, abAltMode);
		gpConEmu->LogString(szInfo);
	}

	if (LoadSrvMapping(ahAttachWnd, srv))
	{
		pIn = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR));
		pOut = ExecuteSrvCmd(srv.nServerPID, pIn, ghWnd);
		if (pOut && (pOut->hdr.cbSize >= (sizeof(CESERVER_REQ_HDR)+sizeof(DWORD))) && (pOut->dwData[0] != 0))
		{
			// Our console server had been already started
			// and we successfully have completed the attach
			lbRc = true;
			goto wrap;
		}
		ExecuteFreeResult(pIn);
		ExecuteFreeResult(pOut);
	}


	// Is it a Far Manager with our ConEmu.dll plugin loaded?
	_wsprintf(szPipe, SKIPLEN(countof(szPipe)) CEPLUGINPIPENAME, L".", anPID);
	hPluginTest = CreateFile(szPipe, GENERIC_READ|GENERIC_WRITE, 0, LocalSecurity(), OPEN_EXISTING, 0, NULL);
	if (hPluginTest && hPluginTest != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hPluginTest);
		goto DoPluginCall;
	}

	// May be there is already ConEmuHk[64].dll loaded? Either it is already in the another ConEmu VCon?
	_wsprintf(szPipe, SKIPLEN(countof(szPipe)) CEHOOKSPIPENAME, L".", anPID);
	hPipeTest = CreateFile(szPipe, GENERIC_READ|GENERIC_WRITE, 0, LocalSecurity(), OPEN_EXISTING, 0, NULL);
	if (hPipeTest && hPipeTest != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hPipeTest);
		goto DoExecute;
	}


	wchar_t szSrv[MAX_PATH+64], szArgs[128];
	wcscpy_c(szSrv, gpConEmu->ms_ConEmuBaseDir);
	wcscat_c(szSrv, (anBits==64) ? L"\\ConEmuC64.exe" : L"\\ConEmuC.exe");

	if (abAltMode && (anType == apt_Console))
	{
		_wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /ATTACH /CONPID=%u /GID=%u /GHWND=%08X", anPID, GetCurrentProcessId(), LODWORD(ghWnd));
	}
	else
	{
		_wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /INJECT=%u", anPID);
		abAltMode = FALSE;
	}

	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;

	if (anType == apt_Gui)
	{
		gpConEmu->CreateGuiAttachMapping(anPID);
	}

	hProcTest = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, anPID);

	// If the attaching process is running as admin (elevated) we have to run ConEmuC as admin too
	if (hProcTest == NULL)
	{
		nErrCode = GetLastError();
		MBoxAssert(hProcTest!=NULL || nErrCode==ERROR_ACCESS_DENIED);

		sei.hwnd = ghWnd;
		sei.fMask = (abAltMode ? 0 : SEE_MASK_NO_CONSOLE)|SEE_MASK_NOCLOSEPROCESS|SEE_MASK_NOASYNC;
		sei.lpVerb = L"runas";
		sei.lpFile = szSrv;
		sei.lpParameters = szArgs;
		sei.lpDirectory = gpConEmu->ms_ConEmuBaseDir;
		sei.nShow = SW_SHOWMINIMIZED;

		lbCreate = ShellExecuteEx(&sei);
		if (lbCreate)
		{
			MBoxAssert(sei.hProcess!=NULL);
			pi.hProcess = sei.hProcess;
		}
	}
	else
	{
		// Normal start
		DWORD dwFlags = 0
			| (abAltMode ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE)
			| CREATE_DEFAULT_ERROR_MODE
			| NORMAL_PRIORITY_CLASS;
		lbCreate = CreateProcess(szSrv, szArgs, NULL, NULL, FALSE, dwFlags, NULL, NULL, &si, &pi);
	}

	if (!lbCreate)
	{
		wchar_t szErrMsg[MAX_PATH+255], szTitle[128];
		DWORD dwErr = GetLastError();
		_wsprintf(szErrMsg, SKIPLEN(countof(szErrMsg)) L"Can't start %s server\n%s %s", abAltMode ? L"injection" : L"console", szSrv, szArgs);
		_wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId());
		DisplayLastError(szErrMsg, dwErr, 0, szTitle);
		goto wrap;
	}

	if (abAltMode)
	{
		lbRc = true;
		goto wrap;
	}

	nWrapperWait = WaitForSingleObject(pi.hProcess, INFINITE);
	nWrapperResult = -1;
	GetExitCodeProcess(pi.hProcess, &nWrapperResult);
	CloseHandle(pi.hProcess);
	if (pi.hThread) CloseHandle(pi.hThread);
	if (((int)nWrapperResult != CERR_HOOKS_WAS_SET) && ((int)nWrapperResult != CERR_HOOKS_WAS_ALREADY_SET))
	{
		goto wrap;
	}


DoExecute:
	// Not the attaching process has our ConEmuHk[64].dll loaded
	// and we can request to start console server for that console or ChildGui
	pIn = ExecuteNewCmd(CECMD_STARTSERVER, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START));
	pIn->NewServer.nGuiPID = GetCurrentProcessId();
	pIn->NewServer.hGuiWnd = ghWnd;
	if (anType == apt_Gui)
	{
		_ASSERTE(ahAttachWnd && IsWindow(ahAttachWnd));
		pIn->NewServer.hAppWnd = ahAttachWnd;
	}
	goto DoPipeCall;

DoPluginCall:
	// Ask Far Manager plugin to do the attach
	pIn = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR));
	goto DoPipeCall;

DoPipeCall:
	pOut = ExecuteCmd(szPipe, pIn, 500, ghWnd);
	if (!pOut || (pOut->hdr.cbSize < pIn->hdr.cbSize) || (pOut->dwData[0] == 0))
	{
		_ASSERTE(pOut && pOut->hdr.cbSize == (sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START)));

		wchar_t szMsg[255], szTitle[128];
		wcscpy_c(szMsg, L"Failed to start console server in the remote process");
		if (hPluginTest && hPluginTest != INVALID_HANDLE_VALUE)
			wcscat_c(szMsg, L"\nFar ConEmu plugin was loaded");
		if (hPipeTest && hPipeTest != INVALID_HANDLE_VALUE)
			wcscat_c(szMsg, L"\nHooks already were set");
		_wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId());
		DisplayLastError(szMsg, (pOut && (pOut->hdr.cbSize >= pIn->hdr.cbSize)) ? pOut->dwData[1] : -1, 0, szTitle);
		goto wrap;
	}


	lbRc = true;
wrap:
	SafeCloseHandle(hProcTest);
	UNREFERENCED_PARAMETER(nErrCode);
	UNREFERENCED_PARAMETER(nWrapperWait);
	ExecuteFreeResult(pIn);
	ExecuteFreeResult(pOut);
	return lbRc;
}
示例#4
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);
}
示例#5
0
// Due to Microsoft bug we need to lock Server reading thread to avoid crash of kernel
// http://conemu.github.io/en/MicrosoftBugs.html#Exception_in_ReadConsoleOutput
void LockServerReadingThread(bool bLock, COORD dwSize, CESERVER_REQ*& pIn, CESERVER_REQ*& pOut)
{
	DWORD nServerPID = gnServerPID;
	if (!nServerPID)
		return;

	DWORD nErrSave = GetLastError();

	if (bLock)
	{
		HANDLE hOurThreadHandle = NULL;

		// We need to give our thread handle (to server process) to avoid
		// locking of server reading thread (in case of our thread fails)
		DWORD dwErr = -1;
		HANDLE hServer = OpenProcess(PROCESS_DUP_HANDLE, FALSE, nServerPID);
		if (!hServer)
		{
			dwErr = GetLastError();
			_ASSERTEX(hServer!=NULL && "Open server handle fails, Can't dup handle!");
		}
		else
		{
			if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), hServer, &hOurThreadHandle,
					SYNCHRONIZE|THREAD_QUERY_INFORMATION, FALSE, 0))
			{
				dwErr = GetLastError();
				_ASSERTEX(hServer!=NULL && "DuplicateHandle fails, Can't dup handle!");
				hOurThreadHandle = NULL;
			}
			CloseHandle(hServer);
		}

		pIn = ExecuteNewCmd(CECMD_SETCONSCRBUF, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SETCONSCRBUF));
		if (pIn)
		{
			pIn->SetConScrBuf.bLock = TRUE;
			pIn->SetConScrBuf.dwSize = dwSize; // Informational
			pIn->SetConScrBuf.hRequestor = hOurThreadHandle;
		}
	}
	else
	{
		if (pIn)
		{
			pIn->SetConScrBuf.bLock = FALSE;
		}
	}

	if (pIn)
	{
		ExecuteFreeResult(pOut);
		pOut = ExecuteSrvCmd(nServerPID, pIn, ghConWnd);
		if (pOut && pOut->DataSize() >= sizeof(CESERVER_REQ_SETCONSCRBUF))
		{
			pIn->SetConScrBuf.hTemp = pOut->SetConScrBuf.hTemp;
		}
	}

	if (!bLock)
	{
		ExecuteFreeResult(pIn);
		ExecuteFreeResult(pOut);
	}

	// Transparently to calling function...
	SetLastError(nErrSave);
}
示例#6
0
bool CAttachDlg::StartAttach(HWND ahAttachWnd, DWORD anPID, DWORD anBits, AttachProcessType anType, BOOL abAltMode)
{
	bool lbRc = false;
	// Тут нужно получить инфу из списка и дернуть собственно аттач
	wchar_t szPipe[MAX_PATH];
	PROCESS_INFORMATION pi = {};
	STARTUPINFO si = {sizeof(si)};
	SHELLEXECUTEINFO sei = {sizeof(sei)};
	CESERVER_REQ *pIn = NULL, *pOut = NULL;
	HANDLE hPipeTest = NULL, hProcTest = NULL;
	DWORD nErrCode = 0;
	bool lbCreate;
	CESERVER_CONSOLE_MAPPING_HDR srv;
	DWORD nWrapperWait = -1;
	DWORD nWrapperResult = -1;

	if (!ahAttachWnd || !anPID || !anBits || !anType)
	{
		MBoxAssert(ahAttachWnd && anPID && anBits && anType);
		goto wrap;
	}

	if (gpSetCls->isAdvLogging)
	{
		wchar_t szInfo[128];
		_wsprintf(szInfo, SKIPLEN(countof(szInfo))
			L"CAttachDlg::StartAttach HWND=x%08X, PID=%u, Bits%u, Type=%u, AltMode=%u",
			(DWORD)(DWORD_PTR)ahAttachWnd, anPID, anBits, (UINT)anType, abAltMode);
		gpConEmu->LogString(szInfo);
	}

	if (LoadSrvMapping(ahAttachWnd, srv))
	{
		pIn = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR));
		pOut = ExecuteSrvCmd(srv.nServerPID, pIn, ghWnd);
		if (pOut && (pOut->hdr.cbSize >= (sizeof(CESERVER_REQ_HDR)+sizeof(DWORD))) && (pOut->dwData[0] != 0))
		{
			lbRc = true; // Успешно подцепились
			goto wrap;
		}
		ExecuteFreeResult(pIn);
		ExecuteFreeResult(pOut);
	}


	// Может быть в процессе уже есть ConEmuHk.dll? Или этот процесс вообще уже во вкладке другого ConEmu?
	_wsprintf(szPipe, SKIPLEN(countof(szPipe)) CEHOOKSPIPENAME, L".", anPID);
	hPipeTest = CreateFile(szPipe, GENERIC_READ|GENERIC_WRITE, 0, LocalSecurity(), OPEN_EXISTING, 0, NULL);
	if (hPipeTest && hPipeTest != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hPipeTest);
		goto DoExecute;
	}


	wchar_t szSrv[MAX_PATH+64], szArgs[128];
	wcscpy_c(szSrv, gpConEmu->ms_ConEmuBaseDir);
	wcscat_c(szSrv, (anBits==64) ? L"\\ConEmuC64.exe" : L"\\ConEmuC.exe");

	if (abAltMode && (anType == apt_Console))
	{
		_wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /ATTACH /CONPID=%u /GID=%u /GHWND=%08X", anPID, GetCurrentProcessId(), (DWORD)ghWnd);
	}
	else
	{
		_wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /INJECT=%u", anPID);
		abAltMode = FALSE;
	}

	TODO("Определить, может он уже под админом? Тогда и ConEmuC.exe под админом запускать нужно");
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;

	if (anType == apt_Gui)
	{
		gpConEmu->CreateGuiAttachMapping(anPID);
	}

	hProcTest = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, anPID);

	if (hProcTest == NULL)
	{
		nErrCode = GetLastError();
		MBoxAssert(hProcTest!=NULL || nErrCode==ERROR_ACCESS_DENIED);

		sei.hwnd = ghWnd;
		sei.fMask = (abAltMode ? 0 : SEE_MASK_NO_CONSOLE)|SEE_MASK_NOCLOSEPROCESS|SEE_MASK_NOASYNC;
		sei.lpVerb = L"runas";
		sei.lpFile = szSrv;
		sei.lpParameters = szArgs;
		sei.lpDirectory = gpConEmu->ms_ConEmuBaseDir;
		sei.nShow = SW_SHOWMINIMIZED;

		lbCreate = ShellExecuteEx(&sei);
		if (lbCreate)
		{
			MBoxAssert(sei.hProcess!=NULL);
			pi.hProcess = sei.hProcess;
		}
	}
	else
	{
		lbCreate = CreateProcess(szSrv, szArgs, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|(abAltMode ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE), NULL, NULL, &si, &pi);
	}

	if (!lbCreate)
	{
		wchar_t szErrMsg[MAX_PATH+255], szTitle[128];
		DWORD dwErr = GetLastError();
		_wsprintf(szErrMsg, SKIPLEN(countof(szErrMsg)) L"Can't start %s server\n%s %s", abAltMode ? L"injection" : L"console", szSrv, szArgs);
		_wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId());
		DisplayLastError(szErrMsg, dwErr, 0, szTitle);
		goto wrap;
	}

	if (abAltMode)
	{
		TODO("Подождать бы завершения процесса, или пока он подцепится к GUI");
		lbRc = true;
		goto wrap;
	}

	nWrapperWait = WaitForSingleObject(pi.hProcess, INFINITE);
	nWrapperResult = -1;
	GetExitCodeProcess(pi.hProcess, &nWrapperResult);
	CloseHandle(pi.hProcess);
	if (pi.hThread) CloseHandle(pi.hThread);
	if (((int)nWrapperResult != CERR_HOOKS_WAS_SET) && ((int)nWrapperResult != CERR_HOOKS_WAS_ALREADY_SET))
	{
		goto wrap;
	}


DoExecute:
	// Теперь можно дернуть созданный в удаленном процессе пайп для запуска в той консоли сервера.
	pIn = ExecuteNewCmd(CECMD_STARTSERVER, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START));
	pIn->NewServer.nGuiPID = GetCurrentProcessId();
	pIn->NewServer.hGuiWnd = ghWnd;
	if (anType == apt_Gui)
	{
		_ASSERTE(ahAttachWnd && IsWindow(ahAttachWnd));
		pIn->NewServer.hAppWnd = ahAttachWnd;
	}
	pOut = ExecuteCmd(szPipe, pIn, 500, ghWnd);
	if (!pOut || (pOut->hdr.cbSize < pIn->hdr.cbSize) || (pOut->dwData[0] == 0))
	{
		_ASSERTE(pOut && pOut->hdr.cbSize == (sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START)));

		wchar_t szMsg[255], szTitle[128];
		wcscpy_c(szMsg, L"Failed to start console server in the remote process");
		if (hPipeTest && hPipeTest != INVALID_HANDLE_VALUE)
			wcscat_c(szMsg, L"\nHooks already was set");
		_wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId());
		DisplayLastError(szMsg, (pOut && (pOut->hdr.cbSize >= pIn->hdr.cbSize)) ? pOut->dwData[1] : -1, 0, szTitle);
		goto wrap;
	}


	lbRc = true;
wrap:
	UNREFERENCED_PARAMETER(nErrCode);
	UNREFERENCED_PARAMETER(nWrapperWait);
	ExecuteFreeResult(pIn);
	ExecuteFreeResult(pOut);
	return lbRc;
}
示例#7
0
文件: Entry.cpp 项目: alexlav/conemu
void SendStarted()
{
	if (gnServerPID == 0)
	{
		gbNonGuiMode = TRUE; // Не посылать ExecuteGuiCmd при выходе. Это не наша консоль
		return; // Режим ComSpec, но сервера нет, соответственно, в GUI ничего посылать не нужно
	}

	CESERVER_REQ *pIn = NULL, *pOut = NULL;
	size_t nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOP); //-V119
	pIn = ExecuteNewCmd(CECMD_CMDSTARTSTOP, nSize);

	if (pIn)
	{
		if (!GetModuleFileName(NULL, pIn->StartStop.sModuleName, countof(pIn->StartStop.sModuleName)))
			pIn->StartStop.sModuleName[0] = 0;
		#ifdef _DEBUG
		LPCWSTR pszFileName = wcsrchr(pIn->StartStop.sModuleName, L'\\');
		#endif

		pIn->StartStop.nStarted = sst_AppStart;
		pIn->StartStop.hWnd = ghConWnd;
		pIn->StartStop.dwPID = gnSelfPID;
		pIn->StartStop.nImageBits = WIN3264TEST(32,64);

		pIn->StartStop.nSubSystem = gnImageSubsystem;
		//pIn->StartStop.bRootIsCmdExe = gbRootIsCmdExe; //2009-09-14
		// НЕ MyGet..., а то можем заблокироваться...
		HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

		GetConsoleScreenBufferInfo(hOut, &pIn->StartStop.sbi);
		gbWasBufferHeight = (pIn->StartStop.sbi.dwSize.Y > (pIn->StartStop.sbi.srWindow.Bottom - pIn->StartStop.sbi.srWindow.Top + 100));

		pIn->StartStop.crMaxSize = MyGetLargestConsoleWindowSize(hOut);


		BOOL bAsync = FALSE;
		if (ghConWnd && (gnGuiPID != 0) && (gnImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI))
			bAsync = TRUE;

		pOut = ExecuteSrvCmd(gnServerPID, pIn, ghConWnd, bAsync);


		if (bAsync || pOut)
		{
			if (pOut)
			{
				gbWasBufferHeight = pOut->StartStopRet.bWasBufferHeight;
				gnGuiPID = pOut->StartStopRet.dwPID;
				ghConEmuWnd = pOut->StartStopRet.hWnd;
				_ASSERTE(ghConEmuWnd==NULL || gnGuiPID!=0);
				ghConEmuWndDC = pOut->StartStopRet.hWndDC;
				_ASSERTE(ghConEmuWndDC && user->isWindow(ghConEmuWndDC));

				gnServerPID = pOut->StartStopRet.dwMainSrvPID;
				ExecuteFreeResult(pOut); pOut = NULL;
			}
		}
		else
		{
			gbNonGuiMode = TRUE; // Не посылать ExecuteGuiCmd при выходе. Это не наша консоль
		}

		ExecuteFreeResult(pIn); pIn = NULL;
	}
}