Example #1
0
bool MSection::MyEnterCriticalSection(DWORD anTimeout)
{
	DWORD nCurTID = GetCurrentThreadId(), nExclWait = -1;
	//EnterCriticalSection(&m_cs);
	// дождаться пока секцию отпустят
	// НАДА. Т.к. может быть задан nTimeout (для DC)
	DWORD dwTryLockSectionStart = GetTickCount(), dwCurrentTick;

	if (!m_cs.TryEnter())
	{
		Sleep(10);

		while (!m_cs.TryEnter())
		{
			if ((mn_TID != nCurTID) && mh_ExclusiveThread)
			{
				BOOL lbLocked = FALSE;

				if (mh_ExclusiveThread)
				{
					HANDLE h = mh_ExclusiveThread;
					nExclWait = WaitForSingleObject(h, 0);
					if (nExclWait != WAIT_TIMEOUT)
					{
						// Все, m_cs протух. Его нужно пересоздать

						Process_Lock();

						// Первым выполнить Process_Lock мог другой поток.
						// Нужно проверить хэндл на соответствие, если он другой
						// то на этом шаге уже не дергаться
						if (h == mh_ExclusiveThread)
						{
							_ASSERTEX(FALSE && "Exclusively locked thread was abnormally terminated?");

							SafeCloseHandle(mh_ExclusiveThread);

							lbLocked = m_cs.RecreateAndLock();

							_ASSERTEX(mn_LockedTID[0] = mn_TID);
							mn_LockedTID[0] = 0;
							if (mn_LockedCount[0] > 0)
							{
								mn_LockedCount[0] --; // на [0] mn_Locked не распространяется
							}

							mn_TID = nCurTID;
						}

						Process_Unlock();
					}
				}

				if (lbLocked)
				{
					break;
				}
			}

			Sleep(10);
			DEBUGSTR(L"TryEnterCriticalSection failed!!!\n");
			dwCurrentTick = GetTickCount();

			if (anTimeout != (DWORD)-1)
			{
				if (((dwCurrentTick - dwTryLockSectionStart) > anTimeout))
				{
					#ifndef CSECTION_NON_RAISE
					_ASSERTEX((dwCurrentTick - dwTryLockSectionStart) <= anTimeout);
					#endif
					return false;
				}
			}

			#ifdef _DEBUG
			else if ((dwCurrentTick - dwTryLockSectionStart) > 3000)
			{
				#ifndef CSECTION_NON_RAISE
				_ASSERTEX((dwCurrentTick - dwTryLockSectionStart) <= 3000);
				#endif
				dwTryLockSectionStart = GetTickCount();
			}
			#endif
		}
	}

	return true;
}
Example #2
0
BOOL MSection::Lock(BOOL abExclusive, DWORD anTimeout/*=-1*/)
{
	DWORD dwTID = GetCurrentThreadId();

	// Может эта нить уже полностью заблокирована?
	if (mb_Exclusive && dwTID == mn_TID)
	{
		//111126 возвращался FALSE
		_ASSERTEX(!mb_Exclusive || dwTID != mn_TID);
		return TRUE; // Уже, но Unlock делать не нужно!
	}

	if (!abExclusive)
	{
		if (!mb_Exclusive)
		{
			// Быстрая блокировка, не запрещающая чтение другим нитям.
			// Запрещено только изменение (пересоздание буфера например)
			AddRef(dwTID);
		}
		// Если другая нить уже захватила exclusive
		else //if (mb_Exclusive)
		{
			_ASSERTEX(mb_Exclusive);
			//int nLeft = ReleaseRef(dwTID); // Иначе можем попасть на взаимную блокировку
			//if (nLeft > 0)
			//{
			//	// Нужно избегать этого. Значит выше по стеку в этой нити
			//	// более одного раза был выполнен non exclusive lock
			//	_ASSERTEX(nLeft == 0);
			//}
			#ifdef _DEBUG
			int nInThreadLeft = 0;
			for (int i=1; i<countof(mn_LockedTID); i++)
			{
				if (mn_LockedTID[i] == dwTID)
				{
					_ASSERTEX(mn_LockedCount[i]>=0);
					nInThreadLeft = mn_LockedCount[i];
					break;
				}
			}
			if (nInThreadLeft > 0)
			{
				// Нужно избегать этого. Значит выше по стеку в этой нити
				// более одного раза был выполнен non exclusive lock
				_ASSERTEX(nInThreadLeft == 0);
			}
			#endif


			DEBUGSTR(L"!!! Failed non exclusive lock, trying to use CriticalSection\n");
			bool lbEntered = MyEnterCriticalSection(anTimeout); // дождаться пока секцию отпустят
			// mb_Exclusive может быть выставлен, если сейчас другая нить пытается выполнить exclusive lock
			_ASSERTEX(!mb_Exclusive); // После LeaveCriticalSection mb_Exclusive УЖЕ должен быть сброшен
			AddRef(dwTID); // накрутить счетчик

			// Но поскольку нам нужен только nonexclusive lock
			if (lbEntered)
				m_cs.Leave();
		}
	}
	else // abExclusive
	{
		// Требуется Exclusive Lock
		#ifdef _DEBUG
		if (mb_Exclusive)
		{
			// Этого надо стараться избегать
			DEBUGSTR(L"!!! Exclusive lock found in other thread\n");
		}
        #endif

		// Если есть ExclusiveLock (в другой нити) - дождется сама EnterCriticalSection
		#ifdef _DEBUG
		BOOL lbPrev = mb_Exclusive;
		DWORD nPrevTID = mn_TID;
		#endif

		// Сразу установим mb_Exclusive, чтобы в других нитях случайно не прошел nonexclusive lock
		// иначе может получиться, что nonexclusive lock мешает выполнить exclusive lock (ждут друг друга)
		mb_Exclusive = TRUE;
		TODO("Need to check, if MyEnterCriticalSection failed on timeout!\n");

		if (!MyEnterCriticalSection(anTimeout))
		{
			// Пока поставил _ASSERTE, чтобы посмотреть, возникают ли Timeout-ы при блокировке
			_ASSERTEX(FALSE);

			if (mn_TID == 0)  // поскольку заблокировать не удалось - сбросим флажок
				mb_Exclusive = FALSE;

			return FALSE;
		}

		// 120710 - добавил "|| (mn_TID==dwTID)". Это в том случае, если предыдущая ExclusiveThread была прибита.
		_ASSERTEX(!(lbPrev && mb_Exclusive) || (mn_TID==dwTID)); // После LeaveCriticalSection mb_Exclusive УЖЕ должен быть сброшен
		mn_TID = dwTID; // И запомним, в какой нити это произошло

		HANDLE h = mh_ExclusiveThread;
		mh_ExclusiveThread = OpenThread(SYNCHRONIZE, FALSE, dwTID);
		SafeCloseHandle(h);

		mb_Exclusive = TRUE; // Флаг могла сбросить другая нить, выполнившая Leave
		_ASSERTEX(mn_LockedTID[0] == 0 && mn_LockedCount[0] == 0);
		mn_LockedTID[0] = dwTID;
		mn_LockedCount[0] ++; // на [0] mn_Locked не распространяется

		/*if (abRelockExclusive) {
			ReleaseRef(dwTID); // Если до этого был nonexclusive lock
		}*/

		// B если есть nonexclusive locks - дождаться их завершения
		if (mn_Locked)
		{
			//WARNING: Тут есть шанс наколоться, если сначала был NonExclusive, а потом в этой же нити - Exclusive
			// В таких случаях нужно вызывать с параметром abRelockExclusive
			WaitUnlocked(dwTID, anTimeout);
		}
	}

	return TRUE;
}
// Warning, напрямую НЕ вызывать. Пользоваться "общей" PostMacro
void CPluginW2800::PostMacroApi(const wchar_t* asMacro, INPUT_RECORD* apRec, bool abShowParseErrors)
{
	if (!InfoW2800 || !InfoW2800->AdvControl)
		return;

	MacroSendMacroText mcr = {sizeof(MacroSendMacroText)};
	//mcr.Flags = 0; // По умолчанию - вывод на экран разрешен
	bool bEnableOutput = true;

	while ((asMacro[0] == L'@' || asMacro[0] == L'^') && asMacro[1] && asMacro[1] != L' ')
	{
		switch (*asMacro)
		{
		case L'@':
			bEnableOutput = false;
			break;
		case L'^':
			mcr.Flags |= KMFLAGS_NOSENDKEYSTOPLUGINS;
			break;
		}
		asMacro++;
	}

	if (bEnableOutput)
		mcr.Flags |= KMFLAGS_ENABLEOUTPUT;

	// This macro was not adopted to Lua?
	_ASSERTE(*asMacro && *asMacro != L'$');

	// Вообще говоря, если тут попадается макрос в старом формате - то мы уже ничего не сделаем...
	// Начиная с Far 3 build 2851 - все макросы переведены на Lua

	mcr.SequenceText = asMacro;
	if (apRec)
		mcr.AKey = *apRec;

	mcr.Flags |= KMFLAGS_SILENTCHECK;

	if (!InfoW2800->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, MSSC_CHECK, &mcr))
	{
		if (abShowParseErrors)
		{
			wchar_t* pszErrText = NULL;
			size_t iRcSize = InfoW2800->MacroControl(&guid_ConEmu, MCTL_GETLASTERROR, 0, NULL);
			MacroParseResult* Result = iRcSize ? (MacroParseResult*)calloc(iRcSize,1) : NULL;
			if (Result)
			{
				Result->StructSize = sizeof(*Result);
				_ASSERTE(FALSE && "Check MCTL_GETLASTERROR");
				InfoW2800->MacroControl(&guid_ConEmu, MCTL_GETLASTERROR, iRcSize, Result);

				size_t cchMax = (Result->ErrSrc ? lstrlen(Result->ErrSrc) : 0) + lstrlen(asMacro) + 255;
				pszErrText = (wchar_t*)malloc(cchMax*sizeof(wchar_t));
				_wsprintf(pszErrText, SKIPLEN(cchMax)
					L"Error in Macro. Far %u.%u build %u r%u\n"
					L"ConEmu plugin %02u%02u%02u%s[%u] {2800}\n"
					L"Code: %u, Line: %u, Col: %u%s%s\n"
					L"----------------------------------\n"
					L"%s",
					gFarVersion.dwVerMajor, gFarVersion.dwVerMinor, gFarVersion.dwBuild, gFarVersion.Bis ? 1 : 0,
					MVV_1, MVV_2, MVV_3, _CRT_WIDE(MVV_4a), WIN3264TEST(32,64),
					Result->ErrCode, (UINT)(int)Result->ErrPos.Y+1, (UINT)(int)Result->ErrPos.X+1,
					Result->ErrSrc ? L", Hint: " : L"", Result->ErrSrc ? Result->ErrSrc : L"",
					asMacro);

				SafeFree(Result);
			}
			else
			{
				size_t cchMax = lstrlen(asMacro) + 255;
				pszErrText = (wchar_t*)malloc(cchMax*sizeof(wchar_t));
				_wsprintf(pszErrText, SKIPLEN(cchMax)
					L"Error in Macro. Far %u.%u build %u r%u\n"
					L"ConEmu plugin %02u%02u%02u%s[%u] {2800}\n"
					L"----------------------------------\n"
					L"%s",
					gFarVersion.dwVerMajor, gFarVersion.dwVerMinor, gFarVersion.dwBuild, gFarVersion.Bis ? 1 : 0,
					MVV_1, MVV_2, MVV_3, _CRT_WIDE(MVV_4a), WIN3264TEST(32,64),
					asMacro);
			}

			if (pszErrText)
			{
				DWORD nTID;
				HANDLE h = CreateThread(NULL, 0, BackgroundMacroError, pszErrText, 0, &nTID);
				SafeCloseHandle(h);
			}
		}
	}
	else
	{
		//gFarVersion.dwBuild
		InfoW2800->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, 0, &mcr);
	}
}
Example #4
0
// accept処理を非同期で行う
unsigned __stdcall I4C3DReceiveThreadProc(void* pParam)
{
    LoggingMessage(Log_Debug, _T(MESSAGE_DEBUG_PROCESSING), GetLastError(), g_FILE, __LINE__);

    I4C3DContext* pContext = (I4C3DContext*)pParam;

    SOCKET newClient = NULL;
    SOCKADDR_IN address = {0};
    int nLen = 0;
    HANDLE hChildThread = NULL;
    UINT uThreadID = 0;
    I4C3DChildContext* pChildContext = NULL;
    char cTermination = 0;

    DWORD dwResult = 0;
    WSAEVENT hEvent = NULL;
    WSAEVENT hEventArray[2] = {0};
    WSANETWORKEVENTS events = {0};

    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (hEvent == NULL) {
        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
        I4C3DExit(EXIT_SYSTEM_ERROR);
        return EXIT_SYSTEM_ERROR;
    }

    I4C3DAccessor accessor;
    if (!accessor.SetListeningSocket(pContext->receiver, &pContext->address, g_backlog, hEvent, FD_ACCEPT | FD_CLOSE)) {
        SafeCloseHandle(hEvent);
        I4C3DExit(EXIT_SOCKET_ERROR);
        return EXIT_SOCKET_ERROR;
    }

    hEventArray[0] = hEvent;
    hEventArray[1] = pContext->hStopEvent;

    for (;;) {
        dwResult = WSAWaitForMultipleEvents(2, hEventArray, FALSE, WSA_INFINITE, FALSE);
        if (dwResult == WSA_WAIT_FAILED) {
            LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
            break;
        }

        if (dwResult - WSA_WAIT_EVENT_0 == 0) {
            WSAEnumNetworkEvents(pContext->receiver, hEvent, &events);
            if (events.lNetworkEvents & FD_CLOSE) {
                break;
            } else if (events.lNetworkEvents & FD_ACCEPT) {
                // accept
                if ( !CheckChildThreadCount() ) {
                    LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
                    continue;
                }

                nLen = sizeof(address);
                newClient = accept(pContext->receiver, (SOCKADDR*)&address, &nLen);
                if (newClient == INVALID_SOCKET) {
                    LoggingMessage(Log_Error, _T(MESSAGE_ERROR_SOCKET_INVALID), GetLastError(), g_FILE, __LINE__);
                    break;
                }

                // Create child thread.
                pChildContext = (I4C3DChildContext*)calloc(1, sizeof(I4C3DChildContext));
                if (pChildContext == NULL) {
                    LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
                    break;
                }

                // 設定ファイルから終端文字を取得
                if (cTermination == 0) {
                    GetTerminationFromFile(pContext, &cTermination);
                }
                pChildContext->cTermination = cTermination;

                pChildContext->pContext = pContext;
                pChildContext->clientSocket = newClient;
                hChildThread = (HANDLE)_beginthreadex(NULL, 0, I4C3DAcceptedThreadProc, pChildContext, CREATE_SUSPENDED, &uThreadID);
                if (hChildThread == INVALID_HANDLE_VALUE) {
                    LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
                    break;
                } else {
                    pChildContext->hChildThread = hChildThread;
                    AddChildThread( hChildThread );
                    ResumeThread(hChildThread);
                }
            }

        } else if (dwResult - WSA_WAIT_EVENT_0 == 1) {
            RemoveAllChildThread();
            pContext->pController->UnInitialize();
            break;
        }
    }
    SafeCloseHandle(hEvent);

    shutdown(pContext->receiver, SD_BOTH);
    closesocket(pContext->receiver);

    LoggingMessage(Log_Debug, _T(MESSAGE_DEBUG_PROCESSING), GetLastError(), g_FILE, __LINE__);
    return EXIT_SUCCESS;
}
Example #5
0
//
// Invoke()
//
// invoke the GIB program and return the recommended play
//
int CGIB::Invoke(CPlayer* pPlayer, CHandHoldings* pHand, CHandHoldings* pDummyHand, CPlayerStatusDialog* pStatusDlg)
{
	SECURITY_ATTRIBUTES saAttr; 
	
	//
	// create the GIB monitor dialog
	//
	CGIBDialog	gibDialog(pMAINFRAME);
	int nProcessingTime = theApp.GetValue(tnGIBAnalysisTime);
	gibDialog.m_nProcessTime = nProcessingTime;
//	gibDialog.m_hEventCancel = m_hEventCancel;

	
	// Set the bInheritHandle flag so pipe handles are inherited. 
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 
	
	//
	// create input and output pipes for the child process
	//

	// Create a pipe for the child process's STDOUT. 
	if (!CreatePipe(&m_hChildStdoutRd,	// returns the pipe's input handle
				    &m_hChildStdoutWr, 	// returns the pipe's output handle
					&saAttr, 
					0)) 
	{
		CString strError = "Stdout pipe creation failed\n"; 
		TRACE(strError); 
		pMAINFRAME->SetGIBMonitorText(strError);
		return ExitGracefully(-5);
	}
	// then create a pipe for the child process's STDIN. 
	if (!CreatePipe(&m_hChildStdinRd, 
					&m_hChildStdinWr, 
					&saAttr, 
					0)) 
	{
		CString strError = "Stdin pipe creation failed\n"; 
		TRACE(strError); 
		pMAINFRAME->SetGIBMonitorText(strError);
		return ExitGracefully(-5);
	}

	//
	// Now create the child process (GIB)
	//
	PROCESS_INFORMATION piProcInfo; 
	if (!LaunchProgram(piProcInfo)) 
	{
		TRACE("Create process failed"); 
		return ExitGracefully(-1);
	}
	HANDLE hGIBProcess = piProcInfo.hProcess;
	DWORD nGIBProcessID = piProcInfo.dwProcessId;

	// now close the readable handle to the child's stdin
	SafeCloseHandle(m_hChildStdinRd);
	// and the writable handle to the child's stdout
	SafeCloseHandle(m_hChildStdoutWr);

	//
	//------------------------------------------------------------------
	//
	// create the GIB input file
	//
	CFile file;
	CFileException fileException;
	CString strTempFile, strTempPath;
	GetTempPath(1024, strTempPath.GetBuffer(1024));
	strTempPath.ReleaseBuffer();
	GetTempFileName(strTempPath, "ezb", 0, strTempFile.GetBuffer(2048));
	strTempFile.ReleaseBuffer();
//	strTempFile.Format("%s\\%s", theApp.GetValueString(tszProgramDirectory), tszGIBTempFilename);
/*
	LPTSTR szBuffer = strTempFile.GetBuffer(MAX_PATH);
	GetTempFileName(theApp.GetValueString(tszProgramDirectory), "ezb", 0, szBuffer);
	strTempFile.ReleaseBuffer();
*/
//	CString strInput;
//	strInput.Format("-T %d %s\n",theApp.GetValue(tnGIBAnalysisTime),strTempFile);
	int nCode = file.Open(strTempFile, 
			  			  CFile::modeWrite | CFile::modeCreate | CFile::shareDenyWrite, 
						  &fileException);
	if (nCode == 0) 
	{
		CString strError = "Error opening temporary input file for GIB"; 
		TRACE(strError); 
		pMAINFRAME->SetGIBMonitorText(strError);
		return ExitGracefully(-2);
	}
	//
	CString strFileContents;
	CreateGIBInputFile(file, pPlayer, pHand, pDummyHand, strFileContents);
	file.Close();

	// then send the parameters line
	CString strParameters, strShortParameters;
	strParameters.Format("-T %d %s\n",nProcessingTime,strTempFile);
	strShortParameters.Format("-T %d",nProcessingTime);
	DWORD dwWritten;
	int nErrCode;
	if (!WriteFile(m_hChildStdinWr, (LPCTSTR)strParameters, strParameters.GetLength(), &dwWritten, NULL)) 
	{
		CString strError = "Error providing parameters to GIB"; 
		TRACE(strError); 
		pMAINFRAME->SetGIBMonitorText(strError);
		nErrCode = GetLastError();
		return ExitGracefully(-3);
	}

	//
	// update the GIB monitor window
	//
	CString strGIBText = "========================================\n";
	strGIBText += FormString("Launching %s %s\n",
							 theApp.GetValueString(tszGIBPath),
							 strShortParameters);
//	strGIBText += FormString("Input file contents:\n%s", strFileContents);
	strGIBText += "Awaiting Responses...\n";
	strGIBText += "----------------------------------------\n";
//	pMAINFRAME->SetGIBMonitorText(strGIBText);
	pMAINFRAME->AppendGIBMonitorText(strGIBText);
	

	//
	//------------------------------------------------------------
	//
	// now set up the wait loop and the cancel dialog,
	// then sit and wait for the process to run or for a cancel message
	//

/*
	//
	// create the "Cancel GIB" dialog thread
	// (this is a user interface thread)
	//
	CGIBMonitorThread* pMonitorThread = new CGIBMonitorThread(m_hEventFinished, m_hEventCancel, nProcessingTime);
	pMonitorThread->CreateThread(CREATE_SUSPENDED);
	pMonitorThread->SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
	pMonitorThread->ResumeThread();

	// wait for the monitor thread to initialize
	DWORD nCode0 = WaitForSingleObject(m_hEventFinished,
									   INFINITE);		
*/

	//
	// create the wait thread
	// (this is a worker thread)
	//
	GIBStruct gibData;
	gibData.hReadHandle = m_hChildStdoutRd;
	gibData.pGIBDialog = &gibDialog;
	CWinThread* pWaitThread = AfxBeginThread(CGIB::ReadGIBOutput, &gibData, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);

	// copy its handle se that we can check its exit code later
  	HANDLE hWaitThread;
	BOOL bCode = ::DuplicateHandle(GetCurrentProcess(), pWaitThread->m_hThread, 
								   GetCurrentProcess(), &hWaitThread, 
								   0, FALSE, DUPLICATE_SAME_ACCESS);
	// and launch the threads
//	MonitorThread->ResumeThread();
	pWaitThread->ResumeThread();


	//
	// Show the Wait/Cancel dialog
	//
	m_bGIBPending = TRUE;		// mark dialog as active
	bCode = gibDialog.DoModal();

	// see if the user cancelled
	if (!bCode) 
	{
/*
		// lock out the wait thread and cancel operations
		if (ClearGIBPending())
		{
*/
		//
		pMAINFRAME->SetStatusText("GIB cancelled.");
		//
		TerminateProcess(hGIBProcess, 0);
		TerminateThread(hWaitThread, 0);
		// wait for the read thread to end
		WaitForSingleObject(hWaitThread, INFINITE);
		// close the wait thread handle
		CloseHandle(hWaitThread);
		CloseHandle(hGIBProcess);
		// and delete the thread object
		delete pWaitThread;
		// close pipe handles 
		SafeCloseHandle(m_hChildStdinWr);
		SafeCloseHandle(m_hChildStdoutRd);
		// and throw an exception
		throw CGIBException();
//		}
	}

/*
	// set up events
	HANDLE eventArray[2];
	eventArray[0] = m_hEventCancel;
	eventArray[1] = pWaitThread->m_hThread;

	//
	// then sit back and wait for the thread(s)
	//
	for(;;)
	{
		// wait for the cancelled or finished messages
		DWORD nCode = WaitForMultipleObjects(2,				// 2 events to wait for
											 eventArray,	// events array
											 FALSE,			// not all at once
											 INFINITE);		// wait 4-ever
		//
		if (nCode == WAIT_FAILED)
		{
			ASSERT(FALSE);
			break;
		}
		else if (nCode == WAIT_OBJECT_0) 
		{
			// got the cancel message, so kill GIB & the wait thread
			// the following is very dangersous --
			// so kids, don't try this at home
			TerminateThread(pWaitThread, 0);
			TerminateProcess(hGIBProcess, 0);
			return GIB_CANCEL;
		}
		else if (nCode == WAIT_OBJECT_0 + 1)
		{
			// GIB finished message
			// signal the GIB monitor that GIB has finished
			SetEvent(m_hEventFinished);
			break;
		}
	}

*/

	//
	//------------------------------------------------------------
	//
	// presumably, GIB has finished running
	//

	// wait for the GIB thread to exit, then get the card code
	DWORD nCardPlayed, nErrorCode;
	bCode = WaitForSingleObject(hWaitThread, INFINITE);
	bCode = GetExitCodeThread(hWaitThread, &nCardPlayed);
	if (!bCode)
		nErrorCode = GetLastError();

	// close the wait thread handle
	CloseHandle(hWaitThread);

	// delete the temporary file
	DeleteFile(strTempFile);
 
	// and kill the child process
	// first send a Ctrl-C to the app 
	// (this doesn't seem to do anything)
	CString strInput = "\03";	// Ctrl-C
	if (!WriteFile(m_hChildStdinWr, (LPCTSTR)strInput, strInput.GetLength(), &dwWritten, NULL)) 
	{
		CString strError = "Error stopping GIB"; 
		TRACE(strError); 
		pMAINFRAME->SetGIBMonitorText(strError);
		nErrCode = GetLastError();
		return ExitGracefully(-4);
	}

	// close the writable handle to the child's stdin
	SafeCloseHandle(m_hChildStdinWr);

	// then call terminateProcess
	TerminateProcess(hGIBProcess, 0);
	CloseHandle(hGIBProcess);

	// then close the readable handle to the child's stdout
	SafeCloseHandle(m_hChildStdoutRd);

	//
	// done
	//
	return nCardPlayed; 
} 
Example #6
0
/*****************************************************************************
 * CKsIrpTarget::Close()
 *****************************************************************************
 *//*!
 * @brief
 * Close the Irp Target.
 */
