Exemplo n.º 1
0
int WINAPI OnStretchDIBits(HDC hdc, int XDest, int YDest, int nDestWidth, int nDestHeight, int XSrc, int YSrc, int nSrcWidth, int nSrcHeight, const VOID *lpBits, const BITMAPINFO *lpBitsInfo, UINT iUsage, DWORD dwRop)
{
	//typedef int (WINAPI* OnStretchDIBits_t)(HDC hdc, int XDest, int YDest, int nDestWidth, int nDestHeight, int XSrc, int YSrc, int nSrcWidth, int nSrcHeight, const VOID *lpBits, const BITMAPINFO *lpBitsInfo, UINT iUsage, DWORD dwRop);
	ORIGINALFASTEX(StretchDIBits,NULL);
	int iRc = 0;

	if (F(StretchDIBits))
		iRc = F(StretchDIBits)(hdc, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc, nSrcWidth, nSrcHeight, lpBits, lpBitsInfo, iUsage, dwRop);

	// Если рисуют _прямо_ на канвасе ConEmu
	if (iRc != (int)GDI_ERROR && hdc && hdc == ghTempHDC)
	{
		// Уведомить GUI, что у него прямо на канвасе кто-то что-то нарисовал :)
		CESERVER_REQ* pIn = ExecuteNewCmd(CECMD_LOCKDC, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_LOCKDC));
		if (pIn)
		{
			pIn->LockDc.hDcWnd = ghConEmuWndDC; // На всякий случай
			pIn->LockDc.bLock = TRUE;
			pIn->LockDc.Rect.left = XDest;
			pIn->LockDc.Rect.top = YDest;
			pIn->LockDc.Rect.right = XDest+nDestWidth-1;
			pIn->LockDc.Rect.bottom = YDest+nDestHeight-1;

			CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd);

			if (pOut)
				ExecuteFreeResult(pOut);
			ExecuteFreeResult(pIn);
		}
	}

	return iRc;
}
Exemplo n.º 2
0
void CorrectGuiChildRect(DWORD anStyle, DWORD anStyleEx, RECT& rcGui)
{
	RECT rcShift = {};

	if ((anStyle != gGuiClientStyles.nStyle) || (anStyleEx != gGuiClientStyles.nStyleEx))
	{
		DWORD nSize = sizeof(CESERVER_REQ_HDR)+sizeof(GuiStylesAndShifts);
		CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_GUICLIENTSHIFT, nSize);
		if (pIn)
		{
			pIn->GuiAppShifts.nStyle = anStyle;
			pIn->GuiAppShifts.nStyleEx = anStyleEx;
			wchar_t szOurExe[MAX_PATH*2] = L"";
			GetModuleFileName(NULL, szOurExe, countof(szOurExe));
			lstrcpyn(pIn->GuiAppShifts.szExeName, PointToName(szOurExe), countof(pIn->GuiAppShifts.szExeName));

			wchar_t szGuiPipeName[128];
			msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", (DWORD)ghConEmuWnd);

			CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 10000, NULL);
			if (pOut)
			{
				gGuiClientStyles = pOut->GuiAppShifts;
				ExecuteFreeResult(pOut);
			}
			ExecuteFreeResult(pIn);
		}
	}

	rcShift = gGuiClientStyles.Shifts;

	rcGui.left += rcShift.left; rcGui.top += rcShift.top;
	rcGui.right += rcShift.right; rcGui.bottom += rcShift.bottom;
}
Exemplo n.º 3
0
// Undocumented function
BOOL WINAPI OnSetConsoleKeyShortcuts(BOOL bSet, BYTE bReserveKeys, LPVOID p1, DWORD n1)
{
	//typedef BOOL (WINAPI* OnSetConsoleKeyShortcuts_t)(BOOL,BYTE,LPVOID,DWORD);
	ORIGINALFASTEX(SetConsoleKeyShortcuts,NULL);
	BOOL lbRc = FALSE;

	if (F(SetConsoleKeyShortcuts))
		lbRc = F(SetConsoleKeyShortcuts)(bSet, bReserveKeys, p1, n1);

	if (ghConEmuWnd && IsWindow(ghConEmuWnd))
	{
		DWORD nLastErr = GetLastError();
		DWORD nSize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE)*2;
		CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_KEYSHORTCUTS, nSize);
		if (pIn)
		{
			pIn->Data[0] = bSet;
			pIn->Data[1] = bReserveKeys;

			wchar_t szGuiPipeName[128];
			msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", LODWORD(ghConWnd));

			CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 1000, NULL);

			if (pOut)
				ExecuteFreeResult(pOut);
			ExecuteFreeResult(pIn);
		}
		SetLastError(nLastErr);
	}

	return lbRc;
}
Exemplo n.º 4
0
BOOL WINAPI OnBitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop)
{
	//typedef int (WINAPI* OnBitBlt_t)(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);
	ORIGINALFASTEX(BitBlt,NULL);
	BOOL bRc = FALSE;

	if (F(BitBlt))
		bRc = F(BitBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop);

	// Если рисуют _прямо_ на канвасе ConEmu
	if (bRc && hdcDest && hdcDest == ghTempHDC)
	{
		// Уведомить GUI, что у него прямо на канвасе кто-то что-то нарисовал :)
		CESERVER_REQ* pIn = ExecuteNewCmd(CECMD_LOCKDC, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_LOCKDC));
		if (pIn)
		{
			pIn->LockDc.hDcWnd = ghConEmuWndDC; // На всякий случай
			pIn->LockDc.bLock = TRUE;
			pIn->LockDc.Rect.left = nXDest;
			pIn->LockDc.Rect.top = nYDest;
			pIn->LockDc.Rect.right = nXDest+nWidth-1;
			pIn->LockDc.Rect.bottom = nYDest+nHeight-1;

			CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd);

			if (pOut)
				ExecuteFreeResult(pOut);
			ExecuteFreeResult(pIn);
		}
	}

	return bRc;
}
Exemplo n.º 5
0
bool AllocateSendCurrentDirectory(CESERVER_REQ* &ppCmd, DWORD &pcbCurMaxSize, LPCWSTR asDirectory, LPCWSTR asPassiveDirectory /*= NULL*/)
{
	int iALen = asDirectory ? (lstrlen(asDirectory)+1) : 0;
	int iPLen = asPassiveDirectory ? (lstrlen(asPassiveDirectory)+1) : 0;
	if ((iALen < 0) || (iPLen < 0) || (!iALen && !iPLen))
		return false;

	size_t cbMax = sizeof(CESERVER_REQ_HDR) + sizeof(CESERVER_REQ_STORECURDIR) + (iALen + iPLen) * sizeof(*asDirectory);
	if (!ExecuteNewCmd(ppCmd, pcbCurMaxSize, CECMD_STORECURDIR, cbMax))
		return false;

	ppCmd->CurDir.iActiveCch = iALen;
	ppCmd->CurDir.iPassiveCch = iPLen;
	wchar_t* psz = ppCmd->CurDir.szDir;
	if (iALen)
	{
		lstrcpyn(psz, asDirectory, iALen);
		psz += iALen;
	}
	if (iPLen)
	{
		lstrcpyn(psz, asPassiveDirectory, iPLen);
	}

	return true;
}
Exemplo n.º 6
0
void PatchGuiMessage(bool bReceived, HWND& hWnd, UINT& Msg, WPARAM& wParam, LPARAM& lParam)
{
	if (!ghAttachGuiClient)
		return;

	switch (Msg)
	{
	case WM_MOUSEACTIVATE:
		if (wParam == (WPARAM)ghConEmuWnd)
		{
			wParam = (WPARAM)ghAttachGuiClient;
		}
		break;

	case WM_LBUTTONDOWN:
		if (bReceived && ghConEmuWnd && ghConWnd)
		{
			HWND hActiveCon = (HWND)GetWindowLongPtr(ghConEmuWnd, GWLP_USERDATA);
			if (hActiveCon != ghConWnd)
			{
				CESERVER_REQ* pIn = ExecuteNewCmd(CECMD_ACTIVATECON, sizeof(CESERVER_REQ_HDR) + sizeof(CESERVER_REQ_ACTIVATECONSOLE));
				if (pIn)
				{
					pIn->ActivateCon.hConWnd = ghConWnd;
					CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd);
					ExecuteFreeResult(pIn);
					ExecuteFreeResult(pOut);
				}
			}
			#if 0
			// Если окно ChildGui активируется кликом - то ConEmu (holder)
			// может остаться "под" предыдущим окном бывшим в фокусе...
			// Победить пока не получается.
			DWORD nTID = 0, nPID = 0;
			HWND hFore = GetForegroundWindow();
			if (hFore && ((nTID = GetWindowThreadProcessId(hFore, &nPID)) != 0))
			{
				if ((nPID != GetCurrentProcessId()) && (nPID != gnGuiPID))
				{
					SetForegroundWindow(ghConEmuWnd);
				}
			}
			#endif
		}
		break;

	#ifdef _DEBUG
	case WM_DESTROY:
		if (hWnd == ghAttachGuiClient)
		{
			int iDbg = -1;
		}
		break;
	#endif
	}
}
Exemplo n.º 7
0
BOOL WINAPI OnStretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop)
{
	//typedef int (WINAPI* OnStretchBlt_t)(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop);
	ORIGINAL_EX(StretchBlt);
	BOOL bRc = FALSE;

	//#ifdef _DEBUG
	//HWND h = WindowFromDC(hdcDest);
	//#endif

	// Если рисуют _прямо_ на канвасе ConEmu
	if (/*bRc &&*/ hdcDest && hdcDest == ghTempHDC)
	{
		if (
			(!StretchBltBatch.bottom && !StretchBltBatch.top)
			|| (nYOriginDest <= StretchBltBatch.top)
			|| (nXOriginDest != StretchBltBatch.left)
			|| (StretchBltBatch.right != (nXOriginDest+nWidthDest-1))
			|| (StretchBltBatch.bottom != (nYOriginDest-1))
			)
		{
			// Сброс батча
			StretchBltBatch.left = nXOriginDest;
			StretchBltBatch.top = nYOriginDest;
			StretchBltBatch.right = nXOriginDest+nWidthDest-1;
			StretchBltBatch.bottom = nYOriginDest+nHeightDest-1;
		}
		else
		{
			StretchBltBatch.bottom = nYOriginDest+nHeightDest-1;
		}

		// Уведомить GUI, что у него прямо на канвасе кто-то что-то нарисовал :)
		CESERVER_REQ* pIn = ExecuteNewCmd(CECMD_LOCKDC, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_LOCKDC));
		if (pIn)
		{
			pIn->LockDc.hDcWnd = ghConEmuWndDC; // На всякий случай
			pIn->LockDc.bLock = TRUE;
			pIn->LockDc.Rect = StretchBltBatch;

			CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd);

			if (pOut)
				ExecuteFreeResult(pOut);
			ExecuteFreeResult(pIn);
		}
	}

	if (F(StretchBlt))
		bRc = F(StretchBlt)(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, dwRop);

	return bRc;
}
Exemplo n.º 8
0
// When _st_ is 0: remove progress.
// When _st_ is 1: set progress value to _pr_ (number, 0-100).
// When _st_ is 2: set error state in progress on Windows 7 taskbar
void GuiSetProgress(WORD st, WORD pr)
{
	CESERVER_REQ* pIn = ExecuteNewCmd(CECMD_SETPROGRESS, sizeof(CESERVER_REQ_HDR)+sizeof(WORD)*2);
	if (pIn)
	{
		pIn->wData[0] = st;
		pIn->wData[1] = pr;

		CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd);
		ExecuteFreeResult(pIn);
		ExecuteFreeResult(pOut);
	}
}
Exemplo n.º 9
0
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;
		}
	}
}
Exemplo n.º 10
0
BOOL ExecuteNewCmd(CESERVER_REQ* &ppCmd, DWORD &pcbCurMaxSize, DWORD nCmd, size_t nSize)
{
	if (!ppCmd || (pcbCurMaxSize < nSize))
	{
		DWORD nErr = GetLastError();
		ExecuteFreeResult(ppCmd);
		ppCmd = ExecuteNewCmd(nCmd, nSize);
		if (ppCmd != NULL)
		{
			// Обмен данными идет и между 32bit & 64bit процессами, размеры __int64 недопустимы
			_ASSERTE(nSize == (DWORD)nSize);
			pcbCurMaxSize = (DWORD)nSize;
			ppCmd->hdr.nLastError = nErr;
		}
	}
	else
	{
		ExecutePrepareCmd(ppCmd, nCmd, nSize);
	}
	
	return (ppCmd != NULL);
}
Exemplo n.º 11
0
CESERVER_REQ* ExecuteNewCmdOnCreate(CESERVER_CONSOLE_MAPPING_HDR* pSrvMap, HWND hConWnd, enum CmdOnCreateType aCmd,
				LPCWSTR asAction, LPCWSTR asFile, LPCWSTR asParam,
				DWORD* anShellFlags, DWORD* anCreateFlags, DWORD* anStartFlags, DWORD* anShowCmd,
				int mn_ImageBits, int mn_ImageSubsystem,
				HANDLE hStdIn, HANDLE hStdOut, HANDLE hStdErr)
{
	bool bEnabled = false;
	if (!pSrvMap)
	{
		static bool bWasEnabled = false;
		static DWORD nLastWasEnabledTick = 0;

		// Чтобы проверки слишком часто не делать
		if (!nLastWasEnabledTick || ((GetTickCount() - nLastWasEnabledTick) > 1000))
		{
			CESERVER_CONSOLE_MAPPING_HDR *Info = (CESERVER_CONSOLE_MAPPING_HDR*)calloc(1,sizeof(*Info));
			if (Info)
			{
				if (::LoadSrvMapping(hConWnd, *Info))
				{
					bEnabled = (Info->nLoggingType == glt_Processes);
				}
				free(Info);
			}

			nLastWasEnabledTick = GetTickCount();
		}

		bWasEnabled = bEnabled;
	}
	else
	{
		bEnabled = (pSrvMap->nLoggingType == glt_Processes);
	}
	// Если логирование не просили
	if (!bEnabled)
	{
		return NULL;
	}

	//szBaseDir[0] = 0;

	//// Проверим, а надо ли?
	//MFileMapping<CESERVER_CONSOLE_MAPPING_HDR> ConMap;
	//ConMap.InitName(CECONMAPNAME, (DWORD)FarHwnd);
	//CESERVER_CONSOLE_MAPPING_HDR* p = ConMap.Open();
	//if (p && p->hConEmuRoot && isWindow(p->hConEmuRoot))
	//{

	////	bDosBoxAllowed = pInfo->bDosBox;
	////	wcscpy_c(szBaseDir, pInfo->sConEmuBaseDir);
	////	wcscat_c(szBaseDir, L"\\");
	//if (p->nLoggingType != glt_Processes)
	//	return NULL;

	//DWORD dwGuiProcessId = 0;
	//if (!ghConEmuWnd || !GetWindowThreadProcessId(ghConEmuWnd, &dwGuiProcessId))
	//	return NULL;

	//MFileMapping<ConEmuGuiMapping> GuiInfoMapping;
	//GuiInfoMapping.InitName(CEGUIINFOMAPNAME, dwGuiProcessId);
	//const ConEmuGuiMapping* pInfo = GuiInfoMapping.Open();
	//if (!pInfo)
	//	return NULL;
	//else if (pInfo->nProtocolVersion != CESERVER_REQ_VER)
	//	return NULL;
	//else
	//{
	//	bDosBoxAllowed = pInfo->bDosBox;
	//	wcscpy_c(szBaseDir, pInfo->sConEmuBaseDir);
	//	wcscat_c(szBaseDir, L"\\");
	//	if (pInfo->nLoggingType != glt_Processes)
	//		return NULL;
	//}
	//GuiInfoMapping.CloseMap();

	
	CESERVER_REQ *pIn = NULL;
	
	int nActionLen = (asAction ? lstrlen(asAction) : 0)+1;
	int nFileLen = (asFile ? lstrlen(asFile) : 0)+1;
	int nParamLen = (asParam ? lstrlen(asParam) : 0)+1;
	
	pIn = ExecuteNewCmd(CECMD_ONCREATEPROC, sizeof(CESERVER_REQ_HDR)
		+sizeof(CESERVER_REQ_ONCREATEPROCESS)+(nActionLen+nFileLen+nParamLen)*sizeof(wchar_t));
	
	pIn->OnCreateProc.nSourceBits = WIN3264TEST(32,64); //-V112
	//pIn->OnCreateProc.bUnicode = TRUE;
	pIn->OnCreateProc.nImageSubsystem = mn_ImageSubsystem;
	pIn->OnCreateProc.nImageBits = mn_ImageBits;
	pIn->OnCreateProc.hStdIn = (unsigned __int64)hStdIn;
	pIn->OnCreateProc.hStdOut = (unsigned __int64)hStdOut;
	pIn->OnCreateProc.hStdErr = (unsigned __int64)hStdErr;
	
	if (aCmd == eShellExecute)
		wcscpy_c(pIn->OnCreateProc.sFunction, L"Shell");
	else if (aCmd == eCreateProcess)
		wcscpy_c(pIn->OnCreateProc.sFunction, L"Create");
	else if (aCmd == eInjectingHooks)
		wcscpy_c(pIn->OnCreateProc.sFunction, L"Inject");
	else if (aCmd == eHooksLoaded)
		wcscpy_c(pIn->OnCreateProc.sFunction, L"HkLoad");
	else if (aCmd == eSrvLoaded)
		wcscpy_c(pIn->OnCreateProc.sFunction, L"SrLoad");
	else if (aCmd == eParmsChanged)
		wcscpy_c(pIn->OnCreateProc.sFunction, L"Changed");
	else if (aCmd == eLoadLibrary)
		wcscpy_c(pIn->OnCreateProc.sFunction, L"LdLib");
	else if (aCmd == eFreeLibrary)
		wcscpy_c(pIn->OnCreateProc.sFunction, L"FrLib");
	else
		wcscpy_c(pIn->OnCreateProc.sFunction, L"Unknown");
	
	pIn->OnCreateProc.nShellFlags = anShellFlags ? *anShellFlags : 0;
	pIn->OnCreateProc.nCreateFlags = anCreateFlags ? *anCreateFlags : 0;
	pIn->OnCreateProc.nStartFlags = anStartFlags ? *anStartFlags : 0;
	pIn->OnCreateProc.nShowCmd = anShowCmd ? *anShowCmd : 0;
	pIn->OnCreateProc.nActionLen = nActionLen;
	pIn->OnCreateProc.nFileLen = nFileLen;
	pIn->OnCreateProc.nParamLen = nParamLen;
	
	wchar_t* psz = pIn->OnCreateProc.wsValue;
	if (nActionLen > 1)
		_wcscpy_c(psz, nActionLen, asAction);
	psz += nActionLen;
	if (nFileLen > 1)
		_wcscpy_c(psz, nFileLen, asFile);
	psz += nFileLen;
	if (nParamLen > 1)
		_wcscpy_c(psz, nParamLen, asParam);
	psz += nParamLen;
	
	return pIn;
}
Exemplo n.º 12
0
BOOL WINAPI PlugServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam)
{
	BOOL lbRc = FALSE;
	//HANDLE hPipe = (HANDLE)ahPipe;
	//CESERVER_REQ *pIn=NULL;
	//BYTE cbBuffer[64]; // Для большей части команд нам хватит
	//DWORD cbRead = 0, cbWritten = 0, dwErr = 0;
	BOOL fSuccess = FALSE;
	MSectionThread SCT(csTabs);
	// Send a message to the pipe server and read the response.
	//fSuccess = ReadFile(hPipe, cbBuffer, sizeof(cbBuffer), &cbRead, NULL);
	//dwErr = GetLastError();

	//if (!fSuccess && (dwErr != ERROR_MORE_DATA))
	//{
	//	_ASSERTE("ReadFile(pipe) failed"==NULL);
	//	CloseHandle(hPipe);
	//	return 0;
	//}

	//pIn = (CESERVER_REQ*)cbBuffer; // Пока cast, если нужно больше - выделим память
	//_ASSERTE(pIn->hdr.cbSize>=sizeof(CESERVER_REQ_HDR) && cbRead>=sizeof(CESERVER_REQ_HDR));
	//_ASSERTE(pIn->hdr.nVersion == CESERVER_REQ_VER);

	if (pIn->hdr.cbSize < sizeof(CESERVER_REQ_HDR) || /*in.nSize < cbRead ||*/ pIn->hdr.nVersion != CESERVER_REQ_VER)
	{
		//CloseHandle(hPipe);
		gpPlugServer->BreakConnection(pInst);
		return FALSE;
	}

	//int nAllSize = pIn->hdr.cbSize;
	//pIn = (CESERVER_REQ*)Alloc(nAllSize,1);
	//_ASSERTE(pIn!=NULL);

	//if (!pIn)
	//{
	//	CloseHandle(hPipe);
	//	return 0;
	//}

	//memmove(pIn, cbBuffer, cbRead);
	//_ASSERTE(pIn->hdr.nVersion==CESERVER_REQ_VER);
	//LPBYTE ptrData = ((LPBYTE)pIn)+cbRead;
	//nAllSize -= cbRead;

	//while(nAllSize>0)
	//{
	//	//_tprintf(TEXT("%s\n"), chReadBuf);

	//	// Break if TransactNamedPipe or ReadFile is successful
	//	if (fSuccess)
	//		break;

	//	// Read from the pipe if there is more data in the message.
	//	fSuccess = ReadFile(
	//	               hPipe,      // pipe handle
	//	               ptrData,    // buffer to receive reply
	//	               nAllSize,   // size of buffer
	//	               &cbRead,    // number of bytes read
	//	               NULL);      // not overlapped

	//	// Exit if an error other than ERROR_MORE_DATA occurs.
	//	if (!fSuccess && ((dwErr = GetLastError()) != ERROR_MORE_DATA))
	//		break;

	//	ptrData += cbRead;
	//	nAllSize -= cbRead;
	//}

	//TODO("Может возникнуть ASSERT, если консоль была закрыта в процессе чтения");
	//_ASSERTE(nAllSize==0);

	//if (nAllSize>0)
	//{
	//	if (((LPVOID)cbBuffer) != ((LPVOID)pIn))
	//		Free(pIn);

	//	CloseHandle(hPipe);
	//	return 0; // удалось считать не все данные
	//}

	UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR);

	// Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат
	//fSuccess = WriteFile( hPipe, pOut, pOut->nSize, &cbWritten, NULL);

	if (pIn->hdr.nCmd == CMD_LANGCHANGE)
	{
		_ASSERTE(nDataSize>=4); //-V112
		// LayoutName: "00000409", "00010409", ...
		// А HKL от него отличается, так что передаем DWORD
		// HKL в x64 выглядит как: "0x0000000000020409", "0xFFFFFFFFF0010409"
		DWORD hkl = pIn->dwData[0];
		DWORD dwLastError = 0;
		HKL hkl1 = NULL, hkl2 = NULL;

		if (hkl)
		{
			WCHAR szLoc[10]; _wsprintf(szLoc, SKIPLEN(countof(szLoc)) L"%08x", hkl);
			hkl1 = LoadKeyboardLayout(szLoc, KLF_ACTIVATE|KLF_REORDER|KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS);
			hkl2 = ActivateKeyboardLayout(hkl1, KLF_SETFORPROCESS|KLF_REORDER);

			if (!hkl2)
				dwLastError = GetLastError();
			else
				fSuccess = TRUE;
		}

		pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2;
		if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		{
			lbRc = TRUE;
			ppReply->dwData[0] = fSuccess;
			ppReply->dwData[1] = fSuccess ? ((DWORD)(LONG)(LONG_PTR)hkl2) : dwLastError;
		}

	}
	//} else if (pIn->hdr.nCmd == CMD_DEFFONT) {
	//	// исключение - асинхронный, результат не требуется
	//	SetConsoleFontSizeTo(FarHwnd, 4, 6);
	//	MoveWindow(FarHwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 1); // чтобы убрать возможные полосы прокрутки...
	else if (pIn->hdr.nCmd == CMD_REQTABS || pIn->hdr.nCmd == CMD_SETWINDOW)
	{
		MSectionLock SC; SC.Lock(csTabs, FALSE, 1000);
		DWORD nSetWindowWait = (DWORD)-1;

		if (pIn->hdr.nCmd == CMD_SETWINDOW)
		{
			ResetEvent(ghSetWndSendTabsEvent);

			// Для FAR2 - сброс QSearch выполняется в том же макро, в котором актирируется окно
			if (gFarVersion.dwVerMajor == 1 && pIn->dwData[1])
			{
				// А вот для FAR1 - нужно шаманить
				ProcessCommand(CMD_CLOSEQSEARCH, TRUE/*bReqMainThread*/, pIn->dwData/*хоть и не нужно?*/);
			}

			// Пересылается 2 DWORD
			BOOL bCmdRc = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->dwData);

			DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW waiting...\n");

			WARNING("Почему для FAR1 не ждем? Есть возможность заблокироваться в 1.7 или что?");
			if ((gFarVersion.dwVerMajor >= 2) && bCmdRc)
			{
				DWORD nTimeout = 2000;
				#ifdef _DEBUG
				if (IsDebuggerPresent()) nTimeout = 120000;
				#endif
				
				nSetWindowWait = WaitForSingleObject(ghSetWndSendTabsEvent, nTimeout);
			}

			DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW finished\n");
		}

		if (gpTabs)
		{
			//fSuccess = WriteFile(hPipe, gpTabs, gpTabs->hdr.cbSize, &cbWritten, NULL);
			pcbReplySize = gpTabs->hdr.cbSize;
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				memmove(ppReply->Data, gpTabs->Data, pcbReplySize - sizeof(ppReply->hdr));
				lbRc = TRUE;
			}
		}

		SC.Unlock();
	}
	else if (pIn->hdr.nCmd == CMD_FARSETCHANGED)
	{
		// Установить переменные окружения
		// Плагин это получает в ответ на CECMD_RESOURCES, посланное в GUI при загрузке плагина
		_ASSERTE(nDataSize>=8);
		FAR_REQ_FARSETCHANGED *pFarSet = (FAR_REQ_FARSETCHANGED*)pIn->Data;

		cmd_FarSetChanged(pFarSet);

		pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
		if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		{
			lbRc = TRUE;
			ppReply->dwData[0] = TRUE;
		}

		//_ASSERTE(nDataSize<sizeof(gsMonitorEnvVar));
		//gbMonitorEnvVar = false;
		//// Плагин FarCall "нарушает" COMSPEC (копирует содержимое запускаемого процесса)
		//bool lbOk = false;

		//if (nDataSize<sizeof(gsMonitorEnvVar))
		//{
		//	memcpy(gsMonitorEnvVar, pszName, nDataSize);
		//	lbOk = true;
		//}

		//UpdateEnvVar(pszName);
		////while (*pszName && *pszValue) {
		////	const wchar_t* pszChanged = pszValue;
		////	// Для ConEmuOutput == AUTO выбирается по версии ФАРа
		////	if (!lstrcmpi(pszName, L"ConEmuOutput") && !lstrcmp(pszChanged, L"AUTO")) {
		////		if (gFarVersion.dwVerMajor==1)
		////			pszChanged = L"ANSI";
		////		else
		////			pszChanged = L"UNICODE";
		////	}
		////	// Если в pszValue пустая строка - удаление переменной
		////	SetEnvironmentVariableW(pszName, (*pszChanged != 0) ? pszChanged : NULL);
		////	//
		////	pszName = pszValue + lstrlenW(pszValue) + 1;
		////	if (*pszName == 0) break;
		////	pszValue = pszName + lstrlenW(pszName) + 1;
		////}
		//gbMonitorEnvVar = lbOk;
	}
	else if (pIn->hdr.nCmd == CMD_DRAGFROM)
	{
		#ifdef _DEBUG
		BOOL  *pbClickNeed = (BOOL*)pIn->Data;
		COORD *crMouse = (COORD *)(pbClickNeed+1);
		#endif

		ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, pIn->Data);
		CESERVER_REQ* pCmdRet = NULL;
		ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet);

		if (pCmdRet)
		{
			//fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL);
			pcbReplySize = pCmdRet->hdr.cbSize;
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr));
			}
			Free(pCmdRet);
		}

		//if (gpCmdRet && gpCmdRet == pCmdRet)
		//{
		//	Free(gpCmdRet);
		//	gpCmdRet = NULL; gpData = NULL; gpCursor = NULL;
		//}
	}
	else if (pIn->hdr.nCmd == CMD_EMENU)
	{
		COORD *crMouse = (COORD *)pIn->Data;
#ifdef _DEBUG
		const wchar_t *pszUserMacro = (wchar_t*)(crMouse+1);
#endif
		DWORD ClickArg[2] = {TRUE, MAKELONG(crMouse->X, crMouse->Y)};
		
		// Выделить файл под курсором
		DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) begin\n");
		BOOL lb1 = ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, ClickArg/*pIn->Data*/);
		DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) done\n");

		// А теперь, собственно вызовем меню
		DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) begin\n");
		BOOL lb2 = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data);
		DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) done\n");

		pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2;
		if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		{
			lbRc = TRUE;
			ppReply->dwData[0] = lb1;
			ppReply->dwData[1] = lb1;
		}
	}
	else if (pIn->hdr.nCmd == CMD_ACTIVEWNDTYPE)
	{
		int nWindowType = -1;
		//CESERVER_REQ Out;
		//ExecutePrepareCmd(&Out, CMD_ACTIVEWNDTYPE, sizeof(CESERVER_REQ_HDR)+sizeof(DWORD));

		if (gFarVersion.dwVerMajor>=2)
			nWindowType = GetActiveWindowType();

		//fSuccess = WriteFile(hPipe, &Out, Out.hdr.cbSize, &cbWritten, NULL);

		pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
		if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		{
			lbRc = TRUE;
			ppReply->dwData[0] = nDataSize;
		}		
	}
	else
	{
		CESERVER_REQ* pCmdRet = NULL;
		BOOL lbCmd = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet);

		if (pCmdRet)
		{
			//fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL);
			pcbReplySize = pCmdRet->hdr.cbSize;
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr));
			}
			Free(pCmdRet);
		}

		//if (gpCmdRet && gpCmdRet == pCmdRet) {
		//	Free(gpCmdRet);
		//	gpCmdRet = NULL; gpData = NULL; gpCursor = NULL;
		//}
	}

	//// Освободить память
	//if (((LPVOID)cbBuffer) != ((LPVOID)pIn))
	//	Free(pIn);

	//CloseHandle(hPipe);
	return lbRc;
}
Exemplo n.º 13
0
// Для облегчения жизни - сервер кеширует данные, калбэк может использовать ту же память (*pcbMaxReplySize)
BOOL WINAPI HookServerCommand(LPVOID pInst, CESERVER_REQ* pCmd, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam)
{
	WARNING("Собственно, выполнение команд!");
	
	BOOL lbRc = FALSE, lbFRc;
	
	switch (pCmd->hdr.nCmd)
	{
	case CECMD_ATTACHGUIAPP:
		{
			// При 'внешнем' аттаче инициированном юзером из ConEmu
			_ASSERTEX(pCmd->AttachGuiApp.hConEmuWnd && ghConEmuWnd==pCmd->AttachGuiApp.hConEmuWnd);
			//ghConEmuWndDC = pOut->AttachGuiApp.hConEmuWndDC; -- еще нету
			AttachGuiWindow(pCmd->AttachGuiApp.hAppWindow);
			// Результат
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize);
			if (lbRc)
				ppReply->dwData[0] = (DWORD)ghAttachGuiClient;
		} // CECMD_ATTACHGUIAPP
		break;
	case CECMD_SETFOCUS:
		break;
	case CECMD_SETPARENT:
		break;
	case CECMD_CTRLBREAK:
		if (CHECK_CMD_SIZE(pCmd,2*sizeof(DWORD)))
		{
			lbFRc = GenerateConsoleCtrlEvent(pCmd->dwData[0], pCmd->dwData[1]);
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize);
			if (lbRc)
				ppReply->dwData[0] = lbFRc;
		} // CECMD_CTRLBREAK
		break;
	case CECMD_SETGUIEXTERN:
		if (ghAttachGuiClient && (pCmd->DataSize() >= sizeof(CESERVER_REQ_SETGUIEXTERN)))
		{
			SetGuiExternMode(pCmd->SetGuiExtern.bExtern, NULL/*pCmd->SetGuiExtern.bDetach ? &pCmd->SetGuiExtern.rcOldPos : NULL*/);
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize);
			if (lbRc)
				ppReply->dwData[0] = gbGuiClientExternMode;

			if (pCmd->SetGuiExtern.bExtern && pCmd->SetGuiExtern.bDetach)
			{
				gbAttachGuiClient = gbGuiClientAttached = FALSE;
				ghAttachGuiClient = ghConEmuWndDC = ghConEmuWnd = NULL;
				gnServerPID = 0;
			}

		} // CECMD_SETGUIEXTERN
		break;
	case CECMD_LANGCHANGE:
		{
			LONG_PTR hkl = (LONG_PTR)(LONG)pCmd->dwData[0];
			BOOL lbRc = ActivateKeyboardLayout((HKL)hkl, KLF_SETFORPROCESS) != NULL;
			DWORD nErrCode = lbRc ? 0 : GetLastError();
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+2*sizeof(DWORD);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize))
			{
				ppReply->dwData[0] = lbRc;
				ppReply->dwData[1] = nErrCode;
			}
		} // CECMD_LANGCHANGE
		break;
	case CECMD_MOUSECLICK:
		{
			BOOL bProcessed = FALSE;
			if ((gReadConsoleInfo.InReadConsoleTID || gReadConsoleInfo.LastReadConsoleInputTID)
				&& (pCmd->DataSize() >= 4*sizeof(WORD)))
			{
				bProcessed = OnReadConsoleClick(pCmd->wData[0], pCmd->wData[1], (pCmd->wData[2] != 0), (pCmd->wData[3] != 0));
			}

			lbRc = TRUE;
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize))
			{
				ppReply->dwData[0] = bProcessed;
			}
		} // CECMD_MOUSECLICK
		break;
	case CECMD_PROMPTCMD:
		{
			BOOL bProcessed = FALSE;
			if ((gReadConsoleInfo.InReadConsoleTID || gReadConsoleInfo.LastReadConsoleInputTID)
				&& (pCmd->DataSize() >= 2*sizeof(wchar_t)))
			{
				bProcessed = OnExecutePromptCmd((LPCWSTR)pCmd->wData);
			}

			lbRc = TRUE;
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize))
			{
				ppReply->dwData[0] = bProcessed;
			}
		}
		break;
	case CECMD_STARTSERVER:
		{
			int nErrCode = -1;
			wchar_t szSelf[MAX_PATH+16], *pszNamePtr, szArgs[128];
			PROCESS_INFORMATION pi = {};
			STARTUPINFO si = {sizeof(si)};

			if (GetModuleFileName(ghOurModule, szSelf, MAX_PATH) && ((pszNamePtr = (wchar_t*)PointToName(szSelf)) != NULL))
			{
				// Запускаем сервер той же битности, что и текущий процесс
				_wcscpy_c(pszNamePtr, 16, WIN3264TEST(L"ConEmuC.exe",L"ConEmuC64.exe"));
				if (gnImageSubsystem==IMAGE_SUBSYSTEM_WINDOWS_GUI)
				{
					_ASSERTEX(pCmd->NewServer.hAppWnd!=0);
					_wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /GID=%u /GHWND=%08X /GUIATTACH=%08X /PID=%u",
							pCmd->NewServer.nGuiPID, (DWORD)pCmd->NewServer.hGuiWnd, (DWORD)pCmd->NewServer.hAppWnd, GetCurrentProcessId());
					gbAttachGuiClient = TRUE;
				}
				else
				{
					_ASSERTEX(pCmd->NewServer.hAppWnd==0);
					_wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /GID=%u /GHWND=%08X /ATTACH /PID=%u",
						pCmd->NewServer.nGuiPID, (DWORD)pCmd->NewServer.hGuiWnd, GetCurrentProcessId());
				}
				lbRc = CreateProcess(szSelf, szArgs, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
				if (lbRc)
				{
					CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
					nErrCode = 0;
				}
				else
				{
					nErrCode = HRESULT_FROM_WIN32(GetLastError());
				}
			}

			lbRc = true; // Вернуть результат однозначно

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize))
			{
				ppReply->dwData[0] = pi.dwProcessId;
				ppReply->dwData[1] = (DWORD)nErrCode;
			}
		} // CECMD_STARTSERVER
		break;
	}
	
	// Если (lbRc == FALSE) - в пайп будет отдана "пустышка" ((DWORD)0)
	return lbRc;
}
Exemplo n.º 14
0
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;
	}
}
Exemplo n.º 15
0
// Не интересуется результатом команды!
BOOL CConEmuPipe::Execute(int nCmd, LPCVOID apData, UINT anDataSize)
{
	WARNING("Если указан mdw_Timeout - создать нить и выполнять команду в ней. Ожидать нить не более и прибить ее, если пришел Timeout");
	MCHKHEAP

	if (!((nCmd >= (int)CMD_FIRST_FAR_CMD && nCmd <= (int)CMD_LAST_FAR_CMD)))
	{
		TCHAR szError[128];
		_wsprintf(szError, SKIPLEN(countof(szError)) _T("Invalid command id (%i)!\nPID=%u, TID=%u"), nCmd, GetCurrentProcessId(), GetCurrentThreadId());
		MBoxA(szError);
		return FALSE;
	}

#ifdef _DEBUG
	WCHAR szMsg[64]; _wsprintf(szMsg, SKIPLEN(countof(szMsg)) _T("Pipe:Execute(%i)\n"), nCmd);
	DEBUGSTR(szMsg);
#endif
	int nAllSize = sizeof(CESERVER_REQ_HDR)+anDataSize;
	CESERVER_REQ* pIn = ExecuteNewCmd(nCmd, nAllSize);

	if (!pIn)
	{
		_ASSERTE(pIn!=NULL);
		TCHAR szError[128];
		_wsprintf(szError, SKIPLEN(countof(szError)) _T("Pipe: Can't allocate memory (%i) bytes, Cmd = %i!"), nAllSize, nCmd);
		MBoxA(szError);
		Close();
		return FALSE;
	}

	if (apData && anDataSize)
	{
		memmove(pIn->Data, apData, anDataSize);
	}

	DWORD dwTickStart = timeGetTime();

	BYTE cbReadBuf[512];
	BOOL fSuccess;
	DWORD cbRead, dwErr;
	// Send a message to the pipe server and read the response.
	fSuccess = TransactNamedPipe(
					mh_Pipe,                // pipe handle
					pIn,                    // message to server
					pIn->hdr.cbSize,        // message length
					cbReadBuf,              // buffer to receive reply
					sizeof(cbReadBuf),      // size of read buffer
					&cbRead,                // bytes read
					NULL);                  // not overlapped
	dwErr = GetLastError();

	gpSetCls->debugLogCommand(pIn, FALSE, dwTickStart, timeGetTime()-dwTickStart, ms_PipeName);

	if (!fSuccess && dwErr == ERROR_BROKEN_PIPE)
	{
		// Плагин не вернул данных, но обработал команду
		Close();
		SafeFree(pIn);
		return TRUE;
	}
	else if (!fSuccess && (dwErr != ERROR_MORE_DATA))
	{
		DEBUGSTR(L" - FAILED!\n");
		TCHAR szError[128];
		_wsprintf(szError, SKIPLEN(countof(szError)) _T("Pipe: TransactNamedPipe failed, Cmd = %i, ErrCode = 0x%08X!"), nCmd, dwErr);
		MBoxA(szError);
		Close();
		SafeFree(pIn);
		return FALSE;
	}

	if (cbRead < sizeof(DWORD))
	{
		pOut = NULL;
		Close();
		SafeFree(pIn);
		return FALSE;
	}

	pOut = (CESERVER_REQ*)cbReadBuf;

	// Проверка размера
	if (pOut->hdr.cbSize <= sizeof(pOut->hdr))
	{
		_ASSERTE(pOut->hdr.cbSize == 0);
		pOut = NULL;
		Close();
		SafeFree(pIn);
		return FALSE;
	}

	if (pOut->hdr.nVersion != CESERVER_REQ_VER)
	{
		gpConEmu->ReportOldCmdVersion(pOut->hdr.nCmd, pOut->hdr.nVersion, -1, pOut->hdr.nSrcPID, pOut->hdr.hModule, pOut->hdr.nBits);
		pOut = NULL;
		Close();
		SafeFree(pIn);
		return FALSE;
	}

	nAllSize = pOut->hdr.cbSize;
	pOut = NULL;

	if (nAllSize==0)
	{
		DEBUGSTR(L" - FAILED!\n");
		DisplayLastError(L"Empty data recieved from server", 0);
		Close();
		SafeFree(pIn);
		return FALSE;
	}

	pOut = (CESERVER_REQ*)calloc(nAllSize,1);
	_ASSERTE(pOut!=NULL);
	memmove(pOut, cbReadBuf, cbRead);
	_ASSERTE(pOut->hdr.nVersion==CESERVER_REQ_VER);
	LPBYTE ptrData = ((LPBYTE)pOut)+cbRead;
	nAllSize -= cbRead;

	while (nAllSize>0)
	{
		//_tprintf(TEXT("%s\n"), chReadBuf);

		// Break if TransactNamedPipe or ReadFile is successful
		if (fSuccess)
			break;

		// Read from the pipe if there is more data in the message.
		fSuccess = ReadFile(
						mh_Pipe,    // pipe handle
						ptrData,    // buffer to receive reply
						nAllSize,   // size of buffer
						&cbRead,    // number of bytes read
						NULL);      // not overlapped

		// Exit if an error other than ERROR_MORE_DATA occurs.
		if (!fSuccess && (GetLastError() != ERROR_MORE_DATA))
			break;

		ptrData += cbRead;
		nAllSize -= cbRead;
	}

	TODO("Может возникнуть ASSERT, если консоль была закрыта в процессе чтения");
	_ASSERTE(nAllSize==0);
	SafeCloseHandle(mh_Pipe);
	SafeFree(pIn);
	lpCursor = pOut->Data;
	dwMaxDataSize = pOut->hdr.cbSize - sizeof(CESERVER_REQ_HDR);
	return TRUE;
}
Exemplo n.º 16
0
// Вызывается ТОЛЬКО в главной нити!
void CPluginBackground::UpdateBackground()
{
	if (!mn_BgPluginsCount)
		return;

	if (!ghConEmuWndDC || !IsWindow(ghConEmuWndDC))
		return;

	if (mb_ThNeedLoad)
	{
		LoadThSet(TRUE/*Мы уже в главной нити*/);
	}

	//RECT rcClient; GetClientRect(ghConEmuWndDC, &rcClient);
	struct PaintBackgroundArg Arg = m_Default;
	Arg.cbSize = sizeof(struct PaintBackgroundArg);
	//m_Default.dcSizeX = Arg.dcSizeX = rcClient.right+1;
	//m_Default.dcSizeY = Arg.dcSizeY = rcClient.bottom+1;
	m_Default.dcSizeX = Arg.dcSizeX = (m_Default.rcConWorkspace.right-m_Default.rcConWorkspace.left+1)*m_Default.MainFont.nFontCellWidth;
	m_Default.dcSizeY = Arg.dcSizeY = (m_Default.rcConWorkspace.bottom-m_Default.rcConWorkspace.top+1)*m_Default.MainFont.nFontHeight;
	// **********************************************************************************
	// запомнить данные из m_Default в m_Last, но т.к. там есть указатели - move не катит
	// **********************************************************************************
	//memmove(&m_Last, &m_Default, sizeof(m_Last));
	m_Last.MainFont = m_Default.MainFont;
	memmove(m_Last.crPalette, m_Default.crPalette, sizeof(m_Last.crPalette));
	m_Last.dcSizeX = m_Default.dcSizeX;
	m_Last.dcSizeY = m_Default.dcSizeY;
	m_Last.rcDcLeft = m_Default.rcDcLeft;
	m_Last.rcDcRight = m_Default.rcDcRight;
	m_Last.rcConWorkspace = m_Default.rcConWorkspace;
	m_Last.conCursor = m_Default.conCursor;
	m_Last.FarInterfaceSettings.Raw = m_Default.FarInterfaceSettings.Raw;
	m_Last.FarPanelSettings.Raw = m_Default.FarPanelSettings.Raw;
	memmove(m_Last.nFarColors, m_Default.nFarColors, sizeof(m_Last.nFarColors));
	m_Last.bPanelsAllowed = m_Default.bPanelsAllowed;
	// struct tag_BkPanelInfo
	m_Last.LeftPanel.bVisible = m_Default.LeftPanel.bVisible;
	m_Last.LeftPanel.bFocused = m_Default.LeftPanel.bFocused;
	m_Last.LeftPanel.bPlugin = m_Default.LeftPanel.bPlugin;
	m_Last.LeftPanel.rcPanelRect = m_Default.LeftPanel.rcPanelRect;
	m_Last.RightPanel.bVisible = m_Default.RightPanel.bVisible;
	m_Last.RightPanel.bFocused = m_Default.RightPanel.bFocused;
	m_Last.RightPanel.bPlugin = m_Default.RightPanel.bPlugin;
	m_Last.RightPanel.rcPanelRect = m_Default.RightPanel.rcPanelRect;
	// строки
	lstrcpyW(m_Last.LeftPanel.szCurDir, m_Default.LeftPanel.szCurDir);
	lstrcpyW(m_Last.LeftPanel.szFormat, m_Default.LeftPanel.szFormat);
	lstrcpyW(m_Last.LeftPanel.szHostFile, m_Default.LeftPanel.szHostFile);
	lstrcpyW(m_Last.RightPanel.szCurDir, m_Default.RightPanel.szCurDir);
	lstrcpyW(m_Last.RightPanel.szFormat, m_Default.RightPanel.szFormat);
	lstrcpyW(m_Last.RightPanel.szHostFile, m_Default.RightPanel.szHostFile);
	// **********************************************************************************

	if (m_Default.dcSizeX < 1 || m_Default.dcSizeY < 1)
	{
		_ASSERTE(m_Default.dcSizeX >= 1 && m_Default.dcSizeY >= 1);
		return;
	}

	SetDcPanelRect(&Arg.rcDcLeft, &Arg.LeftPanel, &Arg);
	SetDcPanelRect(&Arg.rcDcRight, &Arg.RightPanel, &Arg);

	// gpTabs отстает от реальности.
	Arg.Place = m_Default.Place;
	//if (!gpTabs)
	//	Arg.Place = pbp_Panels;
	//else if (gnCurrentWindowType == WTYPE_EDITOR)
	//	Arg.Place = pbp_Editor;
	//else if (gnCurrentWindowType == WTYPE_VIEWER)
	//	Arg.Place = pbp_Viewer;
	//else if (Arg.LeftPanel.bVisible || Arg.RightPanel.bVisible)
	//{
	//	_ASSERTE(gnCurrentWindowType == WTYPE_PANELS);
	//	Arg.Place = pbp_Panels;
	//}

	BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER)};
	bi.biWidth = Arg.dcSizeX;
	bi.biHeight = Arg.dcSizeY;
	bi.biPlanes = 1;
	bi.biBitCount = 32; //-V112
	bi.biCompression = BI_RGB;

	//_ASSERTE(Arg.LeftPanel.bVisible || Arg.RightPanel.bVisible);
	HDC hScreen = GetDC(NULL);

	RECT rcMeta = {0,0, Arg.dcSizeX, Arg.dcSizeY}; // (in pixels)
	int iWidthMM = GetDeviceCaps(hScreen, HORZSIZE); if (iWidthMM <= 0) { _ASSERTE(iWidthMM>0); iWidthMM = 1024; }
	int iHeightMM = GetDeviceCaps(hScreen, VERTSIZE); if (iHeightMM <= 0) { _ASSERTE(iHeightMM>0); iHeightMM = 768; }
	int iWidthPels = GetDeviceCaps(hScreen, HORZRES); if (iWidthPels <= 0) { _ASSERTE(iWidthPels>0); iWidthPels = 0; }
	int iHeightPels = GetDeviceCaps(hScreen, VERTRES); if (iHeightPels <= 0) { _ASSERTE(iHeightPels>0); iHeightPels = 0; }
	RECT rcMetaMM = {0,0, (rcMeta.right * iWidthMM * 100)/iWidthPels, (rcMeta.bottom * iHeightMM * 100)/iHeightPels}; // (in .01-millimeter units)

	HDC hdc = NULL;
	HENHMETAFILE hEmf = NULL;
	COLORREF* pBits = NULL;
	HBITMAP hDib = NULL, hOld = NULL;
