Example #1
0
/**
 * Perform an immediate command.  Takes parameters a la sprintf
 * Assumes final string will not overrun line[] length
 */
void Parser::command(const char *format, ...) {
	debugC(1, kDebugParser, "Command(%s, ...)", format);

	va_list marker;
	va_start(marker, format);
	vsprintf(_vm->_line, format, marker);
	va_end(marker);

	lineHandler();
}
CResourceCompilerHelper::ERcCallResult CResourceCompilerHelper::CallResourceCompiler(
	const char* szFileName, 
	const char* szAdditionalSettings, 
	IResourceCompilerListener* listener, 
	bool bMayShowWindow, 
	CResourceCompilerHelper::ERcExePath rcExePath, 
	bool bSilent,
	bool bNoUserDialog,
	const wchar_t* szWorkingDirectory,
	const wchar_t* szRootPath)
{
	// make command for execution
	SettingsManagerHelpers::CFixedString<wchar_t, MAX_PATH * 3> wRemoteCmdLine;
	CSettingsManagerTools smTools = CSettingsManagerTools();

	if (!szAdditionalSettings)
	{
		szAdditionalSettings = "";
	}

	wchar_t szRcDirectory[512];
	{
		wchar_t pathBuffer[512];
		switch (rcExePath)
		{
		case eRcExePath_registry:
			smTools.GetRootPathUtf16(true, SettingsManagerHelpers::CWCharBuffer(pathBuffer, sizeof(pathBuffer)));
			break;
		case eRcExePath_settingsManager:
			smTools.GetRootPathUtf16(false, SettingsManagerHelpers::CWCharBuffer(pathBuffer, sizeof(pathBuffer)));
			break;
		case eRcExePath_currentFolder:
			wcscpy(pathBuffer, L".");
			break;
		case eRcExePath_customPath:
			wcscpy(pathBuffer, szRootPath);
			break;
		default:
			return eRcCallResult_notFound;
		}

		if (!pathBuffer[0])
		{
			wcscpy(pathBuffer, L".");
		}

		if (smTools.Is64bitWindows() && (DirectoryExists(pathBuffer, L"/Bin64/rc") || !DirectoryExists(pathBuffer, L"/Bin32/rc")))
		{
			swprintf_s(szRcDirectory, L"%s/Bin64/rc", pathBuffer);
		}
		else
		{
			swprintf_s(szRcDirectory, L"%s/Bin32/rc", pathBuffer);
		}
	}

	wchar_t szRegSettingsBuffer[1024];
	smTools.GetEngineSettingsManager()->GetValueByRef("RC_Parameters", SettingsManagerHelpers::CWCharBuffer(szRegSettingsBuffer, sizeof(szRegSettingsBuffer)));

	wRemoteCmdLine.appendAscii("\"");
	wRemoteCmdLine.append(szRcDirectory);
	wRemoteCmdLine.appendAscii("/");
	wRemoteCmdLine.appendAscii(RC_EXECUTABLE);	
	wRemoteCmdLine.appendAscii("\"");

	if (!szFileName)
	{
		wRemoteCmdLine.appendAscii(" /userdialog=0 ");
		wRemoteCmdLine.appendAscii(szAdditionalSettings);
		wRemoteCmdLine.appendAscii(" ");
		wRemoteCmdLine.append(szRegSettingsBuffer);
	}
	else
	{
		wRemoteCmdLine.appendAscii(" \"");
		wRemoteCmdLine.appendAscii(szFileName);
		wRemoteCmdLine.appendAscii("\"");
		wRemoteCmdLine.appendAscii(bNoUserDialog ? " /userdialog=0 " : " /userdialog=1 ");
		wRemoteCmdLine.appendAscii(szAdditionalSettings);
		wRemoteCmdLine.appendAscii(" ");
		wRemoteCmdLine.append(szRegSettingsBuffer);
	}

	// Create a pipe to read the stdout of the RC.
	SECURITY_ATTRIBUTES saAttr;
	HANDLE hChildStdOutRd, hChildStdOutWr;
	HANDLE hChildStdInRd, hChildStdInWr;
	if (listener)
	{
		ZeroMemory(&saAttr, sizeof(saAttr));
		saAttr.bInheritHandle = TRUE;
		saAttr.lpSecurityDescriptor = 0;
		CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &saAttr, 0);
		SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN
		CreatePipe(&hChildStdInRd, &hChildStdInWr, &saAttr, 0);
		SetHandleInformation(hChildStdInWr, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN
	}

	STARTUPINFOW si;
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	si.dwX = 100;
	si.dwY = 100;
	if (listener)
	{
		si.hStdError = hChildStdOutWr;
		si.hStdOutput = hChildStdOutWr;
		si.hStdInput = hChildStdInRd;
		si.dwFlags = STARTF_USEPOSITION | STARTF_USESTDHANDLES;
	}
	else
	{
		si.dwFlags = STARTF_USEPOSITION;
	}

	PROCESS_INFORMATION pi;
	ZeroMemory(&pi, sizeof(pi));

	bool bShowWindow;
	if (bMayShowWindow)
	{
		wchar_t buffer[20];
		smTools.GetEngineSettingsManager()->GetValueByRef("ShowWindow", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer)));
		bShowWindow = (wcscmp(buffer, L"true") == 0);
	}
	else
	{
		bShowWindow = false;
	}

	const wchar_t* const szStartingDirectory = szWorkingDirectory ? szWorkingDirectory : szRcDirectory;

	if (!CreateProcessW(
		NULL,                   // No module name (use command line).
		const_cast<wchar_t*>(wRemoteCmdLine.c_str()), // Command line.
		NULL,                   // Process handle not inheritable.
		NULL,                   // Thread handle not inheritable.
		TRUE,                   // Set handle inheritance to TRUE.
		bShowWindow ? 0 : CREATE_NO_WINDOW, // creation flags.
		NULL,                   // Use parent's environment block.
		szStartingDirectory,    // Set starting directory.
		&si,                    // Pointer to STARTUPINFO structure.
		&pi))                   // Pointer to PROCESS_INFORMATION structure.
	{
		// The following  code block is commented out instead of being deleted 
		// because it's good to have at hand for a debugging session.







		if (!bSilent)
		{
			ShowMessageBoxRcNotFound(wRemoteCmdLine.c_str(), szStartingDirectory);
		}

		return eRcCallResult_notFound;
	}

	bool bFailedToReadOutput = false;

	if (listener)
	{
		// Close the pipe that writes to the child process, since we don't actually have any input for it.
		CloseHandle(hChildStdInWr);

		// Read all the output from the child process.
		CloseHandle(hChildStdOutWr);
		ResourceCompilerLineHandler lineHandler(listener);
		LineStreamBuffer lineBuffer(&lineHandler, &ResourceCompilerLineHandler::HandleLine);
		for (;;)
		{
			char buffer[2048];
			DWORD bytesRead;
			if (!ReadFile(hChildStdOutRd, buffer, sizeof(buffer), &bytesRead, NULL) || (bytesRead == 0))
			{
				break;
			}
			lineBuffer.HandleText(buffer, bytesRead);
		} 

		bFailedToReadOutput = lineBuffer.IsTruncated();
	}

	// Wait until child process exits.
	WaitForSingleObject(pi.hProcess, INFINITE);

	DWORD exitCode = eRcExitCode_Error;
	if (bFailedToReadOutput || GetExitCodeProcess(pi.hProcess, &exitCode) == 0)
	{
		exitCode = eRcExitCode_Error;
	}

	// Close process and thread handles. 
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	switch (exitCode)
	{
	case eRcExitCode_Success:
	case eRcExitCode_UserFixing:
		return eRcCallResult_success;
	case eRcExitCode_Crash:
		return eRcCallResult_crash;
	default:
		return eRcCallResult_error;
	}
}
CResourceCompilerHelper::ERcCallResult CResourceCompilerHelper::CallResourceCompiler(
	const TCHAR* szFileName, 
	const TCHAR* szAdditionalSettings, 
	IResourceCompilerListener* listener, 
	bool bMayShowWindow, 
	bool bUseQuota, 
	CResourceCompilerHelper::ERcExePath rcExePath, 
	bool bSilent,
	bool bNoUserDialog,
	const TCHAR *szWorkingDirectory)
{
	// make command for execution
	TCHAR szRemoteCmdLine[MAX_PATH*3];

	if (!szAdditionalSettings)
	{
		szAdditionalSettings = _T("");
	}

	tstring path;
	switch (rcExePath)
	{
	case eRcExePath_registry:
		path = GetRootPath(true);
		break;
	case eRcExePath_settingsManager:
		path = GetRootPath(false);
		break;
	case eRcExePath_currentFolder:
		path = _T(".");
		break;
	default:
		return eRcCallResult_notFound;
	}

	if (path.empty())
	{
		path = _T(".");
	}

	TCHAR szRemoteDirectory[512];
	_stprintf_s(szRemoteDirectory, _T("%s/Bin32/rc"), path.c_str());

	const TCHAR* const szHideCustom = ((g_pSettingsManager->GetValue<tstring>(_T("HideCustom"))==_T("true")) || bNoUserDialog) 
		? _T("") 
		: _T(" /userdialogcustom=0");

	if (!szFileName)
	{
		_stprintf_s(szRemoteCmdLine, _T("%s/rc.exe /userdialog=0 %s"), szRemoteDirectory, szAdditionalSettings);
	}
	else
	{
		const TCHAR* const szFormat = bUseQuota
			? _T("%s/rc.exe \"%s\" %s %s %s")
			: _T("%s/rc.exe %s %s %s %s");
		const TCHAR* const szUserDialog = bNoUserDialog
			? _T("/userdialog=0")
			: _T("/userdialog=1");
		_stprintf_s(szRemoteCmdLine, szFormat, szRemoteDirectory, szFileName, szUserDialog, szAdditionalSettings, szHideCustom);
	}

	// Create a pipe to read the stdout of the RC.
	SECURITY_ATTRIBUTES saAttr;
	std::memset(&saAttr, 0, sizeof(saAttr));
	saAttr.bInheritHandle = TRUE;
	saAttr.lpSecurityDescriptor = 0;
	HANDLE hChildStdOutRd, hChildStdOutWr;
	CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &saAttr, 0);
	SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN
	HANDLE hChildStdInRd, hChildStdInWr;
	CreatePipe(&hChildStdInRd, &hChildStdInWr, &saAttr, 0);
	SetHandleInformation(hChildStdInWr, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN

	STARTUPINFO si;
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	si.dwX = 100;
	si.dwY = 100;
	si.hStdError = hChildStdOutWr;
	si.hStdOutput = hChildStdOutWr;
	si.hStdInput = hChildStdInRd;
	si.dwFlags = STARTF_USEPOSITION | STARTF_USESTDHANDLES;

	PROCESS_INFORMATION pi;
	ZeroMemory(&pi, sizeof(pi));

	if (!CreateProcess(
		NULL,                   // No module name (use command line).
		szRemoteCmdLine,        // Command line.
		NULL,                   // Process handle not inheritable.
		NULL,                   // Thread handle not inheritable.
		TRUE,                   // Set handle inheritance to TRUE.
		bMayShowWindow && (g_pSettingsManager->GetValue<tstring>(_T("ShowWindow"))==_T("true"))?0:CREATE_NO_WINDOW, // creation flags.
		NULL,                   // Use parent's environment block.
		szWorkingDirectory?szWorkingDirectory:szRemoteDirectory,  // Set starting directory.
		&si,                    // Pointer to STARTUPINFO structure.
		&pi ))                  // Pointer to PROCESS_INFORMATION structure.
	{
		TCHAR szMessage[65535] = _T("");
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, szMessage, 65354, NULL);
		GetCurrentDirectory(65534, szMessage);
		if (!bSilent)
		{
			MessageBox(0,_T("ResourceCompiler was not found.\n\nPlease verify CryENGINE RootPath."),_T("Error"),MB_ICONERROR|MB_OK);
		}
		return eRcCallResult_notFound;
	}

	// Close the pipe that writes to the child process, since we don't actually have any input for it.
	CloseHandle(hChildStdInWr);

	// Read all the output from the child process.
	CloseHandle(hChildStdOutWr);
	ResourceCompilerLineHandler lineHandler(listener);
	LineStreamBuffer lineBuffer(&lineHandler, &ResourceCompilerLineHandler::HandleLine);
	for (;;)
	{
		char buffer[2048];
		DWORD bytesRead;
		if (!ReadFile(hChildStdOutRd, buffer, sizeof(buffer), &bytesRead, NULL) || (bytesRead == 0))
		{
			break;
		}
		lineBuffer.HandleText(buffer, bytesRead);
	} 

	// Wait until child process exits.
	WaitForSingleObject(pi.hProcess, INFINITE);

	bool ok = true;
	{
		DWORD exitCode = 1;
		if ((GetExitCodeProcess(pi.hProcess, &exitCode) == 0) || (exitCode != 0))
		{
			ok = false;
		}	
	}

	// Close process and thread handles. 
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	return ok ? eRcCallResult_success : eRcCallResult_error;
}
Example #4
0
CResourceCompilerHelper::ERcCallResult CResourceCompilerHelper::CallResourceCompiler(
	const char* szFileName, 
	const char* szAdditionalSettings, 
	IResourceCompilerListener* listener, 
	bool bMayShowWindow, 
	CResourceCompilerHelper::ERcExePath rcExePath, 
	bool bSilent,
	bool bNoUserDialog,
	const wchar_t* szWorkingDirectory,
	const wchar_t* szRootPath)
{
	// make command for execution
	SettingsManagerHelpers::CFixedString<wchar_t, MAX_PATH*3> wRemoteCmdLine;

	if (!szAdditionalSettings)
	{
		szAdditionalSettings = "";
	}

	wchar_t szRemoteDirectory[512];
	{
		wchar_t pathBuffer[512];
		switch (rcExePath)
		{
		case eRcExePath_registry:
			GetRootPathUtf16(true, SettingsManagerHelpers::CWCharBuffer(pathBuffer, sizeof(pathBuffer)));
			break;
		case eRcExePath_settingsManager:
			GetRootPathUtf16(false, SettingsManagerHelpers::CWCharBuffer(pathBuffer, sizeof(pathBuffer)));
			break;
		case eRcExePath_currentFolder:
			wcscpy(pathBuffer, L".");
			break;
		case eRcExePath_customPath:
			wcscpy(pathBuffer, szRootPath);
			break;
		default:
			return eRcCallResult_notFound;
		}

		if (!pathBuffer[0])
		{
			wcscpy(pathBuffer, L".");
		}

		swprintf_s(szRemoteDirectory, L"%s/Bin32/rc", pathBuffer);
	}

	if (!szFileName)
	{
		wRemoteCmdLine.appendAscii("\"");
		wRemoteCmdLine.append(szRemoteDirectory);
		wRemoteCmdLine.appendAscii("/rc.exe\" /userdialog=0 ");
		wRemoteCmdLine.appendAscii(szAdditionalSettings);
	}
	else
	{
		wRemoteCmdLine.appendAscii("\"");
		wRemoteCmdLine.append(szRemoteDirectory);
		wRemoteCmdLine.appendAscii("/rc.exe\" \"");
		wRemoteCmdLine.appendAscii(szFileName);
		wRemoteCmdLine.appendAscii("\" ");
		wRemoteCmdLine.appendAscii(bNoUserDialog ? "/userdialog=0 " : "/userdialog=1 ");
		wRemoteCmdLine.appendAscii(szAdditionalSettings);
	}

	// Create a pipe to read the stdout of the RC.
	SECURITY_ATTRIBUTES saAttr;
	::memset(&saAttr, 0, sizeof(saAttr));
	saAttr.bInheritHandle = TRUE;
	saAttr.lpSecurityDescriptor = 0;
	HANDLE hChildStdOutRd, hChildStdOutWr;
	CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &saAttr, 0);
	SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN
	HANDLE hChildStdInRd, hChildStdInWr;
	CreatePipe(&hChildStdInRd, &hChildStdInWr, &saAttr, 0);
	SetHandleInformation(hChildStdInWr, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN

	STARTUPINFOW si;
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	si.dwX = 100;
	si.dwY = 100;
	si.hStdError = hChildStdOutWr;
	si.hStdOutput = hChildStdOutWr;
	si.hStdInput = hChildStdInRd;
	si.dwFlags = STARTF_USEPOSITION | STARTF_USESTDHANDLES;

	PROCESS_INFORMATION pi;
	ZeroMemory(&pi, sizeof(pi));

	bool bShowWindow = false;
	{
		wchar_t buffer[20];
		g_pSettingsManager->GetValueByRef("ShowWindow", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer)));
		bShowWindow = (wcscmp(buffer, L"true") == 0);
	}

	if (!CreateProcessW(
		NULL,                   // No module name (use command line).
		const_cast<wchar_t*>(wRemoteCmdLine.c_str()), // Command line.
		NULL,                   // Process handle not inheritable.
		NULL,                   // Thread handle not inheritable.
		TRUE,                   // Set handle inheritance to TRUE.
		(bMayShowWindow && bShowWindow) ? 0  : CREATE_NO_WINDOW, // creation flags.
		NULL,                   // Use parent's environment block.
		szWorkingDirectory?szWorkingDirectory:szRemoteDirectory,  // Set starting directory.
		&si,                    // Pointer to STARTUPINFO structure.
		&pi ))                  // Pointer to PROCESS_INFORMATION structure.
	{
		/*
		This code block is commented out instead of being deleted because it's
		good to have at hand for a debugging session.

		const size_t charsInMessageBuffer = 32768;   // msdn about FormatMessage(): "The output buffer cannot be larger than 64K bytes."
		wchar_t szMessageBuffer[charsInMessageBuffer] = L"";   
		FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, szMessageBuffer, charsInMessageBuffer, NULL);
		GetCurrentDirectoryW(charsInMessageBuffer, szMessageBuffer);
		*/

		if (!bSilent)
		{
			MessageBoxA(0, "ResourceCompiler was not found.\n\nPlease verify CryENGINE RootPath.", "Error", MB_ICONERROR|MB_OK);
		}

		return eRcCallResult_notFound;
	}

	// Close the pipe that writes to the child process, since we don't actually have any input for it.
	CloseHandle(hChildStdInWr);

	// Read all the output from the child process.
	CloseHandle(hChildStdOutWr);
	ResourceCompilerLineHandler lineHandler(listener);
	LineStreamBuffer lineBuffer(&lineHandler, &ResourceCompilerLineHandler::HandleLine);
	for (;;)
	{
		char buffer[2048];
		DWORD bytesRead;
		if (!ReadFile(hChildStdOutRd, buffer, sizeof(buffer), &bytesRead, NULL) || (bytesRead == 0))
		{
			break;
		}
		lineBuffer.HandleText(buffer, bytesRead);
	} 

	// Wait until child process exits.
	WaitForSingleObject(pi.hProcess, INFINITE);

	bool ok = true;
	DWORD exitCode = 1;
	{
		if ((GetExitCodeProcess(pi.hProcess, &exitCode) == 0) || (exitCode != 0))
		{
			ok = false;
		}	
	}

	// Close process and thread handles. 
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	if (exitCode == eRcExitCode_Crash)
	{
		return eRcCallResult_crash;
	}

	if (lineBuffer.IsTruncated())
	{
		return eRcCallResult_error;
	}

	return ok ? eRcCallResult_success : eRcCallResult_error;
}