BOOL CKsIrpTarget::Close()
{
    BOOL Success = SafeCloseHandle(m_Handle);
    
    return Success;
}
Example #7
0
BOOL WINAPI DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
	BOOL lbAllow = TRUE;

	switch(ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
		{
			gnDllState = ds_DllProcessAttach;
			#ifdef _DEBUG
			HANDLE hProcHeap = GetProcessHeap();
			#endif
			HeapInitialize();
			
			ghOurModule = (HMODULE)hModule;
			ghConWnd = GetConsoleWindow();
			if (ghConWnd)
				GetConsoleTitle(gsInitConTitle, countof(gsInitConTitle));
			gnSelfPID = GetCurrentProcessId();
			ghWorkingModule = (u64)hModule;
			gfGetRealConsoleWindow = GetConsoleWindow;
			user = (UserImp*)calloc(1, sizeof(*user));
			GetMainThreadId(); // Инициализировать gnHookMainThreadId
			gcchLastWriteConsoleMax = 4096;
			gpszLastWriteConsole = (wchar_t*)calloc(gcchLastWriteConsoleMax,sizeof(*gpszLastWriteConsole));
			gInQueue.Initialize(512, NULL);

			#ifdef _DEBUG
			gAllowAssertThread = am_Pipe;
			#endif
			
			#ifdef _DEBUG
				#ifdef UseDebugExceptionFilter
					gfnPrevFilter = SetUnhandledExceptionFilter(HkExceptionFilter);
				#endif
			#endif

			#ifdef SHOW_STARTED_MSGBOX
			if (!IsDebuggerPresent())
			{
				::MessageBox(ghConEmuWnd, L"ConEmuHk*.dll loaded", L"ConEmu hooks", MB_SYSTEMMODAL);
			}
			#endif
			#ifdef _DEBUG
			DWORD dwConMode = -1;
			GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwConMode);
			#endif

			//_ASSERTE(ghHeap == NULL);
			//ghHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 200000, 0);

			wchar_t szEvtName[64];
			msprintf(szEvtName, countof(szEvtName), CECONEMUROOTPROCESS, gnSelfPID);
			HANDLE hRootProcessFlag = OpenEvent(SYNCHRONIZE|EVENT_MODIFY_STATE, FALSE, szEvtName);
			DWORD nWaitRoot = -1;
			if (hRootProcessFlag)
			{
				nWaitRoot = WaitForSingleObject(hRootProcessFlag, 0);
				gbSelfIsRootConsoleProcess = (nWaitRoot == WAIT_OBJECT_0);
			}
			SafeCloseHandle(hRootProcessFlag);

			
			#ifdef HOOK_USE_DLLTHREAD
			_ASSERTEX(FALSE && "Hooks starting in background thread?");
			//HANDLE hEvents[2];
			//hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
			//hEvents[1] = 
			ghStartThread = CreateThread(NULL, 0, DllStart, NULL/*(LPVOID)(hEvents[0])*/, 0, &gnStartThreadID);
			if (ghStartThread == NULL)
			{
				//_ASSERTE(ghStartThread!=NULL);
				wchar_t szMsg[128]; DWORD nErrCode = GetLastError();
				msprintf(szMsg, countof(szMsg),
					L"Failed to start DllStart thread!\nErrCode=0x%08X\nPID=%u",
					nErrCode, GetCurrentProcessId());
				GuiMessageBox(ghConEmuWnd, szMsg, L"ConEmu hooks", 0);
			}
			else
			{
				DWORD nThreadWait = WaitForSingleObject(ghStartThread, 5000);
				DllThreadClose();
			}
			//DWORD nThreadWait = WaitForMultipleObjects(hEvents, countof(hEvents), FALSE, INFINITE);
			//CloseHandle(hEvents[0]);
			#else
			DllStart(NULL);
			#endif
			
			user->setAllowLoadLibrary();
		}
		break;
		
		case DLL_THREAD_ATTACH:
		{
			gnDllThreadCount++;
			if (gbHooksWasSet)
				InitHooksRegThread();
		}
		break;
		case DLL_THREAD_DETACH:
		{
			#ifdef SHOW_SHUTDOWN_STEPS
			gnDbgPresent = 0;
			ShutdownStep(L"DLL_THREAD_DETACH");
			#endif

			if (gbHooksWasSet)
				DoneHooksRegThread();
			// DLL_PROCESS_DETACH зовется как выяснилось не всегда
			if (gnHookMainThreadId && (GetCurrentThreadId() == gnHookMainThreadId) && !gbDllDeinitialized)
			{
				gbDllDeinitialized = true;
				//WARNING!!! OutputDebugString must NOT be used from ConEmuHk::DllMain(DLL_PROCESS_DETACH). See Issue 465
				DllStop();
			}
			gnDllThreadCount--;
			ShutdownStep(L"DLL_THREAD_DETACH done, left=%i", gnDllThreadCount);
		}
		break;
		
		case DLL_PROCESS_DETACH:
		{
			ShutdownStep(L"DLL_PROCESS_DETACH");
			gnDllState = ds_DllProcessDetach;
			if (gbHooksWasSet)
				lbAllow = FALSE; // Иначе свалимся, т.к. FreeLibrary перехвачена
			// Уже могли дернуть в DLL_THREAD_DETACH
			if (!gbDllDeinitialized)
			{
				gbDllDeinitialized = true;
				//WARNING!!! OutputDebugString must NOT be used from ConEmuHk::DllMain(DLL_PROCESS_DETACH). See Issue 465
				DllStop();
			}
			// -- free не нужен, т.к. уже вызван HeapDeinitialize()
			//free(user);
			ShutdownStep(L"DLL_PROCESS_DETACH done");
		}
		break;
	}

	return lbAllow;
}
Example #8
0
	UINT ExecuteDownloader(LPWSTR pszCommand, LPWSTR szCmdDirectory)
	{
		UINT iRc;
		DWORD nWait;
		DWORD nThreadWait = WAIT_TIMEOUT;
		PipeThreadParm threadParm = {this};

		ZeroStruct(m_SI); m_SI.cb = sizeof(m_SI);
		ZeroStruct(m_PI);

		mb_Terminating = false;

		DWORD nCreateFlags = 0
			//| CREATE_NO_WINDOW
			| NORMAL_PRIORITY_CLASS;

		m_SI.dwFlags |= STARTF_USESHOWWINDOW;

		m_SI.wShowWindow = RELEASEDEBUGTEST(SW_HIDE,SW_SHOWNA);

		if (!szCmdStringFormat || !*szCmdStringFormat)
		{
			// We need to redirect only StdError output

			SECURITY_ATTRIBUTES saAttr = {sizeof(saAttr), NULL, TRUE};
			if (!CreatePipe(&mh_PipeErrRead, &mh_PipeErrWrite, &saAttr, 0))
			{
				iRc = GetLastError();
				_ASSERTE(FALSE && "CreatePipe was failed");
				if (!iRc)
					iRc = E_UNEXPECTED;
				goto wrap;
			}
			// Ensure the read handle to the pipe for STDOUT is not inherited.
			SetHandleInformation(mh_PipeErrRead, HANDLE_FLAG_INHERIT, 0);

			mh_PipeErrThread = apiCreateThread(StdErrReaderThread, (LPVOID)&threadParm, &mn_PipeErrThreadId, "Downloader::ReaderThread");
			if (mh_PipeErrThread != NULL)
			{
				m_SI.dwFlags |= STARTF_USESTDHANDLES;
				// Let's try to change only Error pipe?
				m_SI.hStdError = mh_PipeErrWrite;
			}
		}

		// Now we can run the downloader
		if (!CreateProcess(NULL, pszCommand, NULL, NULL, TRUE/*!Inherit!*/, nCreateFlags, NULL, szCmdDirectory, &m_SI, &m_PI))
		{
			iRc = GetLastError();
			_ASSERTE(FALSE && "Create downloader process was failed");
			if (!iRc)
				iRc = E_UNEXPECTED;
			goto wrap;
		}

		nWait = WaitForSingleObject(m_PI.hProcess, INFINITE);

		if (GetExitCodeProcess(m_PI.hProcess, &nWait)
			&& (nWait == 0)) // CERR_DOWNLOAD_SUCCEEDED is not returned for compatibility purposes
		{
			iRc = 0; // OK
		}
		else
		{
			_ASSERTE(nWait == 0 && "Downloader has returned an error");
			iRc = nWait;
		}

	wrap:
		// Finalize reading routine
		mb_Terminating = true;
		if (mh_PipeErrThread)
		{
			nThreadWait = WaitForSingleObject(mh_PipeErrThread, 0);
			if (nThreadWait == WAIT_TIMEOUT)
			{
				apiCancelSynchronousIo(mh_PipeErrThread);
			}
		}
		SafeCloseHandle(mh_PipeErrRead);
		SafeCloseHandle(mh_PipeErrWrite);
		if (mh_PipeErrThread)
		{
			if (nThreadWait == WAIT_TIMEOUT)
			{
				nThreadWait = WaitForSingleObject(mh_PipeErrThread, 5000);
			}
			if (nThreadWait == WAIT_TIMEOUT)
			{
				_ASSERTE(FALSE && "StdErr reading thread hangs, terminating");
				apiTerminateThread(mh_PipeErrThread, 999);
			}
			SafeCloseHandle(mh_PipeErrThread);
		}
		// Exit
		return iRc;
	};
