예제 #1
0
BOOL WINAPI OnSetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
{
	//typedef BOOL (WINAPI* OnSetConsoleActiveScreenBuffer_t)(HANDLE hConsoleOutput);
	ORIGINALFAST(SetConsoleActiveScreenBuffer);

	if (!ghStdOutHandle)
		ghStdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);

	#ifdef _DEBUG
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	HANDLE hIn  = GetStdHandle(STD_INPUT_HANDLE);
	HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
	#endif

	BOOL lbRc = FALSE;
	if (F(SetConsoleActiveScreenBuffer))
		lbRc = F(SetConsoleActiveScreenBuffer)(hConsoleOutput);

	if (lbRc && (ghCurrentOutBuffer || (hConsoleOutput != ghStdOutHandle)))
	{
		#ifdef SHOWCREATEBUFFERINFO
		CONSOLE_SCREEN_BUFFER_INFO lsbi = {};
		BOOL lbTest = GetConsoleScreenBufferInfo(hConsoleOutput, &lsbi);
		DWORD nErrCode = GetLastError();
		_ASSERTE(lbTest && lsbi.dwSize.Y && "GetConsoleScreenBufferInfo(hConsoleOutput) failed");
		#endif

		ghCurrentOutBuffer = hConsoleOutput;
		RequestLocalServerParm Parm = {(DWORD)sizeof(Parm), slsf_SetOutHandle, &ghCurrentOutBuffer};
		RequestLocalServer(&Parm);
	}

	return lbRc;
}
예제 #2
0
BOOL WINAPI OnSetConsoleCursorPosition(HANDLE hConsoleOutput, COORD dwCursorPosition)
{
	//typedef BOOL (WINAPI* OnSetConsoleCursorPosition_t)(HANDLE,COORD);
	ORIGINALFAST(SetConsoleCursorPosition);

	BOOL lbRc;

	if (gbIsVimAnsi)
	{
		#ifdef DUMP_VIM_SETCURSORPOS
		wchar_t szDbg[80]; msprintf(szDbg, countof(szDbg), L"ViM trying to set cursor pos: {%i,%i}\n", (UINT)dwCursorPosition.X, (UINT)dwCursorPosition.Y);
		OutputDebugString(szDbg);
		#endif
		lbRc = FALSE;
	}
	else
	{
		lbRc = F(SetConsoleCursorPosition)(hConsoleOutput, dwCursorPosition);
	}

	if (ghConsoleCursorChanged)
		SetEvent(ghConsoleCursorChanged);

	return lbRc;
}
예제 #3
0
COORD WINAPI OnGetLargestConsoleWindowSize(HANDLE hConsoleOutput)
{
	//typedef COORD (WINAPI* OnGetLargestConsoleWindowSize_t)(HANDLE hConsoleOutput);
	ORIGINALFAST(GetLargestConsoleWindowSize);
	COORD cr = {80,25}, crLocked = {0,0};

	if (ghConEmuWndDC && IsVisibleRectLocked(crLocked))
	{
		cr = crLocked;
	}
	else
	{
		if (F(GetLargestConsoleWindowSize))
		{
			cr = F(GetLargestConsoleWindowSize)(hConsoleOutput);
		}

		// Wine BUG
		//if (!cr.X || !cr.Y)
		if ((cr.X == 80 && cr.Y == 24) && IsWine())
		{
			cr.X = 255;
			cr.Y = 255;
		}
	}

	return cr;
}
예제 #4
0
HANDLE WINAPI OnCreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode, const SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwFlags, LPVOID lpScreenBufferData)
{
	//typedef HANDLE(WINAPI* OnCreateConsoleScreenBuffer_t)(DWORD dwDesiredAccess, DWORD dwShareMode, const SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwFlags, LPVOID lpScreenBufferData);
	ORIGINALFAST(CreateConsoleScreenBuffer);

	#ifdef SHOWCREATEBUFFERINFO
	wchar_t szDebugInfo[255];
	msprintf(szDebugInfo, countof(szDebugInfo), L"CreateConsoleScreenBuffer(0x%X,0x%X,0x%X,0x%X,0x%X)",
		dwDesiredAccess, dwShareMode, (DWORD)(DWORD_PTR)lpSecurityAttributes, dwFlags, (DWORD)(DWORD_PTR)lpScreenBufferData);

	#endif

	if ((dwShareMode & (FILE_SHARE_READ|FILE_SHARE_WRITE)) != (FILE_SHARE_READ|FILE_SHARE_WRITE))
		dwShareMode |= (FILE_SHARE_READ|FILE_SHARE_WRITE);

	if ((dwDesiredAccess & (GENERIC_READ|GENERIC_WRITE)) != (GENERIC_READ|GENERIC_WRITE))
		dwDesiredAccess |= (GENERIC_READ|GENERIC_WRITE);

	if (!ghStdOutHandle)
		ghStdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);

	HANDLE h = INVALID_HANDLE_VALUE;
	if (F(CreateConsoleScreenBuffer))
		h = F(CreateConsoleScreenBuffer)(dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlags, lpScreenBufferData);