#ifdef CREATE_EMF_TEMP_FILES
	wchar_t szEmfFile[MAX_PATH] = {};
#endif
	wchar_t *pszEmfFile = NULL;


	if (SETBACKGROUND_USE_EMF==1)
	{
		#ifdef CREATE_EMF_TEMP_FILES
		GetTempPath(MAX_PATH-32, szEmfFile);
		int nLen = lstrlen(szEmfFile);
		if (*szEmfFile && szEmfFile[nLen-1] != L'\\')
		{
			szEmfFile[nLen++] = L'\\';
			szEmfFile[nLen] = 0;
		}
		_wsprintf(szEmfFile+nLen, SKIPLEN(31) L"CeBack%u.emf", GetCurrentProcessId());
		pszEmfFile = szEmfFile;
		#endif

		hdc = CreateEnhMetaFile(hScreen, pszEmfFile, &rcMetaMM, L"ConEmu\0Far Background\0\0");
		if (!hdc)
		{
			_ASSERTE(hdc!=NULL);
			return;
		}
	}
	else
	{
		hdc = CreateCompatibleDC(hScreen);
		if (!hdc)
		{
			_ASSERTE(hdc!=NULL);
			return;
		}
		_ASSERTE(pBits = NULL);
		hDib = CreateDIBSection(hScreen, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);
	}
	ReleaseDC(NULL, hScreen); hScreen = NULL;

	Arg.hdc = hdc;

	if (SETBACKGROUND_USE_EMF==1)
	{
		HBRUSH hFillBr = CreateSolidBrush (
			#ifdef _DEBUG
				RGB(128,128,0)
			#else
				RGB(0,0,0)
			#endif
		);
		FillRect(hdc, &rcMeta, hFillBr);
		DeleteObject(hFillBr);
	}
	else
	{
		if (!hDib || !pBits)
		{
			_ASSERTE(hDib && pBits);
			if (hDib)
				DeleteObject(hDib);
			if (hdc)
				DeleteDC(hdc);
			return;
		}

		hOld = (HBITMAP)SelectObject(hdc, hDib);

		// Залить черным - по умолчанию
		#ifdef _DEBUG
			memset(pBits, 128, bi.biWidth*bi.biHeight*4); //-V112
		#else
			memset(pBits, 0, bi.biWidth*bi.biHeight*4);
		#endif
	}

	// Painting!
	int nProcessed = 0;
	MSectionLock SC; SC.Lock(csBgPlugins, TRUE);
	DWORD nFromLevel = 0, nNextLevel, nSuggested;
	DWORD dwDrawnPlaces = Arg.Place;

	while(true)
	{
		nNextLevel = nFromLevel;
		struct RegisterBackgroundArg *p = mp_BgPlugins;

		for(int i = 0; i < mn_BgPluginsCount; i++, p++)
		{
			if (p->Cmd != rbc_Register ||
			        !(p->dwPlaces & Arg.Place) ||
			        !(p->PaintConEmuBackground))
				continue; // пустая, неактивная в данном контексте, или некорректная ячейка

			// Слои
			nSuggested = p->dwSuggestedLevel;

			if (nSuggested < nFromLevel)
			{
				continue; // Этот слой уже обработан
			}
			else if (nSuggested > nFromLevel)
			{
				// Этот слой нужно будет обработать в следующий раз
				if ((nNextLevel == nFromLevel) || (nSuggested < nNextLevel))
					nNextLevel = nSuggested;

				continue;
			}

			// На уровне 0 (заливающий фон) должен быть только один плагин
			Arg.dwLevel = (nProcessed == 0) ? 0 : (nFromLevel == 0 && nProcessed) ? 1 : nFromLevel;
			Arg.lParam = mp_BgPlugins[i].lParam;
			Arg.dwDrawnPlaces = 0;
			//mp_BgPlugins[i].PaintConEmuBackground(&Arg);
			UpdateBackground_Exec(mp_BgPlugins+i, &Arg);
			// Что плагин покрасил (панели/редактор/вьювер считаются покрашенными по умолчанию)
			dwDrawnPlaces |= Arg.dwDrawnPlaces;
			//
			nProcessed++;
		}

		if (nNextLevel == nFromLevel)
			break; // больше слоев нет

		nFromLevel = nNextLevel;
	}

	SC.Unlock();
	// Sending background to GUI!

	if (nProcessed < 1)
	{
		// Ситуация возникает при старте ConEmu, когда панелей "еще нет"
		//_ASSERTE(nProcessed >= 1);
		if (mb_BgWasSent)
		{
			mb_BgWasSent = FALSE;
			CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_SETBACKGROUND, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SETBACKGROUND));
			if (pIn)
			{
				pIn->Background.nType = 1;
				pIn->Background.bEnabled = FALSE;
				pIn->Background.dwDrawnPlaces = 0;
				CESERVER_REQ *pOut = ExecuteGuiCmd(FarHwnd, pIn, FarHwnd);

				if (pOut)
				{
					ExecuteFreeResult(pOut);
				}
				ExecuteFreeResult(pIn);
			}
		}
	}
	else // есть "отработавшие" плагины, обновить Background!
	{
		GdiFlush();
		DWORD nBitSize = 0, nBitsError = 0;
		if (SETBACKGROUND_USE_EMF==1)
		{
			hEmf = CloseEnhMetaFile(hdc);
			hdc = NULL;

			nBitSize = GetEnhMetaFileBits(hEmf, 0, NULL);
			if (nBitSize == 0)
			{
				dwDrawnPlaces = 0;
				nBitsError = GetLastError();
				_ASSERTE(nBitSize!=0);
				if (hEmf)
				{
					// В случае ошибки - сразу удаляем
					DeleteEnhMetaFile(hEmf);
					hEmf = NULL;
				}
			}
		}
		else
		{
			nBitSize = bi.biWidth*bi.biHeight*sizeof(COLORREF);
		}
		DWORD nWholeSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SETBACKGROUND)+nBitSize; //-V103 //-V119
		CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_SETBACKGROUND, nWholeSize);

		if (!pIn)
		{
			_ASSERTE(pIn);
		}
		else
		{
			pIn->Background.nType = 1;
			pIn->Background.bEnabled = TRUE;
			pIn->Background.dwDrawnPlaces = dwDrawnPlaces;
			if (SETBACKGROUND_USE_EMF==1)
				pIn->Background.bmp.bfType = 0x4645/*EF*/;
			else
				pIn->Background.bmp.bfType = 0x4D42/*BM*/;
			pIn->Background.bmp.bfSize = nBitSize+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //-V119
			pIn->Background.bmp.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //-V119
			pIn->Background.bi = bi;

			if (SETBACKGROUND_USE_EMF==1)
			{
				LPBYTE pBits = ((LPBYTE)&pIn->Background)+sizeof(pIn->Background);
				DWORD nBitsRc = (nBitSize && hEmf) ? GetEnhMetaFileBits(hEmf, nBitSize, pBits) : 0;
				_ASSERTE(nBitsRc == nBitSize);
				if (!nBitsRc)
				{
					_ASSERTE(nBitsRc!=NULL);
					// Отключить нафиг
					ExecutePrepareCmd(&pIn->hdr, CECMD_SETBACKGROUND, nWholeSize-nBitSize);
					pIn->Background.nType = 1;
					pIn->Background.bEnabled = FALSE;
					pIn->Background.dwDrawnPlaces = 0;
				}
			}
			else
			{
				memmove(((LPBYTE)&pIn->Background)+sizeof(pIn->Background), pBits, bi.biWidth*bi.biHeight*sizeof(COLORREF));
			}
			CESERVER_REQ *pOut = ExecuteGuiCmd(FarHwnd, pIn, FarHwnd);

			// Вызывается ТОЛЬКО в главной нити
			_ASSERTE(GetCurrentThreadId() == gnMainThreadId);
			if (pOut)
			{
				mb_BgWasSent = TRUE;
				// Сбросим флажок "Ошибка уже была показана"
				if (pOut->BackgroundRet.nResult == esbr_OK)
				{
					mb_BgErrorShown = FALSE;
				}
				// Показать ошибку, если есть
				else if ((pOut->BackgroundRet.nResult > esbr_OK) && (pOut->BackgroundRet.nResult <= esbr_LastErrorNo)
					&& (pOut->BackgroundRet.nResult != esbr_ConEmuInShutdown)
					&& !mb_BgErrorShown)
				{
					mb_BgErrorShown = TRUE;
					Plugin()->ShowMessage(CEBkError_ExecFailed+pOut->BackgroundRet.nResult, 0);
				}
				ExecuteFreeResult(pOut);
			}
			else if (!mb_BgErrorShown)
			{
				mb_BgErrorShown = TRUE;
				Plugin()->ShowMessage(CEBkError_ExecFailed, 0);
			}

			ExecuteFreeResult(pIn);
		}
	}

	if (SETBACKGROUND_USE_EMF == 0)
	{
		if (hdc && hOld)
			SelectObject(hdc, hOld);
		if (hDib)
			DeleteObject(hDib);
		if (hdc)
			DeleteDC(hdc);
	}
	else
	{
		if (hdc)
		{
			hEmf = CloseEnhMetaFile(hdc);
			hdc = NULL;
		}
		if (hEmf)
		{
			DeleteEnhMetaFile(hEmf);
			hEmf = NULL;
		}
	}
}
Exemplo n.º 17
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);
}
Exemplo n.º 18
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;
}
Exemplo n.º 19
0
//// Эта функция пайп не закрывает!
//void CGuiServer::GuiServerThreadCommand(HANDLE hPipe)
BOOL CGuiServer::GuiServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam)
{
	BOOL lbRc = FALSE;
	CGuiServer* pGSrv = (CGuiServer*)lParam;

	if (!pGSrv)
	{
		_ASSERTE(((CGuiServer*)lParam)!=NULL);
		pGSrv = &gpConEmu->m_GuiServer;
	}

	if (pIn->hdr.bAsync)
		pGSrv->mp_GuiServer->BreakConnection(pInst);

	gpSetCls->debugLogCommand(pIn, TRUE, timeGetTime(), 0, pGSrv ? pGSrv->ms_ServerPipe : NULL);

	#ifdef _DEBUG
	UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR);
	#endif
	// Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат

	#ifdef ALLOW_WINE_MSG
	if (gbIsWine)
	{
		wchar_t szMsg[128];
		msprintf(szMsg, countof(szMsg), L"CGuiServer::GuiServerCommand.\nGUI TID=%u\nSrcPID=%u, SrcTID=%u, Cmd=%u",
			GetCurrentThreadId(), pIn->hdr.nSrcPID, pIn->hdr.nSrcThreadId, pIn->hdr.nCmd);
		MessageBox(szMsg, MB_ICONINFORMATION);
	}
	#endif

	switch (pIn->hdr.nCmd)
	{
		case CECMD_NEWCMD:
		{
			// Приходит из другой копии ConEmu.exe, когда она запущена с ключом /single, /showhide, /showhideTSA
			DEBUGSTRCMD(L"GUI recieved CECMD_NEWCMD\n");

			LPCWSTR pszCommand = pIn->NewCmd.GetCommand();
			_ASSERTE(pszCommand!=NULL && "Must be at least empty string but NOT NULL");

			if (pIn->NewCmd.isAdvLogging && !gpSetCls->isAdvLogging)
			{
				gpSetCls->isAdvLogging = pIn->NewCmd.isAdvLogging;
				gpConEmu->CreateLog();
			}

			if (gpSetCls->isAdvLogging && (pIn->NewCmd.isAdvLogging > gpSetCls->isAdvLogging))
			{
				wchar_t szLogLevel[80];
				_wsprintf(szLogLevel, SKIPLEN(countof(szLogLevel)) L"Changing log level! Old=%u, New=%u", (UINT)gpSetCls->isAdvLogging, (UINT)pIn->NewCmd.isAdvLogging);
				gpConEmu->LogString(szLogLevel);
				gpSetCls->isAdvLogging = pIn->NewCmd.isAdvLogging;
			}

			if (gpSetCls->isAdvLogging)
			{
				size_t cchAll = 120 + _tcslen(pIn->NewCmd.szConEmu) + _tcslen(pIn->NewCmd.szCurDir) + _tcslen(pszCommand);
				wchar_t* pszInfo = (wchar_t*)malloc(cchAll*sizeof(*pszInfo));
				if (pszInfo)
				{
					_wsprintf(pszInfo, SKIPLEN(cchAll) L"CECMD_NEWCMD: Wnd=x%08X, Act=%u, ConEmu=%s, Dir=%s, Cmd=%s",
						(DWORD)(DWORD_PTR)pIn->NewCmd.hFromConWnd, pIn->NewCmd.ShowHide,
						pIn->NewCmd.szConEmu, pIn->NewCmd.szCurDir, pszCommand);
					gpConEmu->LogString(pszInfo);
					free(pszInfo);
				}
			}

			BOOL bAccepted = FALSE;

			if (pIn->NewCmd.szConEmu[0])
			{
				bAccepted = (lstrcmpi(gpConEmu->ms_ConEmuExeDir, pIn->NewCmd.szConEmu) == 0);
			}
			else
			{
				bAccepted = TRUE;
			}

			if (bAccepted)
			{
				bool bCreateTab = (pIn->NewCmd.ShowHide == sih_None || pIn->NewCmd.ShowHide == sih_StartDetached)
					// Issue 1275: When minimized into TSA (on all VCon are closed) we need to restore and run new tab
					|| (pszCommand[0] && !CVConGroup::isVConExists(0));

				RConStartArgs rTest;
				if (pszCommand[0])
				{
					rTest.pszSpecialCmd = lstrdup(pszCommand);
					rTest.ProcessNewConArg();
				}

				bool bSkipActivation = false;

				// Может быть пусто
				if (bCreateTab && pszCommand[0])
				{
					RConStartArgs *pArgs = new RConStartArgs;

					// New tab must be started with same credentials that calling tab if others was not specified
					{
						if (!rTest.HasInheritedArgs())
						{
							CVConGuard VCon;
							if ((pIn->NewCmd.hFromConWnd || pIn->NewCmd.hFromDcWnd)
								&& CVConGroup::GetVConByHWND(pIn->NewCmd.hFromConWnd, pIn->NewCmd.hFromDcWnd, &VCon))
							{
								const RConStartArgs& r = VCon->RCon()->GetArgs();
								if (r.HasInheritedArgs())
								{
									pArgs->AssignInheritedArgs(&r);
								}
							}
						}
					}

					pArgs->Detached = (pIn->NewCmd.ShowHide == sih_StartDetached) ? crb_On : crb_Off;
					pArgs->pszSpecialCmd = lstrdup(pszCommand);
					if (pIn->NewCmd.szCurDir[0] == 0)
					{
						_ASSERTE(pIn->NewCmd.szCurDir[0] != 0);
					}
					else
					{
						pArgs->pszStartupDir = lstrdup(pIn->NewCmd.szCurDir);
					}

					LPCWSTR pszStrings = pIn->NewCmd.GetEnvStrings();
					if (pszStrings && pIn->NewCmd.cchEnvStrings)
					{
						size_t cbBytes = pIn->NewCmd.cchEnvStrings*sizeof(*pArgs->pszEnvStrings);
						pArgs->pszEnvStrings = (wchar_t*)malloc(cbBytes);
						if (pArgs->pszEnvStrings)
						{
							memmove(pArgs->pszEnvStrings, pszStrings, cbBytes);
							pArgs->cchEnvStrings = pIn->NewCmd.cchEnvStrings;
						}
					}

					if (gpSetCls->IsMulti() || CVConGroup::isDetached())
					{
						gpConEmu->PostCreateCon(pArgs);
					}
					else
					{
						// Если хотят в одном окне - только одну консоль
						gpConEmu->CreateWnd(pArgs);
						SafeDelete(pArgs);
						// New window created? Don't activate this one.
						bSkipActivation = true;
					}
				}
				else
				{
					_ASSERTE(pIn->NewCmd.ShowHide==sih_ShowMinimize || pIn->NewCmd.ShowHide==sih_ShowHideTSA || pIn->NewCmd.ShowHide==sih_Show);
				}

				// gh#151: Do animation after starting tab creation
				if (!bSkipActivation && (rTest.BackgroundTab != crb_On))
				{
					gpConEmu->DoMinimizeRestore(bCreateTab ? sih_SetForeground : pIn->NewCmd.ShowHide);
				}
			}

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE);
			lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize);
			if (lbRc)
			{
				ppReply->Data[0] = bAccepted;
			}

			break;
		} //CECMD_NEWCMD

		case CECMD_TABSCMD:
		{
			// 0: спрятать/показать табы, 1: перейти на следующую, 2: перейти на предыдущую, 3: commit switch
			DEBUGSTRCMD(L"GUI recieved CECMD_TABSCMD\n");
			_ASSERTE(nDataSize>=1);
			DWORD nTabCmd = pIn->Data[0];
			gpConEmu->TabCommand((ConEmuTabCommand)nTabCmd);

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				ppReply->Data[0] = TRUE;
			}
			break;
		} // CECMD_TABSCMD

		case CECMD_ATTACH2GUI:
		{
			// Получен запрос на Attach из сервера

			MCHKHEAP;

			CESERVER_REQ_SRVSTARTSTOPRET Ret = {};
			lbRc = CVConGroup::AttachRequested(pIn->StartStop.hWnd, &(pIn->StartStop), Ret);

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SRVSTARTSTOPRET)+(Ret.cchEnvCommands*sizeof(wchar_t));
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				SafeFree(Ret.pszCommands);
				goto wrap;
			}

			if (lbRc)
			{
				_ASSERTE(sizeof(ppReply->SrvStartStopRet) == sizeof(Ret));
				memmove(&ppReply->SrvStartStopRet, &Ret, sizeof(Ret));

				// Environment strings (inherited from parent console)
				if (Ret.cchEnvCommands && Ret.pszCommands)
				{
					memmove(ppReply->SrvStartStopRet.szCommands, Ret.pszCommands, Ret.cchEnvCommands*sizeof(wchar_t));
					ppReply->SrvStartStopRet.cchEnvCommands = Ret.cchEnvCommands;
				}
				else
				{
					ppReply->SrvStartStopRet.cchEnvCommands = 0;
				}
				SafeFree(Ret.pszCommands);

				_ASSERTE((ppReply->StartStopRet.nBufferHeight == 0) || ((int)ppReply->StartStopRet.nBufferHeight > (pIn->StartStop.sbi.srWindow.Bottom-pIn->StartStop.sbi.srWindow.Top)));
			}

			MCHKHEAP;

			break;
		} // CECMD_ATTACH2GUI

		case CECMD_SRVSTARTSTOP:
		{
			MCHKHEAP;

			// SRVSTART не приходит если запускается cmd под админом или из Win+G
			bool lbAllocated = false;

			if (pIn->SrvStartStop.Started == srv_Started)
			{
				// Запущен процесс сервера
				HWND hConWnd = (HWND)pIn->dwData[1];
				_ASSERTE(hConWnd && IsWindow(hConWnd));

				DWORD nStartTick = timeGetTime();

				struct MsgSrvStartedArg
				{
					HWND  hConWnd;
					DWORD nSrcPID;
					DWORD dwKeybLayout;
					DWORD timeStart;
					DWORD timeRecv;
					DWORD timeFin;
					CESERVER_REQ_SRVSTARTSTOPRET Ret;

					//111002 - вернуть должен HWND окна отрисовки (дочернее окно ConEmu)
					static LRESULT OnSrvStarted(LPARAM lParam)
					{
						MsgSrvStartedArg *pArg = (MsgSrvStartedArg*)lParam;

						HWND hWndDC = NULL;

						DWORD nServerPID = pArg->nSrcPID;
						HWND  hWndCon = pArg->hConWnd;
						DWORD dwKeybLayout = pArg->dwKeybLayout;
						pArg->timeRecv = timeGetTime();

						DWORD t1, t2; int iFound = -1;

						hWndDC = CVConGroup::DoSrvCreated(nServerPID, hWndCon, dwKeybLayout, t1, t2, iFound, pArg->Ret);

						UNREFERENCED_PARAMETER(dwKeybLayout);
						UNREFERENCED_PARAMETER(hWndCon);

						pArg->timeFin = timeGetTime();
						if (hWndDC == NULL)
						{
							_ASSERTE(hWndDC!=NULL);
						}
						else
						{
							#ifdef _DEBUG
							DWORD nRecvDur = pArg->timeRecv - pArg->timeStart;
							DWORD nProcDur = pArg->timeFin - pArg->timeRecv;

							#define MSGSTARTED_TIMEOUT 10000
							if ((nRecvDur > MSGSTARTED_TIMEOUT) || (nProcDur > MSGSTARTED_TIMEOUT))
							{
								_ASSERTE((nRecvDur <= MSGSTARTED_TIMEOUT) && (nProcDur <= MSGSTARTED_TIMEOUT));
							}
							#endif
						}

						return (LRESULT)hWndDC;
					};
				} arg = {hConWnd, pIn->hdr.nSrcPID, pIn->SrvStartStop.dwKeybLayout, nStartTick};

				gpConEmu->CallMainThread(true, arg.OnSrvStarted, (LPARAM)&arg);

				HWND hWndDC = arg.Ret.Info.hWndDc;
				HWND hWndBack = arg.Ret.Info.hWndBack;
				_ASSERTE(hWndDC!=NULL);

				#ifdef _DEBUG
				DWORD dwErr = GetLastError(), nEndTick = timeGetTime(), nDelta = nEndTick - nStartTick;
				if (hWndDC && nDelta >= EXECUTE_CMD_WARN_TIMEOUT)
				{
					if (!IsDebuggerPresent())
					{
						//_ASSERTE(nDelta <= EXECUTE_CMD_WARN_TIMEOUT || (pIn->hdr.nCmd == CECMD_CMDSTARTSTOP && nDelta <= EXECUTE_CMD_WARN_TIMEOUT2));
						_ASSERTEX(nDelta <= EXECUTE_CMD_WARN_TIMEOUT);
					}
				}
				#endif

				pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SRVSTARTSTOPRET)+(arg.Ret.cchEnvCommands*sizeof(wchar_t));
				if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				{
					SafeFree(arg.Ret.pszCommands);
					goto wrap;
				}
				lbAllocated = true;

				_ASSERTE(sizeof(ppReply->SrvStartStopRet) == sizeof(arg.Ret));
				memmove(&ppReply->SrvStartStopRet, &arg.Ret, sizeof(arg.Ret));

				// Environment strings (inherited from parent console)
				if (arg.Ret.cchEnvCommands && arg.Ret.pszCommands)
				{
					memmove(ppReply->SrvStartStopRet.szCommands, arg.Ret.pszCommands, arg.Ret.cchEnvCommands*sizeof(wchar_t));
					ppReply->SrvStartStopRet.cchEnvCommands = arg.Ret.cchEnvCommands;
				}
				else
				{
					ppReply->SrvStartStopRet.cchEnvCommands = 0;
				}
				SafeFree(arg.Ret.pszCommands);
			}
			else if (pIn->SrvStartStop.Started == srv_Stopped)
			{
				// Процесс сервера завершается
				CRealConsole* pRCon = NULL;
				CVConGuard VCon;

				for (size_t i = 0;; i++)
				{
					if (!CVConGroup::GetVCon(i, &VCon))
						break;

					pRCon = VCon->RCon();
					if (pRCon && (pRCon->GetServerPID(true) == pIn->hdr.nSrcPID || pRCon->GetServerPID(false) == pIn->hdr.nSrcPID))
					{
						break;
					}
					pRCon = NULL;
				}

				gpConEmu->mn_ShellExitCode = pIn->SrvStartStop.nShellExitCode;

				if (pRCon)
					pRCon->OnServerClosing(pIn->hdr.nSrcPID, &pIn->SrvStartStop.nShellExitCode);

				//pIn->dwData[0] = 1;
			}
			else
			{
				_ASSERTE((pIn->dwData[0] == 1) || (pIn->dwData[0] == 101));
			}

			MCHKHEAP;

			if (!lbAllocated)
			{
				pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SRVSTARTSTOPRET);
				if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
					goto wrap;
			}

			lbRc = TRUE;
			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               pOut,         // buffer to write from
			//               pOut->hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O

			//ExecuteFreeResult(pOut);
			break;
		} // CECMD_SRVSTARTSTOP

		case CECMD_ASSERT:
		{
			DWORD nBtn = MessageBox(NULL, pIn->AssertInfo.szDebugInfo, pIn->AssertInfo.szTitle, pIn->AssertInfo.nBtns);

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				ppReply->dwData[0] = nBtn;
			}

			//ExecutePrepareCmd(&pIn->hdr, CECMD_ASSERT, sizeof(CESERVER_REQ_HDR) + sizeof(DWORD));
			//pIn->dwData[0] = nBtn;
			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               pIn,         // buffer to write from
			//               pIn->hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O
			break;
		} // CECMD_ASSERT

		case CECMD_ATTACHGUIAPP:
		{
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;
			ppReply->AttachGuiApp = pIn->AttachGuiApp;

			//CESERVER_REQ Out;
			//ExecutePrepareCmd(&Out.hdr, CECMD_ATTACHGUIAPP, sizeof(CESERVER_REQ_HDR)+sizeof(Out.AttachGuiApp));
			//Out.AttachGuiApp = pIn->AttachGuiApp;

			#ifdef SHOW_GUIATTACH_START
			if (pIn->AttachGuiApp.hWindow == NULL)
			{
				wchar_t szDbg[1024];
				_wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"AttachGuiApp requested from:\n%s\nPID=%u", pIn->AttachGuiApp.sAppFilePathName, pIn->AttachGuiApp.nPID);
				//MBoxA(szDbg);
				MessageBox(NULL, szDbg, L"ConEmu", MB_SYSTEMMODAL);
			}
			#endif

			// Уведомить ожидающую вкладку
			CRealConsole* pRCon = CVConGroup::AttachRequestedGui(pIn->AttachGuiApp.nServerPID, pIn->AttachGuiApp.sAppFilePathName, pIn->AttachGuiApp.nPID);
			if (pRCon)
			{
				CVConGuard VCon(pRCon->VCon());
				RECT rcPrev = ppReply->AttachGuiApp.rcWindow;
				HWND hBack = pRCon->VCon()->GetBack();

				//// Размер должен быть независим от возможности наличия прокрутки в VCon
				//GetWindowRect(hBack, &ppReply->AttachGuiApp.rcWindow);
				//ppReply->AttachGuiApp.rcWindow.right -= ppReply->AttachGuiApp.rcWindow.left;
				//ppReply->AttachGuiApp.rcWindow.bottom -= ppReply->AttachGuiApp.rcWindow.top;
				//ppReply->AttachGuiApp.rcWindow.left = ppReply->AttachGuiApp.rcWindow.top = 0;
				////MapWindowPoints(NULL, hBack, (LPPOINT)&ppReply->AttachGuiApp.rcWindow, 2);
				//pRCon->CorrectGuiChildRect(ppReply->AttachGuiApp.nStyle, ppReply->AttachGuiApp.nStyleEx, ppReply->AttachGuiApp.rcWindow);

				// Уведомить RCon и ConEmuC, что гуй подцепился
				// Вызывается два раза. Первый (при запуске exe) ahGuiWnd==NULL, второй - после фактического создания окна
				pRCon->SetGuiMode(pIn->AttachGuiApp.nFlags, pIn->AttachGuiApp.hAppWindow, pIn->AttachGuiApp.Styles.nStyle, pIn->AttachGuiApp.Styles.nStyleEx, pIn->AttachGuiApp.sAppFilePathName, pIn->AttachGuiApp.nPID, pIn->hdr.nBits, rcPrev);

				ppReply->AttachGuiApp.nFlags = agaf_Success | (pRCon->isActive(false) ? 0 : agaf_Inactive);
				ppReply->AttachGuiApp.nServerPID = pRCon->GetServerPID();
				ppReply->AttachGuiApp.nPID = ppReply->AttachGuiApp.nServerPID;
				ppReply->AttachGuiApp.hConEmuDc = pRCon->GetView();
				ppReply->AttachGuiApp.hConEmuBack = hBack;
				ppReply->AttachGuiApp.hConEmuWnd = ghWnd;
				ppReply->AttachGuiApp.hAppWindow = pIn->AttachGuiApp.hAppWindow;
				ppReply->AttachGuiApp.hSrvConWnd = pRCon->ConWnd();
				ppReply->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(gpConEmu->mn_MainThreadId);
				ZeroStruct(ppReply->AttachGuiApp.Styles.Shifts);
				CRealConsole::CorrectGuiChildRect(pIn->AttachGuiApp.Styles.nStyle, pIn->AttachGuiApp.Styles.nStyleEx, ppReply->AttachGuiApp.Styles.Shifts, pIn->AttachGuiApp.sAppFilePathName);
			}
			else
			{
				ppReply->AttachGuiApp.nFlags = agaf_Fail;
				_ASSERTE(FALSE && "No one tab is waiting for ChildGui process");
			}

			lbRc = TRUE;

			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               &Out,         // buffer to write from
			//               Out.hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O
			break;
		} // CECMD_ATTACHGUIAPP

		case CECMD_GUICLIENTSHIFT:
		{
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(GuiStylesAndShifts);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;
			ppReply->GuiAppShifts = pIn->GuiAppShifts;

			ZeroStruct(ppReply->GuiAppShifts.Shifts);
			CRealConsole::CorrectGuiChildRect(pIn->GuiAppShifts.nStyle, pIn->GuiAppShifts.nStyleEx, ppReply->GuiAppShifts.Shifts, pIn->GuiAppShifts.szExeName);

			lbRc = TRUE;
			break;
		} // CECMD_GUICLIENTSHIFT

		case CECMD_GUIMACRO:
		{
			// Допустимо, если GuiMacro пытаются выполнить извне
			CVConGuard VCon;

			CVConGroup::GetActiveVCon(&VCon);

			DWORD nFarPluginPID = VCon->RCon()->GetFarPID(true);
			LPWSTR pszResult = ConEmuMacro::ExecuteMacro(pIn->GuiMacro.sMacro, VCon->RCon(), (nFarPluginPID==pIn->hdr.nSrcPID), &pIn->GuiMacro);

			int nLen = pszResult ? _tcslen(pszResult) : 0;

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_GUIMACRO)+nLen*sizeof(wchar_t);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				SafeFree(pszResult);
				goto wrap;
			}

			if (pszResult)
			{
				lstrcpy(ppReply->GuiMacro.sMacro, pszResult);
				ppReply->GuiMacro.nSucceeded = 1;
				free(pszResult);
			}
			else
			{
				ppReply->GuiMacro.sMacro[0] = 0;
				ppReply->GuiMacro.nSucceeded = 0;
			}

			lbRc = TRUE;
			break;
		} // CECMD_GUIMACRO

		case CECMD_CMDSTARTSTOP:
		{
			CRealServer* pRSrv = NULL;
			CVConGuard VCon;

			DWORD nSrvPID = pIn->hdr.nSrcPID;
			DWORD nMonitorTID = (pIn->DataSize() >= sizeof(pIn->StartStop)) ? pIn->StartStop.dwAID : 0;

			if (CVConGroup::GetVConBySrvPID(nSrvPID, nMonitorTID, &VCon))
				pRSrv = &VCon->RCon()->m_RConServer;

			if (pRSrv)
			{
				CESERVER_REQ* pOut = pRSrv->cmdStartStop(pInst, pIn, pIn->DataSize());
				if (pOut)
				{
					DWORD nDataSize = pOut->DataSize();
					pcbReplySize = pOut->hdr.cbSize;
					if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pOut->hdr.nCmd, pcbReplySize))
					{
						if (nDataSize > 0)
						{
							memmove(ppReply->Data, pOut->Data, nDataSize);
						}
						lbRc = TRUE;
					}
					ExecuteFreeResult(pOut);
				}
			}
			break;
		} // CECMD_CMDSTARTSTOP

		//case CECMD_DEFTERMSTARTED:
		//{
		//	if (gpConEmu->mp_DefTrm)
		//		gpConEmu->mp_DefTrm->OnDefTermStarted(pIn);

		//	pcbReplySize = sizeof(CESERVER_REQ_HDR);
		//	if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
		//		goto wrap;
		//	lbRc = TRUE;
		//	break;
		//} // CECMD_DEFTERMSTARTED

		default:
			_ASSERTE(FALSE && "Command was not handled in CGuiServer::GuiServerCommand");
	}

	//// Освободить память
	//if (pIn && (LPVOID)pIn != (LPVOID)&in)
	//{
	//	free(pIn); pIn = NULL;
	//}
