Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 12 additions & 30 deletions Utilities/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1125,13 +1125,6 @@ bool fs::is_optical_raw_device([[maybe_unused]] const std::string& path)

bool fs::get_optical_raw_device(const std::string& path, std::string* raw_device)
{
// Skip a useless check to detect an optical raw device if navigating on subfolders (e.g. C:/subfolder_1/subfolder_2/), it means we are on a hdd/ssd.
// A path for an optical drive should include only the drive letter (e.g. E:/)
if (path.find_first_of(":") != path.find_last_not_of(delim))
{
return false;
}

if (fs::is_optical_raw_device(path))
{
if (raw_device)
Expand All @@ -1143,38 +1136,27 @@ bool fs::get_optical_raw_device(const std::string& path, std::string* raw_device
}

#ifdef _WIN32
constexpr u32 BUF_SIZE = 1000;
WCHAR drive_list[BUF_SIZE] = {0};

// GetLogicalDriveStrings() returns a double-null terminated list of null-terminated strings.
// E.g. A:\<nul>B:\<nul>C:\<nul><nul>
const DWORD copied = GetLogicalDriveStrings(BUF_SIZE, drive_list);
// Skip a useless check to detect an optical raw device if navigating on subfolders (e.g. C:\subfolder_1\subfolder_2\),
// it means we are on a HDD/SSD. A path for an optical drive should include only the drive letter (e.g. E:\)
const size_t drive_delim_pos = path.find_first_of(":");

if (copied == 0 || copied > BUF_SIZE)
if (drive_delim_pos != 1 || drive_delim_pos != path.find_last_not_of(delim))
{
return false;
}

for (const WCHAR* drive = drive_list; drive && *drive; drive += wcslen(drive) + 1)
const std::string drive_letter = path.substr(0, drive_delim_pos + 1); // e.g. "E:"
const std::string drive_path = drive_letter + "\\"; // e.g. "E:\"

if (GetDriveTypeA(drive_path.c_str()) == DRIVE_CDROM)
{
if (GetDriveType(drive) == DRIVE_CDROM)
if (raw_device)
{
const std::wstring ws(drive);
const std::string s = std::string(ws.begin(), ws.end() - 1);

if (path.starts_with(s))
{
if (raw_device)
{
*raw_device = "\\\\.\\" + s;
}

return true;
}
*raw_device = "\\\\.\\" + drive_letter;
}
}

return false;
return true;
}
#endif
return false;
}
Expand Down
8 changes: 8 additions & 0 deletions rpcs3/Crypto/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ void bytes_to_hex(std::string& hex_str, const unsigned char* data, unsigned int
{
fmt::throw_exception("Failed to read bytes: %s", std::make_error_code(err).message());
}

// Padding handling for values ​​< 0x10 (e.g. 0x05 becomes "5" instead of "05")
// If to_chars only writes 1 character, we move to the right and put '0'
if (ptr == &hex_str[i] + 1)
{
hex_str[i + 1] = hex_str[i];
hex_str[i] = '0';
}
}
}

Expand Down
29 changes: 15 additions & 14 deletions rpcs3/Loader/ISO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static void* get_aligned_buf()
return s_aligned_buf.buf;
}

static bool is_iso_file(const fs::file& file, u64* size = nullptr)
static bool is_iso_file(iso_file& file, u64* size = nullptr)
{
if (!file || file.size() < 32768ULL + 6)
{
Expand Down Expand Up @@ -87,7 +87,7 @@ bool is_iso_file(const std::string& path, u64* size, bool* is_raw_device)
// "new_path" is updated with the raw device path in case "path" points to a BD drive
const bool raw_device = fs::get_optical_raw_device(path, &new_path);

if (!raw_device && fs::is_dir(path))
if (!raw_device && !fs::is_file(path))
{
return false;
}
Expand All @@ -97,7 +97,7 @@ bool is_iso_file(const std::string& path, u64* size, bool* is_raw_device)
*is_raw_device = raw_device;
}

fs::file file(std::make_unique<iso_file>(new_path, fs::read));
iso_file file(new_path);

return is_iso_file(file, size);
}
Expand Down Expand Up @@ -337,7 +337,7 @@ iso_type_status iso_file_decryption::retrieve_key(iso_archive& archive, std::str
return iso_type_status::ERROR_OPENING_KEY;
}

