diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index aee6a6a0076..24de8340e45 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 @@ -1460,6 +1461,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/ntsyscalls.h b/dlls/ntdll/ntsyscalls.h index b03002b7cd8..0de8ef81818 100644 --- a/dlls/ntdll/ntsyscalls.h +++ b/dlls/ntdll/ntsyscalls.h @@ -203,48 +203,49 @@ SYSCALL_ENTRY( 0x00c7, NtSetInformationVirtualMemory, 24 ) \ SYSCALL_ENTRY( 0x00c8, NtSetIntervalProfile, 8 ) \ SYSCALL_ENTRY( 0x00c9, NtSetIoCompletion, 20 ) \ - SYSCALL_ENTRY( 0x00ca, NtSetLdtEntries, 24 ) \ - SYSCALL_ENTRY( 0x00cb, NtSetSecurityObject, 12 ) \ - SYSCALL_ENTRY( 0x00cc, NtSetSystemInformation, 12 ) \ - SYSCALL_ENTRY( 0x00cd, NtSetSystemTime, 8 ) \ - SYSCALL_ENTRY( 0x00ce, NtSetThreadExecutionState, 8 ) \ - SYSCALL_ENTRY( 0x00cf, NtSetTimer, 28 ) \ - SYSCALL_ENTRY( 0x00d0, NtSetTimerResolution, 12 ) \ - SYSCALL_ENTRY( 0x00d1, NtSetValueKey, 24 ) \ - SYSCALL_ENTRY( 0x00d2, NtSetVolumeInformationFile, 20 ) \ - SYSCALL_ENTRY( 0x00d3, NtShutdownSystem, 4 ) \ - SYSCALL_ENTRY( 0x00d4, NtSignalAndWaitForSingleObject, 16 ) \ - SYSCALL_ENTRY( 0x00d5, NtSuspendProcess, 4 ) \ - SYSCALL_ENTRY( 0x00d6, NtSuspendThread, 8 ) \ - SYSCALL_ENTRY( 0x00d7, NtSystemDebugControl, 24 ) \ - SYSCALL_ENTRY( 0x00d8, NtTerminateJobObject, 8 ) \ - SYSCALL_ENTRY( 0x00d9, NtTerminateProcess, 8 ) \ - SYSCALL_ENTRY( 0x00da, NtTerminateThread, 8 ) \ - SYSCALL_ENTRY( 0x00db, NtTestAlert, 0 ) \ - SYSCALL_ENTRY( 0x00dc, NtTraceControl, 24 ) \ - SYSCALL_ENTRY( 0x00dd, NtUnloadDriver, 4 ) \ - SYSCALL_ENTRY( 0x00de, NtUnloadKey, 4 ) \ - SYSCALL_ENTRY( 0x00df, NtUnlockFile, 20 ) \ - SYSCALL_ENTRY( 0x00e0, NtUnlockVirtualMemory, 16 ) \ - SYSCALL_ENTRY( 0x00e1, NtUnmapViewOfSection, 8 ) \ - SYSCALL_ENTRY( 0x00e2, NtUnmapViewOfSectionEx, 12 ) \ - SYSCALL_ENTRY( 0x00e3, NtWaitForAlertByThreadId, 8 ) \ - SYSCALL_ENTRY( 0x00e4, NtWaitForDebugEvent, 16 ) \ - SYSCALL_ENTRY( 0x00e5, NtWaitForKeyedEvent, 16 ) \ - SYSCALL_ENTRY( 0x00e6, NtWaitForMultipleObjects, 20 ) \ - SYSCALL_ENTRY( 0x00e7, NtWaitForSingleObject, 12 ) \ - SYSCALL_ENTRY( 0x00e8, NtWow64AllocateVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x00e9, NtWow64GetNativeSystemInformation, 16 ) \ - SYSCALL_ENTRY( 0x00ea, NtWow64IsProcessorFeaturePresent, 4 ) \ - SYSCALL_ENTRY( 0x00eb, NtWow64QueryInformationProcess64, 20 ) \ - SYSCALL_ENTRY( 0x00ec, NtWow64ReadVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x00ed, NtWow64WriteVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x00ee, NtWriteFile, 36 ) \ - SYSCALL_ENTRY( 0x00ef, NtWriteFileGather, 36 ) \ - SYSCALL_ENTRY( 0x00f0, NtWriteVirtualMemory, 20 ) \ - SYSCALL_ENTRY( 0x00f1, NtYieldExecution, 0 ) \ - SYSCALL_ENTRY( 0x00f2, wine_nt_to_unix_file_name, 16 ) \ - SYSCALL_ENTRY( 0x00f3, wine_unix_to_nt_file_name, 12 ) + SYSCALL_ENTRY( 0x00ca, NtSetIoCompletionEx, 24 ) \ + SYSCALL_ENTRY( 0x00cb, NtSetLdtEntries, 24 ) \ + SYSCALL_ENTRY( 0x00cc, NtSetSecurityObject, 12 ) \ + SYSCALL_ENTRY( 0x00cd, NtSetSystemInformation, 12 ) \ + SYSCALL_ENTRY( 0x00ce, NtSetSystemTime, 8 ) \ + SYSCALL_ENTRY( 0x00cf, NtSetThreadExecutionState, 8 ) \ + SYSCALL_ENTRY( 0x00d0, NtSetTimer, 28 ) \ + SYSCALL_ENTRY( 0x00d1, NtSetTimerResolution, 12 ) \ + SYSCALL_ENTRY( 0x00d2, NtSetValueKey, 24 ) \ + SYSCALL_ENTRY( 0x00d3, NtSetVolumeInformationFile, 20 ) \ + SYSCALL_ENTRY( 0x00d4, NtShutdownSystem, 4 ) \ + SYSCALL_ENTRY( 0x00d5, NtSignalAndWaitForSingleObject, 16 ) \ + SYSCALL_ENTRY( 0x00d6, NtSuspendProcess, 4 ) \ + SYSCALL_ENTRY( 0x00d7, NtSuspendThread, 8 ) \ + SYSCALL_ENTRY( 0x00d8, NtSystemDebugControl, 24 ) \ + SYSCALL_ENTRY( 0x00d9, NtTerminateJobObject, 8 ) \ + SYSCALL_ENTRY( 0x00da, NtTerminateProcess, 8 ) \ + SYSCALL_ENTRY( 0x00db, NtTerminateThread, 8 ) \ + SYSCALL_ENTRY( 0x00dc, NtTestAlert, 0 ) \ + SYSCALL_ENTRY( 0x00dd, NtTraceControl, 24 ) \ + SYSCALL_ENTRY( 0x00de, NtUnloadDriver, 4 ) \ + SYSCALL_ENTRY( 0x00df, NtUnloadKey, 4 ) \ + SYSCALL_ENTRY( 0x00e0, NtUnlockFile, 20 ) \ + SYSCALL_ENTRY( 0x00e1, NtUnlockVirtualMemory, 16 ) \ + SYSCALL_ENTRY( 0x00e2, NtUnmapViewOfSection, 8 ) \ + SYSCALL_ENTRY( 0x00e3, NtUnmapViewOfSectionEx, 12 ) \ + SYSCALL_ENTRY( 0x00e4, NtWaitForAlertByThreadId, 8 ) \ + SYSCALL_ENTRY( 0x00e5, NtWaitForDebugEvent, 16 ) \ + SYSCALL_ENTRY( 0x00e6, NtWaitForKeyedEvent, 16 ) \ + SYSCALL_ENTRY( 0x00e7, NtWaitForMultipleObjects, 20 ) \ + SYSCALL_ENTRY( 0x00e8, NtWaitForSingleObject, 12 ) \ + SYSCALL_ENTRY( 0x00e9, NtWow64AllocateVirtualMemory64, 28 ) \ + SYSCALL_ENTRY( 0x00ea, NtWow64GetNativeSystemInformation, 16 ) \ + SYSCALL_ENTRY( 0x00eb, NtWow64IsProcessorFeaturePresent, 4 ) \ + SYSCALL_ENTRY( 0x00ec, NtWow64QueryInformationProcess64, 20 ) \ + SYSCALL_ENTRY( 0x00ed, NtWow64ReadVirtualMemory64, 28 ) \ + SYSCALL_ENTRY( 0x00ee, NtWow64WriteVirtualMemory64, 28 ) \ + SYSCALL_ENTRY( 0x00ef, NtWriteFile, 36 ) \ + SYSCALL_ENTRY( 0x00f0, NtWriteFileGather, 36 ) \ + SYSCALL_ENTRY( 0x00f1, NtWriteVirtualMemory, 20 ) \ + SYSCALL_ENTRY( 0x00f2, NtYieldExecution, 0 ) \ + SYSCALL_ENTRY( 0x00f3, wine_nt_to_unix_file_name, 16 ) \ + SYSCALL_ENTRY( 0x00f4, wine_unix_to_nt_file_name, 12 ) #define ALL_SYSCALLS64 \ SYSCALL_ENTRY( 0x0000, NtAcceptConnectPort, 48 ) \ @@ -449,39 +450,40 @@ SYSCALL_ENTRY( 0x00c7, NtSetInformationVirtualMemory, 48 ) \ SYSCALL_ENTRY( 0x00c8, NtSetIntervalProfile, 16 ) \ SYSCALL_ENTRY( 0x00c9, NtSetIoCompletion, 40 ) \ - SYSCALL_ENTRY( 0x00ca, NtSetLdtEntries, 32 ) \ - SYSCALL_ENTRY( 0x00cb, NtSetSecurityObject, 24 ) \ - SYSCALL_ENTRY( 0x00cc, NtSetSystemInformation, 24 ) \ - SYSCALL_ENTRY( 0x00cd, NtSetSystemTime, 16 ) \ - SYSCALL_ENTRY( 0x00ce, NtSetThreadExecutionState, 16 ) \ - SYSCALL_ENTRY( 0x00cf, NtSetTimer, 56 ) \ - SYSCALL_ENTRY( 0x00d0, NtSetTimerResolution, 24 ) \ - SYSCALL_ENTRY( 0x00d1, NtSetValueKey, 48 ) \ - SYSCALL_ENTRY( 0x00d2, NtSetVolumeInformationFile, 40 ) \ - SYSCALL_ENTRY( 0x00d3, NtShutdownSystem, 8 ) \ - SYSCALL_ENTRY( 0x00d4, NtSignalAndWaitForSingleObject, 32 ) \ - SYSCALL_ENTRY( 0x00d5, NtSuspendProcess, 8 ) \ - SYSCALL_ENTRY( 0x00d6, NtSuspendThread, 16 ) \ - SYSCALL_ENTRY( 0x00d7, NtSystemDebugControl, 48 ) \ - SYSCALL_ENTRY( 0x00d8, NtTerminateJobObject, 16 ) \ - SYSCALL_ENTRY( 0x00d9, NtTerminateProcess, 16 ) \ - SYSCALL_ENTRY( 0x00da, NtTerminateThread, 16 ) \ - SYSCALL_ENTRY( 0x00db, NtTestAlert, 0 ) \ - SYSCALL_ENTRY( 0x00dc, NtTraceControl, 48 ) \ - SYSCALL_ENTRY( 0x00dd, NtUnloadDriver, 8 ) \ - SYSCALL_ENTRY( 0x00de, NtUnloadKey, 8 ) \ - SYSCALL_ENTRY( 0x00df, NtUnlockFile, 40 ) \ - SYSCALL_ENTRY( 0x00e0, NtUnlockVirtualMemory, 32 ) \ - SYSCALL_ENTRY( 0x00e1, NtUnmapViewOfSection, 16 ) \ - SYSCALL_ENTRY( 0x00e2, NtUnmapViewOfSectionEx, 24 ) \ - SYSCALL_ENTRY( 0x00e3, NtWaitForAlertByThreadId, 16 ) \ - SYSCALL_ENTRY( 0x00e4, NtWaitForDebugEvent, 32 ) \ - SYSCALL_ENTRY( 0x00e5, NtWaitForKeyedEvent, 32 ) \ - SYSCALL_ENTRY( 0x00e6, NtWaitForMultipleObjects, 40 ) \ - SYSCALL_ENTRY( 0x00e7, NtWaitForSingleObject, 24 ) \ - SYSCALL_ENTRY( 0x00e8, NtWriteFile, 72 ) \ - SYSCALL_ENTRY( 0x00e9, NtWriteFileGather, 72 ) \ - SYSCALL_ENTRY( 0x00ea, NtWriteVirtualMemory, 40 ) \ - SYSCALL_ENTRY( 0x00eb, NtYieldExecution, 0 ) \ - SYSCALL_ENTRY( 0x00ec, wine_nt_to_unix_file_name, 32 ) \ - SYSCALL_ENTRY( 0x00ed, wine_unix_to_nt_file_name, 24 ) + SYSCALL_ENTRY( 0x00ca, NtSetIoCompletionEx, 48 ) \ + SYSCALL_ENTRY( 0x00cb, NtSetLdtEntries, 32 ) \ + SYSCALL_ENTRY( 0x00cc, NtSetSecurityObject, 24 ) \ + SYSCALL_ENTRY( 0x00cd, NtSetSystemInformation, 24 ) \ + SYSCALL_ENTRY( 0x00ce, NtSetSystemTime, 16 ) \ + SYSCALL_ENTRY( 0x00cf, NtSetThreadExecutionState, 16 ) \ + SYSCALL_ENTRY( 0x00d0, NtSetTimer, 56 ) \ + SYSCALL_ENTRY( 0x00d1, NtSetTimerResolution, 24 ) \ + SYSCALL_ENTRY( 0x00d2, NtSetValueKey, 48 ) \ + SYSCALL_ENTRY( 0x00d3, NtSetVolumeInformationFile, 40 ) \ + SYSCALL_ENTRY( 0x00d4, NtShutdownSystem, 8 ) \ + SYSCALL_ENTRY( 0x00d5, NtSignalAndWaitForSingleObject, 32 ) \ + SYSCALL_ENTRY( 0x00d6, NtSuspendProcess, 8 ) \ + SYSCALL_ENTRY( 0x00d7, NtSuspendThread, 16 ) \ + SYSCALL_ENTRY( 0x00d8, NtSystemDebugControl, 48 ) \ + SYSCALL_ENTRY( 0x00d9, NtTerminateJobObject, 16 ) \ + SYSCALL_ENTRY( 0x00da, NtTerminateProcess, 16 ) \ + SYSCALL_ENTRY( 0x00db, NtTerminateThread, 16 ) \ + SYSCALL_ENTRY( 0x00dc, NtTestAlert, 0 ) \ + SYSCALL_ENTRY( 0x00dd, NtTraceControl, 48 ) \ + SYSCALL_ENTRY( 0x00de, NtUnloadDriver, 8 ) \ + SYSCALL_ENTRY( 0x00df, NtUnloadKey, 8 ) \ + SYSCALL_ENTRY( 0x00e0, NtUnlockFile, 40 ) \ + SYSCALL_ENTRY( 0x00e1, NtUnlockVirtualMemory, 32 ) \ + SYSCALL_ENTRY( 0x00e2, NtUnmapViewOfSection, 16 ) \ + SYSCALL_ENTRY( 0x00e3, NtUnmapViewOfSectionEx, 24 ) \ + SYSCALL_ENTRY( 0x00e4, NtWaitForAlertByThreadId, 16 ) \ + SYSCALL_ENTRY( 0x00e5, NtWaitForDebugEvent, 32 ) \ + SYSCALL_ENTRY( 0x00e6, NtWaitForKeyedEvent, 32 ) \ + SYSCALL_ENTRY( 0x00e7, NtWaitForMultipleObjects, 40 ) \ + SYSCALL_ENTRY( 0x00e8, NtWaitForSingleObject, 24 ) \ + SYSCALL_ENTRY( 0x00e9, NtWriteFile, 72 ) \ + SYSCALL_ENTRY( 0x00ea, NtWriteFileGather, 72 ) \ + SYSCALL_ENTRY( 0x00eb, NtWriteVirtualMemory, 40 ) \ + SYSCALL_ENTRY( 0x00ec, NtYieldExecution, 0 ) \ + SYSCALL_ENTRY( 0x00ed, wine_nt_to_unix_file_name, 32 ) \ + SYSCALL_ENTRY( 0x00ee, wine_unix_to_nt_file_name, 24 ) 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..a2d587ac197 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -1992,6 +1992,35 @@ NTSTATUS WINAPI NtSetIoCompletion( HANDLE handle, ULONG_PTR key, ULONG_PTR value 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 ); + + if (!completion_reserve_handle) return STATUS_INVALID_HANDLE; + + 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 ); + 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/wine/server_protocol.h b/include/wine/server_protocol.h index 0a9d9516f64..ee610e2b30c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -5412,8 +5412,8 @@ struct add_completion_request apc_param_t ckey; apc_param_t cvalue; apc_param_t information; + obj_handle_t reserve_handle; unsigned int status; - char __pad_44[4]; }; struct add_completion_reply { @@ -6760,7 +6760,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 847 +#define SERVER_PROTOCOL_VERSION 848 /* ### protocol_version end ### */ diff --git a/include/winternl.h b/include/winternl.h index 691c3212393..440054f9a19 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..f4fad9dbeca 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->reserve_handle && !(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..e2125b90ded 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3803,6 +3803,7 @@ typedef union apc_param_t ckey; /* completion key */ apc_param_t cvalue; /* completion value */ apc_param_t information; /* IO_STATUS_BLOCK Information */ + obj_handle_t reserve_handle; /* completion reserve object handle */ unsigned int status; /* completion result */ @END diff --git a/server/request.h b/server/request.h index 0ec527f2b4f..6ca222539bb 100644 --- a/server/request.h +++ b/server/request.h @@ -2237,7 +2237,8 @@ C_ASSERT( FIELD_OFFSET(struct add_completion_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct add_completion_request, ckey) == 16 ); C_ASSERT( FIELD_OFFSET(struct add_completion_request, cvalue) == 24 ); C_ASSERT( FIELD_OFFSET(struct add_completion_request, information) == 32 ); -C_ASSERT( FIELD_OFFSET(struct add_completion_request, status) == 40 ); +C_ASSERT( FIELD_OFFSET(struct add_completion_request, reserve_handle) == 40 ); +C_ASSERT( FIELD_OFFSET(struct add_completion_request, status) == 44 ); C_ASSERT( sizeof(struct add_completion_request) == 48 ); C_ASSERT( FIELD_OFFSET(struct remove_completion_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct remove_completion_request, alertable) == 16 ); diff --git a/server/trace.c b/server/trace.c index 5fd69aa420b..ea4c0aacf12 100644 --- a/server/trace.c +++ b/server/trace.c @@ -4536,6 +4536,7 @@ static void dump_add_completion_request( const struct add_completion_request *re dump_uint64( ", ckey=", &req->ckey ); dump_uint64( ", cvalue=", &req->cvalue ); dump_uint64( ", information=", &req->information ); + fprintf( stderr, ", reserve_handle=%04x", req->reserve_handle ); fprintf( stderr, ", status=%08x", req->status ); }