| 1008 | } |
| 1009 | |
| 1010 | bool create_mod_zip(const std::filesystem::path& output_dir, const ModConfig& config) { |
| 1011 | std::filesystem::path output_path = output_dir / (config.inputs.mod_filename + ".nrm"); |
| 1012 | |
| 1013 | #ifdef _WIN32 |
| 1014 | std::filesystem::path temp_zip_path = output_path; |
| 1015 | temp_zip_path.replace_extension(".zip"); |
| 1016 | std::string command_string = fmt::format("powershell -command Compress-Archive -Force -CompressionLevel Optimal -DestinationPath '{}' -Path '{}','{}','{}'", |
| 1017 | temp_zip_path.string(), (output_dir / symbol_filename).string(), (output_dir / binary_filename).string(), (output_dir / manifest_filename).string()); |
| 1018 | |
| 1019 | for (const auto& cur_file : config.inputs.additional_files) { |
| 1020 | command_string += fmt::format(",'{}'", cur_file.string()); |
| 1021 | } |
| 1022 | |
| 1023 | STARTUPINFOA si{}; |
| 1024 | PROCESS_INFORMATION pi{}; |
| 1025 | |
| 1026 | ZeroMemory( &si, sizeof(si) ); |
| 1027 | si.cb = sizeof(si); |
| 1028 | ZeroMemory( &pi, sizeof(pi) ); |
| 1029 | |
| 1030 | std::vector<char> command_string_buffer; |
| 1031 | command_string_buffer.resize(command_string.size() + 1); |
| 1032 | std::copy(command_string.begin(), command_string.end(), command_string_buffer.begin()); |
| 1033 | command_string_buffer[command_string.size()] = '\x00'; |
| 1034 | |
| 1035 | if (!CreateProcessA(NULL, command_string_buffer.data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { |
| 1036 | fmt::print(stderr, "Process creation failed {}\n", GetLastError()); |
| 1037 | return false; |
| 1038 | } |
| 1039 | |
| 1040 | WaitForSingleObject(pi.hProcess, INFINITE); |
| 1041 | |
| 1042 | DWORD ec; |
| 1043 | GetExitCodeProcess(pi.hProcess, &ec); |
| 1044 | |
| 1045 | CloseHandle(pi.hProcess); |
| 1046 | CloseHandle(pi.hThread); |
| 1047 | |
| 1048 | if (ec != EXIT_SUCCESS) { |
| 1049 | fmt::print(stderr, "Compress-Archive failed with exit code {}\n", ec); |
| 1050 | return false; |
| 1051 | } |
| 1052 | |
| 1053 | std::error_code rename_ec; |
| 1054 | std::filesystem::rename(temp_zip_path, output_path, rename_ec); |
| 1055 | if (rename_ec != std::error_code{}) { |
| 1056 | fmt::print(stderr, "Failed to rename temporary zip to output path\n"); |
| 1057 | return false; |
| 1058 | } |
| 1059 | #else |
| 1060 | std::string args_string{}; |
| 1061 | std::vector<size_t> arg_positions{}; |
| 1062 | |
| 1063 | // Adds an argument with a null terminator to args_string, which is used as a buffer to hold null terminated arguments. |
| 1064 | // Also adds the argument's offset into the string into arg_positions for creating the array of character pointers for the exec. |
| 1065 | auto add_arg = [&args_string, &arg_positions](const std::string& arg){ |
| 1066 | arg_positions.emplace_back(args_string.size()); |
| 1067 | args_string += (arg + '\x00'); |