From 9bd824a4cb0539197c1ce17df9b0461a436d92e4 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 30 Apr 2021 15:07:04 -0500 Subject: [PATCH] ntdll: Implement NtAlertThreadByThreadId and NtWaitForAlertByThreadId. Signed-off-by: Zebediah Figura --- dlls/ntdll/ntdll.spec | 4 ++ dlls/ntdll/unix/loader.c | 2 + dlls/ntdll/unix/sync.c | 93 ++++++++++++++++++++++++++++++++++++++++ dlls/wow64/sync.c | 23 ++++++++++ dlls/wow64/syscall.h | 2 + include/winternl.h | 2 + 6 files changed, 126 insertions(+) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index c3d17d989ac..6d65ac0ad95 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -138,6 +138,7 @@ @ stdcall -syscall NtAdjustPrivilegesToken(long long ptr long ptr ptr) @ stdcall -syscall NtAlertResumeThread(long ptr) @ stdcall -syscall NtAlertThread(long) +@ stdcall -syscall NtAlertThreadByThreadId(ptr) @ stdcall -syscall NtAllocateLocallyUniqueId(ptr) # @ stub NtAllocateUserPhysicalPages @ stdcall -syscall NtAllocateUuids(ptr ptr ptr ptr) @@ -425,6 +426,7 @@ @ stdcall -syscall NtUnmapViewOfSection(long ptr) # @ stub NtVdmControl # @ stub NtW32Call +@ stdcall -syscall NtWaitForAlertByThreadId(ptr ptr) @ stdcall -syscall NtWaitForDebugEvent(long long ptr ptr) @ stdcall -syscall NtWaitForKeyedEvent(long ptr long ptr) @ stdcall -syscall NtWaitForMultipleObjects(long ptr long long ptr) @@ -1162,6 +1164,7 @@ @ stdcall -private -syscall ZwAdjustPrivilegesToken(long long ptr long ptr ptr) NtAdjustPrivilegesToken @ stdcall -private -syscall ZwAlertResumeThread(long ptr) NtAlertResumeThread @ stdcall -private -syscall ZwAlertThread(long) NtAlertThread +@ stdcall -private -syscall ZwAlertThreadByThreadId(ptr) NtAlertThreadByThreadId @ stdcall -private -syscall ZwAllocateLocallyUniqueId(ptr) NtAllocateLocallyUniqueId # @ stub ZwAllocateUserPhysicalPages @ stdcall -private -syscall ZwAllocateUuids(ptr ptr ptr ptr) NtAllocateUuids @@ -1447,6 +1450,7 @@ @ stdcall -private -syscall ZwUnmapViewOfSection(long ptr) NtUnmapViewOfSection # @ stub ZwVdmControl # @ stub ZwW32Call +@ stdcall -private -syscall ZwWaitForAlertByThreadId(ptr ptr) NtWaitForAlertByThreadId @ stdcall -private -syscall ZwWaitForDebugEvent(long long ptr ptr) NtWaitForDebugEvent @ stdcall -private -syscall ZwWaitForKeyedEvent(long ptr long ptr) NtWaitForKeyedEvent @ stdcall -private -syscall ZwWaitForMultipleObjects(long ptr long long ptr) NtWaitForMultipleObjects diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index b15824346b7..736b1a8773e 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -126,6 +126,7 @@ static void * const syscalls[] = NtAdjustPrivilegesToken, NtAlertResumeThread, NtAlertThread, + NtAlertThreadByThreadId, NtAllocateLocallyUniqueId, NtAllocateUuids, NtAllocateVirtualMemory, @@ -331,6 +332,7 @@ static void * const syscalls[] = NtUnlockFile, NtUnlockVirtualMemory, NtUnmapViewOfSection, + NtWaitForAlertByThreadId, NtWaitForDebugEvent, NtWaitForKeyedEvent, NtWaitForMultipleObjects, diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index a13e53a437b..dc9ced540d4 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -32,6 +32,9 @@ #include #include #include +#ifdef HAVE_SYS_MMAN_H +#include +#endif #ifdef HAVE_SYS_SYSCALL_H #include #endif @@ -81,6 +84,12 @@ static const LARGE_INTEGER zero_timeout; static pthread_mutex_t addr_mutex = PTHREAD_MUTEX_INITIALIZER; +static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) +{ + if (!timeout) return "(infinite)"; + return wine_dbgstr_longlong( timeout->QuadPart ); +} + /* return a monotonic time counter, in Win32 ticks */ static inline ULONGLONG monotonic_counter(void) { @@ -2312,6 +2321,90 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl } +union tid_alert_entry +{ + HANDLE event; +}; + +#define TID_ALERT_BLOCK_SIZE (65536 / sizeof(union tid_alert_entry)) +static union tid_alert_entry *tid_alert_blocks[4096]; + +static unsigned int handle_to_index( HANDLE handle, unsigned int *block_idx ) +{ + unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; + *block_idx = idx / TID_ALERT_BLOCK_SIZE; + return idx % TID_ALERT_BLOCK_SIZE; +} + +static union tid_alert_entry *get_tid_alert_entry( HANDLE tid ) +{ + unsigned int block_idx, idx = handle_to_index( tid, &block_idx ); + union tid_alert_entry *entry; + + if (block_idx > ARRAY_SIZE(tid_alert_blocks)) + { + FIXME( "tid %p is too high\n", tid ); + return NULL; + } + + if (!tid_alert_blocks[block_idx]) + { + static const size_t size = TID_ALERT_BLOCK_SIZE * sizeof(union tid_alert_entry); + void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); + if (ptr == MAP_FAILED) return NULL; + if (InterlockedCompareExchangePointer( (void **)&tid_alert_blocks[block_idx], ptr, NULL )) + munmap( ptr, size ); /* someone beat us to it */ + } + + entry = &tid_alert_blocks[block_idx][idx % TID_ALERT_BLOCK_SIZE]; + + if (!entry->event) + { + HANDLE event; + + if (NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE )) + return NULL; + if (InterlockedCompareExchangePointer( &entry->event, event, NULL )) + NtClose( event ); + } + + return entry; +} + + +/*********************************************************************** + * NtAlertThreadByThreadId (NTDLL.@) + */ +NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) +{ + union tid_alert_entry *entry = get_tid_alert_entry( tid ); + + TRACE( "%p\n", tid ); + + if (!entry) return STATUS_INVALID_CID; + + return NtSetEvent( entry->event, NULL ); +} + + +/*********************************************************************** + * NtWaitForAlertByThreadId (NTDLL.@) + */ +NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEGER *timeout ) +{ + union tid_alert_entry *entry = get_tid_alert_entry( NtCurrentTeb()->ClientId.UniqueThread ); + NTSTATUS status; + + TRACE( "%p %s\n", address, debugstr_timeout( timeout ) ); + + if (!entry) return STATUS_INVALID_CID; + + status = NtWaitForSingleObject( entry->event, FALSE, timeout ); + if (!status) return STATUS_ALERTED; + return status; +} + + #ifdef __linux__ NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index 0078508fc7f..5e59c8c5587 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -1624,3 +1624,26 @@ NTSTATUS WINAPI wow64_NtYieldExecution( UINT *args ) { return NtYieldExecution(); } + + +/********************************************************************** + * wow64_NtAlertThreadByThreadId + */ +NTSTATUS WINAPI wow64_NtAlertThreadByThreadId( UINT *args ) +{ + HANDLE tid = get_handle( &args ); + + return NtAlertThreadByThreadId( tid ); +} + + +/********************************************************************** + * wow64_NtWaitForAlertByThreadId + */ +NTSTATUS WINAPI wow64_NtWaitForAlertByThreadId( UINT *args ) +{ + const void *address = get_ptr( &args ); + const LARGE_INTEGER *timeout = get_ptr( &args ); + + return NtWaitForAlertByThreadId( address, timeout ); +} diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h index a565e9cda3a..feca707a9da 100644 --- a/dlls/wow64/syscall.h +++ b/dlls/wow64/syscall.h @@ -30,6 +30,7 @@ SYSCALL_ENTRY( NtAdjustPrivilegesToken ) \ SYSCALL_ENTRY( NtAlertResumeThread ) \ SYSCALL_ENTRY( NtAlertThread ) \ + SYSCALL_ENTRY( NtAlertThreadByThreadId ) \ SYSCALL_ENTRY( NtAllocateLocallyUniqueId ) \ SYSCALL_ENTRY( NtAllocateUuids ) \ SYSCALL_ENTRY( NtAllocateVirtualMemory ) \ @@ -234,6 +235,7 @@ SYSCALL_ENTRY( NtUnlockFile ) \ SYSCALL_ENTRY( NtUnlockVirtualMemory ) \ SYSCALL_ENTRY( NtUnmapViewOfSection ) \ + SYSCALL_ENTRY( NtWaitForAlertByThreadId ) \ SYSCALL_ENTRY( NtWaitForDebugEvent ) \ SYSCALL_ENTRY( NtWaitForKeyedEvent ) \ SYSCALL_ENTRY( NtWaitForMultipleObjects ) \ diff --git a/include/winternl.h b/include/winternl.h index fea9e9df117..9d7a95406ea 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3820,6 +3820,7 @@ NTSYSAPI NTSTATUS WINAPI NtAdjustGroupsToken(HANDLE,BOOLEAN,PTOKEN_GROUPS,ULONG NTSYSAPI NTSTATUS WINAPI NtAdjustPrivilegesToken(HANDLE,BOOLEAN,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD); NTSYSAPI NTSTATUS WINAPI NtAlertResumeThread(HANDLE,PULONG); NTSYSAPI NTSTATUS WINAPI NtAlertThread(HANDLE ThreadHandle); +NTSYSAPI NTSTATUS WINAPI NtAlertThreadByThreadId(HANDLE); NTSYSAPI NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID lpLuid); NTSYSAPI NTSTATUS WINAPI NtAllocateUuids(PULARGE_INTEGER,PULONG,PULONG,PUCHAR); NTSYSAPI NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,ULONG_PTR,SIZE_T*,ULONG,ULONG); @@ -4062,6 +4063,7 @@ NTSYSAPI NTSTATUS WINAPI NtUnlockFile(HANDLE,PIO_STATUS_BLOCK,PLARGE_INTEGER,PL NTSYSAPI NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG); NTSYSAPI NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID); NTSYSAPI NTSTATUS WINAPI NtVdmControl(ULONG,PVOID); +NTSYSAPI NTSTATUS WINAPI NtWaitForAlertByThreadId(const void*,const LARGE_INTEGER*); NTSYSAPI NTSTATUS WINAPI NtWaitForDebugEvent(HANDLE,BOOLEAN,LARGE_INTEGER*,DBGUI_WAIT_STATE_CHANGE*); NTSYSAPI NTSTATUS WINAPI NtWaitForKeyedEvent(HANDLE,const void*,BOOLEAN,const LARGE_INTEGER*); NTSYSAPI NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,const LARGE_INTEGER*); -- 2.33.0