diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index b8f53b300b8..e7768646da2 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -741,122 +741,31 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, /****************************************************************** * NtCreateIoCompletion (NTDLL.@) * ZwCreateIoCompletion (NTDLL.@) - * - * Creates I/O completion object. - * - * PARAMS - * CompletionPort [O] created completion object handle will be placed there - * DesiredAccess [I] desired access to a handle (combination of IO_COMPLETION_*) - * ObjectAttributes [I] completion object attributes - * NumberOfConcurrentThreads [I] desired number of concurrent active worker threads - * */ -NTSTATUS WINAPI NtCreateIoCompletion( PHANDLE CompletionPort, ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES attr, ULONG NumberOfConcurrentThreads ) +NTSTATUS WINAPI NtCreateIoCompletion( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + ULONG threads ) { - NTSTATUS status; - data_size_t len; - struct object_attributes *objattr; - - TRACE("(%p, %x, %p, %d)\n", CompletionPort, DesiredAccess, attr, NumberOfConcurrentThreads); - - if (!CompletionPort) - return STATUS_INVALID_PARAMETER; - - if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status; - - SERVER_START_REQ( create_completion ) - { - req->access = DesiredAccess; - req->concurrent = NumberOfConcurrentThreads; - wine_server_add_data( req, objattr, len ); - if (!(status = wine_server_call( req ))) - *CompletionPort = wine_server_ptr_handle( reply->handle ); - } - SERVER_END_REQ; - - RtlFreeHeap( GetProcessHeap(), 0, objattr ); - return status; + return unix_funcs->NtCreateIoCompletion( handle, access, attr, threads ); } /****************************************************************** * NtSetIoCompletion (NTDLL.@) * ZwSetIoCompletion (NTDLL.@) - * - * Inserts completion message into queue - * - * PARAMS - * CompletionPort [I] HANDLE to completion object - * CompletionKey [I] completion key - * CompletionValue [I] completion value (usually pointer to OVERLAPPED) - * Status [I] operation status - * NumberOfBytesTransferred [I] number of bytes transferred */ -NTSTATUS WINAPI NtSetIoCompletion( HANDLE CompletionPort, ULONG_PTR CompletionKey, - ULONG_PTR CompletionValue, NTSTATUS Status, - SIZE_T NumberOfBytesTransferred ) +NTSTATUS WINAPI NtSetIoCompletion( HANDLE handle, ULONG_PTR key, ULONG_PTR value, + NTSTATUS status, SIZE_T count ) { - NTSTATUS status; - - TRACE("(%p, %lx, %lx, %x, %lx)\n", CompletionPort, CompletionKey, - CompletionValue, Status, NumberOfBytesTransferred); - - SERVER_START_REQ( add_completion ) - { - req->handle = wine_server_obj_handle( CompletionPort ); - req->ckey = CompletionKey; - req->cvalue = CompletionValue; - req->status = Status; - req->information = NumberOfBytesTransferred; - status = wine_server_call( req ); - } - SERVER_END_REQ; - return status; + return unix_funcs->NtSetIoCompletion( handle, key, value, status, count ); } /****************************************************************** * NtRemoveIoCompletion (NTDLL.@) * ZwRemoveIoCompletion (NTDLL.@) - * - * (Wait for and) retrieve first completion message from completion object's queue - * - * PARAMS - * CompletionPort [I] HANDLE to I/O completion object - * CompletionKey [O] completion key - * CompletionValue [O] Completion value given in NtSetIoCompletion or in async operation - * iosb [O] IO_STATUS_BLOCK of completed asynchronous operation - * WaitTime [I] optional wait time in NTDLL format - * */ -NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE CompletionPort, PULONG_PTR CompletionKey, - PULONG_PTR CompletionValue, PIO_STATUS_BLOCK iosb, - PLARGE_INTEGER WaitTime ) +NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR *value, + IO_STATUS_BLOCK *io, LARGE_INTEGER *timeout ) { - NTSTATUS status; - - TRACE("(%p, %p, %p, %p, %p)\n", CompletionPort, CompletionKey, - CompletionValue, iosb, WaitTime); - - for(;;) - { - SERVER_START_REQ( remove_completion ) - { - req->handle = wine_server_obj_handle( CompletionPort ); - if (!(status = wine_server_call( req ))) - { - *CompletionKey = reply->ckey; - *CompletionValue = reply->cvalue; - iosb->Information = reply->information; - iosb->u.Status = reply->status; - } - } - SERVER_END_REQ; - if (status != STATUS_PENDING) break; - - status = NtWaitForSingleObject( CompletionPort, FALSE, WaitTime ); - if (status != WAIT_OBJECT_0) break; - } - return status; + return unix_funcs->NtRemoveIoCompletion( handle, key, value, io, timeout ); } /****************************************************************** @@ -866,130 +775,26 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE CompletionPort, PULONG_PTR Completi NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE port, FILE_IO_COMPLETION_INFORMATION *info, ULONG count, ULONG *written, LARGE_INTEGER *timeout, BOOLEAN alertable ) { - NTSTATUS ret; - ULONG i = 0; - - TRACE("%p %p %u %p %p %u\n", port, info, count, written, timeout, alertable); - - for (;;) - { - while (i < count) - { - SERVER_START_REQ( remove_completion ) - { - req->handle = wine_server_obj_handle( port ); - if (!(ret = wine_server_call( req ))) - { - info[i].CompletionKey = reply->ckey; - info[i].CompletionValue = reply->cvalue; - info[i].IoStatusBlock.Information = reply->information; - info[i].IoStatusBlock.u.Status = reply->status; - } - } - SERVER_END_REQ; - - if (ret != STATUS_SUCCESS) break; - - ++i; - } - - if (i || ret != STATUS_PENDING) - { - if (ret == STATUS_PENDING) - ret = STATUS_SUCCESS; - break; - } - - ret = NtWaitForSingleObject( port, alertable, timeout ); - if (ret != WAIT_OBJECT_0) break; - } - - *written = i ? i : 1; - return ret; + return unix_funcs->NtRemoveIoCompletionEx( port, info, count, written, timeout, alertable ); } /****************************************************************** * NtOpenIoCompletion (NTDLL.@) * ZwOpenIoCompletion (NTDLL.@) - * - * Opens I/O completion object - * - * PARAMS - * CompletionPort [O] completion object handle will be placed there - * DesiredAccess [I] desired access to a handle (combination of IO_COMPLETION_*) - * ObjectAttributes [I] completion object name - * */ NTSTATUS WINAPI NtOpenIoCompletion( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr ) { - NTSTATUS status; - - if (!handle) return STATUS_INVALID_PARAMETER; - if ((status = validate_open_object_attributes( attr ))) return status; - - SERVER_START_REQ( open_completion ) - { - req->access = access; - req->attributes = attr->Attributes; - req->rootdir = wine_server_obj_handle( attr->RootDirectory ); - if (attr->ObjectName) - wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); - status = wine_server_call( req ); - *handle = wine_server_ptr_handle( reply->handle ); - } - SERVER_END_REQ; - return status; + return unix_funcs->NtOpenIoCompletion( handle, access, attr ); } /****************************************************************** * NtQueryIoCompletion (NTDLL.@) * ZwQueryIoCompletion (NTDLL.@) - * - * Requests information about given I/O completion object - * - * PARAMS - * CompletionPort [I] HANDLE to completion port to request - * InformationClass [I] information class - * CompletionInformation [O] user-provided buffer for data - * BufferLength [I] buffer length - * RequiredLength [O] required buffer length - * */ -NTSTATUS WINAPI NtQueryIoCompletion( HANDLE CompletionPort, IO_COMPLETION_INFORMATION_CLASS InformationClass, - PVOID CompletionInformation, ULONG BufferLength, PULONG RequiredLength ) +NTSTATUS WINAPI NtQueryIoCompletion( HANDLE handle, IO_COMPLETION_INFORMATION_CLASS class, + void *buffer, ULONG len, ULONG *ret_len ) { - NTSTATUS status; - - TRACE("(%p, %d, %p, 0x%x, %p)\n", CompletionPort, InformationClass, CompletionInformation, - BufferLength, RequiredLength); - - if (!CompletionInformation) return STATUS_INVALID_PARAMETER; - switch( InformationClass ) - { - case IoCompletionBasicInformation: - { - ULONG *info = CompletionInformation; - - if (RequiredLength) *RequiredLength = sizeof(*info); - if (BufferLength != sizeof(*info)) - status = STATUS_INFO_LENGTH_MISMATCH; - else - { - SERVER_START_REQ( query_completion ) - { - req->handle = wine_server_obj_handle( CompletionPort ); - if (!(status = wine_server_call( req ))) - *info = reply->depth; - } - SERVER_END_REQ; - } - } - break; - default: - status = STATUS_INVALID_PARAMETER; - break; - } - return status; + return unix_funcs->NtQueryIoCompletion( handle, class, buffer, len, ret_len ); } NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue, diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index b09049b855b..0c37723463a 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -826,6 +826,7 @@ static struct unix_funcs unix_funcs = NtContinue, NtCreateEvent, NtCreateFile, + NtCreateIoCompletion, NtCreateKeyedEvent, NtCreateMailslotFile, NtCreateMutant, @@ -846,6 +847,7 @@ static struct unix_funcs unix_funcs = NtMapViewOfSection, NtOpenEvent, NtOpenFile, + NtOpenIoCompletion, NtOpenKeyedEvent, NtOpenMutant, NtOpenSection, @@ -858,6 +860,7 @@ static struct unix_funcs unix_funcs = NtQueryDirectoryFile, NtQueryEvent, NtQueryFullAttributesFile, + NtQueryIoCompletion, NtQueryMutant, NtQueryPerformanceCounter, NtQuerySection, @@ -871,11 +874,14 @@ static struct unix_funcs unix_funcs = NtReleaseKeyedEvent, NtReleaseMutant, NtReleaseSemaphore, + NtRemoveIoCompletion, + NtRemoveIoCompletionEx, NtResetEvent, NtResetWriteWatch, NtResumeThread, NtSetContextThread, NtSetEvent, + NtSetIoCompletion, NtSetLdtEntries, NtSetSystemTime, NtSetTimer, diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index aa9b87c8d20..2174549e773 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -1099,6 +1099,195 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, } +/*********************************************************************** + * NtCreateIoCompletion (NTDLL.@) + */ +NTSTATUS WINAPI NtCreateIoCompletion( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + ULONG threads ) +{ + NTSTATUS status; + data_size_t len; + struct object_attributes *objattr; + + TRACE( "(%p, %x, %p, %d)\n", handle, access, attr, threads ); + + if (!handle) return STATUS_INVALID_PARAMETER; + if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status; + + SERVER_START_REQ( create_completion ) + { + req->access = access; + req->concurrent = threads; + wine_server_add_data( req, objattr, len ); + if (!(status = wine_server_call( req ))) *handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + RtlFreeHeap( GetProcessHeap(), 0, objattr ); + return status; +} + + +/*********************************************************************** + * NtOpenIoCompletion (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenIoCompletion( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr ) +{ + NTSTATUS status; + + if (!handle) return STATUS_INVALID_PARAMETER; + if ((status = validate_open_object_attributes( attr ))) return status; + + SERVER_START_REQ( open_completion ) + { + req->access = access; + req->attributes = attr->Attributes; + req->rootdir = wine_server_obj_handle( attr->RootDirectory ); + if (attr->ObjectName) + wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); + status = wine_server_call( req ); + *handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + return status; +} + + +/*********************************************************************** + * NtSetIoCompletion (NTDLL.@) + */ +NTSTATUS WINAPI NtSetIoCompletion( HANDLE handle, ULONG_PTR key, ULONG_PTR value, + NTSTATUS status, SIZE_T count ) +{ + NTSTATUS ret; + + TRACE( "(%p, %lx, %lx, %x, %lx)\n", handle, key, value, status, count ); + + SERVER_START_REQ( add_completion ) + { + req->handle = wine_server_obj_handle( handle ); + req->ckey = key; + req->cvalue = value; + req->status = status; + req->information = count; + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +} + + +/*********************************************************************** + * NtRemoveIoCompletion (NTDLL.@) + */ +NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR *value, + IO_STATUS_BLOCK *io, LARGE_INTEGER *timeout ) +{ + NTSTATUS status; + + TRACE( "(%p, %p, %p, %p, %p)\n", handle, key, value, io, timeout ); + + for (;;) + { + SERVER_START_REQ( remove_completion ) + { + req->handle = wine_server_obj_handle( handle ); + if (!(status = wine_server_call( req ))) + { + *key = reply->ckey; + *value = reply->cvalue; + io->Information = reply->information; + io->u.Status = reply->status; + } + } + SERVER_END_REQ; + if (status != STATUS_PENDING) return status; + status = NtWaitForSingleObject( handle, FALSE, timeout ); + if (status != WAIT_OBJECT_0) return status; + } +} + + +/*********************************************************************** + * NtRemoveIoCompletionEx (NTDLL.@) + */ +NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORMATION *info, ULONG count, + ULONG *written, LARGE_INTEGER *timeout, BOOLEAN alertable ) +{ + NTSTATUS status; + ULONG i = 0; + + TRACE( "%p %p %u %p %p %u\n", handle, info, count, written, timeout, alertable ); + + for (;;) + { + while (i < count) + { + SERVER_START_REQ( remove_completion ) + { + req->handle = wine_server_obj_handle( handle ); + if (!(status = wine_server_call( req ))) + { + info[i].CompletionKey = reply->ckey; + info[i].CompletionValue = reply->cvalue; + info[i].IoStatusBlock.Information = reply->information; + info[i].IoStatusBlock.u.Status = reply->status; + } + } + SERVER_END_REQ; + if (status != STATUS_SUCCESS) break; + ++i; + } + if (i || status != STATUS_PENDING) + { + if (status == STATUS_PENDING) status = STATUS_SUCCESS; + break; + } + status = NtWaitForSingleObject( handle, alertable, timeout ); + if (status != WAIT_OBJECT_0) break; + } + *written = i ? i : 1; + return status; +} + + +/*********************************************************************** + * NtQueryIoCompletion (NTDLL.@) + */ +NTSTATUS WINAPI NtQueryIoCompletion( HANDLE handle, IO_COMPLETION_INFORMATION_CLASS class, + void *buffer, ULONG len, ULONG *ret_len ) +{ + NTSTATUS status; + + TRACE( "(%p, %d, %p, 0x%x, %p)\n", handle, class, buffer, len, ret_len ); + + if (!buffer) return STATUS_INVALID_PARAMETER; + + switch (class) + { + case IoCompletionBasicInformation: + { + ULONG *info = buffer; + if (ret_len) *ret_len = sizeof(*info); + if (len == sizeof(*info)) + { + SERVER_START_REQ( query_completion ) + { + req->handle = wine_server_obj_handle( handle ); + if (!(status = wine_server_call( req ))) *info = reply->depth; + } + SERVER_END_REQ; + } + else status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + default: + return STATUS_INVALID_PARAMETER; + } + return status; +} + + /*********************************************************************** * NtCreateSection (NTDLL.@) */ diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 958fab4c059..b304e6fe6a5 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -28,7 +28,7 @@ struct ldt_copy; struct msghdr; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 43 +#define NTDLL_UNIXLIB_VERSION 44 struct unix_funcs { @@ -48,6 +48,8 @@ struct unix_funcs IO_STATUS_BLOCK *io, LARGE_INTEGER *alloc_size, ULONG attributes, ULONG sharing, ULONG disposition, ULONG options, void *ea_buffer, ULONG ea_length ); + NTSTATUS (WINAPI *NtCreateIoCompletion)( HANDLE *handle, ACCESS_MASK access, + OBJECT_ATTRIBUTES *attr, ULONG threads ); NTSTATUS (WINAPI *NtCreateKeyedEvent)( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, ULONG flags ); NTSTATUS (WINAPI *NtCreateMailslotFile)( HANDLE *handle, ULONG access, OBJECT_ATTRIBUTES *attr, @@ -94,6 +96,8 @@ struct unix_funcs const OBJECT_ATTRIBUTES *attr ); NTSTATUS (WINAPI *NtOpenFile)( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, IO_STATUS_BLOCK *io, ULONG sharing, ULONG options ); + NTSTATUS (WINAPI *NtOpenIoCompletion)( HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr ); NTSTATUS (WINAPI *NtOpenKeyedEvent)( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr ); NTSTATUS (WINAPI *NtOpenMutant)( HANDLE *handle, ACCESS_MASK access, @@ -119,6 +123,8 @@ struct unix_funcs void *info, ULONG len, ULONG *ret_len ); NTSTATUS (WINAPI *NtQueryFullAttributesFile)( const OBJECT_ATTRIBUTES *attr, FILE_NETWORK_OPEN_INFORMATION *info ); + NTSTATUS (WINAPI *NtQueryIoCompletion)( HANDLE handle, IO_COMPLETION_INFORMATION_CLASS class, + void *buffer, ULONG len, ULONG *ret_len ); NTSTATUS (WINAPI *NtQueryMutant)( HANDLE handle, MUTANT_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len ); NTSTATUS (WINAPI *NtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency ); @@ -141,11 +147,18 @@ struct unix_funcs BOOLEAN alertable, const LARGE_INTEGER *timeout ); NTSTATUS (WINAPI *NtReleaseMutant)( HANDLE handle, LONG *prev_count ); NTSTATUS (WINAPI *NtReleaseSemaphore)( HANDLE handle, ULONG count, ULONG *previous ); + NTSTATUS (WINAPI *NtRemoveIoCompletion)( HANDLE handle, ULONG_PTR *key, ULONG_PTR *value, + IO_STATUS_BLOCK *io, LARGE_INTEGER *timeout ); + NTSTATUS (WINAPI *NtRemoveIoCompletionEx)( HANDLE handle, FILE_IO_COMPLETION_INFORMATION *info, + ULONG count, ULONG *written, + LARGE_INTEGER *timeout, BOOLEAN alertable ); NTSTATUS (WINAPI *NtResetEvent)( HANDLE handle, LONG *prev_state ); NTSTATUS (WINAPI *NtResetWriteWatch)( HANDLE process, PVOID base, SIZE_T size ); NTSTATUS (WINAPI *NtResumeThread)( HANDLE handle, ULONG *count ); NTSTATUS (WINAPI *NtSetContextThread)( HANDLE handle, const CONTEXT *context ); NTSTATUS (WINAPI *NtSetEvent)( HANDLE handle, LONG *prev_state ); + NTSTATUS (WINAPI *NtSetIoCompletion)( HANDLE handle, ULONG_PTR key, ULONG_PTR value, + NTSTATUS status, SIZE_T count ); NTSTATUS (WINAPI *NtSetLdtEntries)( ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2 ); NTSTATUS (WINAPI *NtSetSystemTime)( const LARGE_INTEGER *new, LARGE_INTEGER *old ); NTSTATUS (WINAPI *NtSetTimer)( HANDLE handle, const LARGE_INTEGER *when,