Example #9
0
// Warning, напрямую НЕ вызывать. Пользоваться "общей" PostMacro
void CPluginW1900::PostMacroApi(const wchar_t* asMacro, INPUT_RECORD* apRec, bool abShowParseErrors)
{
	if (!InfoW1900 || !InfoW1900->AdvControl)
		return;

	MacroSendMacroText mcr = {sizeof(MacroSendMacroText)};
	//mcr.Flags = 0; // По умолчанию - вывод на экран разрешен

	while ((asMacro[0] == L'@' || asMacro[0] == L'^') && asMacro[1] && asMacro[1] != L' ')
	{
		switch (*asMacro)
		{
		case L'@':
			mcr.Flags |= KMFLAGS_DISABLEOUTPUT;
			break;
		case L'^':
			mcr.Flags |= KMFLAGS_NOSENDKEYSTOPLUGINS;
			break;
		}
		asMacro++;
	}

	wchar_t* pszMacroCopy = NULL;

	//Far3 build 2576: удален $Text
	//т.к. макросы у нас фаро-независимые - нужны танцы с бубном
	pszMacroCopy = lstrdup(asMacro);
	CharUpperBuff(pszMacroCopy, lstrlen(pszMacroCopy));
	if (wcsstr(pszMacroCopy, L"$TEXT") && !InfoW1900->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, MSSC_CHECK, &mcr))
	{
		SafeFree(pszMacroCopy);
		pszMacroCopy = (wchar_t*)calloc(lstrlen(asMacro)+1,sizeof(wchar_t)*2);
		wchar_t* psz = pszMacroCopy;
		while (*asMacro)
		{
			if (asMacro[0] == L'$'
				&& (asMacro[1] == L'T' || asMacro[1] == L't')
				&& (asMacro[2] == L'E' || asMacro[2] == L'e')
				&& (asMacro[3] == L'X' || asMacro[3] == L'x')
				&& (asMacro[4] == L'T' || asMacro[4] == L't'))
			{
				lstrcpy(psz, L"print("); psz += 6;

				// Пропустить spasing-symbols
				asMacro += 5;
				while (*asMacro == L' ' || *asMacro == L'\t' || *asMacro == L'\r' || *asMacro == L'\n')
					asMacro++;
				// Копировать строку или переменную
				if (*asMacro == L'@' && *(asMacro+1) == L'"')
				{
					*(psz++) = *(asMacro++); *(psz++) = *(asMacro++);
					while (*asMacro)
					{
						*(psz++) = *(asMacro++);
						if (*(asMacro-1) == L'"')
						{
							if (*asMacro != L'"')
								break;
							*(psz++) = *(asMacro++);
						}
					}
				}
				else if (*asMacro == L'"')
				{
					*(psz++) = *(asMacro++);
					while (*asMacro)
					{
						*(psz++) = *(asMacro++);
						if (*(asMacro-1) == L'\\' && *asMacro == L'"')
						{
							*(psz++) = *(asMacro++);
						}
						else if (*(asMacro-1) == L'"')
						{
							break;
						}
					}
				}
				else if (*asMacro == L'%')
				{
					*(psz++) = *(asMacro++);
					while (*asMacro)
					{
						if (wcschr(L" \t\r\n", *asMacro))
							break;
						*(psz++) = *(asMacro++);
					}
				}
				else
				{
					SafeFree(pszMacroCopy);
					break; // ошибка
				}
				// закрыть скобку
				*(psz++) = L')';
			}
			else
			{
				*(psz++) = *(asMacro++);
			}
		}

		// Если успешно пропатчили макрос
		if (pszMacroCopy)
			asMacro = pszMacroCopy;
	}

	mcr.SequenceText = asMacro;
	if (apRec)
		mcr.AKey = *apRec;

	mcr.Flags |= KMFLAGS_SILENTCHECK;

	if (!InfoW1900->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, MSSC_CHECK, &mcr))
	{
		if (abShowParseErrors)
		{
			wchar_t* pszErrText = NULL;
			size_t iRcSize = InfoW1900->MacroControl(&guid_ConEmu, MCTL_GETLASTERROR, 0, NULL);
			MacroParseResult* Result = iRcSize ? (MacroParseResult*)calloc(iRcSize,1) : NULL;
			if (Result)
			{
				Result->StructSize = sizeof(*Result);
				_ASSERTE(FALSE && "Check MCTL_GETLASTERROR");
				InfoW1900->MacroControl(&guid_ConEmu, MCTL_GETLASTERROR, iRcSize, Result);

				size_t cchMax = (Result->ErrSrc ? lstrlen(Result->ErrSrc) : 0) + lstrlen(asMacro) + 255;
				pszErrText = (wchar_t*)malloc(cchMax*sizeof(wchar_t));
				_wsprintf(pszErrText, SKIPLEN(cchMax)
					L"Error in Macro. Far %u.%u build %u r%u\n"
					L"ConEmu plugin %02u%02u%02u%s[%u] {1900}\n"
					L"Code: %u, Line: %u, Col: %u%s%s\n"
					L"----------------------------------\n"
					L"%s",
					gFarVersion.dwVerMajor, gFarVersion.dwVerMinor, gFarVersion.dwBuild, gFarVersion.Bis ? 1 : 0,
					MVV_1, MVV_2, MVV_3, _CRT_WIDE(MVV_4a), WIN3264TEST(32,64),
					Result->ErrCode, (UINT)(int)Result->ErrPos.Y+1, (UINT)(int)Result->ErrPos.X+1,
					Result->ErrSrc ? L", Hint: " : L"", Result->ErrSrc ? Result->ErrSrc : L"",
					asMacro);

				SafeFree(Result);
			}
			else
			{
				size_t cchMax = lstrlen(asMacro) + 255;
				pszErrText = (wchar_t*)malloc(cchMax*sizeof(wchar_t));
				_wsprintf(pszErrText, SKIPLEN(cchMax)
					L"Error in Macro. Far %u.%u build %u r%u\n"
					L"ConEmu plugin %02u%02u%02u%s[%u] {1900}\n"
					L"----------------------------------\n"
					L"%s",
					gFarVersion.dwVerMajor, gFarVersion.dwVerMinor, gFarVersion.dwBuild, gFarVersion.Bis ? 1 : 0,
					MVV_1, MVV_2, MVV_3, _CRT_WIDE(MVV_4a), WIN3264TEST(32,64),
					asMacro);
			}

			if (pszErrText)
			{
				DWORD nTID;
				HANDLE h = apiCreateThread(BackgroundMacroError, pszErrText, &nTID, "BackgroundMacroError");
				SafeCloseHandle(h);
			}
		}
	}
	else
	{
		//gFarVersion.dwBuild
		InfoW1900->MacroControl(&guid_ConEmu, MCTL_SENDSTRING, 0, &mcr);
	}

	SafeFree(pszMacroCopy);
}
Example #10
0
// Проверка окна переднего плана. Если оно принадлежит к хукаемым процесса - вставить хук.
// ДИАЛОГИ НЕ ПРОВЕРЯЮТСЯ
bool CDefaultTerminal::CheckForeground(HWND hFore, DWORD nForePID, bool bRunInThread /*= true*/)
{
	if (!isDefaultTerminalAllowed())
		return false;

	bool lbRc = false;
	bool lbLocked = false;
	DWORD nResult = 0;
	wchar_t szClass[MAX_PATH]; szClass[0] = 0;
	PROCESSENTRY32 prc;
	bool bMonitored = false;
	const wchar_t* pszMonitored = NULL;
	HANDLE hProcess = NULL;
	int nBits = 0;
	wchar_t szCmdLine[MAX_PATH*3];
	wchar_t szName[64];
	PROCESS_INFORMATION pi = {};
	STARTUPINFO si = {sizeof(si)};
	BOOL bStarted = FALSE;

	// Если главное окно еще не создано
	if (!mb_ReadyToHook)
	{
		// Сразу выходим
		goto wrap;
	}

	//_ASSERTE(gpConEmu->isMainThread());
	if (!hFore || !nForePID)
	{
		_ASSERTE(hFore && nForePID);
		goto wrap;
	}

	if (hFore == mh_LastWnd || hFore == mh_LastIgnoredWnd)
	{
		// Это окно уже проверялось
		lbRc = (hFore == mh_LastWnd);
		goto wrap;
	}

	if (bRunInThread && (hFore == mh_LastCall))
	{
		// Просто выйти. Это проверка на частые фоновые вызовы.
		goto wrap;
	}
	mh_LastCall = hFore;

	if (bRunInThread)
	{
		if (gpConEmu->isMainThread())
		{
			// Clear finished threads
			ClearThreads(false);
		}

		HANDLE hPostThread = NULL; DWORD nThreadId = 0;
		ThreadArg* pArg = (ThreadArg*)malloc(sizeof(ThreadArg));
		if (!pArg)
		{
			_ASSERTE(pArg);
			goto wrap;
		}
		pArg->pTerm = this;
		pArg->hFore = hFore;
		pArg->nForePID = nForePID;

		hPostThread = CreateThread(NULL, 0, PostCheckThread, pArg, 0, &nThreadId);
		_ASSERTE(hPostThread!=NULL);
		if (hPostThread)
		{
			m_Threads.push_back(hPostThread);
		}

		lbRc = (hPostThread != NULL); // вернуть OK?
		goto wrap;
	}

	EnterCriticalSection(&mcs);
	lbLocked = true;

	// Clear dead processes and windows
	ClearProcessed(false);

	// Check window class
	if (GetClassName(hFore, szClass, countof(szClass)))
	{
		if ((lstrcmp(szClass, VirtualConsoleClass) == 0)
			//|| (lstrcmp(szClass, L"#32770") == 0) // Ignore dialogs // -- Process dialogs too (Application may be dialog-based)
			|| isConsoleClass(szClass))
		{
			mh_LastIgnoredWnd = hFore;
			goto wrap;
		}
	}

	// Go and check
	if (!GetProcessInfo(nForePID, &prc))
	{
		mh_LastIgnoredWnd = hFore;
		goto wrap;
	}

	CharLowerBuff(prc.szExeFile, lstrlen(prc.szExeFile));

	if (lstrcmp(prc.szExeFile, L"csrss.exe") == 0)
	{
		// This is "System" process and may not be hooked
		mh_LastIgnoredWnd = hFore;
		goto wrap;
	}

	// Is it in monitored applications?
	pszMonitored = gpSet->GetDefaultTerminalAppsMSZ();
	if (pszMonitored)
	{
		// All strings are lower case
		const wchar_t* psz = pszMonitored;
		while (*psz)
		{
			if (_tcscmp(psz, prc.szExeFile) == 0)
			{
				bMonitored = true;
				break;
			}
			psz += _tcslen(psz)+1;
		}
	}

	// And how it is?
	if (!bMonitored)
	{
		mh_LastIgnoredWnd = hFore;
		goto wrap;
	}

	// Need to process
	for (INT_PTR i = m_Processed.size(); i--;)
	{
		if (m_Processed[i].nPID == nForePID)
		{
			bMonitored = false;
			break; // already hooked
		}
	}

	// May be hooked already?
	if (!bMonitored)
	{
		mh_LastWnd = hFore;
		lbRc = true;
		goto wrap;
	}

	_ASSERTE(isDefaultTerminalAllowed());

	hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|SYNCHRONIZE, FALSE, nForePID);
	if (!hProcess)
	{
		// Failed to hook
		mh_LastIgnoredWnd = hFore;
		goto wrap;
	}

	// Need to be hooked
	nBits = GetProcessBits(nForePID, hProcess);
	switch (nBits)
	{
	case 32:
		_wsprintf(szCmdLine, SKIPLEN(countof(szCmdLine)) L"\"%s\\%s\" /DEFTRM=%u",
			gpConEmu->ms_ConEmuBaseDir, L"ConEmuC.exe", nForePID);
		break;
	case 64:
		_wsprintf(szCmdLine, SKIPLEN(countof(szCmdLine)) L"\"%s\\%s\" /DEFTRM=%u",
			gpConEmu->ms_ConEmuBaseDir, L"ConEmuC64.exe", nForePID);
		break;
	}
	if (!*szCmdLine)
	{
		// Unsupported bitness?
		CloseHandle(hProcess);
		mh_LastIgnoredWnd = hFore;
		goto wrap;
	}

	// Prepare event
	_wsprintf(szName, SKIPLEN(countof(szName)) CEDEFAULTTERMHOOK, nForePID);
	SafeCloseHandle(mh_SignEvent);
	mh_SignEvent = CreateEvent(LocalSecurity(), FALSE, FALSE, szName);
	if (mh_SignEvent) SetEvent(mh_SignEvent); // May be excess, but if event already exists...

	// Run hooker
	si.dwFlags = STARTF_USESHOWWINDOW;
	bStarted = CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
	if (!bStarted)
	{
		DisplayLastError(L"Failed to start hooking application!\nDefault terminal feature will not be available!");
		CloseHandle(hProcess);
		mh_LastIgnoredWnd = hFore;
		goto wrap;
	}
	CloseHandle(pi.hThread);
	// Waiting for result
	TODO("Show status in status line?");
	WaitForSingleObject(pi.hProcess, INFINITE);
	GetExitCodeProcess(pi.hProcess, &nResult);
	CloseHandle(pi.hProcess);
	// And what?
	if (nResult == (UINT)CERR_HOOKS_WAS_SET)
	{
		mh_LastWnd = hFore;
		ProcessInfo inf = {};
		inf.hProcess = hProcess;
		hProcess = NULL; // его закрывать НЕ нужно, сохранен в массиве
		inf.nPID = nForePID;
		inf.nHookTick = GetTickCount();
		m_Processed.push_back(inf);
		lbRc = true;
		goto wrap;
	}
	// Failed, remember this
	CloseHandle(hProcess);
	mh_LastIgnoredWnd = hFore;
	_ASSERTE(lbRc == false);
