/** * 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; }
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; }