For React Native.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/tests/file.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index e60d392346b..85847bc3111 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -51,6 +51,7 @@ static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR ); static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* ); static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtAllocateReserveObject)( HANDLE *, const OBJECT_ATTRIBUTES *, MEMORY_RESERVE_OBJECT_TYPE ); static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG, ULONG, PLARGE_INTEGER ); static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG); @@ -76,6 +77,7 @@ static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER); static NTSTATUS (WINAPI *pNtRemoveIoCompletionEx)(HANDLE,FILE_IO_COMPLETION_INFORMATION*,ULONG,ULONG*,LARGE_INTEGER*,BOOLEAN); static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T); +static NTSTATUS (WINAPI *pNtSetIoCompletionEx)(HANDLE, HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T); static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); static NTSTATUS (WINAPI *pNtQueryAttributesFile)(const OBJECT_ATTRIBUTES*,FILE_BASIC_INFORMATION*); static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); @@ -5932,6 +5934,63 @@ static void test_reparse_points(void) CloseHandle( handle ); }
+static void test_set_io_completion_ex(void) +{ + HANDLE completion, completion_reserve, apc_reserve; + LARGE_INTEGER timeout = {{0}}; + IO_STATUS_BLOCK iosb; + ULONG_PTR key, value; + NTSTATUS status; + SIZE_T size = 3; + + if (!pNtSetIoCompletionEx || !pNtAllocateReserveObject) + { + todo_wine + win_skip("NtSetIoCompletionEx() or NtAllocateReserveObject() is unavailable.\n"); + return; + } + + if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32; + + status = pNtCreateIoCompletion(&completion, IO_COMPLETION_ALL_ACCESS, NULL, 0); + ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status); + status = pNtAllocateReserveObject(&completion_reserve, NULL, MemoryReserveObjectTypeIoCompletion); + ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status); + status = pNtAllocateReserveObject(&apc_reserve, NULL, MemoryReserveObjectTypeUserApc); + ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status); + + /* Parameter checks */ + status = pNtSetIoCompletionEx(NULL, completion_reserve, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size); + ok(status == STATUS_INVALID_HANDLE, "Got unexpected status %#lx.\n", status); + + status = pNtSetIoCompletionEx(INVALID_HANDLE_VALUE, completion_reserve, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size); + ok(status == STATUS_OBJECT_TYPE_MISMATCH, "Got unexpected status %#lx.\n", status); + + status = pNtSetIoCompletionEx(completion, NULL, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size); + ok(status == STATUS_INVALID_HANDLE, "Got unexpected status %#lx.\n", status); + + status = pNtSetIoCompletionEx(completion, INVALID_HANDLE_VALUE, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size); + ok(status == STATUS_OBJECT_TYPE_MISMATCH, "Got unexpected status %#lx.\n", status); + + status = pNtSetIoCompletionEx(completion, apc_reserve, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size); + ok(status == STATUS_OBJECT_TYPE_MISMATCH, "Got unexpected status %#lx.\n", status); + + /* Normal call */ + status = pNtSetIoCompletionEx(completion, completion_reserve, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size); + ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status); + + status = pNtRemoveIoCompletion(completion, &key, &value, &iosb, &timeout); + ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status); + ok(key == CKEY_FIRST, "Invalid completion key: %#Ix\n", key); + ok(iosb.Information == size, "Invalid iosb.Information: %Iu\n", iosb.Information); + ok(iosb.Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid iosb.Status: %#lx\n", iosb.Status); + ok(value == CVALUE_FIRST, "Invalid completion value: %#Ix\n", value); + + CloseHandle(apc_reserve); + CloseHandle(completion_reserve); + CloseHandle(completion); +} + START_TEST(file) { HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); @@ -5949,6 +6008,7 @@ START_TEST(file) pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString"); pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U"); pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx"); + pNtAllocateReserveObject= (void *)GetProcAddress(hntdll, "NtAllocateReserveObject"); pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile"); pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile"); pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile"); @@ -5965,6 +6025,7 @@ START_TEST(file) pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion"); pNtRemoveIoCompletionEx = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletionEx"); pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion"); + pNtSetIoCompletionEx = (void *)GetProcAddress(hntdll, "NtSetIoCompletionEx"); pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile"); pNtQueryAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryAttributesFile"); pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile"); @@ -5983,6 +6044,7 @@ START_TEST(file) append_file_test(); nt_mailslot_test(); test_set_io_completion(); + test_set_io_completion_ex(); test_file_io_completion(); test_file_basic_information(); test_file_all_information();
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/ntdll.spec | 2 ++ dlls/ntdll/signal_arm64ec.c | 1 + dlls/ntdll/tests/file.c | 1 - dlls/ntdll/unix/sync.c | 29 +++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + dlls/wow64/sync.c | 16 ++++++++++++++++ include/winternl.h | 1 + server/completion.c | 8 ++++++++ server/file.h | 2 ++ server/object.c | 5 +++++ server/protocol.def | 2 ++ 11 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index ddf1a120517..6d029bb6289 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -400,6 +400,7 @@ @ stdcall -syscall NtSetInformationVirtualMemory(long long ptr ptr ptr long) @ stdcall -syscall NtSetIntervalProfile(long long) @ stdcall -syscall NtSetIoCompletion(ptr long long long long) +@ stdcall -syscall NtSetIoCompletionEx(ptr ptr long long long long) @ stdcall -syscall NtSetLdtEntries(long int64 long int64) # @ stub NtSetLowEventPair # @ stub NtSetLowWaitHighEventPair @@ -1453,6 +1454,7 @@ @ stdcall -private -syscall ZwSetInformationVirtualMemory(long long ptr ptr ptr long) NtSetInformationVirtualMemory @ stdcall -private -syscall ZwSetIntervalProfile(long long) NtSetIntervalProfile @ stdcall -private -syscall ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion +@ stdcall -private -syscall ZwSetIoCompletionEx(ptr ptr long long long long) NtSetIoCompletionEx @ stdcall -private -syscall ZwSetLdtEntries(long int64 long int64) NtSetLdtEntries # @ stub ZwSetLowEventPair # @ stub ZwSetLowWaitHighEventPair diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 438dfe8d439..f0687737f3f 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -443,6 +443,7 @@ DEFINE_SYSCALL(NtSetInformationToken, (HANDLE token, TOKEN_INFORMATION_CLASS cla DEFINE_SYSCALL(NtSetInformationVirtualMemory, (HANDLE process, VIRTUAL_MEMORY_INFORMATION_CLASS info_class, ULONG_PTR count, PMEMORY_RANGE_ENTRY addresses, PVOID ptr, ULONG size)) DEFINE_SYSCALL(NtSetIntervalProfile, (ULONG interval, KPROFILE_SOURCE source)) DEFINE_SYSCALL(NtSetIoCompletion, (HANDLE handle, ULONG_PTR key, ULONG_PTR value, NTSTATUS status, SIZE_T count)) +DEFINE_SYSCALL(NtSetIoCompletionEx, (HANDLE completion_handle, HANDLE completion_reserve_handle, ULONG_PTR key, ULONG_PTR value, NTSTATUS status, SIZE_T count)) DEFINE_SYSCALL(NtSetLdtEntries, (ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2)) DEFINE_SYSCALL(NtSetSecurityObject, (HANDLE handle, SECURITY_INFORMATION info, PSECURITY_DESCRIPTOR descr)) DEFINE_SYSCALL(NtSetSystemInformation, (SYSTEM_INFORMATION_CLASS class, void *info, ULONG length)) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 85847bc3111..95bd1c37cac 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -5945,7 +5945,6 @@ static void test_set_io_completion_ex(void)
if (!pNtSetIoCompletionEx || !pNtAllocateReserveObject) { - todo_wine win_skip("NtSetIoCompletionEx() or NtAllocateReserveObject() is unavailable.\n"); return; } diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 80f82c18730..3841a579ba2 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -1986,12 +1986,41 @@ NTSTATUS WINAPI NtSetIoCompletion( HANDLE handle, ULONG_PTR key, ULONG_PTR value req->cvalue = value; req->status = status; req->information = count; + req->has_reserve = FALSE; ret = wine_server_call( req ); } SERVER_END_REQ; return ret; }
+/*********************************************************************** + * NtSetIoCompletionEx (NTDLL.@) + * + * completion_reserve_handle is a handle allocated by NtAllocateReserveObject() for pre-allocating + * memory for completion objects to deal with low-memory situations. It's not in use for now. + */ +NTSTATUS WINAPI NtSetIoCompletionEx( HANDLE completion_handle, HANDLE completion_reserve_handle, + ULONG_PTR key, ULONG_PTR value, NTSTATUS status, SIZE_T count ) +{ + unsigned int ret; + + TRACE( "(%p, %p, %lx, %lx, %x, %lx)\n", completion_handle, completion_reserve_handle, + key, value, (int)status, count ); + + SERVER_START_REQ( add_completion ) + { + req->handle = wine_server_obj_handle( completion_handle ); + req->ckey = key; + req->cvalue = value; + req->status = status; + req->information = count; + req->reserve_handle = wine_server_obj_handle( completion_reserve_handle ); + req->has_reserve = TRUE; + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +}
/*********************************************************************** * NtRemoveIoCompletion (NTDLL.@) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index eb85130ae1a..276e166c4a9 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1525,6 +1525,7 @@ @ stdcall -private ZwSetInformationToken(long long ptr long) NtSetInformationToken @ stdcall -private ZwSetIntervalProfile(long long) NtSetIntervalProfile @ stdcall -private ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion +@ stdcall -private ZwSetIoCompletionEx(ptr ptr long long long long) NtSetIoCompletionEx @ stdcall -private ZwSetSecurityObject(long long ptr) NtSetSecurityObject @ stdcall -private ZwSetSystemInformation(long ptr long) NtSetSystemInformation @ stdcall -private ZwSetSystemTime(ptr ptr) NtSetSystemTime diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index a445da2d620..54dca19dc1a 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -1449,6 +1449,22 @@ NTSTATUS WINAPI wow64_NtSetIoCompletion( UINT *args ) }
+/********************************************************************** + * wow64_NtSetIoCompletionEx + */ +NTSTATUS WINAPI wow64_NtSetIoCompletionEx( UINT *args ) +{ + HANDLE completion_handle = get_handle( &args ); + HANDLE completion_reserve_handle = get_handle( &args ); + ULONG_PTR key = get_ulong( &args ); + ULONG_PTR value = get_ulong( &args ); + NTSTATUS status = get_ulong( &args ); + SIZE_T count = get_ulong( &args ); + + return NtSetIoCompletionEx( completion_handle, completion_reserve_handle, key, value, status, count ); +} + + /********************************************************************** * wow64_NtSetTimer */ diff --git a/include/winternl.h b/include/winternl.h index bc3ef12bc0d..edccef5ad18 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4675,6 +4675,7 @@ NTSYSAPI NTSTATUS WINAPI NtSetInformationToken(HANDLE,TOKEN_INFORMATION_CLASS,P NTSYSAPI NTSTATUS WINAPI NtSetInformationVirtualMemory(HANDLE,VIRTUAL_MEMORY_INFORMATION_CLASS,ULONG_PTR,PMEMORY_RANGE_ENTRY,PVOID,ULONG); NTSYSAPI NTSTATUS WINAPI NtSetIntervalProfile(ULONG,KPROFILE_SOURCE); NTSYSAPI NTSTATUS WINAPI NtSetIoCompletion(HANDLE,ULONG_PTR,ULONG_PTR,NTSTATUS,SIZE_T); +NTSYSAPI NTSTATUS WINAPI NtSetIoCompletionEx(HANDLE,HANDLE,ULONG_PTR,ULONG_PTR,NTSTATUS,SIZE_T); NTSYSAPI NTSTATUS WINAPI NtSetLdtEntries(ULONG,LDT_ENTRY,ULONG,LDT_ENTRY); NTSYSAPI NTSTATUS WINAPI NtSetLowEventPair(HANDLE); NTSYSAPI NTSTATUS WINAPI NtSetLowWaitHighEventPair(HANDLE); diff --git a/server/completion.c b/server/completion.c index f9e68c523f1..47ae4092417 100644 --- a/server/completion.c +++ b/server/completion.c @@ -344,11 +344,19 @@ DECL_HANDLER(open_completion) DECL_HANDLER(add_completion) { struct completion* completion = get_completion_obj( current->process, req->handle, IO_COMPLETION_MODIFY_STATE ); + struct reserve* reserve = NULL;
if (!completion) return;
+ if (req->has_reserve && !(reserve = get_completion_reserve_obj( current->process, req->reserve_handle, 0 ))) + { + release_object( completion ); + return; + } + add_completion( completion, req->ckey, req->cvalue, req->status, req->information );
+ if (reserve) release_object( reserve ); release_object( completion ); }
diff --git a/server/file.h b/server/file.h index 3d7cdc460ff..eb4eff96575 100644 --- a/server/file.h +++ b/server/file.h @@ -29,6 +29,7 @@ struct fd; struct mapping; struct async_queue; struct completion; +struct reserve;
/* server-side representation of I/O status block */ struct iosb @@ -236,6 +237,7 @@ extern struct dir *get_dir_obj( struct process *process, obj_handle_t handle, un /* completion */
extern struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access ); +extern struct reserve *get_completion_reserve_obj( struct process *process, obj_handle_t handle, unsigned int access ); extern void add_completion( struct completion *completion, apc_param_t ckey, apc_param_t cvalue, unsigned int status, apc_param_t information ); extern void cleanup_thread_completion( struct thread *thread ); diff --git a/server/object.c b/server/object.c index b1665fb5372..cd368ef724a 100644 --- a/server/object.c +++ b/server/object.c @@ -854,6 +854,11 @@ static struct reserve *create_reserve( struct object *root, const struct unicode return reserve; }
+struct reserve *get_completion_reserve_obj( struct process *process, obj_handle_t handle, unsigned int access ) +{ + return (struct reserve *)get_handle_obj( process, handle, access, &completion_reserve_ops ); +} + /* Allocate a reserve object for pre-allocating memory for object types */ DECL_HANDLER(allocate_reserve_object) { diff --git a/server/protocol.def b/server/protocol.def index 9ecb14cbac4..c0e3980c964 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3800,10 +3800,12 @@ typedef union /* add completion to completion port */ @REQ(add_completion) obj_handle_t handle; /* port handle */ + obj_handle_t reserve_handle; /* completion reserve object handle */ apc_param_t ckey; /* completion key */ apc_param_t cvalue; /* completion value */ apc_param_t information; /* IO_STATUS_BLOCK Information */ unsigned int status; /* completion result */ + int has_reserve; /* whether completion reserve object handle is valid */ @END
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149475
Your paranoid android.
=== debian11 (build log) ===
/usr/bin/i686-w64-mingw32-ld: tmp674f4cd6/ntdll-00000000.spec.o:fake:(.edata+0x508): undefined reference to `NtSetIoCompletionEx@24' /usr/bin/i686-w64-mingw32-ld: tmp674f4cd6/ntdll-00000000.spec.o:fake:(.edata+0x1270): undefined reference to `NtSetIoCompletionEx@24' collect2: error: ld returned 1 exit status Task: The win32 Wine build failed
=== debian11b (build log) ===
/usr/bin/x86_64-w64-mingw32-ld: tmp67348f71/ntdll-00000000.spec.o:fake:(.edata+0x504): undefined reference to `NtSetIoCompletionEx' /usr/bin/x86_64-w64-mingw32-ld: tmp67348f71/ntdll-00000000.spec.o:fake:(.edata+0x1268): undefined reference to `NtSetIoCompletionEx' collect2: error: ld returned 1 exit status Task: The wow64 Wine build failed