Fix semaphores and mutexes

This commit is contained in:
momo5502
2025-01-24 13:00:06 +01:00
parent 5160bacd1e
commit 32d91bd139
5 changed files with 87 additions and 9 deletions

View File

@@ -31,6 +31,8 @@ using NTSTATUS = std::uint32_t;
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L)
#define STATUS_MUTANT_NOT_OWNED ((NTSTATUS)0xC0000046L)
#define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS)0xC0000047L)
#define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL)
#define STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
#define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS)0xC00000A0L)

View File

@@ -354,6 +354,8 @@ constexpr auto BASE_NAMED_OBJECTS_DIRECTORY = make_pseudo_handle(0x2, handle_typ
constexpr auto KNOWN_DLLS_SYMLINK = make_pseudo_handle(0x1, handle_types::symlink);
constexpr auto SHARED_SECTION = make_pseudo_handle(0x1, handle_types::section);
constexpr auto WER_PORT_READY = make_pseudo_handle(0x1, handle_types::event);
constexpr auto CONSOLE_HANDLE = make_pseudo_handle(0x1, handle_types::file);
constexpr auto STDOUT_HANDLE = make_pseudo_handle(0x2, handle_types::file);
constexpr auto STDIN_HANDLE = make_pseudo_handle(0x3, handle_types::file);

View File

@@ -108,17 +108,17 @@ struct mutant : ref_counted_object
return true;
}
uint32_t release()
std::pair<uint32_t, bool> release(const uint32_t thread_id)
{
const auto old_count = this->locked_count;
if (this->locked_count <= 0)
if (this->locked_count <= 0 || this->owning_thread_id != thread_id)
{
return old_count;
return {old_count, false};
}
--this->locked_count;
return old_count;
return {old_count, true};
}
void serialize(utils::buffer_serializer& buffer) const
@@ -239,9 +239,34 @@ struct section
struct semaphore : ref_counted_object
{
std::u16string name{};
volatile uint32_t current_count{};
uint32_t current_count{};
uint32_t max_count{};
bool try_lock()
{
if (this->current_count > 0)
{
--this->current_count;
return true;
}
return false;
}
std::pair<uint32_t, bool> release(const uint32_t release_count)
{
const auto old_count = this->current_count;
if (this->current_count + release_count > this->max_count)
{
return {old_count, false};
}
this->current_count += release_count;
return {old_count, true};
}
void serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->name);

View File

@@ -449,14 +449,14 @@ namespace
return STATUS_INVALID_HANDLE;
}
const auto old_count = mutant->release();
const auto [old_count, succeeded] = mutant->release(c.proc.current_thread_id);
if (previous_count)
{
previous_count.write(static_cast<LONG>(old_count));
}
return STATUS_SUCCESS;
return succeeded ? STATUS_SUCCESS : STATUS_MUTANT_NOT_OWNED;
}
NTSTATUS handle_NtCreateMutant(const syscall_context& c, const emulator_object<handle> mutant_handle,
@@ -553,6 +553,12 @@ namespace
const auto name =
read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
if (name == u"\\KernelObjects\\SystemErrorPortReady")
{
event_handle.write(WER_PORT_READY.bits);
return STATUS_SUCCESS;
}
for (auto& entry : c.proc.events)
{
if (entry.second.name == name)
@@ -3020,6 +3026,32 @@ namespace
return STATUS_OBJECT_NAME_NOT_FOUND;
}
NTSTATUS handle_NtReleaseSemaphore(const syscall_context& c, const handle semaphore_handle,
const ULONG release_count, const emulator_object<LONG> previous_count)
{
if (semaphore_handle.value.type != handle_types::semaphore)
{
c.win_emu.log.error("Bad handle type for NtReleaseSemaphore\n");
c.emu.stop();
return STATUS_NOT_SUPPORTED;
}
auto* mutant = c.proc.semaphores.get(semaphore_handle);
if (!mutant)
{
return STATUS_INVALID_HANDLE;
}
const auto [old_count, succeeded] = mutant->release(release_count);
if (previous_count)
{
previous_count.write(static_cast<LONG>(old_count));
}
return succeeded ? STATUS_SUCCESS : STATUS_SEMAPHORE_LIMIT_EXCEEDED;
}
NTSTATUS handle_NtCreateSemaphore(const syscall_context& c, const emulator_object<handle> semaphore_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
@@ -3222,8 +3254,9 @@ namespace
bool is_awaitable_object_type(const handle h)
{
return h.value.type == handle_types::thread //
|| h.value.type == handle_types::mutant //
return h.value.type == handle_types::thread //
|| h.value.type == handle_types::mutant //
|| h.value.type == handle_types::semaphore //
|| h.value.type == handle_types::event;
}
@@ -3537,6 +3570,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtUserModifyUserStartupInfoFlags);
add_handler(NtUserGetDCEx);
add_handler(NtUserGetDpiForCurrentProcess);
add_handler(NtReleaseSemaphore);
#undef add_handler
}

View File

@@ -634,6 +634,11 @@ namespace
break;
case handle_types::event: {
if (h.value.is_pseudo)
{
return true;
}
auto* e = c.events.get(h);
if (e)
{
@@ -653,6 +658,16 @@ namespace
break;
}
case handle_types::semaphore: {
auto* s = c.semaphores.get(h);
if (s)
{
return s->try_lock();
}
break;
}
case handle_types::thread: {
const auto* t = c.threads.get(h);
if (t)