wrap:
	return lbRc;
}
Exemplo n.º 20
0
//// Эта функция пайп не закрывает!
//void CGuiServer::GuiServerThreadCommand(HANDLE hPipe)
BOOL CGuiServer::GuiServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam)
{
	BOOL lbRc = FALSE;
	CGuiServer* pGSrv = (CGuiServer*)lParam;

	if (!pGSrv)
	{
		_ASSERTE(((CGuiServer*)lParam)!=NULL);
		pGSrv = &gpConEmu->m_GuiServer;
	}
	
	if (pIn->hdr.bAsync)
		pGSrv->mp_GuiServer->BreakConnection(pInst);

	gpSetCls->debugLogCommand(pIn, TRUE, timeGetTime(), 0, pGSrv ? pGSrv->ms_ServerPipe : NULL);

	#ifdef _DEBUG
	UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR);
	#endif
	// Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат

	#ifdef ALLOW_WINE_MSG
	if (gbIsWine)
	{
		wchar_t szMsg[128];
		msprintf(szMsg, countof(szMsg), L"CGuiServer::GuiServerCommand.\nGUI TID=%u\nSrcPID=%u, SrcTID=%u, Cmd=%u",
			GetCurrentThreadId(), pIn->hdr.nSrcPID, pIn->hdr.nSrcThreadId, pIn->hdr.nCmd);
		MessageBox(szMsg, MB_ICONINFORMATION);
	}
	#endif

	switch (pIn->hdr.nCmd)
	{
		case CECMD_NEWCMD:
		{
			// Приходит из другой копии ConEmu.exe, когда она запущена с ключом /single, /showhide, /showhideTSA
			DEBUGSTR(L"GUI recieved CECMD_NEWCMD\n");

			if (gpSetCls->isAdvLogging)
			{
				size_t cchAll = 120 + _tcslen(pIn->NewCmd.szConEmu) + _tcslen(pIn->NewCmd.szCurDir) + _tcslen(pIn->NewCmd.szCommand);
				wchar_t* pszInfo = (wchar_t*)malloc(cchAll*sizeof(*pszInfo));
				if (pszInfo)
				{
					_wsprintf(pszInfo, SKIPLEN(cchAll) L"CECMD_NEWCMD: Wnd=x%08X, Act=%u, ConEmu=%s, Dir=%s, Cmd=%s",
						(DWORD)(DWORD_PTR)pIn->NewCmd.hFromConWnd, pIn->NewCmd.ShowHide,
						pIn->NewCmd.szConEmu, pIn->NewCmd.szCurDir, pIn->NewCmd.szCommand);
					gpConEmu->LogString(pszInfo);
					free(pszInfo);
				}
			}

			BOOL bAccepted = FALSE;

			if (pIn->NewCmd.szConEmu[0])
			{
				bAccepted = (lstrcmpi(gpConEmu->ms_ConEmuExeDir, pIn->NewCmd.szConEmu) == 0);
			}
			else
			{
				bAccepted = TRUE;
			}

			if (bAccepted)
			{
				bool bCreateTab = (pIn->NewCmd.ShowHide == sih_None || pIn->NewCmd.ShowHide == sih_StartDetached);
				gpConEmu->OnMinimizeRestore(bCreateTab ? sih_SetForeground : pIn->NewCmd.ShowHide);

				// Может быть пусто
				if (bCreateTab && pIn->NewCmd.szCommand[0])
				{
					RConStartArgs *pArgs = new RConStartArgs;
					pArgs->bDetached = (pIn->NewCmd.ShowHide == sih_StartDetached);
					pArgs->pszSpecialCmd = lstrdup(pIn->NewCmd.szCommand);
					if (pIn->NewCmd.szCurDir[0] == 0)
					{
						_ASSERTE(pIn->NewCmd.szCurDir[0] != 0);
					}
					else
					{
						pArgs->pszStartupDir = lstrdup(pIn->NewCmd.szCurDir);
					}

					if (gpSet->isMulti || CVConGroup::isDetached())
					{
						gpConEmu->PostCreateCon(pArgs);
					}
					else
					{
						// Если хотят в одном окне - только одну консоль
						gpConEmu->CreateWnd(pArgs);
						SafeDelete(pArgs);
					}
				}
				else
				{
					_ASSERTE(pIn->NewCmd.ShowHide==sih_ShowMinimize || pIn->NewCmd.ShowHide==sih_ShowHideTSA || pIn->NewCmd.ShowHide==sih_Show);
				}
			}

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE);
			lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize);
			if (lbRc)
			{
				ppReply->Data[0] = bAccepted;
			}

			break;
		} //CECMD_NEWCMD

		case CECMD_TABSCMD:
		{
			// 0: спрятать/показать табы, 1: перейти на следующую, 2: перейти на предыдущую, 3: commit switch
			DEBUGSTR(L"GUI recieved CECMD_TABSCMD\n");
			_ASSERTE(nDataSize>=1);
			DWORD nTabCmd = pIn->Data[0];
			gpConEmu->TabCommand((ConEmuTabCommand)nTabCmd);

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				ppReply->Data[0] = TRUE;
			}
			break;
		} // CECMD_TABSCMD

		#if 0
		case CECMD_GETALLTABS:
		{
			int nConCount = gpConEmu->GetConCount();
			int nActiveCon = gpConEmu->ActiveConNum();
			size_t cchMax = nConCount*16;
			size_t cchCount = 0;
			CVirtualConsole* pVCon;
			CESERVER_REQ_GETALLTABS::TabInfo* pTabs = (CESERVER_REQ_GETALLTABS::TabInfo*)calloc(cchMax, sizeof(*pTabs));
			for (int V = 0; (pVCon = gpConEmu->GetVCon(V)) != NULL; V++)
			{
				if (!pTabs)
				{
					_ASSERTE(pTabs!=NULL);
					break;
				}

				CRealConsole* pRCon = pVCon->RCon();
				if (!pRCon)
					continue;

				ConEmuTab tab;
				wchar_t szModified[4];
				for (int T = 0; pRCon->GetTab(T, &tab); T++)
				{
					if (cchCount >= cchMax)
					{
						pTabs = (CESERVER_REQ_GETALLTABS::TabInfo*)realloc(pTabs, (cchMax+32)*sizeof(*pTabs));
						if (!pTabs)
						{
							_ASSERTE(pTabs!=NULL);
							break;
						}
						cchMax += 32;
						_ASSERTE(cchCount<cchMax);
					}

					pTabs[cchCount].ActiveConsole == (V == nActiveCon);
					pTabs[cchCount].ActiveTab == (tab.Current != 0);
					pTabs[cchCount].Disabled = ((tab.Type & fwt_Disabled) == fwt_Disabled);
					pTabs[cchCount].ConsoleIdx = V;
					pTabs[cchCount].TabIdx = T;

					// Text
					wcscpy_c(szModified, tab.Modified ? L" * " : L"   ");
					if (V == nActiveCon)
					{
						if (T < 9)
							_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/&%i]%s", V+1, T+1, szModified);
						else if (T == 9)
							_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/1&0]%s", V+1, szModified);
						else
							_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/%i]%s", V+1, T+1, szModified);
					}
					else
					{
						_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/%i]%s", V+1, T+1, szModified);
					}

					cchCount++;
				}
			}
			if (cchCount && pTabs)
			{
				pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_GETALLTABS)+((cchCount-1)*sizeof(CESERVER_REQ_GETALLTABS::TabInfo));
				if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				{
					lbRc = TRUE;
					ppReply->GetAllTabs.Count = cchCount;
					memmove(ppReply->GetAllTabs.Tabs, pTabs, cchCount*sizeof(*pTabs));
				}
			}
			SafeFree(pTabs);
			break;
		} // CECMD_GETALLTABS

		case CECMD_ACTIVATETAB:
		{
			BOOL lbTabOk = FALSE;
			CVirtualConsole *pVCon = gpConEmu->GetVCon(pIn->dwData[0]);
			if (pVCon && pVCon->RCon())
			{
				lbTabOk = pVCon->RCon()->ActivateFarWindow(pIn->dwData[1]);
			}

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				ppReply->dwData[0] = lbTabOk;
			}
			break;
		} // CECMD_ACTIVATETAB
		#endif

		case CECMD_ATTACH2GUI:
		{
			// Получен запрос на Attach из сервера
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;
			//CESERVER_REQ* pOut = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET));

			gpConEmu->AttachRequested(pIn->StartStop.hWnd, &(pIn->StartStop), &(ppReply->StartStopRet));
			_ASSERTE((ppReply->StartStopRet.nBufferHeight == 0) || ((int)ppReply->StartStopRet.nBufferHeight > pIn->StartStop.sbi.dwSize.X));

			lbRc = TRUE;
			//ExecuteFreeResult(pOut);
			break;
		} // CECMD_ATTACH2GUI

		case CECMD_SRVSTARTSTOP:
		{
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;

			if (pIn->SrvStartStop.Started == srv_Started)
			{
				// Запущен процесс сервера
				HWND hConWnd = (HWND)pIn->dwData[1];
				_ASSERTE(hConWnd && IsWindow(hConWnd));

				DWORD nStartTick = timeGetTime();

				//LRESULT l = 0;
				//DWORD_PTR dwRc = 0;
				//2010-05-21 Поскольку это критично - лучше ждать до упора, хотя может быть DeadLock?
				//l = SendMessageTimeout(ghWnd, gpConEmu->mn_MsgSrvStarted, (WPARAM)hConWnd, pIn->hdr.nSrcPID,
				//	SMTO_BLOCK, 5000, &dwRc);

				//111002 - вернуть должен HWND окна отрисовки (дочернее окно ConEmu)
				MsgSrvStartedArg arg = {hConWnd, pIn->hdr.nSrcPID, pIn->SrvStartStop.dwKeybLayout, nStartTick};
				SendMessage(ghWnd, gpConEmu->mn_MsgSrvStarted, 0, (LPARAM)&arg);
				HWND hWndDC = arg.hWndDc;
				HWND hWndBack = arg.hWndBack;
				_ASSERTE(hWndDC!=NULL);

				#ifdef _DEBUG
				DWORD dwErr = GetLastError(), nEndTick = timeGetTime(), nDelta = nEndTick - nStartTick;
				if (hWndDC && nDelta >= EXECUTE_CMD_WARN_TIMEOUT)
				{
					if (!IsDebuggerPresent())
					{
						//_ASSERTE(nDelta <= EXECUTE_CMD_WARN_TIMEOUT || (pIn->hdr.nCmd == CECMD_CMDSTARTSTOP && nDelta <= EXECUTE_CMD_WARN_TIMEOUT2));
						_ASSERTEX(nDelta <= EXECUTE_CMD_WARN_TIMEOUT);
					}
				}
				#endif

				//pIn->dwData[0] = (DWORD)ghWnd; //-V205
				//pIn->dwData[1] = (DWORD)dwRc; //-V205
				//pIn->dwData[0] = (l == 0) ? 0 : 1;
				ppReply->StartStopRet.hWnd = ghWnd;
				ppReply->StartStopRet.hWndDc = hWndDC;
				ppReply->StartStopRet.hWndBack = hWndBack;
				ppReply->StartStopRet.dwPID = GetCurrentProcessId();
			}
			else if (pIn->SrvStartStop.Started == srv_Stopped)
			{
				// Процесс сервера завершается
				CRealConsole* pRCon = NULL;
				CVConGuard VCon;

				for (size_t i = 0;; i++)
				{
					if (!CVConGroup::GetVCon(i, &VCon))
						break;

					pRCon = VCon->RCon();
					if (pRCon && (pRCon->GetServerPID(true) == pIn->hdr.nSrcPID || pRCon->GetServerPID(false) == pIn->hdr.nSrcPID))
					{
						break;
					}
					pRCon = NULL;
				}

				if (pRCon)
					pRCon->OnServerClosing(pIn->hdr.nSrcPID);

				//pIn->dwData[0] = 1;
			}
			else
			{
				_ASSERTE((pIn->dwData[0] == 1) || (pIn->dwData[0] == 101));
			}

			lbRc = TRUE;
			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               pOut,         // buffer to write from
			//               pOut->hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O

			//ExecuteFreeResult(pOut);
			break;
		} // CECMD_SRVSTARTSTOP

		case CECMD_ASSERT:
		{
			DWORD nBtn = MessageBox(NULL, pIn->AssertInfo.szDebugInfo, pIn->AssertInfo.szTitle, pIn->AssertInfo.nBtns);

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				ppReply->dwData[0] = nBtn;
			}

			//ExecutePrepareCmd(&pIn->hdr, CECMD_ASSERT, sizeof(CESERVER_REQ_HDR) + sizeof(DWORD));
			//pIn->dwData[0] = nBtn;
			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               pIn,         // buffer to write from
			//               pIn->hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O
			break;
		} // CECMD_ASSERT

		case CECMD_ATTACHGUIAPP:
		{
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;
			ppReply->AttachGuiApp = pIn->AttachGuiApp;

			//CESERVER_REQ Out;
			//ExecutePrepareCmd(&Out.hdr, CECMD_ATTACHGUIAPP, sizeof(CESERVER_REQ_HDR)+sizeof(Out.AttachGuiApp));
			//Out.AttachGuiApp = pIn->AttachGuiApp;
			
			#ifdef SHOW_GUIATTACH_START
			if (pIn->AttachGuiApp.hWindow == NULL)
			{
				wchar_t szDbg[1024];
				_wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"AttachGuiApp requested from:\n%s\nPID=%u", pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID);
				//MBoxA(szDbg);
				MessageBox(NULL, szDbg, L"ConEmu", MB_SYSTEMMODAL);
			}
			#endif

			// Уведомить ожидающую вкладку
			CRealConsole* pRCon = gpConEmu->AttachRequestedGui(pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID);
			if (pRCon)
			{
				CVConGuard VCon(pRCon->VCon());
				RECT rcPrev = ppReply->AttachGuiApp.rcWindow;
				HWND hBack = pRCon->VCon()->GetBack();

				//// Размер должен быть независим от возможности наличия прокрутки в VCon
				//GetWindowRect(hBack, &ppReply->AttachGuiApp.rcWindow);
				//ppReply->AttachGuiApp.rcWindow.right -= ppReply->AttachGuiApp.rcWindow.left;
				//ppReply->AttachGuiApp.rcWindow.bottom -= ppReply->AttachGuiApp.rcWindow.top;
				//ppReply->AttachGuiApp.rcWindow.left = ppReply->AttachGuiApp.rcWindow.top = 0;
				////MapWindowPoints(NULL, hBack, (LPPOINT)&ppReply->AttachGuiApp.rcWindow, 2);
				//pRCon->CorrectGuiChildRect(ppReply->AttachGuiApp.nStyle, ppReply->AttachGuiApp.nStyleEx, ppReply->AttachGuiApp.rcWindow);
				
				// Уведомить RCon и ConEmuC, что гуй подцепился
				// Вызывается два раза. Первый (при запуске exe) ahGuiWnd==NULL, второй - после фактического создания окна
				pRCon->SetGuiMode(pIn->AttachGuiApp.nFlags, pIn->AttachGuiApp.hAppWindow, pIn->AttachGuiApp.Styles.nStyle, pIn->AttachGuiApp.Styles.nStyleEx, pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID, rcPrev);

				ppReply->AttachGuiApp.nFlags = agaf_Success | (pRCon->isActive(false) ? 0 : agaf_Inactive);
				ppReply->AttachGuiApp.nPID = pRCon->GetServerPID();
				ppReply->AttachGuiApp.hConEmuDc = pRCon->GetView();
				ppReply->AttachGuiApp.hConEmuBack = hBack;
				ppReply->AttachGuiApp.hConEmuWnd = ghWnd;
				ppReply->AttachGuiApp.hAppWindow = pIn->AttachGuiApp.hAppWindow;
				ppReply->AttachGuiApp.hSrvConWnd = pRCon->ConWnd();
				ppReply->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(gpConEmu->mn_MainThreadId);
				ZeroStruct(ppReply->AttachGuiApp.Styles.Shifts);
				CRealConsole::CorrectGuiChildRect(pIn->AttachGuiApp.Styles.nStyle, pIn->AttachGuiApp.Styles.nStyleEx, ppReply->AttachGuiApp.Styles.Shifts);
			}
			else
			{
				ppReply->AttachGuiApp.nFlags = agaf_Fail;
			}

			lbRc = TRUE;

			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               &Out,         // buffer to write from
			//               Out.hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O
			break;
		} // CECMD_ATTACHGUIAPP

		case CECMD_GUICLIENTSHIFT:
		{
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(GuiStylesAndShifts);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;
			ppReply->GuiAppShifts = pIn->GuiAppShifts;

			ZeroStruct(ppReply->GuiAppShifts.Shifts);
			CRealConsole::CorrectGuiChildRect(pIn->GuiAppShifts.nStyle, pIn->GuiAppShifts.nStyleEx, ppReply->GuiAppShifts.Shifts);

			lbRc = TRUE;
			break;
		} // CECMD_GUICLIENTSHIFT
	}

	//// Освободить память
	//if (pIn && (LPVOID)pIn != (LPVOID)&in)
	//{
	//	free(pIn); pIn = NULL;
	//}
