From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/ntdll.spec | 2 + dlls/ntdll/ntsyscalls.h | 218 ++++++++++++++++++------------------ dlls/ntdll/signal_arm64ec.c | 1 + dlls/ntdll/tests/thread.c | 86 +++++++++++++- dlls/ntdll/unix/thread.c | 26 ++++- dlls/wow64/process.c | 22 +++- include/processthreadsapi.h | 7 ++ include/winternl.h | 1 + 8 files changed, 246 insertions(+), 117 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index eb0b3bfabe4..604c342ba35 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -345,6 +345,7 @@ @ stdcall -syscall=0x0049 NtQueryVolumeInformationFile(long ptr ptr long long) @ stdcall -syscall=0x0045 NtQueueApcThread(long ptr long long long) @ stdcall -syscall NtQueueApcThreadEx(long long ptr long long long) +@ stdcall -syscall NtQueueApcThreadEx2(long long long ptr long long long) @ stdcall -syscall NtRaiseException(ptr ptr long) @ stdcall -syscall NtRaiseHardError(long long long ptr long ptr) @ stdcall -syscall=0x0006 NtReadFile(long long ptr ptr ptr ptr long ptr ptr) @@ -1412,6 +1413,7 @@ @ stdcall -private ZwQueryVolumeInformationFile(long ptr ptr long long) NtQueryVolumeInformationFile @ stdcall -private ZwQueueApcThread(long ptr long long long) NtQueueApcThread @ stdcall -private ZwQueueApcThreadEx(long long ptr long long long) NtQueueApcThreadEx +@ stdcall -private ZwQueueApcThreadEx2(long long long ptr long long long) NtQueueApcThreadEx2 @ stdcall -private ZwRaiseException(ptr ptr long) NtRaiseException @ stdcall -private ZwRaiseHardError(long long long ptr long ptr) NtRaiseHardError @ stdcall -private ZwReadFile(long long ptr ptr ptr ptr long ptr ptr) NtReadFile diff --git a/dlls/ntdll/ntsyscalls.h b/dlls/ntdll/ntsyscalls.h index ff4b6d70662..cc88ec87850 100644 --- a/dlls/ntdll/ntsyscalls.h +++ b/dlls/ntdll/ntsyscalls.h @@ -206,63 +206,64 @@ SYSCALL_ENTRY( 0x00ca, NtQuerySystemInformationEx, 24 ) \ SYSCALL_ENTRY( 0x00cb, NtQueryTimerResolution, 12 ) \ SYSCALL_ENTRY( 0x00cc, NtQueueApcThreadEx, 24 ) \ - SYSCALL_ENTRY( 0x00cd, NtRaiseException, 12 ) \ - SYSCALL_ENTRY( 0x00ce, NtRaiseHardError, 24 ) \ - SYSCALL_ENTRY( 0x00cf, NtRegisterThreadTerminatePort, 4 ) \ - SYSCALL_ENTRY( 0x00d0, NtReleaseKeyedEvent, 16 ) \ - SYSCALL_ENTRY( 0x00d1, NtRemoveIoCompletionEx, 24 ) \ - SYSCALL_ENTRY( 0x00d2, NtRemoveProcessDebug, 8 ) \ - SYSCALL_ENTRY( 0x00d3, NtRenameKey, 8 ) \ - SYSCALL_ENTRY( 0x00d4, NtReplaceKey, 12 ) \ - SYSCALL_ENTRY( 0x00d5, NtResetEvent, 8 ) \ - SYSCALL_ENTRY( 0x00d6, NtResetWriteWatch, 12 ) \ - SYSCALL_ENTRY( 0x00d7, NtRestoreKey, 12 ) \ - SYSCALL_ENTRY( 0x00d8, NtResumeProcess, 4 ) \ - SYSCALL_ENTRY( 0x00d9, NtRollbackTransaction, 8 ) \ - SYSCALL_ENTRY( 0x00da, NtSaveKey, 8 ) \ - SYSCALL_ENTRY( 0x00db, NtSecureConnectPort, 36 ) \ - SYSCALL_ENTRY( 0x00dc, NtSetContextThread, 8 ) \ - SYSCALL_ENTRY( 0x00dd, NtSetDebugFilterState, 12 ) \ - SYSCALL_ENTRY( 0x00de, NtSetDefaultLocale, 8 ) \ - SYSCALL_ENTRY( 0x00df, NtSetDefaultUILanguage, 4 ) \ - SYSCALL_ENTRY( 0x00e0, NtSetEaFile, 16 ) \ - SYSCALL_ENTRY( 0x00e1, NtSetInformationDebugObject, 20 ) \ - SYSCALL_ENTRY( 0x00e2, NtSetInformationJobObject, 16 ) \ - SYSCALL_ENTRY( 0x00e3, NtSetInformationKey, 16 ) \ - SYSCALL_ENTRY( 0x00e4, NtSetInformationToken, 16 ) \ - SYSCALL_ENTRY( 0x00e5, NtSetInformationVirtualMemory, 24 ) \ - SYSCALL_ENTRY( 0x00e6, NtSetIntervalProfile, 8 ) \ - SYSCALL_ENTRY( 0x00e7, NtSetIoCompletion, 20 ) \ - SYSCALL_ENTRY( 0x00e8, NtSetIoCompletionEx, 24 ) \ - SYSCALL_ENTRY( 0x00e9, NtSetLdtEntries, 24 ) \ - SYSCALL_ENTRY( 0x00ea, NtSetSecurityObject, 12 ) \ - SYSCALL_ENTRY( 0x00eb, NtSetSystemInformation, 12 ) \ - SYSCALL_ENTRY( 0x00ec, NtSetSystemTime, 8 ) \ - SYSCALL_ENTRY( 0x00ed, NtSetThreadExecutionState, 8 ) \ - SYSCALL_ENTRY( 0x00ee, NtSetTimerResolution, 12 ) \ - SYSCALL_ENTRY( 0x00ef, NtSetVolumeInformationFile, 20 ) \ - SYSCALL_ENTRY( 0x00f0, NtShutdownSystem, 4 ) \ - SYSCALL_ENTRY( 0x00f1, NtSignalAndWaitForSingleObject, 16 ) \ - SYSCALL_ENTRY( 0x00f2, NtSuspendProcess, 4 ) \ - SYSCALL_ENTRY( 0x00f3, NtSuspendThread, 8 ) \ - SYSCALL_ENTRY( 0x00f4, NtSystemDebugControl, 24 ) \ - SYSCALL_ENTRY( 0x00f5, NtTerminateJobObject, 8 ) \ - SYSCALL_ENTRY( 0x00f6, NtTestAlert, 0 ) \ - SYSCALL_ENTRY( 0x00f7, NtTraceControl, 24 ) \ - SYSCALL_ENTRY( 0x00f8, NtUnloadDriver, 4 ) \ - SYSCALL_ENTRY( 0x00f9, NtUnloadKey, 4 ) \ - SYSCALL_ENTRY( 0x00fa, NtUnlockFile, 20 ) \ - SYSCALL_ENTRY( 0x00fb, NtUnlockVirtualMemory, 16 ) \ - SYSCALL_ENTRY( 0x00fc, NtUnmapViewOfSectionEx, 12 ) \ - SYSCALL_ENTRY( 0x00fd, NtWaitForAlertByThreadId, 8 ) \ - SYSCALL_ENTRY( 0x00fe, NtWaitForDebugEvent, 16 ) \ - SYSCALL_ENTRY( 0x00ff, NtWaitForKeyedEvent, 16 ) \ - SYSCALL_ENTRY( 0x0100, NtWow64AllocateVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x0101, NtWow64GetNativeSystemInformation, 16 ) \ - SYSCALL_ENTRY( 0x0102, NtWow64IsProcessorFeaturePresent, 4 ) \ - SYSCALL_ENTRY( 0x0103, NtWow64QueryInformationProcess64, 20 ) \ - SYSCALL_ENTRY( 0x0104, NtWow64ReadVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x0105, NtWow64WriteVirtualMemory64, 28 ) + SYSCALL_ENTRY( 0x00cd, NtQueueApcThreadEx2, 28 ) \ + SYSCALL_ENTRY( 0x00ce, NtRaiseException, 12 ) \ + SYSCALL_ENTRY( 0x00cf, NtRaiseHardError, 24 ) \ + SYSCALL_ENTRY( 0x00d0, NtRegisterThreadTerminatePort, 4 ) \ + SYSCALL_ENTRY( 0x00d1, NtReleaseKeyedEvent, 16 ) \ + SYSCALL_ENTRY( 0x00d2, NtRemoveIoCompletionEx, 24 ) \ + SYSCALL_ENTRY( 0x00d3, NtRemoveProcessDebug, 8 ) \ + SYSCALL_ENTRY( 0x00d4, NtRenameKey, 8 ) \ + SYSCALL_ENTRY( 0x00d5, NtReplaceKey, 12 ) \ + SYSCALL_ENTRY( 0x00d6, NtResetEvent, 8 ) \ + SYSCALL_ENTRY( 0x00d7, NtResetWriteWatch, 12 ) \ + SYSCALL_ENTRY( 0x00d8, NtRestoreKey, 12 ) \ + SYSCALL_ENTRY( 0x00d9, NtResumeProcess, 4 ) \ + SYSCALL_ENTRY( 0x00da, NtRollbackTransaction, 8 ) \ + SYSCALL_ENTRY( 0x00db, NtSaveKey, 8 ) \ + SYSCALL_ENTRY( 0x00dc, NtSecureConnectPort, 36 ) \ + SYSCALL_ENTRY( 0x00dd, NtSetContextThread, 8 ) \ + SYSCALL_ENTRY( 0x00de, NtSetDebugFilterState, 12 ) \ + SYSCALL_ENTRY( 0x00df, NtSetDefaultLocale, 8 ) \ + SYSCALL_ENTRY( 0x00e0, NtSetDefaultUILanguage, 4 ) \ + SYSCALL_ENTRY( 0x00e1, NtSetEaFile, 16 ) \ + SYSCALL_ENTRY( 0x00e2, NtSetInformationDebugObject, 20 ) \ + SYSCALL_ENTRY( 0x00e3, NtSetInformationJobObject, 16 ) \ + SYSCALL_ENTRY( 0x00e4, NtSetInformationKey, 16 ) \ + SYSCALL_ENTRY( 0x00e5, NtSetInformationToken, 16 ) \ + SYSCALL_ENTRY( 0x00e6, NtSetInformationVirtualMemory, 24 ) \ + SYSCALL_ENTRY( 0x00e7, NtSetIntervalProfile, 8 ) \ + SYSCALL_ENTRY( 0x00e8, NtSetIoCompletion, 20 ) \ + SYSCALL_ENTRY( 0x00e9, NtSetIoCompletionEx, 24 ) \ + SYSCALL_ENTRY( 0x00ea, NtSetLdtEntries, 24 ) \ + SYSCALL_ENTRY( 0x00eb, NtSetSecurityObject, 12 ) \ + SYSCALL_ENTRY( 0x00ec, NtSetSystemInformation, 12 ) \ + SYSCALL_ENTRY( 0x00ed, NtSetSystemTime, 8 ) \ + SYSCALL_ENTRY( 0x00ee, NtSetThreadExecutionState, 8 ) \ + SYSCALL_ENTRY( 0x00ef, NtSetTimerResolution, 12 ) \ + SYSCALL_ENTRY( 0x00f0, NtSetVolumeInformationFile, 20 ) \ + SYSCALL_ENTRY( 0x00f1, NtShutdownSystem, 4 ) \ + SYSCALL_ENTRY( 0x00f2, NtSignalAndWaitForSingleObject, 16 ) \ + SYSCALL_ENTRY( 0x00f3, NtSuspendProcess, 4 ) \ + SYSCALL_ENTRY( 0x00f4, NtSuspendThread, 8 ) \ + SYSCALL_ENTRY( 0x00f5, NtSystemDebugControl, 24 ) \ + SYSCALL_ENTRY( 0x00f6, NtTerminateJobObject, 8 ) \ + SYSCALL_ENTRY( 0x00f7, NtTestAlert, 0 ) \ + SYSCALL_ENTRY( 0x00f8, NtTraceControl, 24 ) \ + SYSCALL_ENTRY( 0x00f9, NtUnloadDriver, 4 ) \ + SYSCALL_ENTRY( 0x00fa, NtUnloadKey, 4 ) \ + SYSCALL_ENTRY( 0x00fb, NtUnlockFile, 20 ) \ + SYSCALL_ENTRY( 0x00fc, NtUnlockVirtualMemory, 16 ) \ + SYSCALL_ENTRY( 0x00fd, NtUnmapViewOfSectionEx, 12 ) \ + SYSCALL_ENTRY( 0x00fe, NtWaitForAlertByThreadId, 8 ) \ + SYSCALL_ENTRY( 0x00ff, NtWaitForDebugEvent, 16 ) \ + SYSCALL_ENTRY( 0x0100, NtWaitForKeyedEvent, 16 ) \ + SYSCALL_ENTRY( 0x0101, NtWow64AllocateVirtualMemory64, 28 ) \ + SYSCALL_ENTRY( 0x0102, NtWow64GetNativeSystemInformation, 16 ) \ + SYSCALL_ENTRY( 0x0103, NtWow64IsProcessorFeaturePresent, 4 ) \ + SYSCALL_ENTRY( 0x0104, NtWow64QueryInformationProcess64, 20 ) \ + SYSCALL_ENTRY( 0x0105, NtWow64ReadVirtualMemory64, 28 ) \ + SYSCALL_ENTRY( 0x0106, NtWow64WriteVirtualMemory64, 28 ) #ifdef _WIN64 #define ALL_SYSCALLS \ SYSCALL_ENTRY( 0x0000, NtAccessCheck, 64 ) \ @@ -470,57 +471,58 @@ SYSCALL_ENTRY( 0x00ca, NtQuerySystemInformationEx, 48 ) \ SYSCALL_ENTRY( 0x00cb, NtQueryTimerResolution, 24 ) \ SYSCALL_ENTRY( 0x00cc, NtQueueApcThreadEx, 48 ) \ - SYSCALL_ENTRY( 0x00cd, NtRaiseException, 24 ) \ - SYSCALL_ENTRY( 0x00ce, NtRaiseHardError, 48 ) \ - SYSCALL_ENTRY( 0x00cf, NtRegisterThreadTerminatePort, 8 ) \ - SYSCALL_ENTRY( 0x00d0, NtReleaseKeyedEvent, 32 ) \ - SYSCALL_ENTRY( 0x00d1, NtRemoveIoCompletionEx, 48 ) \ - SYSCALL_ENTRY( 0x00d2, NtRemoveProcessDebug, 16 ) \ - SYSCALL_ENTRY( 0x00d3, NtRenameKey, 16 ) \ - SYSCALL_ENTRY( 0x00d4, NtReplaceKey, 24 ) \ - SYSCALL_ENTRY( 0x00d5, NtResetEvent, 16 ) \ - SYSCALL_ENTRY( 0x00d6, NtResetWriteWatch, 24 ) \ - SYSCALL_ENTRY( 0x00d7, NtRestoreKey, 24 ) \ - SYSCALL_ENTRY( 0x00d8, NtResumeProcess, 8 ) \ - SYSCALL_ENTRY( 0x00d9, NtRollbackTransaction, 16 ) \ - SYSCALL_ENTRY( 0x00da, NtSaveKey, 16 ) \ - SYSCALL_ENTRY( 0x00db, NtSecureConnectPort, 72 ) \ - SYSCALL_ENTRY( 0x00dc, NtSetContextThread, 16 ) \ - SYSCALL_ENTRY( 0x00dd, NtSetDebugFilterState, 24 ) \ - SYSCALL_ENTRY( 0x00de, NtSetDefaultLocale, 16 ) \ - SYSCALL_ENTRY( 0x00df, NtSetDefaultUILanguage, 8 ) \ - SYSCALL_ENTRY( 0x00e0, NtSetEaFile, 32 ) \ - SYSCALL_ENTRY( 0x00e1, NtSetInformationDebugObject, 40 ) \ - SYSCALL_ENTRY( 0x00e2, NtSetInformationJobObject, 32 ) \ - SYSCALL_ENTRY( 0x00e3, NtSetInformationKey, 32 ) \ - SYSCALL_ENTRY( 0x00e4, NtSetInformationToken, 32 ) \ - SYSCALL_ENTRY( 0x00e5, NtSetInformationVirtualMemory, 48 ) \ - SYSCALL_ENTRY( 0x00e6, NtSetIntervalProfile, 16 ) \ - SYSCALL_ENTRY( 0x00e7, NtSetIoCompletion, 40 ) \ - SYSCALL_ENTRY( 0x00e8, NtSetIoCompletionEx, 48 ) \ - SYSCALL_ENTRY( 0x00e9, NtSetLdtEntries, 32 ) \ - SYSCALL_ENTRY( 0x00ea, NtSetSecurityObject, 24 ) \ - SYSCALL_ENTRY( 0x00eb, NtSetSystemInformation, 24 ) \ - SYSCALL_ENTRY( 0x00ec, NtSetSystemTime, 16 ) \ - SYSCALL_ENTRY( 0x00ed, NtSetThreadExecutionState, 16 ) \ - SYSCALL_ENTRY( 0x00ee, NtSetTimerResolution, 24 ) \ - SYSCALL_ENTRY( 0x00ef, NtSetVolumeInformationFile, 40 ) \ - SYSCALL_ENTRY( 0x00f0, NtShutdownSystem, 8 ) \ - SYSCALL_ENTRY( 0x00f1, NtSignalAndWaitForSingleObject, 32 ) \ - SYSCALL_ENTRY( 0x00f2, NtSuspendProcess, 8 ) \ - SYSCALL_ENTRY( 0x00f3, NtSuspendThread, 16 ) \ - SYSCALL_ENTRY( 0x00f4, NtSystemDebugControl, 48 ) \ - SYSCALL_ENTRY( 0x00f5, NtTerminateJobObject, 16 ) \ - SYSCALL_ENTRY( 0x00f6, NtTestAlert, 0 ) \ - SYSCALL_ENTRY( 0x00f7, NtTraceControl, 48 ) \ - SYSCALL_ENTRY( 0x00f8, NtUnloadDriver, 8 ) \ - SYSCALL_ENTRY( 0x00f9, NtUnloadKey, 8 ) \ - SYSCALL_ENTRY( 0x00fa, NtUnlockFile, 40 ) \ - SYSCALL_ENTRY( 0x00fb, NtUnlockVirtualMemory, 32 ) \ - SYSCALL_ENTRY( 0x00fc, NtUnmapViewOfSectionEx, 24 ) \ - SYSCALL_ENTRY( 0x00fd, NtWaitForAlertByThreadId, 16 ) \ - SYSCALL_ENTRY( 0x00fe, NtWaitForDebugEvent, 32 ) \ - SYSCALL_ENTRY( 0x00ff, NtWaitForKeyedEvent, 32 ) + SYSCALL_ENTRY( 0x00cd, NtQueueApcThreadEx2, 56 ) \ + SYSCALL_ENTRY( 0x00ce, NtRaiseException, 24 ) \ + SYSCALL_ENTRY( 0x00cf, NtRaiseHardError, 48 ) \ + SYSCALL_ENTRY( 0x00d0, NtRegisterThreadTerminatePort, 8 ) \ + SYSCALL_ENTRY( 0x00d1, NtReleaseKeyedEvent, 32 ) \ + SYSCALL_ENTRY( 0x00d2, NtRemoveIoCompletionEx, 48 ) \ + SYSCALL_ENTRY( 0x00d3, NtRemoveProcessDebug, 16 ) \ + SYSCALL_ENTRY( 0x00d4, NtRenameKey, 16 ) \ + SYSCALL_ENTRY( 0x00d5, NtReplaceKey, 24 ) \ + SYSCALL_ENTRY( 0x00d6, NtResetEvent, 16 ) \ + SYSCALL_ENTRY( 0x00d7, NtResetWriteWatch, 24 ) \ + SYSCALL_ENTRY( 0x00d8, NtRestoreKey, 24 ) \ + SYSCALL_ENTRY( 0x00d9, NtResumeProcess, 8 ) \ + SYSCALL_ENTRY( 0x00da, NtRollbackTransaction, 16 ) \ + SYSCALL_ENTRY( 0x00db, NtSaveKey, 16 ) \ + SYSCALL_ENTRY( 0x00dc, NtSecureConnectPort, 72 ) \ + SYSCALL_ENTRY( 0x00dd, NtSetContextThread, 16 ) \ + SYSCALL_ENTRY( 0x00de, NtSetDebugFilterState, 24 ) \ + SYSCALL_ENTRY( 0x00df, NtSetDefaultLocale, 16 ) \ + SYSCALL_ENTRY( 0x00e0, NtSetDefaultUILanguage, 8 ) \ + SYSCALL_ENTRY( 0x00e1, NtSetEaFile, 32 ) \ + SYSCALL_ENTRY( 0x00e2, NtSetInformationDebugObject, 40 ) \ + SYSCALL_ENTRY( 0x00e3, NtSetInformationJobObject, 32 ) \ + SYSCALL_ENTRY( 0x00e4, NtSetInformationKey, 32 ) \ + SYSCALL_ENTRY( 0x00e5, NtSetInformationToken, 32 ) \ + SYSCALL_ENTRY( 0x00e6, NtSetInformationVirtualMemory, 48 ) \ + SYSCALL_ENTRY( 0x00e7, NtSetIntervalProfile, 16 ) \ + SYSCALL_ENTRY( 0x00e8, NtSetIoCompletion, 40 ) \ + SYSCALL_ENTRY( 0x00e9, NtSetIoCompletionEx, 48 ) \ + SYSCALL_ENTRY( 0x00ea, NtSetLdtEntries, 32 ) \ + SYSCALL_ENTRY( 0x00eb, NtSetSecurityObject, 24 ) \ + SYSCALL_ENTRY( 0x00ec, NtSetSystemInformation, 24 ) \ + SYSCALL_ENTRY( 0x00ed, NtSetSystemTime, 16 ) \ + SYSCALL_ENTRY( 0x00ee, NtSetThreadExecutionState, 16 ) \ + SYSCALL_ENTRY( 0x00ef, NtSetTimerResolution, 24 ) \ + SYSCALL_ENTRY( 0x00f0, NtSetVolumeInformationFile, 40 ) \ + SYSCALL_ENTRY( 0x00f1, NtShutdownSystem, 8 ) \ + SYSCALL_ENTRY( 0x00f2, NtSignalAndWaitForSingleObject, 32 ) \ + SYSCALL_ENTRY( 0x00f3, NtSuspendProcess, 8 ) \ + SYSCALL_ENTRY( 0x00f4, NtSuspendThread, 16 ) \ + SYSCALL_ENTRY( 0x00f5, NtSystemDebugControl, 48 ) \ + SYSCALL_ENTRY( 0x00f6, NtTerminateJobObject, 16 ) \ + SYSCALL_ENTRY( 0x00f7, NtTestAlert, 0 ) \ + SYSCALL_ENTRY( 0x00f8, NtTraceControl, 48 ) \ + SYSCALL_ENTRY( 0x00f9, NtUnloadDriver, 8 ) \ + SYSCALL_ENTRY( 0x00fa, NtUnloadKey, 8 ) \ + SYSCALL_ENTRY( 0x00fb, NtUnlockFile, 40 ) \ + SYSCALL_ENTRY( 0x00fc, NtUnlockVirtualMemory, 32 ) \ + SYSCALL_ENTRY( 0x00fd, NtUnmapViewOfSectionEx, 24 ) \ + SYSCALL_ENTRY( 0x00fe, NtWaitForAlertByThreadId, 16 ) \ + SYSCALL_ENTRY( 0x00ff, NtWaitForDebugEvent, 32 ) \ + SYSCALL_ENTRY( 0x0100, NtWaitForKeyedEvent, 32 ) #else #define ALL_SYSCALLS ALL_SYSCALLS32 #endif diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 0f4b55b60c4..a93aae89554 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -512,6 +512,7 @@ DEFINE_SYSCALL(NtQueryVirtualMemory, (HANDLE process, LPCVOID addr, MEMORY_INFOR DEFINE_SYSCALL(NtQueryVolumeInformationFile, (HANDLE handle, IO_STATUS_BLOCK *io, void *buffer, ULONG length, FS_INFORMATION_CLASS info_class)) DEFINE_SYSCALL(NtQueueApcThread, (HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3)) DEFINE_SYSCALL(NtQueueApcThreadEx, (HANDLE handle, HANDLE reserve_handle, PNTAPCFUNC func, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3)) +DEFINE_SYSCALL(NtQueueApcThreadEx2, (HANDLE handle, HANDLE reserve_handle, ULONG flags, PNTAPCFUNC func, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3)) DEFINE_WRAPPED_SYSCALL(NtRaiseException, (EXCEPTION_RECORD *rec, ARM64_NT_CONTEXT *context, BOOL first_chance)) DEFINE_SYSCALL(NtRaiseHardError, (NTSTATUS status, ULONG count, ULONG params_mask, void **params, HARDERROR_RESPONSE_OPTION option, HARDERROR_RESPONSE *response)) DEFINE_WRAPPED_SYSCALL(NtReadFile, (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, void *buffer, ULONG length, LARGE_INTEGER *offset, ULONG *key)) diff --git a/dlls/ntdll/tests/thread.c b/dlls/ntdll/tests/thread.c index 102ed854165..caf58c60b89 100644 --- a/dlls/ntdll/tests/thread.c +++ b/dlls/ntdll/tests/thread.c @@ -28,22 +28,38 @@ #include "winternl.h" #include "wine/test.h"
+static BOOL is_wow64; + +static NTSTATUS (WINAPI *pNtAllocateReserveObject)( HANDLE *, const OBJECT_ATTRIBUTES *, MEMORY_RESERVE_OBJECT_TYPE ); static NTSTATUS (WINAPI *pNtCreateThreadEx)( HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, HANDLE, PRTL_THREAD_START_ROUTINE, void *, ULONG, ULONG_PTR, SIZE_T, SIZE_T, PS_ATTRIBUTE_LIST * ); static NTSTATUS (WINAPI *pNtSuspendProcess)(HANDLE process); static NTSTATUS (WINAPI *pNtResumeProcess)(HANDLE process); +static NTSTATUS (WINAPI *pNtQueueApcThreadEx)(HANDLE handle, HANDLE reserve_handle, PNTAPCFUNC func, + ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3); +static NTSTATUS (WINAPI *pNtQueueApcThreadEx2)(HANDLE handle, HANDLE reserve_handle, ULONG flags, PNTAPCFUNC func, + ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3);
static int * (CDECL *p_errno)(void);
+static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); + static void init_function_pointers(void) { - HMODULE hntdll = GetModuleHandleA( "ntdll.dll" ); -#define GET_FUNC(name) p##name = (void *)GetProcAddress( hntdll, #name ); + HMODULE hdll; +#define GET_FUNC(name) p##name = (void *)GetProcAddress( hdll, #name ); + hdll = GetModuleHandleA( "ntdll.dll" ); + GET_FUNC( NtAllocateReserveObject ); GET_FUNC( NtCreateThreadEx ); GET_FUNC( NtSuspendProcess ); + GET_FUNC( NtQueueApcThreadEx ); + GET_FUNC( NtQueueApcThreadEx2 ); GET_FUNC( NtResumeProcess ); GET_FUNC( _errno ); + + hdll = GetModuleHandleA( "kernel32.dll" ); + GET_FUNC( IsWow64Process ); #undef GET_FUNC }
@@ -275,13 +291,79 @@ static void test_thread_bypass_process_freeze(void) CloseHandle( thread ); }
+static int apc_count; + +static void CALLBACK apc_func( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 ) +{ + ++apc_count; +} + +static void test_NtQueueApcThreadEx(void) +{ + NTSTATUS status, expected; + HANDLE reserve; + + if (!pNtQueueApcThreadEx) + { + win_skip( "NtQueueApcThreadEx is not available.\n" ); + return; + } + + status = pNtQueueApcThreadEx( GetCurrentThread(), (HANDLE)QUEUE_USER_APC_CALLBACK_DATA_CONTEXT, apc_func, 0x1234, 0x5678, 0xdeadbeef ); + todo_wine_if(!status) ok( status == STATUS_INVALID_HANDLE, "got %#lx, expected %#lx.\n", status, STATUS_INVALID_HANDLE ); + + status = pNtQueueApcThreadEx( GetCurrentThread(), (HANDLE)QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC, apc_func, 0x1234, 0x5678, 0xdeadbeef ); + ok( status == STATUS_SUCCESS || status == STATUS_INVALID_HANDLE /* wow64 and win64 on Win version before Win10 1809 */, + "got %#lx.\n", status ); + + status = pNtQueueApcThreadEx( GetCurrentThread(), GetCurrentThread(), apc_func, 0x1234, 0x5678, 0xdeadbeef ); + todo_wine_if(!status) ok( status == STATUS_OBJECT_TYPE_MISMATCH, "got %#lx.\n", status ); + + status = pNtAllocateReserveObject( &reserve, NULL, MemoryReserveObjectTypeUserApc ); + ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); + status = pNtQueueApcThreadEx( GetCurrentThread(), reserve, apc_func, 0x1234, 0x5678, 0xdeadbeef ); + ok( !status, "got %#lx.\n", status ); + status = pNtQueueApcThreadEx( GetCurrentThread(), reserve, apc_func, 0x1234, 0x5678, 0xdeadbeef ); + todo_wine_if(!status) ok( status == STATUS_INVALID_PARAMETER_2, "got %#lx.\n", status ); + SleepEx( 0, TRUE ); + status = pNtQueueApcThreadEx( GetCurrentThread(), reserve, apc_func, 0x1234, 0x5678, 0xdeadbeef ); + ok( !status, "got %#lx.\n", status ); + + NtClose( reserve ); + + status = pNtAllocateReserveObject( &reserve, NULL, MemoryReserveObjectTypeIoCompletion ); + ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); + status = pNtQueueApcThreadEx( GetCurrentThread(), reserve, apc_func, 0x1234, 0x5678, 0xdeadbeef ); + todo_wine_if(!status) ok( status == STATUS_OBJECT_TYPE_MISMATCH, "got %#lx.\n", status ); + NtClose( reserve ); + + SleepEx( 0, TRUE ); + + if (!pNtQueueApcThreadEx2) + { + win_skip( "NtQueueApcThreadEx2 is not available.\n" ); + return; + } + expected = is_wow64 ? STATUS_NOT_SUPPORTED : STATUS_SUCCESS; + status = pNtQueueApcThreadEx2( GetCurrentThread(), NULL, QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC, apc_func, 0x1234, 0x5678, 0xdeadbeef ); + todo_wine_if(is_wow64) ok( status == expected, "got %#lx, expected %#lx.\n", status, expected ); + + status = pNtQueueApcThreadEx2( GetCurrentThread(), (HANDLE)QUEUE_USER_APC_CALLBACK_DATA_CONTEXT, 0, apc_func, 0x1234, 0x5678, 0xdeadbeef ); + todo_wine_if(!status) ok( status == STATUS_INVALID_HANDLE, "got %#lx.\n", status ); + + SleepEx( 0, TRUE ); +} + START_TEST(thread) { init_function_pointers();
+ if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE; + test_dbg_hidden_thread_creation(); test_unique_teb(); test_errno(); test_NtCreateUserProcess(); test_thread_bypass_process_freeze(); + test_NtQueueApcThreadEx(); } diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index b7f424e1108..9ff4287cf32 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1721,14 +1721,17 @@ NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code )
/****************************************************************************** - * NtQueueApcThread (NTDLL.@) + * NtQueueApcThreadEx2 (NTDLL.@) */ -NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1, - ULONG_PTR arg2, ULONG_PTR arg3 ) +NTSTATUS WINAPI NtQueueApcThreadEx2( HANDLE handle, HANDLE reserve_handle, ULONG flags, + PNTAPCFUNC func, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 ) { unsigned int ret; union apc_call call;
+ TRACE( "%p %p %#x %p %p %p %p.\n", handle, reserve_handle, flags, func, (void *)arg1, (void *)arg2, (void *)arg3 ); + if (reserve_handle || flags) FIXME( "Unsupported reserve_handle %p, flags %#x.\n", reserve_handle, flags ); + SERVER_START_REQ( queue_apc ) { req->handle = wine_server_obj_handle( handle ); @@ -1754,8 +1757,21 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1 NTSTATUS WINAPI NtQueueApcThreadEx( HANDLE handle, HANDLE reserve_handle, PNTAPCFUNC func, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 ) { - FIXME( "reserve handle should be used: %p\n", reserve_handle ); - return NtQueueApcThread( handle, func, arg1, arg2, arg3 ); + ULONG flags = 0; + + flags = (ULONG_PTR)reserve_handle & (ULONG_PTR)3; + reserve_handle = (HANDLE)((ULONG_PTR)reserve_handle & ~(ULONG_PTR)3); + return NtQueueApcThreadEx2( handle, reserve_handle, flags, func, arg1, arg2, arg3 ); +} + + +/****************************************************************************** + * NtQueueApcThread (NTDLL.@) + */ +NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1, + ULONG_PTR arg2, ULONG_PTR arg3 ) +{ + return NtQueueApcThreadEx2( handle, NULL, QUEUE_USER_APC_FLAGS_NONE, func, arg1, arg2, arg3 ); }
diff --git a/dlls/wow64/process.c b/dlls/wow64/process.c index 957ca0d2691..f82f3f2187e 100644 --- a/dlls/wow64/process.c +++ b/dlls/wow64/process.c @@ -834,8 +834,26 @@ NTSTATUS WINAPI wow64_NtQueueApcThreadEx( UINT *args ) ULONG arg2 = get_ulong( &args ); ULONG arg3 = get_ulong( &args );
- return NtQueueApcThreadEx( handle, reserve_handle, apc_32to64( func ), - (ULONG_PTR)apc_param_32to64( func, arg1 ), arg2, arg3 ); + return NtQueueApcThreadEx2( handle, reserve_handle, 0, apc_32to64( func ), + (ULONG_PTR)apc_param_32to64( func, arg1 ), arg2, arg3 ); +} + + +/********************************************************************** + * wow64_NtQueueApcThreadEx + */ +NTSTATUS WINAPI wow64_NtQueueApcThreadEx2( UINT *args ) +{ + HANDLE handle = get_handle( &args ); + HANDLE reserve_handle = get_handle( &args ); + ULONG flags = get_ulong( &args ); + ULONG func = get_ulong( &args ); + ULONG arg1 = get_ulong( &args ); + ULONG arg2 = get_ulong( &args ); + ULONG arg3 = get_ulong( &args ); + + return NtQueueApcThreadEx2( handle, reserve_handle, flags, apc_32to64( func ), + (ULONG_PTR)apc_param_32to64( func, arg1 ), arg2, arg3 ); }
diff --git a/include/processthreadsapi.h b/include/processthreadsapi.h index 44cb2513980..f5f033c99b2 100644 --- a/include/processthreadsapi.h +++ b/include/processthreadsapi.h @@ -49,6 +49,13 @@ WINBASEAPI HRESULT WINAPI GetThreadDescription(HANDLE,PWSTR *); WINBASEAPI HRESULT WINAPI SetThreadDescription(HANDLE,PCWSTR); WINBASEAPI BOOL WINAPI SetThreadInformation(HANDLE,THREAD_INFORMATION_CLASS,LPVOID,DWORD);
+typedef enum _QUEUE_USER_APC_FLAGS +{ + QUEUE_USER_APC_FLAGS_NONE, + QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC = 0x00000001, + QUEUE_USER_APC_CALLBACK_DATA_CONTEXT = 0x00010000, +} QUEUE_USER_APC_FLAGS; + #ifdef __cplusplus } #endif diff --git a/include/winternl.h b/include/winternl.h index 65f8bb721ee..64e82b20eca 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4583,6 +4583,7 @@ NTSYSAPI NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG,ULO NTSYSAPI NTSTATUS WINAPI NtPulseEvent(HANDLE,LONG*); NTSYSAPI NTSTATUS WINAPI NtQueueApcThread(HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR); NTSYSAPI NTSTATUS WINAPI NtQueueApcThreadEx(HANDLE,HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR); +NTSYSAPI NTSTATUS WINAPI NtQueueApcThreadEx2(HANDLE,HANDLE,ULONG,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR); NTSYSAPI NTSTATUS WINAPI NtQueryAttributesFile(const OBJECT_ATTRIBUTES*,FILE_BASIC_INFORMATION*); NTSYSAPI NTSTATUS WINAPI NtQueryDefaultLocale(BOOLEAN,LCID*); NTSYSAPI NTSTATUS WINAPI NtQueryDefaultUILanguage(LANGID*);