wrap:
	if (lbLocked)
	{
		LeaveCriticalSection(&mcs);
	}
	return lbRc;
}
Example #11
0
// Shutdown Method
void cIocpServer::Shutdown(DWORD maxWait)
{
	mEndServer = true;
	mRunServer = false;

	// Backend Thread
	if ( mIocpBackendThread != NULL )
	{
		WaitForSingleObjectEx( mIocpBackendThread, maxWait, TRUE );
		CloseHandle( mIocpBackendThread );
		mIocpBackendThread = NULL;
	}

	SOCKET sockTemp = mSocket;

	mSocket = INVALID_SOCKET;

	if ( sockTemp != INVALID_SOCKET )
	{
		closesocket( sockTemp );
	}

	// Accept Thread
	if ( mIocpAcceptThread != NULL )
	{
		WaitForSingleObjectEx( mIocpAcceptThread, maxWait, TRUE );
		CloseHandle( mIocpAcceptThread );
		mIocpAcceptThread = NULL;
	}

	// Cause worker threads to exit
	if ( mIocp != NULL )
	{
		for ( int i = 0; i < mIocpWorkerThreadNumber; i++ )
		{
			PostQueuedCompletionStatus( mIocp, 0, 0, IOCP_SHUTDOWN );
		}
	}

	// Make sure worker threads exits.
	for ( int i = 0; i < mIocpWorkerThreadNumber; i++ )
	{
		if ( WaitForSingleObject( mIocpWorkerThread[i], 60000 ) != WAIT_OBJECT_0 )
		{
			DWORD exitCode;
			GetExitCodeThread( mIocpWorkerThread[i], &exitCode);
			if ( exitCode == STILL_ACTIVE )
			{
				TerminateThread( mIocpWorkerThread[i], 0 );
			}
		}
		CloseHandle( mIocpWorkerThread[i] );
		mIocpWorkerThread[i] = NULL;
	}

	// Overlapped I/O Model Pool Socket Context Pool.
	if ( mIoContextFrontBuffer )
	{
		GlobalFree( mIoContextFrontBuffer );
		mIoContextFrontBuffer = NULL;
	}
	if ( mIoContextBackBuffer )
	{
		GlobalFree( mIoContextBackBuffer );
		mIoContextBackBuffer = NULL;
	}
	SafeDelete( mIoContextPool     );
	SafeDelete( mSocketContextPool );

	// completion port
	SafeCloseHandle( mIocp );
}
Example #12
0
void AbstractBTGenerator::Run(HANDLE hThread, bool bFaultingThread)
{
    assert(m_process.IsValid());
    assert(hThread);

    if (!Init())
    {
        assert(false);
        return;
    }

    if (bFaultingThread)
    {
        const QString threadInfo = QString("Faulting thread (%1)").arg( reinterpret_cast<quintptr>(hThread) );
        emit DebugLine(threadInfo);
    }
    else
    {
        const QString threadInfo = QString("Thread %1").arg( reinterpret_cast<quintptr>(hThread) );
        emit DebugLine(threadInfo);
    }

    //HANDLE hFile = CreateFile(L"C:\\test\\test.dmp", FILE_ALL_ACCESS, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
    //if (!MiniDumpWriteDump(m_process.GetHandle(), m_process.GetId(), hFile,
    //    MiniDumpNormal, NULL, NULL, NULL))
    //{
    //    HRESULT hres = (HRESULT) GetLastError();
    //    printf("%08X\n\n", hres);
    //}
    //SafeCloseHandle(hFile);

    DWORD dw = SuspendThread(hThread);
    assert(dw != DWORD(-1));
    if (dw == DWORD(-1))
    {
        qCritical() << "SuspendThread() failed: " << GetLastError();
        return;
    }

    CONTEXT context;
    ZeroMemory(&context, sizeof(context));
    if (!bFaultingThread)
    {
        // if it's not the faulting thread, get its context
        context.ContextFlags = CONTEXT_FULL;
        if (!GetThreadContext(hThread, &context))
        {
            ResumeThread(hThread);
            assert(false);
            qCritical() << "GetThreadContext() failed: " << GetLastError();
            return;
        }
    }
    else
    {
        // if it is, get it from KCrash
        HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, sharedMemoryName);
        if (hMapFile == NULL)
        {
            qCritical() << "OpenFileMapping() failed: " << GetLastError();
            return;
        }
        CONTEXT *othercontext = (CONTEXT*) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CONTEXT));
        if (othercontext == NULL)
        {
            qCritical() << "MapViewOfFile() failed: " << GetLastError();
            SafeCloseHandle(hMapFile);
            return;
        }
        CopyMemory(&context, othercontext, sizeof(CONTEXT));
        UnmapViewOfFile(othercontext); // continue even if it fails
        SafeCloseHandle(hMapFile);
    }

    // some of this stuff is taken from StackWalker
    ZeroMemory(&m_currentFrame, sizeof(m_currentFrame));
    DWORD machineType = IMAGE_FILE_MACHINE_UNKNOWN;
#if defined(_M_IX86)
    machineType = IMAGE_FILE_MACHINE_I386;
    m_currentFrame.AddrPC.Offset = context.Eip;
    m_currentFrame.AddrFrame.Offset = context.Ebp;
    m_currentFrame.AddrStack.Offset = context.Esp;
#elif defined(_M_X64)
    machineType = IMAGE_FILE_MACHINE_AMD64;
    m_currentFrame.AddrPC.Offset = context.Rip;
    m_currentFrame.AddrFrame.Offset = context.Rbp;
    m_currentFrame.AddrStack.Offset = context.Rsp;
#else
# error This architecture is not supported.
#endif
    m_currentFrame.AddrPC.Mode = AddrModeFlat;
    m_currentFrame.AddrFrame.Mode = AddrModeFlat;
    m_currentFrame.AddrStack.Mode = AddrModeFlat;

    SymSetOptions(SymGetOptions() | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
    SymInitialize(m_process.GetHandle(), NULL, FALSE);

    LoadSymbols();

    for (int i = 0; /*nothing*/; i++)
    {
        SetLastError(0);

        if (!StackWalk64(
            machineType,
            m_process.GetHandle(),
            hThread,
            &m_currentFrame,
            &context,
            &Callbacks::ReadProcessMemory,
            &Callbacks::SymFunctionTableAccess64,
            &Callbacks::SymGetModuleBase64,
            NULL))
        {
            emit Finished();
            qDebug() << "Stackwalk finished; GetLastError=" << GetLastError();
            break;
        }
        
        FrameChanged();

        QString modulename = GetModuleName();
        QString functionname = GetFunctionName();
        QString file = GetFile();
        int line = GetLine();
        QString address = QString::number(m_currentFrame.AddrPC.Offset, 16);

        QString debugLine = QString::fromLatin1(BACKTRACE_FORMAT).
            arg(modulename).arg(functionname).arg(file).arg(line).arg(address);
        
        emit DebugLine(debugLine);
    }

    // Resume the target thread now, or else the crashing process will not
    // be terminated
    ResumeThread(hThread);

    SymCleanup(m_process.GetHandle());

    emit DebugLine(QString());
}
Example #13
0
unsigned __stdcall I4C3DAcceptedThreadProc(void* pParam)
{
    LoggingMessage(Log_Debug, _T(MESSAGE_DEBUG_PROCESSING), GetLastError(), g_FILE, __LINE__);

    I4C3DChildContext* pChildContext = (I4C3DChildContext*)pParam;

    I4C3DUDPPacket packet = {0};
    const SIZE_T packetBufferSize = sizeof(packet.szCommand);

    SIZE_T totalRecvBytes = 0;
    int nBytes = 0;
    BOOL bBreak = FALSE;

    DWORD dwResult = 0;
    WSAEVENT hEvent = NULL;
    WSAEVENT hEventArray[2] = {0};
    WSANETWORKEVENTS events = {0};

    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (hEvent == NULL) {
        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);

        shutdown(pChildContext->clientSocket, SD_SEND);
        recv(pChildContext->clientSocket, packet.szCommand, packetBufferSize, 0);
        shutdown(pChildContext->clientSocket, SD_BOTH);
        closesocket(pChildContext->clientSocket);

        RemoveChildThread( pChildContext->hChildThread );
        free(pChildContext);
        return EXIT_FAILURE;
    }
    WSAEventSelect(pChildContext->clientSocket, hEvent, FD_READ | FD_CLOSE);

    hEventArray[0] = hEvent;
    hEventArray[1] = pChildContext->pContext->hStopEvent;

    FillMemory(packet.szCommand, packetBufferSize, 0xFF);
    while (!bBreak) {
        if (!CheckNetworkEventError(events)) {
            break;
        }

        dwResult = WSAWaitForMultipleEvents(2, hEventArray, FALSE, WSA_INFINITE, FALSE);

        DEBUG_PROFILE_MONITOR;

        if (dwResult == WSA_WAIT_FAILED) {
            LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
            break;
        }

        if (dwResult - WSA_WAIT_EVENT_0 == 0) {
            if (WSAEnumNetworkEvents(pChildContext->clientSocket, hEvent, &events) != 0) {
                LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
                break;
            }

            if (events.lNetworkEvents & FD_CLOSE) {
                break;

            } else if (events.lNetworkEvents & FD_READ) {
                nBytes = recv(pChildContext->clientSocket, packet.szCommand + totalRecvBytes, packetBufferSize - totalRecvBytes, 0);

                if (nBytes == SOCKET_ERROR) {
                    if (WSAGetLastError() == WSAEWOULDBLOCK) {
                        continue;
                    } else {
                        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_SOCKET_RECV), WSAGetLastError(), g_FILE, __LINE__);
                    }
                    break;

                } else if (nBytes > 0) {

                    totalRecvBytes += nBytes;
                    PCSTR pTermination = (PCSTR)memchr(packet.szCommand, pChildContext->cTermination, totalRecvBytes);

                    // 終端文字が見つからない場合、バッファをクリア
                    if (pTermination == NULL) {
                        if (totalRecvBytes >= packetBufferSize) {
                            FillMemory(packet.szCommand, packetBufferSize, 0xFF);
                            totalRecvBytes = 0;
                        }
                        continue;
                    }

                    do {

                        DEBUG_PROFILE_MONITOR;

                        // プラグインへ電文転送
                        pChildContext->pContext->pController->Execute(&packet, pTermination-packet.szCommand+1);

                        volatile int i;
                        for (i = 0; i < g_sleepCount; ++i) {
                            Sleep(1);
                        }

                        //} else {
                        //	// Hotkey
                        //	MoveMemory(szCommand, recvBuffer, pTermination-recvBuffer);
                        //	szCommand[pTermination-recvBuffer] = '\0';
                        //	EnterCriticalSection(&g_Lock);
                        //	pChildContext->pContext->pController->Execute(pChildContext->pContext, &delta, szCommand);
                        //	LeaveCriticalSection(&g_Lock);
                        //}

                        if (pTermination == (packet.szCommand + totalRecvBytes - 1)) {
                            FillMemory(packet.szCommand, packetBufferSize, 0xFF);
                            totalRecvBytes = 0;

                        } else if (pTermination < (packet.szCommand + totalRecvBytes - 1)) {
                            int nCopySize = packetBufferSize - (pTermination - packet.szCommand + 1);

                            totalRecvBytes -= (pTermination - packet.szCommand + 1);
                            MoveMemory(packet.szCommand, pTermination+1, nCopySize);
                            FillMemory(packet.szCommand + nCopySize, packetBufferSize - nCopySize, 0xFF);

                        } else {
                            bBreak = TRUE;
                            LoggingMessage(Log_Error, _T(MESSAGE_ERROR_MESSAGE_INVALID), GetLastError(), g_FILE, __LINE__);
                            break;
                        }

                        DEBUG_PROFILE_MONITOR;

                    } while ((pTermination = (LPCSTR)memchr(packet.szCommand, pChildContext->cTermination, totalRecvBytes)) != NULL);

                    DEBUG_PROFILE_MONITOR;
                }

            }

        } else if (dwResult - WSA_WAIT_EVENT_0 == 1) {
            // pChildContext->pContext->hStopEvent に終了イベントがセットされた
            break;
        }

    }
    SafeCloseHandle(hEvent);

    // closesocket
    shutdown(pChildContext->clientSocket, SD_SEND);
    recv(pChildContext->clientSocket, packet.szCommand, packetBufferSize, 0);
    shutdown(pChildContext->clientSocket, SD_BOTH);
    closesocket(pChildContext->clientSocket);

    RemoveChildThread( pChildContext->hChildThread );
    free(pChildContext);

    LoggingMessage(Log_Debug, _T(MESSAGE_DEBUG_PROCESSING), GetLastError(), g_FILE, __LINE__);

    return EXIT_SUCCESS;
}
Example #14
0
HRESULT CKsIrpTarget::SyncIoctl(
        IN  HANDLE  handle,
        IN  ULONG   ulIoctl,
        IN  PVOID   pvInBuffer,
        IN  ULONG   cbInBuffer,
        OUT PVOID   pvOutBuffer,
        OUT ULONG   cbOutBuffer,
        OUT PULONG  pulBytesReturned)
{
    TRACE_ENTER();
    HRESULT hr = S_OK;
    OVERLAPPED overlapped;
        BOOL fRes = TRUE;
        ULONG ulBytesReturned;

    if (!IsValidHandle(handle))
    {
        hr = E_FAIL;
        DebugPrintf(TRACE_ERROR,TEXT("CKsIrpTarget::SyncIoctl Invalid Handle"));
    }
    
    if (!pulBytesReturned)
    {
        pulBytesReturned = &ulBytesReturned;
    }

    if (SUCCEEDED(hr))
    {
        ZeroMemory(&overlapped,sizeof(overlapped));
        overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
        if (!overlapped.hEvent)
        {
            hr = E_OUTOFMEMORY;
            DebugPrintf(TRACE_ERROR,TEXT("CKsIrpTarget::SyncIoctl CreateEvent failed"));
        }
        else
        {
            // Flag the event by setting the low-order bit so we
            // don't get completion port notifications.
            // Really! - see the description of the lpOverlapped parameter in
            // the docs for GetQueuedCompletionStatus
            overlapped.hEvent = (HANDLE)((DWORD_PTR)overlapped.hEvent | 0x1);
        }
    }

    if (SUCCEEDED(hr))
    {
        fRes = DeviceIoControl(handle, ulIoctl, pvInBuffer, cbInBuffer, pvOutBuffer, cbOutBuffer, pulBytesReturned, &overlapped);
        if (!fRes)
        {

            DWORD dwError;
            dwError = GetLastError();
            if (ERROR_IO_PENDING == dwError)
            {
                DWORD dwWait;
                // Wait for completion
                dwWait = ::WaitForSingleObject(overlapped.hEvent,INFINITE);
                assert(WAIT_OBJECT_0 == dwWait);
                if (dwWait != WAIT_OBJECT_0)
                {
                    hr = E_FAIL;
                    DebugPrintf(TRACE_ERROR,TEXT("CKsIrpTarget::SyncIoctl WaitForSingleObject failed dwWait:0x%08x"),dwWait);
                }
            }
            else if (((ERROR_INSUFFICIENT_BUFFER == dwError) || (ERROR_MORE_DATA == dwError)) &&
                (IOCTL_KS_PROPERTY == ulIoctl) &&
                (cbOutBuffer == 0))
            {
                hr = S_OK;
                fRes = TRUE;
            }
            else
            {
                hr = E_FAIL;
            }
        }
        if (!fRes) *pulBytesReturned = 0;
        SafeCloseHandle(overlapped.hEvent);
    }
    
    TRACE_LEAVE_HRESULT(hr);
    return hr;
}
Example #15
0
DWORD CSetDlgFonts::EnumFontsThread(LPVOID apArg)
{
	HDC hdc = GetDC(NULL);
	int aFontCount[] = { 0, 0, 0 };
	wchar_t szName[MAX_PATH];
	// Сначала загрузить имена шрифтов, установленных в систему (или зарегистрированных нами)
	EnumFontFamilies(hdc, (LPCTSTR) NULL, (FONTENUMPROC) EnumFamCallBack, (LPARAM) aFontCount);
	// Теперь - загрузить размеры установленных терминальных шрифтов (aka Raster fonts)
	LOGFONT term = {0}; term.lfCharSet = OEM_CHARSET; wcscpy_c(term.lfFaceName, L"Terminal");
	//CFontMgr::szRasterSizes[0].cx = CFontMgr::szRasterSizes[0].cy = 0;
	memset(CFontMgr::szRasterSizes, 0, sizeof(CFontMgr::szRasterSizes));
	EnumFontFamiliesEx(hdc, &term, (FONTENUMPROCW) EnumFontCallBackEx, 0/*LPARAM*/, 0);
	UINT nMaxCount = countof(CFontMgr::szRasterSizes);

	for(UINT i = 0; i<(nMaxCount-1) && CFontMgr::szRasterSizes[i].cy; i++)
	{
		UINT k = i;

		for(UINT j = i+1; j<nMaxCount && CFontMgr::szRasterSizes[j].cy; j++)
		{
			if (CFontMgr::szRasterSizes[j].cy < CFontMgr::szRasterSizes[k].cy)
				k = j;
			else if (CFontMgr::szRasterSizes[j].cy == CFontMgr::szRasterSizes[k].cy
					&& CFontMgr::szRasterSizes[j].cx < CFontMgr::szRasterSizes[k].cx)
				k = j;
		}

		if (k != i)
		{
			SIZE sz = CFontMgr::szRasterSizes[k];
			CFontMgr::szRasterSizes[k] = CFontMgr::szRasterSizes[i];
			CFontMgr::szRasterSizes[i] = sz;
		}
	}

	DeleteDC(hdc);

	HWND hFontsPg = gpSetCls->GetPage(thi_Fonts);
	if (hFontsPg)
	{
		for (size_t sz=0; sz<countof(CFontMgr::szRasterSizes) && CFontMgr::szRasterSizes[sz].cy; sz++)
		{
			swprintf_c(szName, L"[%s %ix%i]", CFontMgr::RASTER_FONTS_NAME, CFontMgr::szRasterSizes[sz].cx, CFontMgr::szRasterSizes[sz].cy);
			int nIdx = SendDlgItemMessage(hFontsPg, tFontFace, CB_INSERTSTRING, sz, (LPARAM)szName);
			SendDlgItemMessage(hFontsPg, tFontFace, CB_SETITEMDATA, nIdx, 1);
		}

		GetDlgItemText(hFontsPg, tFontFace, szName, countof(szName));
		CSetDlgLists::SelectString(hFontsPg, tFontFace, szName);
		GetDlgItemText(hFontsPg, tFontFace2, szName, countof(szName));
		CSetDlgLists::SelectString(hFontsPg, tFontFace2, szName);
	}

	SafeCloseHandle(mh_EnumThread);
	_ASSERTE(mh_EnumThread == NULL);

	mb_EnumThreadFinished = true;

	// Если шустрый юзер успел переключиться на вкладку "Views" до окончания
	// загрузки шрифтов - послать в диалог сообщение "Считать список из [thi_Fonts]"
	HWND hViewsPg = gpSetCls->GetPage(thi_Views);
	if (hViewsPg)
		PostMessage(hViewsPg, gpSetCls->mn_MsgLoadFontFromMain, 0, 0);
	HWND hTabsPg = gpSetCls->GetPage(thi_Tabs);
	if (hTabsPg)
		PostMessage(hTabsPg, gpSetCls->mn_MsgLoadFontFromMain, 0, 0);
	HWND hStatusPg = gpSetCls->GetPage(thi_Status);
	if (hStatusPg)
		PostMessage(hStatusPg, gpSetCls->mn_MsgLoadFontFromMain, 0, 0);

	return 0;
}
Example #16
0
	void CloseHandles()
	{
		SafeCloseHandle(m_PI.hProcess);
		SafeCloseHandle(m_PI.hThread);
	};
