mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-25 14:41:02 +00:00
Improvements to NtQueryDirectoryFileEx (#235)
This PR aims to: - [Stub FileBasicInformation in NtSetInformationFile](6d0ad1dd61) - [Make sure a root `windows_path` have slash at the end](02ed4fbb03), this was necessary because `directory_iterator` fails when the path is `C:` (without slash).. - [Improve NtQueryDirectoryFileEx](f6ec1fc9cc) by adding filename filtering support, including more basic file information in the struct, and fixing an issue that prevented the last chunk of files from being enumerated correctly.
This commit is contained in:
@@ -41,9 +41,7 @@ namespace utils
|
||||
|
||||
bool operator()(const std::string_view lhs, const std::string_view rhs) const
|
||||
{
|
||||
return std::ranges::equal(lhs, rhs, [](const char c1, const char c2) {
|
||||
return string::char_to_lower(c1) == string::char_to_lower(c2);
|
||||
});
|
||||
return string::equals_ignore_case(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -149,4 +149,20 @@ namespace utils::string
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
template <class Elem, class Traits, class Alloc>
|
||||
bool equals_ignore_case(const std::basic_string<Elem, Traits, Alloc>& lhs,
|
||||
const std::basic_string<Elem, Traits, Alloc>& rhs)
|
||||
{
|
||||
return std::ranges::equal(lhs, rhs,
|
||||
[](const auto c1, const auto c2) { return char_to_lower(c1) == char_to_lower(c2); });
|
||||
}
|
||||
|
||||
template <class Elem, class Traits>
|
||||
bool equals_ignore_case(const std::basic_string_view<Elem, Traits>& lhs,
|
||||
const std::basic_string_view<Elem, Traits>& rhs)
|
||||
{
|
||||
return std::ranges::equal(lhs, rhs,
|
||||
[](const auto c1, const auto c2) { return char_to_lower(c1) == char_to_lower(c2); });
|
||||
}
|
||||
}
|
||||
|
||||
99
src/common/utils/wildcard.hpp
Normal file
99
src/common/utils/wildcard.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace utils::wildcard
|
||||
{
|
||||
inline bool is_wildcard(char16_t c)
|
||||
{
|
||||
return c == '*' || c == '?' || c == '>' || c == '<' || c == '\"';
|
||||
}
|
||||
|
||||
inline bool has_wildcard(const std::u16string_view mask)
|
||||
{
|
||||
return std::ranges::any_of(mask, is_wildcard);
|
||||
}
|
||||
|
||||
inline bool match_filename(std::u16string_view name, std::u16string_view mask)
|
||||
{
|
||||
if (mask.empty() || mask == u"*" || mask == u"*.*")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t name_pos = 0;
|
||||
size_t mask_pos = 0;
|
||||
|
||||
size_t star_mask_pos = std::u16string_view::npos;
|
||||
size_t star_name_pos = 0;
|
||||
|
||||
while (name_pos < name.size())
|
||||
{
|
||||
if (mask_pos < mask.size())
|
||||
{
|
||||
char16_t mask_char = mask[mask_pos];
|
||||
char16_t name_char = name[name_pos];
|
||||
|
||||
bool char_matches = false;
|
||||
if (mask_char == u'?' || mask_char == u'>')
|
||||
{
|
||||
char_matches = true;
|
||||
}
|
||||
else if (mask_char == u'"')
|
||||
{
|
||||
char_matches = name_char == u'.';
|
||||
}
|
||||
else
|
||||
{
|
||||
char_matches = string::char_to_lower(name_char) == string::char_to_lower(mask_char);
|
||||
}
|
||||
|
||||
// Advance if current characters match
|
||||
if (char_matches)
|
||||
{
|
||||
name_pos++;
|
||||
mask_pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this is a wildcard, skip all consecutive wildcards and save position for backtracking
|
||||
if (mask[mask_pos] == u'*' || mask[mask_pos] == u'<')
|
||||
{
|
||||
mask_pos++;
|
||||
while (mask_pos < mask.size() && (mask[mask_pos] == u'*' || mask[mask_pos] == u'<'))
|
||||
{
|
||||
mask_pos++;
|
||||
}
|
||||
|
||||
if (mask_pos == mask.size())
|
||||
{
|
||||
// There is no need to continue because all that remained were star masks.
|
||||
return true;
|
||||
}
|
||||
|
||||
star_mask_pos = mask_pos;
|
||||
star_name_pos = name_pos;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// The current characters didn't match...
|
||||
// If we had a wildcard earlier, backtrack to it and try to match at the next position
|
||||
if (star_mask_pos != std::u16string_view::npos)
|
||||
{
|
||||
mask_pos = star_mask_pos;
|
||||
name_pos = ++star_name_pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip any remaining wildcards in the mask
|
||||
while (mask_pos < mask.size() && (mask[mask_pos] == u'*' || mask[mask_pos] == u'<'))
|
||||
{
|
||||
mask_pos++;
|
||||
}
|
||||
|
||||
return mask_pos == mask.size();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user