wrap:
	return lbRc;
}
Exemplo n.º 21
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);
}
Exemplo n.º 22
0
// Helper function: Notification ‘Debug’ setting page in ConEmu
void OnPeekReadConsoleInput(char acPeekRead/*'P'/'R'*/, char acUnicode/*'A'/'W'*/, HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nRead)
{
#ifdef TRAP_ON_MOUSE_0x0
	if (lpBuffer && nRead)
	{
		for (UINT i = 0; i < nRead; i++)
		{
			if (lpBuffer[i].EventType == MOUSE_EVENT)
			{
				if (lpBuffer[i].Event.MouseEvent.dwMousePosition.X == 0 && lpBuffer[i].Event.MouseEvent.dwMousePosition.Y == 0)
				{
					_ASSERTE(!(lpBuffer[i].Event.MouseEvent.dwMousePosition.X == 0 && lpBuffer[i].Event.MouseEvent.dwMousePosition.Y == 0));
				}
				//if (lpBuffer[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED && lpBuffer[i].Event.MouseEvent.dwMousePosition.X != 5)
				//{
				//	_ASSERTE(!(lpBuffer[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED && lpBuffer[i].Event.MouseEvent.dwMousePosition.X != 5));
				//}
			}
		}
	}
#endif

	DWORD nCurrentTID = GetCurrentThreadId();

	gReadConsoleInfo.LastReadConsoleInputTID = nCurrentTID;
	gReadConsoleInfo.hConsoleInput2 = hConsoleInput;

	if (nRead)
	{
		if (!gbWasSucceededInRead)
			gbWasSucceededInRead = TRUE;

		// Сброс кешированных значений
		GetConsoleScreenBufferInfoCached(NULL, NULL);
	}

	if (!gFarMode.bFarHookMode || !gFarMode.bMonitorConsoleInput || !nRead || !lpBuffer)
		return;

	//// Пока - только Read. Peek игнорируем
	//if (acPeekRead != 'R')
	//	return;

	CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_PEEKREADINFO, sizeof(CESERVER_REQ_HDR) //-V119
		+sizeof(CESERVER_REQ_PEEKREADINFO)+(nRead-1)*sizeof(INPUT_RECORD));
	if (pIn)
	{
		pIn->PeekReadInfo.nCount = (WORD)nRead;
		pIn->PeekReadInfo.cPeekRead = acPeekRead;
		pIn->PeekReadInfo.cUnicode = acUnicode;
		pIn->PeekReadInfo.h = hConsoleInput;
		pIn->PeekReadInfo.nTID = nCurrentTID;
		pIn->PeekReadInfo.nPID = GetCurrentProcessId();
		pIn->PeekReadInfo.bMainThread = (pIn->PeekReadInfo.nTID == gnHookMainThreadId);
		memmove(pIn->PeekReadInfo.Buffer, lpBuffer, nRead*sizeof(INPUT_RECORD));

		CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd);
		if (pOut) ExecuteFreeResult(pOut);
		ExecuteFreeResult(pIn);
	}


}
Exemplo n.º 23
0
// Если (anFromShowWindow != -1), значит функу зовут из ShowWindow
void OnGuiWindowAttached(HWND hWindow, HMENU hMenu, LPCSTR asClassA, LPCWSTR asClassW, DWORD anStyle, DWORD anStyleEx, BOOL abStyleHidden, int anFromShowWindow/*=-1*/)
{
	DWORD nCurStyle = (DWORD)user->getWindowLongPtrW(hWindow, GWL_STYLE);
	DWORD nCurStyleEx = (DWORD)user->getWindowLongPtrW(hWindow, GWL_EXSTYLE);

	user->allowSetForegroundWindow(ASFW_ANY);

	// VLC создает несколько "подходящих" окон, но ShowWindow зовет
	// только для одного из них. Поэтому фактический аттач делаем
	// только в том случае, если окно "видимое"
	if ((!(nCurStyle & WS_VISIBLE)) && (anFromShowWindow <= SW_HIDE))
	{
		// Значит потом, из ShowWindow
		return;
	}

	ghAttachGuiClient = hWindow;
	gnAttachGuiClientThreadId = user->getWindowThreadProcessId(hWindow, NULL);
	gbForceShowGuiClient = TRUE;
	gbAttachGuiClient = FALSE; // Только одно окно приложения. Пока?

#if 0
	// Для WS_CHILDWINDOW меню нельзя указать при создании окна
	if (!hMenu && !ghAttachGuiClientMenu && (asClassA || asClassW))
	{
		BOOL lbRcClass;
		WNDCLASSEXA wca = {sizeof(WNDCLASSEXA)};
		WNDCLASSEXW wcw = {sizeof(WNDCLASSEXW)};
		if (asClassA)
		{
			lbRcClass = GetClassInfoExA(GetModuleHandle(NULL), asClassA, &wca);
			if (lbRcClass)
				ghAttachGuiClientMenu = LoadMenuA(wca.hInstance, wca.lpszMenuName);
		}
		else
		{
			lbRcClass = GetClassInfoExW(GetModuleHandle(NULL), asClassW, &wcw);
			if (lbRcClass)
				ghAttachGuiClientMenu = LoadMenuW(wca.hInstance, wcw.lpszMenuName);
		}
		hMenu = ghAttachGuiClientMenu;
	}
	if (hMenu)
	{
		// Для WS_CHILDWINDOW - не работает
		SetMenu(hWindow, hMenu);
		HMENU hSys = GetSystemMenu(hWindow, FALSE);
		TODO("Это в принципе прокатывает, но нужно транслировать WM_SYSCOMMAND -> WM_COMMAND, соответственно, перехватывать WndProc, или хук ставить");
		if (hSys)
		{
			TODO("Хотя, хорошо бы не все в Popup засоывать, а извлечь ChildPopups из hMenu");
			InsertMenu(hSys, 0, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hMenu, L"Window menu");
			InsertMenu(hSys, 1, MF_BYPOSITION|MF_SEPARATOR, NULL, NULL);
		}
	}
#endif

	DWORD nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP);
	CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_ATTACHGUIAPP, nSize);

	gnAttachGuiClientFlags = agaf_Success;
	// С приложенями .Net - приходится работать как с WS_CHILD,
	// иначе в них "не нажимаются" тулбары и меню
	if (IsDotNetWindow(hWindow))
	{
		gnAttachGuiClientFlags |= (agaf_DotNet|agaf_WS_CHILD);
	}
	// Если в окне нет меню - работаем с ним как с WS_CHILD
	// так не возникает проблем с активацией и т.д.
	else if (user->getMenu(hWindow) == NULL)
	{
		if (IsQtWindow(asClassA, asClassW))
			gnAttachGuiClientFlags |= (agaf_NoMenu|agaf_QtWindow|agaf_WS_CHILD);
		else
			gnAttachGuiClientFlags |= (agaf_NoMenu|agaf_WS_CHILD);
	}
	pIn->AttachGuiApp.nFlags = gnAttachGuiClientFlags;
	pIn->AttachGuiApp.nPID = GetCurrentProcessId();
	pIn->AttachGuiApp.hAppWindow = hWindow;
	pIn->AttachGuiApp.Styles.nStyle = nCurStyle; // стили могли измениться после создания окна,
	pIn->AttachGuiApp.Styles.nStyleEx = nCurStyleEx; // поэтому получим актуальные
	user->getWindowRect(hWindow, &pIn->AttachGuiApp.rcWindow);
	GetModuleFileName(NULL, pIn->AttachGuiApp.sAppFilePathName, countof(pIn->AttachGuiApp.sAppFilePathName));
	pIn->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(0);

	wchar_t szGuiPipeName[128];
	msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", (DWORD)ghConEmuWnd);


	// AttachThreadInput
	DWORD nConEmuTID = user->getWindowThreadProcessId(ghConEmuWnd, NULL);
	DWORD nTID = GetCurrentThreadId();
	_ASSERTEX(nTID==gnHookMainThreadId || nTID==gnAttachGuiClientThreadId);
	BOOL bAttachRc = user->attachThreadInput(nTID, nConEmuTID, TRUE);
	DWORD nAttachErr = GetLastError();
	UNREFERENCED_PARAMETER(bAttachRc); UNREFERENCED_PARAMETER(nAttachErr);

	HWND hPreFocus = user->getFocus();


	CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 0/*Default timeout*/, NULL);

	ExecuteFreeResult(pIn);

	// abStyleHidden == TRUE, если окно при создании указало флаг WS_VISIBLE (т.е. не собиралось звать ShowWindow)

	if (pOut)
	{
		if (pOut->hdr.cbSize > sizeof(CESERVER_REQ_HDR))
		{
			_ASSERTE((pOut->AttachGuiApp.nFlags & agaf_Success) == agaf_Success);

            BOOL lbRc = FALSE;

			_ASSERTE(pOut->AttachGuiApp.hConEmuBack && pOut->AttachGuiApp.hConEmuDc && (HWND)pOut->AttachGuiApp.hConEmuDc!=(HWND)pOut->AttachGuiApp.hConEmuBack);
			_ASSERTE((ghConEmuWndBack==NULL) || (pOut->AttachGuiApp.hConEmuBack==ghConEmuWndBack));
			_ASSERTE(ghConEmuWnd && (ghConEmuWnd==pOut->AttachGuiApp.hConEmuWnd));
			ghConEmuWnd = pOut->AttachGuiApp.hConEmuWnd;
			SetConEmuHkWindows(pOut->AttachGuiApp.hConEmuDc, pOut->AttachGuiApp.hConEmuBack);

			//gbGuiClientHideCaption = pOut->AttachGuiApp.bHideCaption;
			gGuiClientStyles = pOut->AttachGuiApp.Styles;
            
			#ifdef _DEBUG
            HWND hFocus = user->getFocus();
            DWORD nFocusPID = 0;
            
            if (hFocus)
            {
                user->getWindowThreadProcessId(hFocus, &nFocusPID);
				DWORD nConEmuPID = 0; user->getWindowThreadProcessId(ghConEmuWnd, &nConEmuPID);
                if (nFocusPID != GetCurrentProcessId() && nFocusPID != nConEmuPID)
                {                                                    
                    _ASSERTE(hFocus==NULL || (nFocusPID==GetCurrentProcessId() || nFocusPID == nConEmuPID));
                    hFocus = NULL;
                }
            }
			#endif
            
			if (pOut->AttachGuiApp.hkl)
			{
				LONG_PTR hkl = (LONG_PTR)(LONG)pOut->AttachGuiApp.hkl;
				lbRc = ActivateKeyboardLayout((HKL)hkl, KLF_SETFORPROCESS) != NULL;
				UNREFERENCED_PARAMETER(lbRc);
			}

            //grcAttachGuiClientPos = pOut->AttachGuiApp.rcWindow;
            ReplaceGuiAppWindow(abStyleHidden);

			//if (hPreFocus)
			//{
			//	user->setFocus(hPreFocus);
			//}
			UINT nMsgID = user->registerWindowMessageW(CONEMUMSG_RESTORECHILDFOCUS);
			user->postMessageW(ghConEmuWndBack, nMsgID, 0,0);

			//// !!! OnSetForegroundWindow не подходит - он дергает Cmd.
			////user->setForegroundWindow(ghConEmuWnd);
			//#if 0
			//wchar_t szClass[64] = {}; user->getClassNameW(hFocus, szClass, countof(szClass));
			//MessageBox(NULL, szClass, L"WasFocused", MB_SYSTEMMODAL);
			//#endif
			////if (!(nCurStyle & WS_CHILDWINDOW))
			//{
			//	// Если ставить WS_CHILD - пропадет меню!
			//	//nCurStyle = (nCurStyle | WS_CHILDWINDOW|WS_TABSTOP); // & ~(WS_THICKFRAME/*|WS_CAPTION|WS_MINIMIZEBOX|WS_MAXIMIZEBOX*/);
			//	//user->setWindowLongPtrW(hWindow, GWL_STYLE, nCurStyle);
			//	if (gnAttachGuiClientFlags & agaf_DotNet)
			//	{
			//	}
			//	else
			//	{
			//		SetParent(hWindow, ghConEmuWndBack);
			//	}
			//}
			//
			//RECT rcGui = grcAttachGuiClientPos = pOut->AttachGuiApp.rcWindow;
			//if (user->setWindowPos(hWindow, HWND_TOP, rcGui.left,rcGui.top, rcGui.right-rcGui.left, rcGui.bottom-rcGui.top,
			//	SWP_DRAWFRAME | /*SWP_FRAMECHANGED |*/ (abStyleHidden ? SWP_SHOWWINDOW : 0)))
			//{
			//	if (abStyleHidden)
			//		abStyleHidden = FALSE;
			//}
			//
			//// !!! OnSetForegroundWindow не подходит - он дергает Cmd.
			//user->setForegroundWindow(ghConEmuWnd);
			////if (hFocus)
			////SetFocus(hFocus ? hFocus : hWindow); // hFocus==NULL, эффекта нет
			////OnSetForegroundWindow(hWindow);
			////user->postMessage(ghConEmuWnd, WM_NCACTIVATE, TRUE, 0);
			////user->postMessage(ghConEmuWnd, WM_NCPAINT, 0, 0);
			//user->postMessage(hWindow, WM_NCPAINT, 0, 0);
		}
		ExecuteFreeResult(pOut);
	}

	if (abStyleHidden)
	{
		user->showWindow(hWindow, SW_SHOW);
	}
}
Exemplo n.º 24
0
BOOL WINAPI PlugServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam)
{
    BOOL lbRc = FALSE;
    BOOL fSuccess = FALSE;
    MSectionThread SCT(csTabs);

    if (pIn->hdr.cbSize < sizeof(CESERVER_REQ_HDR) || /*in.nSize < cbRead ||*/ pIn->hdr.nVersion != CESERVER_REQ_VER)
    {
        gpPlugServer->BreakConnection(pInst);
        return FALSE;
    }

    UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR);

    // Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат
    switch (pIn->hdr.nCmd)
    {
    case CMD_LANGCHANGE:
    {
        _ASSERTE(nDataSize>=4); //-V112
        // LayoutName: "00000409", "00010409", ...
        // А HKL от него отличается, так что передаем DWORD
        // HKL в x64 выглядит как: "0x0000000000020409", "0xFFFFFFFFF0010409"
        DWORD hkl = pIn->dwData[0];
        DWORD dwLastError = 0;
        HKL hkl1 = NULL, hkl2 = NULL;

        if (hkl)
        {
            WCHAR szLoc[10];
            _wsprintf(szLoc, SKIPLEN(countof(szLoc)) L"%08x", hkl);
            hkl1 = LoadKeyboardLayout(szLoc, KLF_ACTIVATE|KLF_REORDER|KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS);
            hkl2 = ActivateKeyboardLayout(hkl1, KLF_SETFORPROCESS|KLF_REORDER);

            if (!hkl2)
                dwLastError = GetLastError();
            else
                fSuccess = TRUE;
        }

        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2;
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = fSuccess;
            ppReply->dwData[1] = fSuccess ? ((DWORD)(LONG)(LONG_PTR)hkl2) : dwLastError;
        }

        break;
    } // CMD_LANGCHANGE