Example #17
0
static void DeleteWatchedDir(WatchedDir *wd)
{
    free((void*)wd->dirPath);
    SafeCloseHandle(wd->hDir);
    free(wd);
}
Example #18
0
int ComspecInit()
{
    TODO("Определить код родительского процесса, и если это FAR - запомнить его (для подключения к пайпу плагина)");
    TODO("Размер получить из GUI, если оно есть, иначе - по умолчанию");
    TODO("GUI может скорректировать размер с учетом полосы прокрутки");
    WARNING("CreateFile(CONOUT$) по идее возвращает текущий ScreenBuffer. Можно его самим возвращать в ComspecDone");

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

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

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

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

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

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

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

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

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

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

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

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

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

    SendStarted();
    //ConOutCloseHandle()
    return 0;
}
Example #19
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)!"), nCmd);
		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();
		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();
		return FALSE;
	}

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

	pOut = (CESERVER_REQ*)cbReadBuf;
	
	// Проверка размера
	if (pOut->hdr.cbSize <= sizeof(pOut->hdr))
	{
		_ASSERTE(pOut->hdr.cbSize == 0);
		pOut = NULL;
		Close();
		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();
		return FALSE;
	}

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

	if (nAllSize==0)
	{
		DEBUGSTR(L" - FAILED!\n");
		DisplayLastError(L"Empty data recieved from server", 0);
		Close();
		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;
}
// CIR_OK=0 - OK, CIR_AlreadyInjected=1 - Already injected, иначе - ошибка
// Здесь вызывается CreateRemoteThread
CINFILTRATE_EXIT_CODES InjectRemote(DWORD nRemotePID, bool abDefTermOnly /*= false */)
{
	CINFILTRATE_EXIT_CODES iRc = CIR_GeneralError/*-1*/;
	bool lbWin64 = WIN3264TEST((IsWindows64()!=0),true);
	bool is32bit;
	int  nBits;
	DWORD nWrapperWait = (DWORD)-1, nWrapperResult = (DWORD)-1;
	HANDLE hProc = NULL;
	wchar_t szSelf[MAX_PATH+16], szHooks[MAX_PATH+16];
	wchar_t *pszNamePtr, szArgs[32];
	wchar_t szName[64];
	HANDLE hEvent = NULL;
	HANDLE hDefTermReady = NULL;
	bool bAlreadyHooked = false;
	HANDLE hSnap = NULL;
	MODULEENTRY32 mi = {sizeof(mi)};
	HMODULE ptrOuterKernel = NULL;

	if (!GetModuleFileName(NULL, szSelf, MAX_PATH))
	{
		iRc = CIR_GetModuleFileName/*-200*/;
		goto wrap;
	}
	wcscpy_c(szHooks, szSelf);
	pszNamePtr = (wchar_t*)PointToName(szHooks);
	if (!pszNamePtr)
	{
		iRc = CIR_GetModuleFileName/*-200*/;
		goto wrap;
	}


	// Hey, may be ConEmuHk.dll is already loaded?
	hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, nRemotePID);
	if (!hSnap || (hSnap == INVALID_HANDLE_VALUE))
	{
		iRc = CIR_SnapshotCantBeOpened/*-113*/;
		goto wrap;
	}
	else if (hSnap && Module32First(hSnap, &mi))
	{
		// 130829 - Let load newer(!) ConEmuHk.dll into target process.
		// 141201 - Also we need to be sure in kernel32.dll address

		LPCWSTR pszConEmuHk = WIN3264TEST(L"conemuhk.", L"conemuhk64.");
		size_t nDllNameLen = lstrlen(pszConEmuHk);
		// Out preferred module name
		wchar_t szOurName[40] = {};
		wchar_t szMinor[8] = L""; lstrcpyn(szMinor, _CRT_WIDE(MVV_4a), countof(szMinor));
		_wsprintf(szOurName, SKIPLEN(countof(szOurName))
			CEDEFTERMDLLFORMAT /*L"ConEmuHk%s.%02u%02u%02u%s.dll"*/,
			WIN3264TEST(L"",L"64"), MVV_1, MVV_2, MVV_3, szMinor);
		CharLowerBuff(szOurName, lstrlen(szOurName));

		// Go to enumeration
		wchar_t szName[64];
		do {
			LPCWSTR pszName = PointToName(mi.szModule);

			// Name of ConEmuHk*.*.dll module may be changed (copied to %APPDATA%)
			if (!pszName || !*pszName)
				continue;

			lstrcpyn(szName, pszName, countof(szName));
			CharLowerBuff(szName, lstrlen(szName));

			if (!ptrOuterKernel
				&& (lstrcmp(szName, L"kernel32.dll") == 0))
			{
				ptrOuterKernel = mi.hModule;
			}

			// ConEmuHk*.*.dll?
			if (!bAlreadyHooked
				&& (wmemcmp(szName, pszConEmuHk, nDllNameLen) == 0)
				&& (wmemcmp(szName+lstrlen(szName)-4, L".dll", 4) == 0))
			{
				// Yes! ConEmuHk.dll already loaded into nRemotePID!
				// But what is the version? Let don't downgrade loaded version!
				if (lstrcmp(szName, szOurName) >= 0)
				{
					// OK, szName is newer or equal to our build
					bAlreadyHooked = true;
				}
			}

			// Stop enumeration?
			if (bAlreadyHooked && ptrOuterKernel)
				break;
		} while (Module32Next(hSnap, &mi));

		// Check done
	}
	SafeCloseHandle(hSnap);


	// Already hooked?
	if (bAlreadyHooked)
	{
		iRc = CIR_AlreadyInjected/*1*/;
		goto wrap;
	}


	if (!ptrOuterKernel)
	{
		iRc = CIR_OuterKernelAddr/*-112*/;
		goto wrap;
	}


	// Check, if we can access that process
	hProc = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, nRemotePID);
	if (hProc == NULL)
	{
		iRc = CIR_OpenProcess/*-201*/;
		goto wrap;
	}


	// Go to hook

	// Preparing Events
	_wsprintf(szName, SKIPLEN(countof(szName)) CEDEFAULTTERMHOOK, nRemotePID);
	if (!abDefTermOnly)
	{
		// When running in normal mode (NOT set up as default terminal)
		// we need full initialization procedure, not a light one when hooking explorer.exe
		hEvent = OpenEvent(EVENT_MODIFY_STATE|SYNCHRONIZE, FALSE, szName);
		if (hEvent)
		{
			ResetEvent(hEvent);
			CloseHandle(hEvent);
		}
	}
	else
	{
		hEvent = CreateEvent(LocalSecurity(), FALSE, FALSE, szName);
		SetEvent(hEvent);

		_wsprintf(szName, SKIPLEN(countof(szName)) CEDEFAULTTERMHOOKOK, nRemotePID);
		hDefTermReady = CreateEvent(LocalSecurity(), FALSE, FALSE, szName);
		ResetEvent(hDefTermReady);
	}

	// Creating as remote thread.
	// Resetting this event notify ConEmuHk about
	// 1) need to determine MainThreadId
	// 2) need to start pipe server
	_wsprintf(szName, SKIPLEN(countof(szName)) CECONEMUROOTTHREAD, nRemotePID);
	hEvent = OpenEvent(EVENT_MODIFY_STATE|SYNCHRONIZE, FALSE, szName);
	if (hEvent)
	{
		ResetEvent(hEvent);
		CloseHandle(hEvent);
	}


	// Определить битность процесса, Если он 32битный, а текущий - ConEmuC64.exe
	// Перезапустить 32битную версию ConEmuC.exe
	nBits = GetProcessBits(nRemotePID, hProc);
	if (nBits == 0)
	{
		// Do not even expected, ConEmu GUI must run ConEmuC elevated if required.
		iRc = CIR_GetProcessBits/*-204*/;
		goto wrap;
	}

	is32bit = (nBits == 32);

	if (is32bit != WIN3264TEST(true,false))
	{
		// По идее, такого быть не должно. ConEmu должен был запустить соответствующий conemuC*.exe
		_ASSERTE(is32bit == WIN3264TEST(true,false));
		PROCESS_INFORMATION pi = {};
		STARTUPINFO si = {sizeof(si)};

		_wcscpy_c(pszNamePtr, 16, is32bit ? L"ConEmuC.exe" : L"ConEmuC64.exe");
		_wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /INJECT=%u", nRemotePID);

		if (!CreateProcess(szHooks, szArgs, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
		{
			iRc = CIR_CreateProcess/*-202*/;
			goto wrap;
		}
		nWrapperWait = WaitForSingleObject(pi.hProcess, INFINITE);
		GetExitCodeProcess(pi.hProcess, &nWrapperResult);
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		if ((nWrapperResult != CERR_HOOKS_WAS_SET) && (nWrapperResult != CERR_HOOKS_WAS_ALREADY_SET))
		{
			iRc = CIR_WrapperResult/*-203*/;
			SetLastError(nWrapperResult);
			goto wrap;
		}
		// Значит всю работу сделал враппер
		iRc = CIR_OK/*0*/;
		goto wrap;
	}

	// Поехали
	_wcscpy_c(pszNamePtr, 16, is32bit ? L"ConEmuHk.dll" : L"ConEmuHk64.dll");
	if (!FileExists(szHooks))
	{
		iRc = CIR_ConEmuHkNotFound/*-250*/;
		goto wrap;
	}

	if (abDefTermOnly)
	{
		CINFILTRATE_EXIT_CODES iFRc = PrepareHookModule(szHooks);
		if (iFRc != 0)
		{
			iRc = iFRc;
			goto wrap;
		}
	}

	iRc = InfiltrateDll(hProc, ptrOuterKernel, szHooks);

	// Если создавали временную копию - запланировать ее удаление
	if (abDefTermOnly && (lstrcmpi(szHooks, szSelf) != 0))
	{
		MoveFileEx(szHooks, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
	}
wrap:
	if (hProc != NULL)
		CloseHandle(hProc);
	// But check the result of the operation

	//_ASSERTE(FALSE && "WaitForSingleObject(hDefTermReady)");

	if ((iRc == 0) && hDefTermReady)
	{
		_ASSERTE(abDefTermOnly);
		DWORD nWaitReady = WaitForSingleObject(hDefTermReady, CEDEFAULTTERMHOOKWAIT/*==0*/);
		if (nWaitReady == WAIT_TIMEOUT)
		{
			iRc = CIR_DefTermWaitingFailed/*-300*/; // Failed to start hooking thread in remote process
		}
	}
	return iRc;
}
Example #21
0
//------------------------------------------------------------------------
///| Parsing the command line |///////////////////////////////////////////
//------------------------------------------------------------------------
// Returns:
//   true  - continue normal startup
//   false - exit process with iResult code
bool CConEmuStart::ParseCommandLine(LPCWSTR pszCmdLine, int& iResult)
{
	bool bRc = false;
	iResult = 100;

	_ASSERTE(pszCmdLine!=NULL);
	opt.cmdLine.Set(pszCmdLine ? pszCmdLine : L"");

	// pszCmdLine *may* or *may not* start with our executable or full path to our executable
	LPCWSTR pszTemp = opt.cmdLine;
	LPCWSTR cmdLineRest = SkipNonPrintable(opt.cmdLine);
	LPCWSTR pszName, pszArgStart;
	LPCWSTR psUnknown = NULL;
	CEStr   szArg, szNext;
	CEStr   szExeName, szExeNameOnly;

	// Set %ConEmuArgs% env var
	// It may be usefull if we need to restart ConEmu
	// from batch/script with the same arguments (selfupdate etc.)
	LPCWSTR pszCopyToEnvStart = NULL;

	// Have to get our exectuable name and name without extension
	szExeName.Set(PointToName(gpConEmu->ms_ConEmuExe));
	szExeNameOnly.Set(szExeName);
	wchar_t* pszDot = (wchar_t*)PointToExt(szExeNameOnly.ms_Val);
	_ASSERTE(pszDot);
	if (pszDot) *pszDot = 0;


	// Check the first argument in the command line (most probably it will be our executable path/name)
	if (NextArg(&pszTemp, szArg) != 0)
	{
		_ASSERTE(FALSE && "GetCommandLine() is empty");
		// Treat as empty command line, allow to start
		bRc = true; iResult = 0;
		goto wrap;
	}
	pszName = PointToName(szArg);
	if ((lstrcmpi(pszName, szExeName) == 0)
		|| (lstrcmpi(pszName, szExeNameOnly) == 0))
	{
		// OK, our executable was specified properly in the command line
		_ASSERTE(*pszTemp != L' ');
		cmdLineRest = SkipNonPrintable(pszTemp);
	}


	// Must be empty at the moment
	_ASSERTE(opt.runCommand.IsEmpty());

	// Does the command line contain our switches?
	// Or we need to append all switches to starting shell?
	if (cmdLineRest && *cmdLineRest)
	{
		pszTemp = cmdLineRest;
		if (NextArg(&pszTemp, szArg) == 0)
		{
			if ((*szArg.ms_Val != L'/')
				&& (*szArg.ms_Val != L'-')
				/*&& !wcschr(szArg.ms_Val, L'/')*/
				)
			{
				// Save it for further use
				opt.runCommand.Set(cmdLineRest);
				// And do not process it (no switches at all)
				cmdLineRest = NULL;
				opt.params = -1;
			}
		}
	}


	// Let parse the reset
	szArg.Empty();
	szNext.Empty();

	// Processing loop begin
	if (cmdLineRest && *cmdLineRest)
	{
		pszCopyToEnvStart = cmdLineRest;
		opt.cfgSwitches.Set(pszCopyToEnvStart);

		while (NextArg(&cmdLineRest, szArg, &pszArgStart) == 0)
		{
			bool lbNotFound = false;

			// ':' removed from checks because otherwise it will not warn
			// on invalid usage of "-new_console:a" for example
			if (szArg.ms_Val[0] == L'-' && szArg.ms_Val[1] && !wcspbrk(szArg.ms_Val+1, L"\\//|.&<>^"))
			{
				// Seems this is to be the "switch" too
				// Use both notations ('-' and '/')
				*szArg.ms_Val = L'/';
			}

			LPCWSTR curCommand = szArg.ms_Val;

			#define NeedNextArg() \
				if (NextArg(&cmdLineRest, szNext) != 0) { iResult = 101; goto wrap; } \
				curCommand = szNext.ms_Val;


			if (*curCommand != L'/')
			{
				continue; // Try next switch?
			}
			else
			{
				opt.params++;

				if (!klstricmp(curCommand, _T("/autosetup")))
				{
					BOOL lbTurnOn = TRUE;

					NeedNextArg();

					if (*curCommand == _T('0'))
					{
						lbTurnOn = FALSE;
					}
					else
					{
						NeedNextArg();

						DWORD dwAttr = GetFileAttributes(curCommand);

						if (dwAttr == (DWORD)-1 || (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
						{
							iResult = 102;
							goto wrap;
						}
					}

					HKEY hk = NULL; DWORD dw;
					int nSetupRc = 100;

					if (0 != RegCreateKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Command Processor"),
										   0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dw))
					{
						iResult = 103;
						goto wrap;
					}

					if (lbTurnOn)
					{
						size_t cchMax = _tcslen(curCommand);
						LPCWSTR pszArg1 = NULL;
						if (*cmdLineRest)
						{
							// May be ‘/GHWND=NEW’ or smth else
							pszArg1 = cmdLineRest;
							cchMax += _tcslen(pszArg1);
						}
						cchMax += 16; // + quotations, spaces and so on

						wchar_t* pszCmd = (wchar_t*)calloc(cchMax, sizeof(*pszCmd));
						_wsprintf(pszCmd, SKIPLEN(cchMax) L"\"%s\"%s%s%s", curCommand,
							pszArg1 ? L" \"" : L"", pszArg1 ? pszArg1 : L"", pszArg1 ? L"\"" : L"");


						if (0 == RegSetValueEx(hk, _T("AutoRun"), 0, REG_SZ, (LPBYTE)pszCmd,
											(DWORD)sizeof(*pszCmd)*(_tcslen(pszCmd)+1)))
							nSetupRc = 1;

						free(pszCmd);
					}
					else
					{
						if (0==RegDeleteValue(hk, _T("AutoRun")))
							nSetupRc = 1;
					}

					RegCloseKey(hk);
					// сбросить CreateInNewEnvironment для ConMan
					ResetConman();
					iResult = nSetupRc;
					goto wrap;
				}
				else if (!klstricmp(curCommand, _T("/bypass"))
					|| !klstricmp(curCommand, _T("/apparent"))
					|| !klstricmp(curCommand, _T("/system"))
					|| !klstricmp(curCommand, _T("/interactive"))
					|| !klstricmp(curCommand, _T("/demote")))
				{
					// -bypass
					// Этот ключик был придуман для прозрачного запуска консоли
					// в режиме администратора
					// (т.е. чтобы окно UAC нормально всплывало, но не мелькало консольное окно)
					// Но не получилось, пока требуются хэндлы процесса, а их не получается
					// передать в НЕ приподнятый процесс (исходный ConEmu GUI).

					// -apparent
					// Same as -bypass, but run the process as SW_SHOWNORMAL

					// -demote
					// Запуск процесса (ком.строка после "/demote") в режиме простого юзера,
					// когда текущий процесс уже запущен "под админом". "Понизить" текущие
					// привилегии просто так нельзя, поэтому запуск идет через TaskSheduler.

					// -system
					// Non-interactive process, started as System account
					// It's used when starting consoles, our server works fine as non-interactive

					// -interactive
					// Used when ConEmu.exe is started under System account,
					// but we need to give starting process interactive capabilities.

					_ASSERTE(opt.runCommand.IsEmpty());
					pszTemp = cmdLineRest;
					if ((NextArg(&pszTemp, szNext) == 0)
						&& (szNext.ms_Val[0] == L'-' || szNext.ms_Val[0] == L'/')
						&& (lstrcmpi(szNext.ms_Val+1, L"cmd") == 0))
					{
						opt.runCommand.Set(pszTemp);
					}
					else
					{
						opt.runCommand.Set(cmdLineRest);
					}

					if (opt.runCommand.IsEmpty())
					{
						CEStr lsMsg(L"Invalid cmd line. '", curCommand, L"' exists, command line is empty");
						DisplayLastError(lsMsg, -1);
						goto wrap;
					}

					// Information
					#ifdef _DEBUG
					STARTUPINFO siOur = {sizeof(siOur)};
					GetStartupInfo(&siOur);
					#endif

					STARTUPINFO si = {sizeof(si)};
					PROCESS_INFORMATION pi = {};
					si.dwFlags = STARTF_USESHOWWINDOW;
					// Only `-demote` and `-apparent` switches were implemented to start application visible
					// All others are intended to run our server process, without blinking of course
					if ((0 == klstricmp(curCommand, _T("/demote")))
						|| (0 == klstricmp(curCommand, _T("/apparent"))))
						si.wShowWindow = SW_SHOWNORMAL;
					else
						si.wShowWindow = SW_HIDE;

					wchar_t szCurDir[MAX_PATH+1] = L"";
					GetCurrentDirectory(countof(szCurDir), szCurDir);

					BOOL b;
					DWORD nErr = 0;

					// if we were started from TaskScheduler, it would be nice to wait a little
					// to let parent (creator of the scheduler task) know we were started successfully
					bool bFromScheduler = false;

					// Log the command to be started
					{
						CEStr lsLog(
							L"Starting process",
							L": ", curCommand,
							L" `", opt.runCommand.ms_Val, L"`");
						LogString(lsLog);
					}

					if (!klstricmp(curCommand, _T("/demote")))
					{
						b = CreateProcessDemoted(opt.runCommand.ms_Val, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL,
							szCurDir, &si, &pi, &nErr);
					}
					else if (!klstricmp(curCommand, _T("/system")))
					{
						b = CreateProcessSystem(opt.runCommand.ms_Val, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL,
							szCurDir, &si, &pi);
					}
					else if (!klstricmp(curCommand, _T("/interactive")))
					{
						b = CreateProcessInteractive((DWORD)-1, NULL, opt.runCommand.ms_Val, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL,
							szCurDir, &si, &pi, &nErr);
						bFromScheduler = true;
					}
					else // -bypass, -apparent
					{
						b = CreateProcess(NULL, opt.runCommand.ms_Val, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL,
							NULL, &si, &pi);
						nErr = b ? 0 : GetLastError();
						bFromScheduler = true;
					}

					// Log the result
					{
						CEStr lsLog; wchar_t szExtra[32] = L"";
						if (b)
						{
							if (pi.dwProcessId)
								_wsprintf(szExtra, SKIPCOUNT(szExtra) L", PID=%u", pi.dwProcessId);
							lsLog = lstrmerge(
								L"Process was created successfully",
								szExtra);
						}
						else
						{
							_wsprintf(szExtra, SKIPCOUNT(szExtra) L", ErrorCode=%u", nErr);
							lsLog = lstrmerge(
								L"Failed to start process",
								szExtra);
						}
						LogString(lsLog);
					}

					// If the error was not shown yet
					if (nErr) DisplayLastError(opt.runCommand, nErr);

					// if we were started from TaskScheduler, it would be nice to wait a little
					// to let parent (creator of the scheduler task) know we were started successfully
					if (bFromScheduler)
					{
						LogString(L"Sleeping for 5 seconds");
						Sleep(5*1000);
					}

					// Success?
					if (b)
					{
						iResult = 0;
					}

					// Done, close handles, if they were opened
					SafeCloseHandle(pi.hProcess);
					SafeCloseHandle(pi.hThread);

					goto wrap;
				}
				else if (!klstricmp(curCommand, _T("/multi")))
				{
					gpConEmu->AppendExtraArgs(curCommand);
					gpConEmu->opt.MultiConValue = true;
				}
				else if (!klstricmp(curCommand, _T("/nomulti")))
				{
					gpConEmu->AppendExtraArgs(curCommand);
					gpConEmu->opt.MultiConValue = false;
				}
				else if (!klstricmp(curCommand, _T("/visible")))
				{
					gpConEmu->opt.VisValue = true;
				}
				else if (!klstricmp(curCommand, _T("/ct")) || !klstricmp(curCommand, _T("/cleartype"))
					|| !klstricmp(curCommand, _T("/ct0")) || !klstricmp(curCommand, _T("/ct1")) || !klstricmp(curCommand, _T("/ct2")))
				{
					switch (curCommand[3])
					{
					case L'0':
						gpConEmu->opt.ClearTypeVal = NONANTIALIASED_QUALITY; break;
					case L'1':
						gpConEmu->opt.ClearTypeVal = ANTIALIASED_QUALITY; break;
					default:
						gpConEmu->opt.ClearTypeVal = CLEARTYPE_NATURAL_QUALITY;
					}
				}
				// Interface language
				else if (!klstricmp(curCommand, _T("/lng")))
				{
					NeedNextArg();

					if (!gpConEmu->opt.Language.Exists)
					{
						gpConEmu->opt.Language = curCommand;
						gpConEmu->AppendExtraArgs(L"/lng", curCommand);
					}
				}
				// Optional specific "ConEmu.l10n"
				else if (!klstricmp(curCommand, _T("/lngfile")))
				{
					NeedNextArg();

					if (!gpConEmu->opt.LanguageFile.Exists)
					{
						gpConEmu->opt.LanguageFile = curCommand;
						gpConEmu->AppendExtraArgs(L"/lngfile", curCommand);
					}
				}
				// имя шрифта
				else if (!klstricmp(curCommand, _T("/font")))
				{
					NeedNextArg();

					if (!gpConEmu->opt.FontVal.Exists)
					{
						gpConEmu->opt.FontVal = curCommand;
						gpConEmu->AppendExtraArgs(L"/font", curCommand);
					}
				}
				// Высота шрифта
				else if (!klstricmp(curCommand, _T("/size")))
				{
					NeedNextArg();

					if (!gpConEmu->opt.SizeVal.Exists)
					{
						gpConEmu->opt.SizeVal.SetInt(curCommand);
					}
				}
				// ADD fontname; by Mors
				else if (!klstricmp(curCommand, _T("/fontfile")))
				{
					CESwitch szFile(sw_Str);
					if (!GetCfgParm(cmdLineRest, szFile, MAX_PATH))
					{
						goto wrap;
					}
					gpConEmu->AppendExtraArgs(L"/fontfile", szFile.GetStr());
					gpFontMgr->RegisterFont(szFile.GetStr(), TRUE);
				}
				// Register all fonts from specified directory
				else if (!klstricmp(curCommand, _T("/fontdir")))
				{
					CESwitch szDir(sw_Str);
					if (!GetCfgParm(cmdLineRest, szDir, MAX_PATH))
					{
						goto wrap;
					}
					gpConEmu->AppendExtraArgs(L"/fontdir", szDir.GetStr());
					gpFontMgr->RegisterFontsDir(szDir.GetStr());
				}
				else if (!klstricmp(curCommand, _T("/fs")))
				{
					gpConEmu->opt.WindowModeVal = wmFullScreen;
				}
				else if (!klstricmp(curCommand, _T("/max")))
				{
					gpConEmu->opt.WindowModeVal = wmMaximized;
				}
				else if (!klstricmp(curCommand, _T("/min"))
					|| !klstricmp(curCommand, _T("/mintsa"))
					|| !klstricmp(curCommand, _T("/starttsa")))
				{
					gpConEmu->WindowStartMinimized = true;
					if (klstricmp(curCommand, _T("/min")) != 0)
					{
						gpConEmu->WindowStartTsa = true;
						gpConEmu->WindowStartNoClose = (klstricmp(curCommand, _T("/mintsa")) == 0);
					}
				}
				else if (!klstricmp(curCommand, _T("/tsa")) || !klstricmp(curCommand, _T("/tray")))
				{
					gpConEmu->ForceMinimizeToTray = true;
				}
				else if (!klstricmp(curCommand, _T("/detached")))
				{
					gpConEmu->m_StartDetached = crb_On;
				}
				else if (!klstricmp(curCommand, _T("/here")))
				{
					gpConEmu->mb_ConEmuHere = true;
					gpConEmu->StoreWorkDir();
				}
				else if (!klstricmp(curCommand, _T("/update")))
				{
					gpConEmu->opt.AutoUpdateOnStart = true;
				}
				else if (!klstricmp(curCommand, _T("/noupdate")))
				{
					// This one has more weight than AutoUpdateOnStart
					gpConEmu->opt.DisableAutoUpdate = true;
				}
				else if (!klstricmp(curCommand, _T("/nokeyhook"))
					|| !klstricmp(curCommand, _T("/nokeyhooks"))
					|| !klstricmp(curCommand, _T("/nokeybhook"))
					|| !klstricmp(curCommand, _T("/nokeybhooks")))
				{
					gpConEmu->DisableKeybHooks = true;
				}
				else if (!klstricmp(curCommand, _T("/nocloseconfirm")))
				{
					gpConEmu->DisableCloseConfirm = true;
				}
				else if (!klstricmp(curCommand, _T("/nomacro")))
				{
					gpConEmu->DisableAllMacro = true;
				}
				else if (!klstricmp(curCommand, _T("/nohotkey"))
					|| !klstricmp(curCommand, _T("/nohotkeys")))
				{
					gpConEmu->DisableAllHotkeys = true;
				}
				else if (!klstricmp(curCommand, _T("/nodeftrm"))
					|| !klstricmp(curCommand, _T("/nodefterm")))
				{
					gpConEmu->DisableSetDefTerm = true;
				}
				else if (!klstricmp(curCommand, _T("/noregfont"))
					|| !klstricmp(curCommand, _T("/noregfonts")))
				{
					gpConEmu->DisableRegisterFonts = true;
				}
				else if (!klstricmp(curCommand, _T("/inside"))
					|| !lstrcmpni(curCommand, _T("/inside="), 8))
				{
					bool bRunAsAdmin = isPressed(VK_SHIFT);
					bool bSyncDir = false;
					LPCWSTR pszSyncFmt = NULL;

					gpConEmu->mb_ConEmuHere = true;
					gpConEmu->StoreWorkDir();

					if (curCommand[7] == _T('='))
					{
						bSyncDir = true;
						pszSyncFmt = curCommand+8; // \eCD /d %1 - \e - ESC, \b - BS, \n - ENTER, %1 - "dir", %2 - "bash dir"
					}

					CConEmuInside::InitInside(bRunAsAdmin, bSyncDir, pszSyncFmt, 0, NULL);
				}
				else if (!klstricmp(curCommand, _T("/insidepid")))
				{
					NeedNextArg();

					bool bRunAsAdmin = isPressed(VK_SHIFT);

					wchar_t* pszEnd;
					// Здесь указывается PID, в который нужно внедриться.
					DWORD nInsideParentPID = wcstol(curCommand, &pszEnd, 10);
					if (nInsideParentPID)
					{
						CConEmuInside::InitInside(bRunAsAdmin, false, NULL, nInsideParentPID, NULL);
					}
				}
				else if (!klstricmp(curCommand, _T("/insidewnd")))
				{
					NeedNextArg();

					if (curCommand[0] == L'0' && (curCommand[1] == L'x' || curCommand[1] == L'X'))
						curCommand += 2;
					else if (curCommand[0] == L'x' || curCommand[0] == L'X')
						curCommand ++;

					bool bRunAsAdmin = isPressed(VK_SHIFT);

					wchar_t* pszEnd;
					// Здесь указывается HWND, в котором нужно создаваться.
					HWND hParent = (HWND)(DWORD_PTR)wcstoul(curCommand, &pszEnd, 16);
					if (hParent && IsWindow(hParent))
					{
						CConEmuInside::InitInside(bRunAsAdmin, false, NULL, 0, hParent);
					}
				}
				else if (!klstricmp(curCommand, _T("/icon")))
				{
					NeedNextArg();

					if (!gpConEmu->opt.IconPrm.Exists && *curCommand)
					{
						gpConEmu->opt.IconPrm = true;
						gpConEmu->mps_IconPath = ExpandEnvStr(curCommand);
					}
				}
				else if (!klstricmp(curCommand, _T("/dir")))
				{
					NeedNextArg();

					if (*curCommand)
					{
						// Например, "%USERPROFILE%"
						wchar_t* pszExpand = NULL;
						if (wcschr(curCommand, L'%') && ((pszExpand = ExpandEnvStr(curCommand)) != NULL))
						{
							gpConEmu->StoreWorkDir(pszExpand);
							SafeFree(pszExpand);
						}
						else
						{
							gpConEmu->StoreWorkDir(curCommand);
						}
					}
				}
				else if (!klstricmp(curCommand, _T("/updatejumplist")))
				{
					// Copy current Task list to Win7 Jump list (Taskbar icon)
					gpConEmu->mb_UpdateJumpListOnStartup = true;
				}
				else if (!klstricmp(curCommand, L"/log") || !klstricmp(curCommand, L"/log0")
					|| !klstricmp(curCommand, L"/log1") || !klstricmp(curCommand, L"/log2")
					|| !klstricmp(curCommand, L"/log3") || !klstricmp(curCommand, L"/log4"))
				{
					if (!klstricmp(curCommand, L"/log") || !klstricmp(curCommand, L"/log0"))
						gpConEmu->opt.AdvLogging.SetInt(1);
					else
						gpConEmu->opt.AdvLogging.SetInt((BYTE)(curCommand[4] - L'0')); // 1..4
					// Do create logging service
					DEBUGSTRSTARTUP(L"Creating log file");
					gpConEmu->CreateLog();
				}
				else if (!klstricmp(curCommand, _T("/single")) || !klstricmp(curCommand, _T("/reuse")))
				{
					// "/reuse" switch to be remastered
					gpConEmu->AppendExtraArgs(curCommand);
					gpSetCls->SingleInstanceArg = sgl_Enabled;
				}
				else if (!klstricmp(curCommand, _T("/nosingle")))
				{
					gpConEmu->AppendExtraArgs(curCommand);
					gpSetCls->SingleInstanceArg = sgl_Disabled;
				}
				else if (!klstricmp(curCommand, _T("/DesktopMode")))
				{
					gpConEmu->opt.DesktopMode = true;
				}
				else if (!klstricmp(curCommand, _T("/quake"))
					|| !klstricmp(curCommand, _T("/quakeauto"))
					|| !klstricmp(curCommand, _T("/noquake")))
				{
					if (!klstricmp(curCommand, _T("/quake")))
						gpConEmu->opt.QuakeMode = 1;
					else if (!klstricmp(curCommand, _T("/quakeauto")))
						gpConEmu->opt.QuakeMode = 2;
					else
					{
						gpConEmu->opt.QuakeMode = 0;
						if (gpSetCls->SingleInstanceArg == sgl_Default)
							gpSetCls->SingleInstanceArg = sgl_Disabled;
					}
				}
				else if (!klstricmp(curCommand, _T("/showhide")) || !klstricmp(curCommand, _T("/showhideTSA")))
				{
					gpSetCls->SingleInstanceArg = sgl_Enabled;
					gpSetCls->SingleInstanceShowHide = !klstricmp(curCommand, _T("/showhide"))
						? sih_ShowMinimize : sih_ShowHideTSA;
				}
				else if (!klstricmp(curCommand, _T("/reset"))
					|| !klstricmp(curCommand, _T("/resetdefault"))
					|| !klstricmp(curCommand, _T("/basic")))
				{
					gpConEmu->opt.ResetSettings = true;
					if (!klstricmp(curCommand, _T("/resetdefault")))
					{
						gpSetCls->isFastSetupDisabled = true;
					}
					else if (!klstricmp(curCommand, _T("/basic")))
					{
						gpSetCls->isFastSetupDisabled = true;
						gpSetCls->isResetBasicSettings = true;
					}
				}
				else if (!klstricmp(curCommand, _T("/nocascade"))
					|| !klstricmp(curCommand, _T("/dontcascade")))
				{
					gpConEmu->AppendExtraArgs(curCommand);
					gpSetCls->isDontCascade = true;
				}
				else if (!klstricmp(curCommand, _T("/WndX")) || !klstricmp(curCommand, _T("/WndY"))
					|| !klstricmp(curCommand, _T("/WndW")) || !klstricmp(curCommand, _T("/WndWidth"))
					|| !klstricmp(curCommand, _T("/WndH")) || !klstricmp(curCommand, _T("/WndHeight")))
				{
					TCHAR ch = curCommand[4];
					CharUpperBuff(&ch, 1);

					CESwitch psz(sw_Str); bool bParm = false;
					if (!GetCfgParm(cmdLineRest, bParm, psz, 32))
					{
						goto wrap;
					}
					gpConEmu->opt.SizePosPrm = true;

					// Direct X/Y implies /nocascade
					if (ch == _T('X') || ch == _T('Y'))
					{
						// TODO: isDontCascade must be in our opt struct !!!
						gpSetCls->isDontCascade = true;
					}

					switch (ch)
					{
					case _T('X'): gpConEmu->opt.sWndX.SetStr(psz.Str, sw_Str); break;
					case _T('Y'): gpConEmu->opt.sWndY.SetStr(psz.Str, sw_Str); break;
					case _T('W'): gpConEmu->opt.sWndW.SetStr(psz.Str, sw_Str); break;
					case _T('H'): gpConEmu->opt.sWndH.SetStr(psz.Str, sw_Str); break;
					}
				}
				else if (!klstricmp(curCommand, _T("/Monitor")))
				{
					CESwitch psz(sw_Str); bool bParm = false;
					if (!GetCfgParm(cmdLineRest, bParm, psz, 64))
					{
						goto wrap;
					}

					if ((gpConEmu->opt.Monitor.Mon = MonitorFromParam(psz.Str)) != NULL)
					{
						gpConEmu->opt.Monitor.Exists = true;
						gpConEmu->opt.Monitor.Type = sw_Int;
						gpStartEnv->hStartMon = gpConEmu->opt.Monitor.Mon;
					}
				}
				else if (!klstricmp(curCommand, _T("/Buffer")) || !klstricmp(curCommand, _T("/BufferHeight")))
				{
					NeedNextArg();

					if (!gpConEmu->opt.BufferHeightVal.Exists)
					{
						gpConEmu->opt.BufferHeightVal.SetInt(curCommand);

						if (gpConEmu->opt.BufferHeightVal.GetInt() < 0)
						{
							//setParent = true; -- Maximus5 - нефиг, все ручками
							gpConEmu->opt.BufferHeightVal = -gpConEmu->opt.BufferHeightVal.GetInt();
						}

						if (gpConEmu->opt.BufferHeightVal.GetInt() < LONGOUTPUTHEIGHT_MIN)
							gpConEmu->opt.BufferHeightVal = LONGOUTPUTHEIGHT_MIN;
						else if (gpConEmu->opt.BufferHeightVal.GetInt() > LONGOUTPUTHEIGHT_MAX)
							gpConEmu->opt.BufferHeightVal = LONGOUTPUTHEIGHT_MAX;
					}
				}
				else if (!klstricmp(curCommand, _T("/Config")))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.ConfigVal, 127))
					{
						goto wrap;
					}
				}
				else if (!klstricmp(curCommand, _T("/Palette")))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.PaletteVal, MAX_PATH))
					{
						goto wrap;
					}
				}
				else if (!klstricmp(curCommand, _T("/LoadRegistry")))
				{
					gpConEmu->AppendExtraArgs(curCommand);
					gpConEmu->opt.ForceUseRegistryPrm = true;
				}
				else if (!klstricmp(curCommand, _T("/LoadCfgFile")) || !klstricmp(curCommand, _T("/LoadXmlFile")))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.LoadCfgFile, MAX_PATH, true))
					{
						goto wrap;
					}
				}
				else if (!klstricmp(curCommand, _T("/SaveCfgFile")) || !klstricmp(curCommand, _T("/SaveXmlFile")))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.SaveCfgFile, MAX_PATH, true))
					{
						goto wrap;
					}
				}
				else if (!klstricmp(curCommand, _T("/GuiMacro")))
				{
					// -- выполняется только последний
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.ExecGuiMacro, 0x8000, false))
					{
						goto wrap;
					}
				}
				else if (!klstricmp(curCommand, _T("/UpdateSrcSet")))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.UpdateSrcSet, MAX_PATH*4, false))
					{
						goto wrap;
					}
				}
				else if (!klstricmp(curCommand, _T("/AnsiLog")))
				{
					// -- используем последний из параметров, если их несколько
					if (!GetCfgParm(cmdLineRest, gpConEmu->opt.AnsiLogPath, MAX_PATH-40, true))
					{
						goto wrap;
					}
				}
				else if (!klstricmp(curCommand, _T("/SetDefTerm")))
				{
					gpConEmu->opt.SetUpDefaultTerminal = true;
				}
				else if (!klstricmp(curCommand, _T("/ZoneId")))
				{
					gpConEmu->opt.FixZoneId = true;
				}
				else if (!klstricmp(curCommand, _T("/Exit")))
				{
					gpConEmu->opt.ExitAfterActionPrm = true;
				}
				else if (!klstricmp(curCommand, _T("/QuitOnClose")))
				{
					gpConEmu->mb_ForceQuitOnClose = true;
				}
				else if (!klstricmp(curCommand, _T("/Title")))
				{
					bool bOk = false;
					CESwitch pszTitle(sw_Str);
					if (!GetCfgParm(cmdLineRest, bOk, pszTitle, 127))
					{
						goto wrap;
					}
					gpConEmu->SetTitleTemplate(pszTitle.GetStr());
				}
				else if (!klstricmp(curCommand, _T("/FindBugMode")))
				{
					gpConEmu->mb_FindBugMode = true;
				}
				else if (!klstricmp(curCommand, _T("/debug"))
					|| !klstricmp(curCommand, _T("/debugw"))
					|| !klstricmp(curCommand, _T("/debugi")))
				{
					// These switches were already processed
				}
				else if (!klstricmp(curCommand, _T("/?")) || !klstricmp(curCommand, _T("/h")) || !klstricmp(curCommand, _T("/help")))
				{
					if (gpLng) gpLng->Reload();
					ConEmuAbout::OnInfo_About();
					iResult = -1;
					goto wrap;
				}
				// Final `-cmd ...` or `-cmdlist ...`
				else if (
					!klstricmp(curCommand, _T("/cmd"))
					|| !klstricmp(curCommand, _T("/cmdlist"))
					)
				{
					if (opt.cfgSwitches.ms_Val)
					{
						_ASSERTE(pszArgStart>pszCopyToEnvStart);
						_ASSERTE((INT_PTR)(pszArgStart - pszCopyToEnvStart) <= opt.cfgSwitches.GetLen());
						opt.cfgSwitches.ms_Val[pszArgStart - pszCopyToEnvStart] = 0;
					}

					opt.runCommand.Set(SkipNonPrintable(cmdLineRest));
					opt.isScript = (klstricmp(curCommand, L"/cmdlist") == 0);
					break;
				}
				else
				{
					// Show error on unknown switch
					psUnknown = pszArgStart;
					break;
				}
			} // (*curCommand == L'/')

			// Avoid assertions in NextArg
			szArg.Empty(); szNext.Empty();
		} // while (NextArg(&cmdLineRest, szArg, &pszArgStart) == 0)
	}
	// Processing loop end

	if (psUnknown)
	{
		DEBUGSTRSTARTUP(L"Unknown switch, exiting!");
		if (gpSet->isLogging())
		{
			// For direct logging we do not use lng resources
			CEStr lsLog(L"\r\n", L"Unknown switch specified: ", psUnknown, L"\r\n\r\n");
			gpConEmu->LogString(lsLog, false, false);
		}

		CEStr szNewConWarn;
		LPCWSTR pszTestSwitch =
			(psUnknown[0] == L'-' || psUnknown[0] == L'/')
				? ((psUnknown[1] == L'-' || psUnknown[1] == L'/')
					? (psUnknown+2) : (psUnknown+1))
				: psUnknown;
		if ((lstrcmpni(pszTestSwitch, L"new_console", 11) == 0)
			|| (lstrcmpni(pszTestSwitch, L"cur_console", 11) == 0))
		{
			szNewConWarn = lstrmerge(L"\r\n\r\n",
				CLngRc::getRsrc(lng_UnknownSwitch4/*"Switch -new_console must be specified *after* /cmd or /cmdlist"*/)
				);
		}

		CEStr lsMsg(
			CLngRc::getRsrc(lng_UnknownSwitch1/*"Unknown switch specified:"*/),
			L"\r\n\r\n",
			psUnknown,
			szNewConWarn,
			L"\r\n\r\n",
			CLngRc::getRsrc(lng_UnknownSwitch2/*"Visit website to get thorough switches description:"*/),
			L"\r\n"
			CEGUIARGSPAGE
			L"\r\n\r\n",
			CLngRc::getRsrc(lng_UnknownSwitch3/*"Or run ‘ConEmu.exe -?’ to get the brief."*/)
			);

		MBoxA(lsMsg);
		goto wrap;
	}

	// Set "ConEmuArgs" and "ConEmuArgs2"
	ProcessConEmuArgsVar();

	// Continue normal startup
	bRc = true;
