void CSettingsManagerTools::GetRootPathAscii(bool pullFromRegistry, SettingsManagerHelpers::CCharBuffer buffer) { wchar_t wbuffer[MAX_PATH]; GetRootPathUtf16(pullFromRegistry, SettingsManagerHelpers::CWCharBuffer(wbuffer, sizeof(wbuffer))); SettingsManagerHelpers::GetAsciiFilename(wbuffer, buffer); }
void* CResourceCompilerHelper::AsyncCallResourceCompiler( const char* szFileName, const char* szAdditionalSettings, 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 NULL; } 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); } STARTUPINFOW si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwX = 100; si.dwY = 100; si.dwFlags = STARTF_USEPOSITION; 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. { if (!bSilent) { MessageBoxA(0, "ResourceCompiler was not found.\n\nPlease verify CryENGINE RootPath.", "Error", MB_ICONERROR|MB_OK); } return NULL; } return pi.hProcess; }
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; }