#if 0
    case CMD_DEFFONT:
    {
        // исключение - асинхронный, результат не требуется
        SetConsoleFontSizeTo(FarHwnd, 4, 6);
        MoveWindow(FarHwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 1); // чтобы убрать возможные полосы прокрутки...
        break;
    }
    CMD_DEFFONT
#endif

    case CMD_REQTABS:
    case CMD_SETWINDOW:
    {
        MSectionLock SC;
        SC.Lock(csTabs, FALSE, 1000);
        DWORD nSetWindowWait = (DWORD)-1;

        if (pIn->hdr.nCmd == CMD_SETWINDOW)
        {
            ResetEvent(ghSetWndSendTabsEvent);

            // Для FAR2 - сброс QSearch выполняется в том же макро, в котором актирируется окно
            if (gFarVersion.dwVerMajor == 1 && pIn->dwData[1])
            {
                // А вот для FAR1 - нужно шаманить
                Plugin()->ProcessCommand(CMD_CLOSEQSEARCH, TRUE/*bReqMainThread*/, pIn->dwData/*хоть и не нужно?*/);
            }

            // Пересылается 2 DWORD
            BOOL bCmdRc = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->dwData);

            DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW waiting...\n");

            WARNING("Почему для FAR1 не ждем? Есть возможность заблокироваться в 1.7 или что?");
            if ((gFarVersion.dwVerMajor >= 2) && bCmdRc)
            {
                DWORD nTimeout = 2000;
#ifdef _DEBUG
                if (IsDebuggerPresent()) nTimeout = 120000;
#endif

                nSetWindowWait = WaitForSingleObject(ghSetWndSendTabsEvent, nTimeout);
            }

            if (nSetWindowWait == WAIT_TIMEOUT)
            {
                gbForceSendTabs = TRUE;
                DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW timeout !!!\n");
            }
            else
            {
                DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW finished\n");
            }
        }

        if (gpTabs && (nSetWindowWait != WAIT_TIMEOUT))
        {
            //fSuccess = WriteFile(hPipe, gpTabs, gpTabs->hdr.cbSize, &cbWritten, NULL);
            pcbReplySize = gpTabs->hdr.cbSize;
            if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
            {
                memmove(ppReply->Data, gpTabs->Data, pcbReplySize - sizeof(ppReply->hdr));
                lbRc = TRUE;
            }
        }

        SC.Unlock();
        break;
    } // CMD_REQTABS, CMD_SETWINDOW

    case CMD_FARSETCHANGED:
    {
        // Установить переменные окружения
        // Плагин это получает в ответ на CECMD_RESOURCES, посланное в GUI при загрузке плагина
        _ASSERTE(nDataSize>=8);
        FAR_REQ_FARSETCHANGED *pFarSet = (FAR_REQ_FARSETCHANGED*)pIn->Data;

        cmd_FarSetChanged(pFarSet);

        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = TRUE;
        }

        //_ASSERTE(nDataSize<sizeof(gsMonitorEnvVar));
        //gbMonitorEnvVar = false;
        //// Плагин FarCall "нарушает" COMSPEC (копирует содержимое запускаемого процесса)
        //bool lbOk = false;

        //if (nDataSize<sizeof(gsMonitorEnvVar))
        //{
        //	memcpy(gsMonitorEnvVar, pszName, nDataSize);
        //	lbOk = true;
        //}

        //UpdateEnvVar(pszName);
        ////while (*pszName && *pszValue) {
        ////	const wchar_t* pszChanged = pszValue;
        ////	// Для ConEmuOutput == AUTO выбирается по версии ФАРа
        ////	if (!lstrcmpi(pszName, L"ConEmuOutput") && !lstrcmp(pszChanged, L"AUTO")) {
        ////		if (gFarVersion.dwVerMajor==1)
        ////			pszChanged = L"ANSI";
        ////		else
        ////			pszChanged = L"UNICODE";
        ////	}
        ////	// Если в pszValue пустая строка - удаление переменной
        ////	SetEnvironmentVariableW(pszName, (*pszChanged != 0) ? pszChanged : NULL);
        ////	//
        ////	pszName = pszValue + lstrlenW(pszValue) + 1;
        ////	if (*pszName == 0) break;
        ////	pszValue = pszName + lstrlenW(pszName) + 1;
        ////}
        //gbMonitorEnvVar = lbOk;

        break;
    } // CMD_FARSETCHANGED

    case CMD_DRAGFROM:
    {
#ifdef _DEBUG
        BOOL  *pbClickNeed = (BOOL*)pIn->Data;
        COORD *crMouse = (COORD *)(pbClickNeed+1);
#endif

        Plugin()->ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, pIn->Data);
        CESERVER_REQ* pCmdRet = NULL;
        Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet);

        if (pCmdRet)
        {
            //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL);
            pcbReplySize = pCmdRet->hdr.cbSize;
            if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
            {
                lbRc = TRUE;
                memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr));
            }
            Free(pCmdRet);
        }

        break;
    } // CMD_DRAGFROM

    case CMD_EMENU:
    {
        COORD *crMouse = (COORD *)pIn->Data;
#ifdef _DEBUG
        const wchar_t *pszUserMacro = (wchar_t*)(crMouse+1);
#endif
        DWORD ClickArg[2] = {(DWORD)TRUE, (DWORD)MAKELONG(crMouse->X, crMouse->Y)};

        // Выделить файл под курсором
        DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) begin\n");
        BOOL lb1 = Plugin()->ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, ClickArg/*pIn->Data*/);
        DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) done\n");

        // А теперь, собственно вызовем меню
        DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) begin\n");
        BOOL lb2 = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data);
        DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) done\n");

        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2;
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = lb1;
            ppReply->dwData[1] = lb1;
        }

        break;
    } // CMD_EMENU

    case CMD_ACTIVEWNDTYPE:
    {
        int nWindowType = -1;
        //CESERVER_REQ Out;
        //ExecutePrepareCmd(&Out, CMD_ACTIVEWNDTYPE, sizeof(CESERVER_REQ_HDR)+sizeof(DWORD));

        if (gFarVersion.dwVerMajor>=2)
            nWindowType = Plugin()->GetActiveWindowType();

        //fSuccess = WriteFile(hPipe, &Out, Out.hdr.cbSize, &cbWritten, NULL);

        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = nDataSize;
        }

        break;
    } // CMD_ACTIVEWNDTYPE

    case CECMD_ATTACH2GUI:
    {
        BOOL bAttached = Plugin()->Attach2Gui();
        pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD);
        if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
        {
            lbRc = TRUE;
            ppReply->dwData[0] = bAttached;
        }
        break;
    } // CECMD_ATTACH2GUI

    default:
    {
        CESERVER_REQ* pCmdRet = NULL;
        BOOL lbCmd = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet);

        if (pCmdRet)
        {
            //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL);
            pcbReplySize = pCmdRet->hdr.cbSize;
            if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
            {
                lbRc = TRUE;
                memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr));
            }
            Free(pCmdRet);
        }

    } // default
    } // switch (pIn->hdr.nCmd)

    return lbRc;
}
Exemplo n.º 25
0
void OnShowGuiClientWindow(HWND hWnd, int &nCmdShow, BOOL &rbGuiAttach, BOOL &rbInactive)
{
#ifdef _DEBUG
	STARTUPINFO si = {sizeof(si)};
	GetStartupInfo(&si);
#endif

	rbInactive = FALSE;

	//if (ghConEmuWnd)
	//{
	//	DWORD nConEmuExStyle = user->getWindowLongPtrW(ghConEmuWnd, GWL_EXSTYLE);
	//	if (nConEmuExStyle & WS_EX_TOPMOST)
	//	{
	//		DWORD nExtStyle = user->getWindowLongPtrW(hWnd, GWL_EXSTYLE);
	//		if (!(nExtStyle & WS_EX_TOPMOST))
	//		{
	//			nExtStyle |= WS_EX_TOPMOST;
	//			user->setWindowLongPtrW(hWnd, GWL_EXSTYLE, nExtStyle);
	//		}
	//	}
	//}

	if ((!ghAttachGuiClient) && gbAttachGuiClient && (nCmdShow >= SW_SHOWNORMAL))
	{
		// VLC создает несколько "подходящих" окон, но ShowWindow зовет
		// только для одного из них. Поэтому фактический аттач делаем
		// только в том случае, если окно "видимое"
		HMENU hMenu = user->getMenu(hWnd);
		wchar_t szClassName[255]; user->getClassNameW(hWnd, szClassName, countof(szClassName));
		DWORD nCurStyle = (DWORD)user->getWindowLongPtrW(hWnd, GWL_STYLE);
		DWORD nCurStyleEx = (DWORD)user->getWindowLongPtrW(hWnd, GWL_EXSTYLE);
		BOOL bAttachGui = TRUE;

		if (ghAttachGuiClient == NULL)
		{
			HWND hWndParent = ::GetParent(hWnd);
			DWORD dwStyle = nCurStyle, dwExStyle = nCurStyleEx;
			BOOL bStyleHidden;

			CheckCanCreateWindow(NULL, szClassName, dwStyle, dwExStyle, hWndParent, bAttachGui, bStyleHidden);
		}

		// Пробуем
		if (bAttachGui)
		{
			OnGuiWindowAttached(hWnd, hMenu, NULL, szClassName, nCurStyle, nCurStyleEx, FALSE, nCmdShow);
		}
	}

	if (gbForceShowGuiClient && (ghAttachGuiClient == hWnd))
	{
		//if (nCmdShow == SW_HIDE)
		//	nCmdShow = SW_SHOWNORMAL;

		HWND hCurParent = user->getParent(hWnd);
		if (hCurParent != ghConEmuWndBack)
		{
			DWORD nCurStyle = (DWORD)user->getWindowLongPtrW(hWnd, GWL_STYLE);
			DWORD nCurStyleEx = (DWORD)user->getWindowLongPtrW(hWnd, GWL_EXSTYLE);

			DWORD nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP);
			CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_ATTACHGUIAPP, nSize);

			pIn->AttachGuiApp.nFlags = gnAttachGuiClientFlags;
			pIn->AttachGuiApp.nPID = GetCurrentProcessId();
			pIn->AttachGuiApp.hAppWindow = hWnd;
			pIn->AttachGuiApp.Styles.nStyle = nCurStyle; // стили могли измениться после создания окна,
			pIn->AttachGuiApp.Styles.nStyleEx = nCurStyleEx; // поэтому получим актуальные
			user->getWindowRect(hWnd, &pIn->AttachGuiApp.rcWindow);
			GetModuleFileName(NULL, pIn->AttachGuiApp.sAppFilePathName, countof(pIn->AttachGuiApp.sAppFilePathName));

			wchar_t szGuiPipeName[128];
			msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", (DWORD)ghConEmuWnd);

			CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 0/*Default timeout*/, NULL);
			ExecuteFreeResult(pIn);
			if (pOut)
			{
				if (pOut->hdr.cbSize > sizeof(CESERVER_REQ_HDR) && (pOut->AttachGuiApp.nFlags & agaf_Success))
				{
					//grcAttachGuiClientPos = pOut->AttachGuiApp.rcWindow;

					_ASSERTE((ghConEmuWndBack==NULL) || (pOut->AttachGuiApp.hConEmuBack==ghConEmuWndBack));
					_ASSERTE(ghConEmuWnd && (ghConEmuWnd==pOut->AttachGuiApp.hConEmuWnd));
					ghConEmuWnd = pOut->AttachGuiApp.hConEmuWnd;
					SetConEmuHkWindows(pOut->AttachGuiApp.hConEmuDc, pOut->AttachGuiApp.hConEmuBack);
					//gbGuiClientHideCaption = pOut->AttachGuiApp.bHideCaption;
					gGuiClientStyles = pOut->AttachGuiApp.Styles;
					//Если приложение создается в НЕ активной вкладке - фокус нужно вернуть в ConEmu
					rbInactive = (pOut->AttachGuiApp.nFlags & agaf_Inactive) == agaf_Inactive;
				}
				ExecuteFreeResult(pOut);
			}

			//OnSetParent(hWnd, ghConEmuWndBack);
		}

        ReplaceGuiAppWindow(FALSE);
		
		//RECT rcGui = grcAttachGuiClientPos;
		//user->setWindowPos(hWnd, HWND_TOP, rcGui.left,rcGui.top, rcGui.right-rcGui.left, rcGui.bottom-rcGui.top,
		//	SWP_FRAMECHANGED);
	
		nCmdShow = SW_SHOWNORMAL;
		gbForceShowGuiClient = FALSE; // Один раз?
		rbGuiAttach = TRUE;
	}
}
Exemplo n.º 26
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;
}
Exemplo n.º 27
0
// Helper function: Notification ‘Debug’ setting page in ConEmu
void OnPeekReadConsoleInput(char acPeekRead/*'P'/'R'*/, char acUnicode/*'A'/'W'*/, HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD& nRead)
{
#ifdef TRAP_ON_MOUSE_0x0
	if (lpBuffer && nRead)
	{
		for (UINT i = 0; i < nRead; i++)
		{
			if (lpBuffer[i].EventType == MOUSE_EVENT)
			{
				if (lpBuffer[i].Event.MouseEvent.dwMousePosition.X == 0 && lpBuffer[i].Event.MouseEvent.dwMousePosition.Y == 0)
				{
					_ASSERTE(!(lpBuffer[i].Event.MouseEvent.dwMousePosition.X == 0 && lpBuffer[i].Event.MouseEvent.dwMousePosition.Y == 0));
				}
				//if (lpBuffer[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED && lpBuffer[i].Event.MouseEvent.dwMousePosition.X != 5)
				//{
				//	_ASSERTE(!(lpBuffer[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED && lpBuffer[i].Event.MouseEvent.dwMousePosition.X != 5));
				//}
			}
		}
	}
#endif

	DWORD nCurrentTID = GetCurrentThreadId();

	gReadConsoleInfo.LastReadConsoleInputTID = nCurrentTID;
	gReadConsoleInfo.hConsoleInput2 = hConsoleInput;

	if (nRead)
	{
		if (!gbWasSucceededInRead)
			gbWasSucceededInRead = TRUE;

		// Сброс кешированных значений
		GetConsoleScreenBufferInfoCached(NULL, NULL);
	}

	if (!nRead || !lpBuffer)
		return;

	if (gFarMode.bFarHookMode && gFarMode.bMonitorConsoleInput)
	{
		CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_PEEKREADINFO, sizeof(CESERVER_REQ_HDR) //-V119
			+sizeof(CESERVER_REQ_PEEKREADINFO)+(nRead-1)*sizeof(INPUT_RECORD));
		if (pIn)
		{
			pIn->PeekReadInfo.nCount = (WORD)nRead;
			pIn->PeekReadInfo.cPeekRead = acPeekRead;
			pIn->PeekReadInfo.cUnicode = acUnicode;
			pIn->PeekReadInfo.h = hConsoleInput;
			pIn->PeekReadInfo.nTID = nCurrentTID;
			pIn->PeekReadInfo.nPID = GetCurrentProcessId();
			pIn->PeekReadInfo.bMainThread = (pIn->PeekReadInfo.nTID == gnHookMainThreadId);
			memmove(pIn->PeekReadInfo.Buffer, lpBuffer, nRead*sizeof(INPUT_RECORD));

			CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd);
			if (pOut) ExecuteFreeResult(pOut);
			ExecuteFreeResult(pIn);
		}
	}

	// Temp bugfix for unexpected WINDOW_BUFFER_SIZE_EVENT
	if (gFarMode.bFarHookMode && (acPeekRead == 'R') && IsWin10())
	{
		static WINDOW_BUFFER_SIZE_RECORD last_size = {};
		INPUT_RECORD *src = lpBuffer, *dst = lpBuffer, *buf_end = lpBuffer + nRead;
		while (src < buf_end)
		{
			if (src != dst)
			{
				*dst = *src;
			}

			if (src->EventType != WINDOW_BUFFER_SIZE_EVENT)
			{
				++src; ++dst;
				continue;
			}

			// OK, reported size was changed since last call
			if (last_size.dwSize != src->Event.WindowBufferSizeEvent.dwSize)
			{
				last_size = src->Event.WindowBufferSizeEvent;
				++src; ++dst;
				continue;
			}

			// Size was not changed
			_ASSERTE(nRead > 0);
			--nRead;
			++src;
			dst->EventType = 0;
		}
	}
}