wrap:
	return bRc;
}
Example #22
0
/*****************************************************************************
 * CKsIrpTarget::SynchronizedIoctl()
 *****************************************************************************
 *//*!
 * @brief
 * Synchronized I/O control.
 * @param
 * Handle The file handle to send the I/O control to.
 * @param
 * CtlCode The I/O control code to send.
 * @param
 * InputBuffer Pointer to the input buffer.
 * @param
 * InputBufferSize Size in bytes of the input buffer.
 * @param
 * OutputBuffer Pointer to the output buffer.
 * @param
 * OutputBufferSize Size in bytes of the output buffer.
 * @param
 * OutBytesReturned The number of bytes written to the output buffer.
 * @return
 * Returns S_OK on success, otherwise appropriate error code.
 */
HRESULT 
CKsIrpTarget::
SynchronizedIoctl
(
	IN		HANDLE	Handle,
	IN		ULONG	CtlCode,
	IN		PVOID	InputBuffer,
	IN		ULONG	InputBufferSize,
	OUT		PVOID	OutputBuffer,
	OUT		ULONG	OutputBufferSize,
	OUT		ULONG *	OutBytesReturned
)
{
    HRESULT hr = S_OK;

    ULONG BytesReturned;

    if (!OutBytesReturned)
    {
        OutBytesReturned = &BytesReturned;
    }

    if (!IsValidHandle(Handle))
    {
        hr = E_FAIL;

		_DbgPrintF(DEBUGLVL_ERROR,("[CKsIrpTarget::SynchronizedIoctl] - Invalid Handle"));
    }
    
    OVERLAPPED Overlapped;

	if (SUCCEEDED(hr))
    {
        ZeroMemory(&Overlapped, sizeof(OVERLAPPED));

        Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

        if (Overlapped.hEvent)
        {
            // Flag the event by setting the low-order bit so we
            // don't get completion port notifications.
            // Really! - see the description of the lpOverlapped parameter in
            // the docs for GetQueuedCompletionStatus
            Overlapped.hEvent = (HANDLE)((DWORD_PTR)Overlapped.hEvent | 0x1);
        }
        else
        {
            hr = E_OUTOFMEMORY;

			_DbgPrintF(DEBUGLVL_ERROR,("[CKsIrpTarget::SynchronizedIoctl] - CreateEvent failed"));
        }
    }

    if (SUCCEEDED(hr))
    {
        BOOL Result = DeviceIoControl(Handle, CtlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, OutBytesReturned, &Overlapped);

        if (!Result)
        {
            DWORD w32Error = GetLastError();

            if (ERROR_IO_PENDING == w32Error)
            {
                // Wait for completion
                DWORD Wait = ::WaitForSingleObject(Overlapped.hEvent, INFINITE);

                ASSERT(WAIT_OBJECT_0 == Wait);

                if (Wait != WAIT_OBJECT_0)
                {
                    hr = E_FAIL;

					_DbgPrintF(DEBUGLVL_ERROR,("[CKsIrpTarget::SynchronizedIoctl] - WaitForSingleObject failed Wait: 0x%08x", Wait));
                }
            }
            else if (((ERROR_INSUFFICIENT_BUFFER == w32Error) || (ERROR_MORE_DATA == w32Error)) &&
					 (IOCTL_KS_PROPERTY == CtlCode) &&
					 (OutputBufferSize == 0))
            {
                hr = S_OK;

                Result = TRUE;
            }
            else
            {
                hr = E_FAIL;
            }
        }

        if (!Result) 
		{
			*OutBytesReturned = 0;
		}

        SafeCloseHandle(Overlapped.hEvent);
    }
    
    return hr;
}
Example #23
0
static void FreeWatchedDir(WatchedDir *wd)
{
    free(wd->dirPath);
    SafeCloseHandle(wd->hDir);
    free(wd);
}
Example #24
0
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int retCode = 1;    // by default it's error

