Пример #1
0
int ToolRunner::Run_Capture(LPCTSTR command, LPCTSTR params, LPCTSTR dir)
{
	tstring clopts(_T("\"\" "));
	clopts.insert(1, command);
	clopts += params;

	if (!m_pWrapper->IsTextFilter())
	{
		tstring tempstr(clopts);
		tempstr.insert(0, _T("> "));
		tempstr += _T("\n");
		m_pWrapper->_AddToolOutput(tempstr.c_str());
	}

	if (_tcslen(dir) == 0)
		dir = NULL;

	OSVERSIONINFO osv = {sizeof(OSVERSIONINFO), 0, 0, 0, 0, _T("")};

	::GetVersionEx(&osv);
	bool bWin9x = osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS;
	
	SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), 0, 0};
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = NULL;

	SECURITY_DESCRIPTOR sd;
	if (!bWin9x)
	{
		// On NT we can have a proper security descriptor...
		::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
		::SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
		sa.lpSecurityDescriptor = &sd;
	}

	HANDLE hWritePipe, hReadPipe;
	HANDLE hStdInWrite, hStdInRead;
	
    if (!::CreatePipe(&hReadPipe, &hWritePipe, &sa, 0))
	{
		CLastErrorInfo lei;
		m_pWrapper->_AddToolOutput(_T("\n> Failed to create StdOut and StdErr Pipe: "));
		m_pWrapper->_AddToolOutput((LPCTSTR)lei);

		return lei.GetErrorCode();
	}

	// read handle, write handle, security attributes,  number of bytes reserved for pipe - 0 default
	
	if (!::CreatePipe(&hStdInRead, &hStdInWrite, &sa, 0))
	{
		CLastErrorInfo lei;

		m_pWrapper->_AddToolOutput(_T("\n> Failed to create StdIn Pipe: "));
		m_pWrapper->_AddToolOutput((LPCTSTR)lei);

		return lei.GetErrorCode();
	}

	::SetHandleInformation(hReadPipe, HANDLE_FLAG_INHERIT, 0);
	::SetHandleInformation(hStdInWrite, HANDLE_FLAG_INHERIT, 0);

	STARTUPINFO si;
	memset(&si, 0, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	si.wShowWindow = SW_HIDE;
	si.hStdInput = hStdInRead;
	si.hStdOutput = hWritePipe;
	si.hStdError = hWritePipe;

	PROCESS_INFORMATION pi = {0, 0, 0, 0};

	DWORD dwCreationFlags = CREATE_NEW_CONSOLE; // CREATE_NEW_PROCESS_GROUP;

	std::vector<TCHAR> cmdbuf(clopts.length() + 1);
	memcpy(&cmdbuf[0], clopts.c_str(), clopts.size() * sizeof(TCHAR));

	bool bCreated = ::CreateProcess(
		NULL, 
		&cmdbuf[0], 
		&sa, /*LPSECURITY_ATTRIBUTES lpProcessAttributes*/
		NULL, /*LPSECURITYATTRIBUTES lpThreadAttributes*/
		TRUE, /*BOOL bInheritHandles*/ 
		dwCreationFlags, /*DWORD dwCreationFlags*/
		NULL, /*LPVOID lpEnvironment*/
		dir, /*LPCTSTR lpWorkingDir*/
		&si, /*LPSTARTUPINFO lpStartupInfo*/
		&pi /*LPPROCESS_INFORMATION lpProcessInformation*/ 
	) != 0;

	if (!bCreated)
	{
		::CloseHandle(hReadPipe);
		::CloseHandle(hWritePipe);
		::CloseHandle(hStdInRead);
		::CloseHandle(hStdInWrite);

		CLastErrorInfo lei;
		m_pWrapper->_AddToolOutput(_T("\n> Failed to create process: "));
		m_pWrapper->_AddToolOutput((LPCTSTR)lei);

		return lei.GetErrorCode();
	}

	unsigned int dwBytesToWrite;
	unsigned char* stdinbuf;
	stdinbuf = m_pWrapper->GetStdIOBuffer(dwBytesToWrite);
	if (!dwBytesToWrite)
		stdinbuf = NULL;

	DWORD dwBytesAvail, dwBytesRead, exitCode, timeDeathDetected;
	dwBytesAvail = dwBytesRead = exitCode = timeDeathDetected = 0;
	DWORD dwBytesWritten = 0;
	bool bCompleted = false;
	BYTE buffer[TOOLS_BUFFER_SIZE];

	while (!bCompleted)
	{
		Sleep(50);

		if (dwBytesToWrite > 0)
		{
			// We have a filter (we think), so write the filter data into the stdin
			// of the process we started.
			DWORD dwWrote;
			::WriteFile(hStdInWrite, stdinbuf+dwBytesWritten, dwBytesToWrite, &dwWrote, NULL);
			dwBytesWritten += dwWrote;
			dwBytesToWrite -= dwWrote;
			
			if(dwBytesToWrite == 0)
			{
				// Now close stdin so that the filter doesn't wait forever for more data.
				::CloseHandle(hStdInWrite);
				hStdInWrite = NULL;
			}
		}

		//The PeekNamedPipe function copies data from a named or 
		// anonymous pipe into a buffer without removing it from the pipe.
		if (!::PeekNamedPipe(hReadPipe, NULL, 0, NULL, &dwBytesAvail, NULL) )
		{
			dwBytesAvail = 0;
		}

		if (dwBytesAvail > 0)
		{
			BOOL bRead = ::ReadFile(hReadPipe, buffer, sizeof(buffer)-1, &dwBytesRead, NULL);
			buffer[dwBytesRead] = NULL;

			if (bRead && dwBytesRead)
			{
				CA2CT conv(reinterpret_cast<const char*>(buffer));
				m_pWrapper->_AddToolOutput(&conv[0], -1);
			}
			else
			{
				// Couldn't read from the pipe, must be finished...
				bCompleted = true;
			}
		}
		else
		{
			exitCode = STILL_ACTIVE;

			// No data from the process, is it still active?
			::GetExitCodeProcess(pi.hProcess, &exitCode);
			if (STILL_ACTIVE != exitCode)
			{
				if (bWin9x)
				{
					// If we're running on Windows 9x then we give the
					// process some time to return the remainder of its data.
					// We wait until a pre-set amount of time has elapsed and
					// then exit.

					if (timeDeathDetected == 0)
					{
						timeDeathDetected = ::GetTickCount();
					}
					else
					{
						///@todo Get this value from the registry...
						if ((::GetTickCount() - timeDeathDetected) > 500)
						{
							bCompleted = true;
						}
					}
				}
				else
				{
					// If NT, then the process is already dead.
					bCompleted = true;
				}
			}
		}

		// While we're here, we check to see if we've been told to close.
		if (!GetCanRun())
		{
			if (WAIT_OBJECT_0 != ::WaitForSingleObject(pi.hProcess, 500)) 
			{
				// We should do this only if the GUI process is stuck and
				// don't answer to a normal termination command.
				// This function is dangerous: dependant DLLs don't know the process
				// is terminated, and memory isn't released.
				m_pWrapper->_AddToolOutput(_T("\n> Forcefully terminating process...\n"));
				::TerminateProcess(pi.hProcess, 1);
			}

			bCompleted = true;
		}
	} // while (!bCompleted)

	if (WAIT_OBJECT_0 != ::WaitForSingleObject(pi.hProcess, 1000)) 
	{
		m_pWrapper->_AddToolOutput(_T("\n> Process failed to respond; forcing abrupt termination..."));
		::TerminateProcess(pi.hProcess, 2);
	}

	::GetExitCodeProcess(pi.hProcess, &exitCode);

	m_RetCode = exitCode;

	::CloseHandle(pi.hProcess);
	::CloseHandle(pi.hThread);
	::CloseHandle(hReadPipe);
	::CloseHandle(hWritePipe);
	::CloseHandle(hStdInRead);
	
	if (hStdInWrite) // might already be closed
		::CloseHandle(hStdInWrite);

	return m_RetCode;
}
Пример #2
0
CString CCommonAppUtils::GetAppForFile
    ( const CString& fileName
    , const CString& extension
    , const CString& verb
    , bool applySecurityHeuristics)
{
    CString application;

    // normalize file path

    CString fullFileName = ExpandEnvironmentStrings (fileName);
    CString normalizedFileName = L"\"" + fullFileName + L"\"";

    // registry lookup

    CString extensionToUse = extension.IsEmpty()
        ? CPathUtils::GetFileExtFromPath (fullFileName)
        : extension;

    if (!extensionToUse.IsEmpty())
    {
        // lookup by verb

        CString documentClass;
        DWORD buflen = 0;
        AssocQueryString(ASSOCF_INIT_DEFAULTTOSTAR, ASSOCSTR_COMMAND, extensionToUse, verb, NULL, &buflen);
        std::unique_ptr<TCHAR[]> cmdbuf(new TCHAR[buflen + 1]);
        if (FAILED(AssocQueryString(ASSOCF_INIT_DEFAULTTOSTAR, ASSOCSTR_COMMAND, extensionToUse, verb, cmdbuf.get(), &buflen)))
        {
            documentClass = CRegString (extensionToUse + L"\\", L"", FALSE, HKEY_CLASSES_ROOT);

            CString key = documentClass + L"\\Shell\\" + verb + L"\\Command\\";
            application = CRegString (key, L"", FALSE, HKEY_CLASSES_ROOT);
        }
        else
        {
            application = cmdbuf.get();
        }

        // fallback to "open"

        if (application.IsEmpty())
        {
            buflen = 0;
            AssocQueryString(ASSOCF_INIT_DEFAULTTOSTAR, ASSOCSTR_COMMAND, extensionToUse, L"open", NULL, &buflen);
            std::unique_ptr<TCHAR[]> cmdopenbuf (new TCHAR[buflen + 1]);
            if (FAILED(AssocQueryString(ASSOCF_INIT_DEFAULTTOSTAR, ASSOCSTR_COMMAND, extensionToUse, L"open", cmdopenbuf.get(), &buflen)))
            {
                CString key = documentClass + L"\\Shell\\Open\\Command\\";
                application = CRegString (key, L"", FALSE, HKEY_CLASSES_ROOT);
            }
            else
            {
                application = cmdopenbuf.get();
            }
        }
    }

    // normalize application path

    application = ExpandEnvironmentStrings (application);

    // security heuristics:
    // some scripting languages (e.g. python) will execute the document
    // instead of open it. Try to identify these cases.

    if (applySecurityHeuristics)
    {
        if (   (application.Find (L"%2") >= 0)
            || (application.Find (L"%*") >= 0))
        {
            // consumes extra parameters
            // -> probably a script execution
            // -> retry with "open" verb or ask user

            if (verb.CompareNoCase (L"open") == 0)
                application.Empty();
            else
                return GetAppForFile ( fileName
                                     , extension
                                     , L"open"
                                     , true);
        }
    }

    // exit here, if we were not successful

    if (application.IsEmpty())
        return application;

    // resolve parameters

    if (application.Find (L"%1") < 0)
        application += L" %1";

    if (application.Find(L"\"%1\"") >= 0)
        application.Replace(L"\"%1\"", L"%1");

    application.Replace (L"%1", normalizedFileName);

    return application;
}
Пример #3
0
int ToolRunner::Run_NoCapture(LPCTSTR command, LPCTSTR params, LPCTSTR dir)
{
	int result = 0;

	tstring tempstr(_T("\"\" "));
	tempstr.insert(1, command);
	tempstr += params;

	if (_tcslen(dir) == 0)
		dir = NULL;

	OSVERSIONINFO osv = {sizeof(OSVERSIONINFO), 0, 0, 0, 0, _T("")};

	::GetVersionEx(&osv);
	bool bWin9x = osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS;
	
	SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), 0, 0};
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = NULL;

	SECURITY_DESCRIPTOR sd;
	if (!bWin9x)
	{
		// On NT we can have a proper security descriptor...
		::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
		::SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
		sa.lpSecurityDescriptor = &sd;
	}

	STARTUPINFO si;
	memset(&si, 0, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);

	PROCESS_INFORMATION pi = {0, 0, 0, 0};

	std::vector<TCHAR> cmdbuf(tempstr.length()+1);
	memcpy(&cmdbuf[0], tempstr.c_str(), tempstr.size() * sizeof(TCHAR));

	DWORD dwCreationFlags = CREATE_NEW_CONSOLE; // CREATE_NEW_PROCESS_GROUP - causes Ctrl-C to be disabled.

	bool bCreated = ::CreateProcess(
		NULL, 
		&cmdbuf[0], 
		&sa, /*LPSECURITY_ATTRIBUTES lpProcessAttributes*/
		NULL, /*LPSECURITYATTRIBUTES lpThreadAttributes*/
		TRUE, /*BOOL bInheritHandles*/ 
		dwCreationFlags, /*DWORD dwCreationFlags*/
		NULL, /*LPVOID lpEnvironment*/
		dir, /*LPCTSTR lpWorkingDir*/
		&si, /*LPSTARTUPINFO lpStartupInfo*/
		&pi /*LPPROCESS_INFORMATION lpProcessInformation*/ 
	) != 0;

	if (!bCreated)
	{
		CLastErrorInfo lei;
		m_pWrapper->_AddToolOutput(_T("\n> Failed to create process: "));
		m_pWrapper->_AddToolOutput((LPCTSTR)lei);

		return lei.GetErrorCode();
	}

	// We're waiting for this one to finish because it's a filter process - 
	// i.e. it will change the current file.
	if (m_pWrapper->IsFilter())
	{
		::WaitForSingleObject(pi.hProcess, INFINITE);
		DWORD dwExitCode;
		::GetExitCodeProcess(pi.hProcess, &dwExitCode);
		result = dwExitCode;
	}
	else
	{
		result = pi.dwProcessId;
	}
	
	// Detach...
	::CloseHandle(pi.hProcess);
	::CloseHandle(pi.hThread);

	PostRun();

	return result;
}