#ifdef SHOWCREATEBUFFERINFO
	msprintf(szDebugInfo+lstrlen(szDebugInfo), 32, L"=0x%X", (DWORD)(DWORD_PTR)h);
	GuiMessageBox(ghConEmuWnd, szDebugInfo, L"ConEmuHk", MB_SETFOREGROUND|MB_SYSTEMMODAL);
#endif

	return h;
}
예제 #5
0
HWND WINAPI OnGetConsoleWindow(void)
{
	//typedef HWND (WINAPI* OnGetConsoleWindow_t)(void);
	ORIGINALFAST(GetConsoleWindow);

	_ASSERTE(F(GetConsoleWindow) != GetRealConsoleWindow);
	// && F(GetConsoleWindow) != GetConsoleWindow - for minhook generation

	if (ghConEmuWndDC && IsWindow(ghConEmuWndDC) /*ghConsoleHwnd*/)
	{
		if (ghAttachGuiClient)
		{
			// В GUI режиме (notepad, putty) отдавать реальный результат GetRealConsoleWindow()
			// в этом режиме не нужно отдавать ни ghConEmuWndDC, ни серверную консоль
			HWND hReal = GetRealConsoleWindow();
			return hReal;
		}
		else
		{
			//return ghConsoleHwnd;
			return ghConEmuWndDC;
		}
	}

	HWND h;
	h = F(GetConsoleWindow)();
	return h;
}
예제 #6
0
BOOL WINAPI OnFreeConsole(void)
{
	//typedef BOOL (WINAPI* OnFreeConsole_t)(void);
	ORIGINALFAST(FreeConsole);
	BOOL lbRc = FALSE;

	if (ph && ph->PreCallBack)
	{
		SETARGS(&lbRc);

		if (!ph->PreCallBack(&args))
			return lbRc;
	}

	//ReleaseConsoleInputSemaphore();

	lbRc = F(FreeConsole)();

	if (ph && ph->PostCallBack)
	{
		SETARGS(&lbRc);
		ph->PostCallBack(&args);
	}

	return lbRc;
}
예제 #7
0
DWORD WINAPI OnGetConsoleAliasesW(LPWSTR AliasBuffer, DWORD AliasBufferLength, LPWSTR ExeName)
{
	//typedef DWORD (WINAPI* OnGetConsoleAliasesW_t)(LPWSTR AliasBuffer, DWORD AliasBufferLength, LPWSTR ExeName);
	ORIGINALFAST(GetConsoleAliasesW);
	DWORD nError = 0;
	DWORD nRc = F(GetConsoleAliasesW)(AliasBuffer,AliasBufferLength,ExeName);

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

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

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

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

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

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

					ExecuteFreeResult(pOut);
				}
			}
		}

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

	return nRc;
}
예제 #8
0
BOOL WINAPI OnSetConsoleCursorInfo(HANDLE hConsoleOutput, const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
{
	//typedef BOOL (WINAPI* OnSetConsoleCursorInfo_t)(HANDLE,const CONSOLE_CURSOR_INFO *);
	ORIGINALFAST(SetConsoleCursorInfo);

	BOOL lbRc = F(SetConsoleCursorInfo)(hConsoleOutput, lpConsoleCursorInfo);

	if (ghConsoleCursorChanged)
		SetEvent(ghConsoleCursorChanged);

	return lbRc;
}
예제 #9
0
BOOL WINAPI OnFreeLibrary(HMODULE hModule)
{
	//typedef BOOL (WINAPI* OnFreeLibrary_t)(HMODULE hModule);
	ORIGINALFAST(FreeLibrary);
	return OnFreeLibraryWork((FARPROC)F(FreeLibrary), ph, FALSE, hModule);
}
예제 #10
0
BOOL WINAPI OnSetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize)
{
	//typedef BOOL (WINAPI* OnSetConsoleScreenBufferSize_t)(HANDLE hConsoleOutput, COORD dwSize);
	ORIGINALFAST(SetConsoleScreenBufferSize);
	BOOL lbRc = FALSE, lbRetry = FALSE;
	COORD crLocked;
	DWORD dwErr = -1;

	CONSOLE_SCREEN_BUFFER_INFO sbi = {};
	BOOL lbSbi = GetConsoleScreenBufferInfo(hConsoleOutput, &sbi);
	UNREFERENCED_PARAMETER(lbSbi);

	#ifdef _DEBUG
	wchar_t szDbgSize[512];
	msprintf(szDbgSize, countof(szDbgSize), L"SetConsoleScreenBufferSize(%08X, {%ix%i}), Current={%ix%i}, Wnd={%ix%i}\n",
		LODWORD(hConsoleOutput), dwSize.X, dwSize.Y, sbi.dwSize.X, sbi.dwSize.Y,
		sbi.srWindow.Right-sbi.srWindow.Left+1, sbi.srWindow.Bottom-sbi.srWindow.Top+1);
	DebugStringConSize(szDbgSize);
	#endif

	BOOL lbLocked = IsVisibleRectLocked(crLocked);

	if (lbLocked && ((crLocked.X > dwSize.X) || (crLocked.Y > dwSize.Y)))
	{
		// Размер _видимой_ области. Консольным приложениям запрещено менять его "изнутри".
		// Размер может менять только пользователь ресайзом окна ConEmu
		if (crLocked.X > dwSize.X)
			dwSize.X = crLocked.X;
		if (crLocked.Y > dwSize.Y)
			dwSize.Y = crLocked.Y;

		#ifdef _DEBUG
		msprintf(szDbgSize, countof(szDbgSize), L"---> IsVisibleRectLocked, dwSize was patched {%ix%i}\n",
			dwSize.X, dwSize.Y);
		DebugStringConSize(szDbgSize);
		#endif
	}

	// Do not do useless calls
	if ((dwSize.X == sbi.dwSize.X) && (dwSize.Y == sbi.dwSize.Y))
	{
		lbRc = TRUE;
		goto wrap;
	}

	if (F(SetConsoleScreenBufferSize))
	{
		CESERVER_REQ *pIn = NULL, *pOut = NULL;
		LockServerReadingThread(true, dwSize, pIn, pOut);

		lbRc = F(SetConsoleScreenBufferSize)(hConsoleOutput, dwSize);
		dwErr = GetLastError();

		// The specified dimensions also cannot be less than the minimum size allowed
		// by the system. This minimum depends on the current font size for the console
		// (selected by the user) and the SM_CXMIN and SM_CYMIN values returned by the
		// GetSystemMetrics function.
		if (!lbRc && (dwErr == ERROR_INVALID_PARAMETER))
		{
			// Попытаться увеличить/уменьшить шрифт в консоли
			lbRetry = apiFixFontSizeForBufferSize(hConsoleOutput, dwSize);

			if (lbRetry)
			{
				lbRc = F(SetConsoleScreenBufferSize)(hConsoleOutput, dwSize);
				if (lbRc)
					dwErr = 0;
			}

			// Иногда при закрытии Far возникает ERROR_INVALID_PARAMETER
			// при этом, szDbgSize:
			// SetConsoleScreenBufferSize(0000000C, {80x1000}), Current={94x33}, Wnd={94x33}
			// т.е. коррекция не выполнялась
			_ASSERTE(lbRc && (dwErr != ERROR_INVALID_PARAMETER));
			if (!lbRc)
				SetLastError(dwErr); // вернуть "ошибку"
		}

		LockServerReadingThread(false, dwSize, pIn, pOut);
	}

wrap:
	return lbRc;
}
예제 #11
0
BOOL WINAPI OnSetConsoleWindowInfo(HANDLE hConsoleOutput, BOOL bAbsolute, const SMALL_RECT *lpConsoleWindow)
{
	//typedef BOOL (WINAPI* OnSetConsoleWindowInfo_t)(HANDLE hConsoleOutput, BOOL bAbsolute, const SMALL_RECT *lpConsoleWindow);
	ORIGINALFAST(SetConsoleWindowInfo);
	BOOL lbRc = FALSE;
	SMALL_RECT tmp;
	COORD crLocked;

	#ifdef _DEBUG
	CONSOLE_SCREEN_BUFFER_INFO sbi = {};
	BOOL lbSbi = GetConsoleScreenBufferInfo(hConsoleOutput, &sbi);
	UNREFERENCED_PARAMETER(lbSbi);

	wchar_t szDbgSize[512];
	msprintf(szDbgSize, countof(szDbgSize), L"SetConsoleWindowInfo(%08X, %s, {%ix%i}-{%ix%i}), Current={%ix%i}, Wnd={%ix%i}-{%ix%i}\n",
		LODWORD(hConsoleOutput), bAbsolute ? L"ABS" : L"REL",
		lpConsoleWindow->Left, lpConsoleWindow->Top, lpConsoleWindow->Right, lpConsoleWindow->Bottom,
		sbi.dwSize.X, sbi.dwSize.Y,
		sbi.srWindow.Left, sbi.srWindow.Top, sbi.srWindow.Right, sbi.srWindow.Bottom);
	DebugStringConSize(szDbgSize);
	#endif

	BOOL lbLocked = IsVisibleRectLocked(crLocked);

	if (lpConsoleWindow && lbLocked)
	{
		tmp = *lpConsoleWindow;
		if (((tmp.Right - tmp.Left + 1) != crLocked.X) || ((tmp.Bottom - tmp.Top + 1) != crLocked.Y))
		{

			// Размер _видимой_ области. Консольным приложениям запрещено менять его "изнутри".
			// Размер может менять только пользователь ресайзом окна ConEmu
			if ((tmp.Right - tmp.Left + 1) != crLocked.X)
			{
				if (!bAbsolute)
				{
					WARNING("Need to be corrected!");
					tmp.Left = tmp.Right = 0;
				}
				else
				{
					tmp.Right = tmp.Left + crLocked.X - 1;
				}
			}

			if ((tmp.Bottom - tmp.Top + 1) != crLocked.Y)
			{
				if (!bAbsolute)
				{
					WARNING("Need to be corrected!");
					if (tmp.Top != tmp.Bottom)
					{
						tmp.Top = tmp.Bottom = 0;
					}
				}
				else
				{
					tmp.Bottom = tmp.Top + crLocked.Y - 1;
				}
			}

			lpConsoleWindow = &tmp;

			#ifdef _DEBUG
			msprintf(szDbgSize, countof(szDbgSize), L"---> IsVisibleRectLocked, lpConsoleWindow was patched {%ix%i}-{%ix%i}\n",
				tmp.Left, tmp.Top, tmp.Right, tmp.Bottom);
			DebugStringConSize(szDbgSize);
			#endif
		}
	}

	if (F(SetConsoleWindowInfo))
	{
		lbRc = F(SetConsoleWindowInfo)(hConsoleOutput, bAbsolute, lpConsoleWindow);
	}

	return lbRc;
}
예제 #12
0
BOOL WINAPI OnAllocConsole(void)
{
	//typedef BOOL (WINAPI* OnAllocConsole_t)(void);
	ORIGINALFAST(AllocConsole);
	BOOL lbRc = FALSE, lbAllocated = FALSE;
	COORD crLocked;
	HMODULE hKernel = NULL;
	DWORD nErrCode = 0;
	BOOL lbAttachRc = FALSE;
	HWND hOldConWnd = GetRealConsoleWindow();

	if (ph && ph->PreCallBack)
	{
		SETARGS(&lbRc);

		if (!ph->PreCallBack(&args))
			return lbRc;
	}

	if (gbPrepareDefaultTerminal && gbIsNetVsHost)
	{
		if (!ghConWnd)
			gnVsHostStartConsole = 2;
		else
			gnVsHostStartConsole = 0;
	}

	// Попытаться создать консольное окно "по тихому"
	if (gpDefTerm && !hOldConWnd && !gnServerPID)
	{
		HWND hCreatedCon = gpDefTerm->AllocHiddenConsole(false);
		if (hCreatedCon)
		{
			hOldConWnd = hCreatedCon;
			lbAllocated = TRUE;
		}
	}

	// GUI приложение во вкладке. Если окна консоли еще нет - попробовать прицепиться
	// к родительской консоли (консоли серверного процесса)
	if ((gbAttachGuiClient || ghAttachGuiClient) && !gbPrepareDefaultTerminal)
	{
		if (AttachServerConsole())
		{
			hOldConWnd = GetRealConsoleWindow();
			lbAllocated = TRUE; // Консоль уже есть, ничего не надо
		}
	}

	DefTermMsg(L"AllocConsole calling");

	if (!lbAllocated && F(AllocConsole))
	{
		lbRc = F(AllocConsole)();

		if (lbRc && !gbPrepareDefaultTerminal && IsVisibleRectLocked(crLocked))
		{
			// Размер _видимой_ области. Консольным приложениям запрещено менять его "изнутри".
			// Размер может менять только пользователь ресайзом окна ConEmu
			HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
			CONSOLE_SCREEN_BUFFER_INFO csbi = {};
			if (GetConsoleScreenBufferInfo(hStdOut, &csbi))
			{
				//specified width and height cannot be less than the width and height of the console screen buffer's window
				SMALL_RECT rNewRect = {0, 0, crLocked.X-1, crLocked.Y-1};
				OnSetConsoleWindowInfo(hStdOut, TRUE, &rNewRect);
				#ifdef _DEBUG
				COORD crNewSize = {crLocked.X, max(crLocked.Y, csbi.dwSize.Y)};
				#endif
				hkFunc.setConsoleScreenBufferSize(hStdOut, crLocked);
			}
		}
	}

	//InitializeConsoleInputSemaphore();

	if (ph && ph->PostCallBack)
	{
		SETARGS(&lbRc);
		ph->PostCallBack(&args);
	}

	HWND hNewConWnd = GetRealConsoleWindow();

	// Обновить ghConWnd и мэппинг
	OnConWndChanged(hNewConWnd);

	#ifdef _DEBUG
	//_ASSERTEX(lbRc && ghConWnd);
	wchar_t szAlloc[500], szFile[MAX_PATH];
	GetModuleFileName(NULL, szFile, countof(szFile));
	msprintf(szAlloc, countof(szAlloc), L"OnAllocConsole\nOld=x%08X, New=x%08X, ghConWnd=x%08X\ngbPrepareDefaultTerminal=%i, gbIsNetVsHost=%i\n%s",
		LODWORD(hOldConWnd), LODWORD(hNewConWnd), LODWORD(ghConWnd), gbPrepareDefaultTerminal, gbIsNetVsHost, szFile);
	// VisualStudio host file calls AllocConsole TWICE(!)
	// Second call is totally spare (console already created)
	//MessageBox(NULL, szAlloc, L"OnAllocConsole called", MB_SYSTEMMODAL);
	#endif

	if (hNewConWnd && (hNewConWnd != hOldConWnd) && gpDefTerm && gbIsNetVsHost)
	{
		DefTermMsg(L"Calling gpDefTerm->OnAllocConsoleFinished");
		gpDefTerm->OnAllocConsoleFinished();
		SetLastError(0);
	}
	else if (hNewConWnd)
	{
		DefTermMsg(L"Console was already allocated");
	}
	else
	{
		DefTermMsg(L"Something was wrong");
	}

	TODO("Можно бы по настройке установить параметры. Кодовую страницу, например");

	return lbRc;
}
예제 #13
0
BOOL WINAPI OnSetConsoleOutputCP(UINT wCodePageID)
{
	//typedef BOOL (WINAPI* OnSetConsoleOutputCP_t)(UINT wCodePageID);
	ORIGINALFAST(SetConsoleOutputCP);
	_ASSERTE(OnSetConsoleOutputCP!=SetConsoleOutputCP);
	BOOL lbRc = FALSE;
	SCOCP sco = {wCodePageID, (OnSetConsoleCP_t)F(SetConsoleOutputCP), CreateEvent(NULL,FALSE,FALSE,NULL)};
	DWORD nTID = 0, nWait = -1, nErr;
	/*
	wchar_t szErrText[255], szTitle[64];
	msprintf(szTitle, SKIPLEN(countof(szTitle)) L"PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId());
	*/
	#ifdef _DEBUG
	DWORD nPrevCP = GetConsoleOutputCP();
	#endif
	DWORD nCurCP = 0;
	HANDLE hThread = apiCreateThread(SetConsoleCPThread, &sco, &nTID, "OnSetConsoleOutputCP(%u)", wCodePageID);

	if (!hThread)
	{
		nErr = GetLastError();
		_ASSERTE(hThread!=NULL);
		/*
		msprintf(szErrText, SKIPLEN(countof(szErrText)) L"chcp(out) failed, ErrCode=0x%08X\nConEmuHooks.cpp:OnSetConsoleOutputCP", nErr);
		Message BoxW(NULL, szErrText, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL);
		lbRc = FALSE;
		*/
	}
	else
	{
		HANDLE hEvents[2] = {hThread, sco.hReady};
		nWait = WaitForMultipleObjects(2, hEvents, FALSE, SETCONCP_READYTIMEOUT);

		if (nWait != WAIT_OBJECT_0)
			nWait = WaitForSingleObject(hThread, SETCONCP_TIMEOUT);

		if (nWait == WAIT_OBJECT_0)
		{
			lbRc = sco.lbRc;
		}
		else
		{
			//BUGBUG: На некоторых системых (Win2k3, WinXP) SetConsoleCP (и иже с ними) просто зависают
			apiTerminateThread(hThread,100);
			nCurCP = GetConsoleOutputCP();
			if (nCurCP == wCodePageID)
			{
				lbRc = TRUE; // таки получилось
			}
			else
			{
				_ASSERTE(nCurCP == wCodePageID);
				/*
				msprintf(szErrText, SKIPLEN(countof(szErrText))
				          L"chcp(out) hung detected\n"
				          L"ConEmuHooks.cpp:OnSetConsoleOutputCP\n"
				          L"ReqOutCP=%u, PrevOutCP=%u, CurOutCP=%u\n"
				          //L"\nPress <OK> to stop waiting"
				          ,wCodePageID, nPrevCP, nCurCP);
				Message BoxW(NULL, szErrText, szTitle, MB_ICONSTOP|MB_SYSTEMMODAL);
				*/
			}
			//nWait = WaitForSingleObject(hThread, 0);
			//if (nWait == WAIT_TIMEOUT)
			//	apiTerminateThread(hThread,100);
			//if (GetConsoleOutputCP() == wCodePageID)
			//	lbRc = TRUE;
		}

		CloseHandle(hThread);
	}

	if (sco.hReady)
		CloseHandle(sco.hReady);

	return lbRc;
}