#ifdef DEBUG
    // Memory leak detection (only enable _CRTDBG_LEAK_CHECK_DF for
    // regular termination so that leaks aren't checked on exceptions,
    // aborts, etc. where some clean-up might not take place)
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF);
    //_CrtSetBreakAlloc(421);
    TryLoadMemTrace();
#endif

    DisableDataExecution();
    // ensure that C functions behave consistently under all OS locales
    // (use Win32 functions where localized input or output is desired)
    setlocale(LC_ALL, "C");
    // don't show system-provided dialog boxes when accessing files on drives
    // that are not mounted (e.g. a: drive without floppy or cd rom drive
    // without a cd).
    SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);

#if defined(DEBUG) || defined(SVN_PRE_RELEASE_VER)
    if (str::StartsWith(lpCmdLine, "/tester")) {
        extern int TesterMain(); // in Tester.cpp
        return TesterMain();
    }

    if (str::StartsWith(lpCmdLine, "/regress")) {
        extern int RegressMain(); // in Regress.cpp
        return RegressMain();
    }
#endif
#ifdef SUPPORTS_AUTO_UPDATE
    if (str::StartsWith(lpCmdLine, "-autoupdate")) {
        bool quit = AutoUpdateMain();
        if (quit)
            return 0;
    }
#endif

    srand((unsigned int)time(NULL));

    // load uiautomationcore.dll before installing crash handler (i.e. initializing
    // dbghelp.dll), so that we get function names/offsets in GetCallstack()
    uia::Initialize();
