ntdll: Move the IO completion functions to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-06-13 11:56:30 +02:00
parent 948a6a47b8
commit 06fa3d32a7
4 changed files with 223 additions and 210 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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.@)
*/

View File

@ -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,