iso_type_status iso_file_decryption::check_type(const std::string& path, std::string& key_path, aes_context* aes_ctx)
iso_type_status iso_file_decryption::check_type(const std::string& path, std::string* key_path, aes_context* aes_ctx)
{
if (!is_iso_file(path))
{
Expand All @@ -363,8 +363,12 @@ iso_type_status iso_file_decryption::check_type(const std::string& path, std::st
{
if (fs::is_file(path))
{
key_path = path;
return get_key(key_path, aes_ctx);
if (key_path)
{
*key_path = path;
}

return get_key(path, aes_ctx);
}
}

Expand All @@ -381,7 +385,7 @@ bool iso_file_decryption::init(const std::string& path, iso_archive* archive)
// Store the ISO region information (needed by both the "Redump" type (only on "decrypt()" method) and "3k3y" type)
//

fs::file iso_file(std::make_unique<iso_file>(path, fs::read));
iso_file iso_file(path);

if (!is_iso_file(iso_file))
{
Expand All @@ -390,7 +394,7 @@ bool iso_file_decryption::init(const std::string& path, iso_archive* archive)
}

// Reset the file position after it was changed by is_iso_file()
iso_file.seek(0);
iso_file.seek(0, fs::seek_set);

std::array<u8, ISO_SECTOR_SIZE * 2> sec0_sec1;

Expand Down Expand Up @@ -447,7 +451,7 @@ bool iso_file_decryption::init(const std::string& path, iso_archive* archive)
else
{
// Try to detect the Redump type. If so, the decryption context is set into "m_aes_dec"
status = check_type(path, key_path, &m_aes_dec);
status = check_type(path, &key_path, &m_aes_dec);
}

switch (status)
Expand Down Expand Up @@ -968,17 +972,14 @@ iso_archive::iso_archive(const std::string& path)
// "m_path" is updated with the raw device path in case "path" points to a BD drive
fs::get_optical_raw_device(path, &m_path);

fs::file iso_file(std::make_unique<iso_file>(m_path, fs::read));

if (!iso_file || !is_iso_file(iso_file))
if (!is_iso_file(m_path))
{
// Not ISO... TODO: throw something?
iso_log.error("iso_archive: Failed to recognize ISO file: '%s'", path);
return;
}

// Reset the file position after it was changed by is_iso_file()
iso_file.seek(0);
fs::file iso_file(std::make_unique<iso_file>(m_path));

u8 descriptor_type = -2;
bool use_ucs2_decoding = false;
Expand Down
5 changes: 3 additions & 2 deletions rpcs3/Loader/ISO.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class iso_file_decryption
static iso_type_status retrieve_key(iso_archive& archive, std::string& key_path, aes_context& aes_ctx);

public:
static iso_type_status check_type(const std::string& path, std::string& key_path, aes_context* aes_ctx = nullptr);
static iso_type_status check_type(const std::string& path, std::string* key_path = nullptr, aes_context* aes_ctx = nullptr);

iso_encryption_type get_enc_type() const { return m_enc_type; }

Expand Down Expand Up @@ -116,7 +116,7 @@ class iso_file : public fs::file_base
u64 file_offset(u64 pos) const;

public:
iso_file(const std::string& path, bs_t<fs::open_mode> mode);
iso_file(const std::string& path, bs_t<fs::open_mode> mode = fs::read);
iso_file(const std::string& path, bs_t<fs::open_mode> mode, const iso_fs_node& node);

explicit operator bool() const { return m_file.operator bool(); }
Expand Down Expand Up @@ -173,6 +173,7 @@ class iso_archive

const std::string& path() const { return m_path; }
const iso_fs_node& root() const { return m_root; }

iso_fs_node* retrieve(const std::string& path);
bool exists(const std::string& path);
bool is_file(const std::string& path);
Expand Down
3 changes: 1 addition & 2 deletions rpcs3/rpcs3qt/game_list_context_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,8 +605,7 @@ void game_list_context_menu::show_single_selection_context_menu(const game_info&
// Check integrity
if (QString::fromStdString(current_game.category) == cat::cat_disc_game)
{
std::string key_path;
const iso_type_status iso_type = iso_file_decryption::check_type(current_game.path, key_path);
const iso_type_status iso_type = iso_file_decryption::check_type(current_game.path);

// If it's an ISO file (e.g. even a decrypted ISO), always provide the entry on the context menu but disable
// it if the ISO does not support integrity check (e.g. non Redump ISO) or no integrity DB is found.
Expand Down
Loading