#ifdef DEBUG
    dbghelp::RememberCallstackLogs();
#endif

    SetupCrashHandler();

    ScopedOle ole;
    InitAllCommonControls();
    ScopedGdiPlus gdiPlus(true);
    mui::Initialize();
    uitask::Initialize();

    prefs::Load();

    CommandLineInfo i(GetCommandLine());

    SetCurrentLang(i.lang ? i.lang : gGlobalPrefs->uiLanguage);

    // This allows ad-hoc comparison of gdi, gdi+ and gdi+ quick when used
    // in layout
#if 0
    RedirectIOToConsole();
    BenchEbookLayout(L"C:\\kjk\\downloads\\pg12.mobi");
    system("pause");
    goto Exit;
#endif

    if (i.showConsole) {
        RedirectIOToConsole();
        RedirectDllIOToConsole();
    }
    if (i.makeDefault)
        AssociateExeWithPdfExtension();
    if (i.pathsToBenchmark.Count() > 0) {
        BenchFileOrDir(i.pathsToBenchmark);
        if (i.showConsole)
            system("pause");
    }
    if (i.exitImmediately)
        goto Exit;
    gCrashOnOpen = i.crashOnOpen;

    gPolicyRestrictions = GetPolicies(i.restrictedUse);
    GetFixedPageUiColors(gRenderCache.textColor, gRenderCache.backgroundColor);
    DebugGdiPlusDevice(gUseGdiRenderer);

    if (!RegisterWinClass())
        goto Exit;

    CrashIf(hInstance != GetModuleHandle(NULL));
    if (!InstanceInit(nCmdShow))
        goto Exit;

    if (i.hwndPluginParent) {
        if (!SetupPluginMode(i))
            goto Exit;
    }

    if (i.printerName) {
        // note: this prints all PDF files. Another option would be to
        // print only the first one
        for (size_t n = 0; n < i.fileNames.Count(); n++) {
            bool ok = PrintFile(i.fileNames.At(n), i.printerName, !i.silent, i.printSettings);
            if (!ok)
                retCode++;
        }
        --retCode; // was 1 if no print failures, turn 1 into 0
        goto Exit;
    }

    bool showStartPage = i.fileNames.Count() == 0 && gGlobalPrefs->rememberOpenedFiles && gGlobalPrefs->showStartPage;
    if (showStartPage) {
        // make the shell prepare the image list, so that it's ready when the first window's loaded
        SHFILEINFO sfi;
        SHGetFileInfo(L".pdf", 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);
    }

    if (gGlobalPrefs->reopenOnce) {
        WStrVec moreFileNames;
        ParseCmdLine(gGlobalPrefs->reopenOnce, moreFileNames);
        moreFileNames.Reverse();
        for (WCHAR **fileName = moreFileNames.IterStart(); fileName; fileName = moreFileNames.IterNext()) {
            i.fileNames.Append(*fileName);
        }
        moreFileNames.RemoveAt(0, moreFileNames.Count());
        str::ReplacePtr(&gGlobalPrefs->reopenOnce, NULL);
    }

    HANDLE hMutex = NULL;
    HWND hPrevWnd = NULL;
    if (i.printDialog || i.stressTestPath || gPluginMode) {
        // TODO: pass print request through to previous instance?
    }
    else if (i.reuseDdeInstance) {
        hPrevWnd = FindWindow(FRAME_CLASS_NAME, NULL);
    }
    else if (gGlobalPrefs->reuseInstance || gGlobalPrefs->useTabs) {
        hPrevWnd = FindPrevInstWindow(&hMutex);
    }
    if (hPrevWnd) {
        for (size_t n = 0; n < i.fileNames.Count(); n++) {
            OpenUsingDde(hPrevWnd, i.fileNames.At(n), i, 0 == n);
        }
        goto Exit;
    }

    WindowInfo *win = NULL;
    for (size_t n = 0; n < i.fileNames.Count(); n++) {
        win = LoadOnStartup(i.fileNames.At(n), i, !win);
        if (!win) {
            retCode++;
            continue;
        }
        if (i.printDialog)
            OnMenuPrint(win, i.exitWhenDone);
    }
    if (i.fileNames.Count() > 0 && !win) {
        // failed to create any window, even though there
        // were files to load (or show a failure message for)
        goto Exit;
    }
    if (i.printDialog && i.exitWhenDone)
        goto Exit;

    if (!win) {
        win = CreateAndShowWindowInfo();
        if (!win)
            goto Exit;
    }

    UpdateUITextForLanguage(); // needed for RTL languages
    if (win->IsAboutWindow()) {
        // TODO: shouldn't CreateAndShowWindowInfo take care of this?
        UpdateToolbarAndScrollbarState(*win);
    }

    // Make sure that we're still registered as default,
    // if the user has explicitly told us to be
    if (gGlobalPrefs->associatedExtensions)
        RegisterForPdfExtentions(win->hwndFrame);

    if (i.stressTestPath) {
        // don't save file history and preference changes
        gPolicyRestrictions = (gPolicyRestrictions | Perm_RestrictedUse) & ~Perm_SavePreferences;
        RebuildMenuBarForWindow(win);
        StartStressTest(&i, win, &gRenderCache);
    }

    if (gGlobalPrefs->checkForUpdates)
        UpdateCheckAsync(win, true);

    // only hide newly missing files when showing the start page on startup
    if (showStartPage && gFileHistory.Get(0)) {
        gFileExistenceChecker = new FileExistenceChecker();
        gFileExistenceChecker->Start();
    }
    // call this once it's clear whether Perm_SavePreferences has been granted
    prefs::RegisterForFileChanges();

    retCode = RunMessageLoop();

    SafeCloseHandle(&hMutex);
    CleanUpThumbnailCache(gFileHistory);

Exit:
    prefs::UnregisterForFileChanges();

    while (gWindows.Count() > 0) {
        DeleteWindowInfo(gWindows.At(0));
    }

#ifndef DEBUG

    // leave all the remaining clean-up to the OS
    // (as recommended for a quick exit)
    ExitProcess(retCode);

#else

    DeleteObject(GetDefaultGuiFont());
    DeleteBitmap(gBitmapReloadingCue);
    DeleteSplitterBrush();

    // wait for FileExistenceChecker to terminate
    // (which should be necessary only very rarely)
    while (gFileExistenceChecker) {
        Sleep(10);
        uitask::DrainQueue();
    }

    mui::Destroy();
    uitask::Destroy();
    trans::Destroy();

    SaveCallstackLogs();
    dbghelp::FreeCallstackLogs();

    // must be after uitask::Destroy() because we might have queued prefs::Reload()
    // which crashes if gGlobalPrefs is freed
    gFileHistory.UpdateStatesSource(NULL);
    DeleteGlobalPrefs(gGlobalPrefs);

    // it's still possible to crash after this (destructors of static classes,
    // atexit() code etc.) point, but it's very unlikely
    UninstallCrashHandler();

    // output leaks after all destructors of static objects have run
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    return retCode;
#endif
}
Example #25
0
/**
 * @brief
 * 主要処理系のスレッドの初期化を行います。
 *
 * @param pContext
 * I4C3Dモジュールのコンテキストのポインタ。
 *
 * @returns
 * 初期化が成功しスレッドが実行できた場合にTRUE、失敗した場合にはFALSEを返します。
 *
 * 各種設定の読み込みや、主要処理系のスレッドの初期化を行います。
 * 失敗した場合はInitialize()でリソース解放処理が行われます。
 *
 * @see
 * Initialize()
 */
BOOL I4C3DCore::InitializeMainContext(I4C3DContext* pContext)
{
    USHORT uBridgePort = 0;

    // 設定ファイルよりSleepカウントを取得
    PCTSTR szSleepCount = pContext->pAnalyzer->GetGlobalValue(TAG_SLEEPCOUNT);
    if (szSleepCount == NULL || _stscanf_s(szSleepCount, _T("%d"), &g_sleepCount) != 1) {
        g_sleepCount = 1;
    }

    // 設定ファイルよりBridge Portを取得
    PCTSTR szPort = pContext->pAnalyzer->GetGlobalValue(TAG_PORT);
    if (szPort == NULL) {
        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_CFG_PORT), GetLastError(), g_FILE, __LINE__);
        I4C3DExit(EXIT_INVALID_FILE_CONFIGURATION);
        return FALSE;
    }
    if (_stscanf_s(szPort, _T("%hu"), &uBridgePort) != 1) {
        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_CFG_PORT), GetLastError(), g_FILE, __LINE__);
        I4C3DExit(EXIT_INVALID_FILE_CONFIGURATION);
        return FALSE;
    }

    // 設定ファイルより接続クライアント数を取得
    PCTSTR szBacklog = pContext->pAnalyzer->GetGlobalValue(TAG_BACKLOG);
    if (szBacklog == NULL || _stscanf_s(szBacklog, _T("%d"), &g_backlog) != 1) {
        g_backlog = 8;
    }
    g_ChildThreadInfoLimit = min(_countof(g_ChildThreadInfo), g_backlog);
    g_backlog *= 3;	// 全端末SYN2回まで失敗できるだけのバックログ

    // iPhone待ち受けソケット生成
    I4C3DAccessor accessor;
    pContext->receiver = accessor.InitializeTCPSocket(&pContext->address, NULL, FALSE, uBridgePort);
    if (pContext->receiver == INVALID_SOCKET) {
        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_SOCKET_INVALID), GetLastError(), g_FILE, __LINE__);
        I4C3DExit(EXIT_SOCKET_ERROR);
        return FALSE;
    }

    // 待ちうけ終了イベント作成
    pContext->hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (pContext->hStopEvent == NULL) {
        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
        closesocket(pContext->receiver);
        I4C3DExit(EXIT_SYSTEM_ERROR);
        return FALSE;
    }

    pContext->hThread = (HANDLE)_beginthreadex(NULL, 0, &I4C3DReceiveThreadProc, (void*)pContext, CREATE_SUSPENDED, NULL/*&pContext->uThreadID*/);
    if (pContext->hThread == INVALID_HANDLE_VALUE) {
        LoggingMessage(Log_Error, _T(MESSAGE_ERROR_HANDLE_INVALID), GetLastError(), g_FILE, __LINE__);
        SafeCloseHandle(pContext->hStopEvent);
        closesocket(pContext->receiver);
        I4C3DExit(EXIT_SYSTEM_ERROR);
        return FALSE;
    }

    ResumeThread(pContext->hThread);

    return TRUE;
}