#include "pch.h" #include "CreoUtilities.h" #include #include #include // Set Creo working directory ChangeDirectoryResult CreoUtilities::SetWorkingDirectory(const std::string& target_directory) { ChangeDirectoryResult result; result.target_directory = target_directory; try { // Validate input if (target_directory.empty()) { result.success = false; result.error_message = "Target directory cannot be empty"; return result; } // Get Creo session pfcSession_ptr session = nullptr; try { session = pfcGetCurrentSessionWithCompatibility(pfcC4Compatible); } catch (...) { session = nullptr; } if (!session) { result.success = false; result.error_message = "Failed to get Creo session. Creo may not be running."; return result; } // Get current working directory xstring current_dir_xstr; try { current_dir_xstr = session->GetCurrentDirectory(); result.original_directory = XStringToString(current_dir_xstr); } catch (...) { result.success = false; result.error_message = "Failed to get current directory"; return result; } // Normalize and compare paths std::string normalized_current = NormalizePath(result.original_directory); std::string normalized_target = NormalizePath(target_directory); // Check if directories are the same if (PathsAreEqual(normalized_current, normalized_target)) { // Already at target directory, no change needed result.success = true; result.directory_changed = false; result.current_directory = result.original_directory; result.message = "Already at target directory, no change needed"; return result; } // Directories are different, need to change try { xstring target_dir_xstr = StringToXString(target_directory); session->ChangeDirectory(target_dir_xstr); } catch (...) { result.success = false; result.error_message = "Failed to change directory (directory may not exist or is invalid)"; result.current_directory = result.original_directory; return result; } // Verify the change by reading current directory again try { xstring new_dir_xstr = session->GetCurrentDirectory(); result.current_directory = XStringToString(new_dir_xstr); } catch (...) { result.current_directory = target_directory; // Assume success if we can't verify } // Check if change was successful std::string normalized_new = NormalizePath(result.current_directory); if (PathsAreEqual(normalized_new, normalized_target)) { result.success = true; result.directory_changed = true; result.message = "Working directory changed successfully"; } else { result.success = false; result.directory_changed = false; result.error_message = "Directory change operation completed but verification failed"; } } catch (const std::exception& e) { result.success = false; result.error_message = std::string("Unexpected exception: ") + e.what(); result.current_directory = result.original_directory; } catch (...) { result.success = false; result.error_message = "Unexpected unknown exception occurred"; result.current_directory = result.original_directory; } return result; } // Convert xstring to std::string std::string CreoUtilities::XStringToString(const xstring& xstr) { try { // Check for null xstring if (xstr.IsNull()) { return ""; } std::wstring wstr(xstr); if (wstr.empty()) { return ""; } // Length check to prevent memory issues if (wstr.length() > 32767) { // Windows API limit return ""; } // Use WideCharToMultiByte for proper UTF-8 encoding conversion int wstr_len = static_cast(wstr.length()); int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr_len, NULL, 0, NULL, NULL); if (size_needed <= 0 || size_needed > 65535) { // Safety boundary check return ""; } std::string result(size_needed, 0); WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr_len, &result[0], size_needed, NULL, NULL); return result; } catch (...) { return ""; } } // Convert std::string to xstring xstring CreoUtilities::StringToXString(const std::string& str) { try { if (str.empty()) { return xstring(); } // Length check to prevent memory issues if (str.length() > 65535) { // Reasonable length limit return xstring(); } // Validate input string for invalid characters for (char c : str) { if (c == '\0' && &c != &str.back()) { // Null character in the middle return xstring(); } } // Use MultiByteToWideChar for proper UTF-8 decoding conversion int str_len = static_cast(str.length()); int size_needed = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.c_str(), str_len, NULL, 0); if (size_needed <= 0 || size_needed > 32767) { // Safety boundary check return xstring(); } std::wstring wstr(size_needed, 0); MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.c_str(), str_len, &wstr[0], size_needed); return xstring(wstr.c_str()); } catch (...) { return xstring(); } } // Normalize path for comparison std::string CreoUtilities::NormalizePath(const std::string& path) { if (path.empty()) { return ""; } std::string normalized = path; // Replace forward slashes with backslashes (Windows standard) std::replace(normalized.begin(), normalized.end(), '/', '\\'); // Remove trailing backslash if present (except for root paths like "C:\") if (normalized.length() > 3 && normalized.back() == '\\') { normalized.pop_back(); } // Convert to lowercase for case-insensitive comparison (Windows) std::transform(normalized.begin(), normalized.end(), normalized.begin(), [](unsigned char c) { return std::tolower(c); }); return normalized; } // Compare two paths for equality bool CreoUtilities::PathsAreEqual(const std::string& path1, const std::string& path2) { // Both empty if (path1.empty() && path2.empty()) { return true; } // One empty, one not if (path1.empty() || path2.empty()) { return false; } // Compare normalized paths std::string norm1 = NormalizePath(path1); std::string norm2 = NormalizePath(path2); return norm1 == norm2; }