ntdll: Move the file read/write functions to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e9e5c95058
commit
888d66a237
|
@ -339,296 +339,6 @@ NTSTATUS FILE_GetNtStatus(void)
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_AsyncReadService (INTERNAL)
|
||||
*/
|
||||
static NTSTATUS FILE_AsyncReadService( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
|
||||
{
|
||||
struct async_fileio_read *fileio = user;
|
||||
int fd, needs_close, result;
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case STATUS_ALERTED: /* got some new data */
|
||||
/* check to see if the data is ready (non-blocking) */
|
||||
if ((status = unix_funcs->server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd,
|
||||
&needs_close, NULL, NULL )))
|
||||
break;
|
||||
|
||||
result = unix_funcs->virtual_locked_read(fd, &fileio->buffer[fileio->already], fileio->count-fileio->already);
|
||||
if (needs_close) close( fd );
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
status = STATUS_PENDING;
|
||||
else /* check to see if the transfer is complete */
|
||||
status = FILE_GetNtStatus();
|
||||
}
|
||||
else if (result == 0)
|
||||
{
|
||||
status = fileio->already ? STATUS_SUCCESS : STATUS_PIPE_BROKEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileio->already += result;
|
||||
if (fileio->already >= fileio->count || fileio->avail_mode)
|
||||
status = STATUS_SUCCESS;
|
||||
else
|
||||
status = STATUS_PENDING;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATUS_TIMEOUT:
|
||||
case STATUS_IO_TIMEOUT:
|
||||
if (fileio->already) status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
if (status != STATUS_PENDING)
|
||||
{
|
||||
iosb->u.Status = status;
|
||||
iosb->Information = fileio->already;
|
||||
release_fileio( &fileio->io );
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* do a read call through the server */
|
||||
static NTSTATUS server_read_file( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_context,
|
||||
IO_STATUS_BLOCK *io, void *buffer, ULONG size,
|
||||
LARGE_INTEGER *offset, ULONG *key )
|
||||
{
|
||||
struct async_irp *async;
|
||||
NTSTATUS status;
|
||||
HANDLE wait_handle;
|
||||
ULONG options;
|
||||
|
||||
if (!(async = (struct async_irp *)alloc_fileio( sizeof(*async), irp_completion, handle )))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
async->buffer = buffer;
|
||||
async->size = size;
|
||||
|
||||
SERVER_START_REQ( read )
|
||||
{
|
||||
req->async = server_async( handle, &async->io, event, apc, apc_context, io );
|
||||
req->pos = offset ? offset->QuadPart : 0;
|
||||
wine_server_set_reply( req, buffer, size );
|
||||
status = unix_funcs->virtual_locked_server_call( req );
|
||||
wait_handle = wine_server_ptr_handle( reply->wait );
|
||||
options = reply->options;
|
||||
if (wait_handle && status != STATUS_PENDING)
|
||||
{
|
||||
io->u.Status = status;
|
||||
io->Information = wine_server_reply_size( reply );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, async );
|
||||
|
||||
if (wait_handle) status = wait_async( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), io );
|
||||
return status;
|
||||
}
|
||||
|
||||
/* do a write call through the server */
|
||||
static NTSTATUS server_write_file( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_context,
|
||||
IO_STATUS_BLOCK *io, const void *buffer, ULONG size,
|
||||
LARGE_INTEGER *offset, ULONG *key )
|
||||
{
|
||||
struct async_irp *async;
|
||||
NTSTATUS status;
|
||||
HANDLE wait_handle;
|
||||
ULONG options;
|
||||
|
||||
if (!(async = (struct async_irp *)alloc_fileio( sizeof(*async), irp_completion, handle )))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
async->buffer = NULL;
|
||||
async->size = 0;
|
||||
|
||||
SERVER_START_REQ( write )
|
||||
{
|
||||
req->async = server_async( handle, &async->io, event, apc, apc_context, io );
|
||||
req->pos = offset ? offset->QuadPart : 0;
|
||||
wine_server_add_data( req, buffer, size );
|
||||
status = wine_server_call( req );
|
||||
wait_handle = wine_server_ptr_handle( reply->wait );
|
||||
options = reply->options;
|
||||
if (wait_handle && status != STATUS_PENDING)
|
||||
{
|
||||
io->u.Status = status;
|
||||
io->Information = reply->size;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, async );
|
||||
|
||||
if (wait_handle) status = wait_async( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), io );
|
||||
return status;
|
||||
}
|
||||
|
||||
struct io_timeouts
|
||||
{
|
||||
int interval; /* max interval between two bytes */
|
||||
int total; /* total timeout for the whole operation */
|
||||
int end_time; /* absolute time of end of operation */
|
||||
};
|
||||
|
||||
/* retrieve the I/O timeouts to use for a given handle */
|
||||
static NTSTATUS get_io_timeouts( HANDLE handle, enum server_fd_type type, ULONG count, BOOL is_read,
|
||||
struct io_timeouts *timeouts )
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
timeouts->interval = timeouts->total = -1;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case FD_TYPE_SERIAL:
|
||||
{
|
||||
/* GetCommTimeouts */
|
||||
SERIAL_TIMEOUTS st;
|
||||
IO_STATUS_BLOCK io;
|
||||
|
||||
status = NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io,
|
||||
IOCTL_SERIAL_GET_TIMEOUTS, NULL, 0, &st, sizeof(st) );
|
||||
if (status) break;
|
||||
|
||||
if (is_read)
|
||||
{
|
||||
if (st.ReadIntervalTimeout)
|
||||
timeouts->interval = st.ReadIntervalTimeout;
|
||||
|
||||
if (st.ReadTotalTimeoutMultiplier || st.ReadTotalTimeoutConstant)
|
||||
{
|
||||
timeouts->total = st.ReadTotalTimeoutConstant;
|
||||
if (st.ReadTotalTimeoutMultiplier != MAXDWORD)
|
||||
timeouts->total += count * st.ReadTotalTimeoutMultiplier;
|
||||
}
|
||||
else if (st.ReadIntervalTimeout == MAXDWORD)
|
||||
timeouts->interval = timeouts->total = 0;
|
||||
}
|
||||
else /* write */
|
||||
{
|
||||
if (st.WriteTotalTimeoutMultiplier || st.WriteTotalTimeoutConstant)
|
||||
{
|
||||
timeouts->total = st.WriteTotalTimeoutConstant;
|
||||
if (st.WriteTotalTimeoutMultiplier != MAXDWORD)
|
||||
timeouts->total += count * st.WriteTotalTimeoutMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FD_TYPE_MAILSLOT:
|
||||
if (is_read)
|
||||
{
|
||||
timeouts->interval = 0; /* return as soon as we got something */
|
||||
SERVER_START_REQ( set_mailslot_info )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->flags = 0;
|
||||
if (!(status = wine_server_call( req )) &&
|
||||
reply->read_timeout != TIMEOUT_INFINITE)
|
||||
timeouts->total = reply->read_timeout / -10000;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
break;
|
||||
case FD_TYPE_SOCKET:
|
||||
case FD_TYPE_CHAR:
|
||||
if (is_read) timeouts->interval = 0; /* return as soon as we got something */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (timeouts->total != -1) timeouts->end_time = NtGetTickCount() + timeouts->total;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* retrieve the timeout for the next wait, in milliseconds */
|
||||
static inline int get_next_io_timeout( const struct io_timeouts *timeouts, ULONG already )
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (timeouts->total != -1)
|
||||
{
|
||||
ret = timeouts->end_time - NtGetTickCount();
|
||||
if (ret < 0) ret = 0;
|
||||
}
|
||||
if (already && timeouts->interval != -1)
|
||||
{
|
||||
if (ret == -1 || ret > timeouts->interval) ret = timeouts->interval;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* retrieve the avail_mode flag for async reads */
|
||||
static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL *avail_mode )
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case FD_TYPE_SERIAL:
|
||||
{
|
||||
/* GetCommTimeouts */
|
||||
SERIAL_TIMEOUTS st;
|
||||
IO_STATUS_BLOCK io;
|
||||
|
||||
status = NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io,
|
||||
IOCTL_SERIAL_GET_TIMEOUTS, NULL, 0, &st, sizeof(st) );
|
||||
if (status) break;
|
||||
*avail_mode = (!st.ReadTotalTimeoutMultiplier &&
|
||||
!st.ReadTotalTimeoutConstant &&
|
||||
st.ReadIntervalTimeout == MAXDWORD);
|
||||
}
|
||||
break;
|
||||
case FD_TYPE_MAILSLOT:
|
||||
case FD_TYPE_SOCKET:
|
||||
case FD_TYPE_CHAR:
|
||||
*avail_mode = TRUE;
|
||||
break;
|
||||
default:
|
||||
*avail_mode = FALSE;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* register an async I/O for a file read; helper for NtReadFile */
|
||||
static NTSTATUS register_async_file_read( HANDLE handle, HANDLE event,
|
||||
PIO_APC_ROUTINE apc, void *apc_user,
|
||||
IO_STATUS_BLOCK *iosb, void *buffer,
|
||||
ULONG already, ULONG length, BOOL avail_mode )
|
||||
{
|
||||
struct async_fileio_read *fileio;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!(fileio = (struct async_fileio_read *)alloc_fileio( sizeof(*fileio), FILE_AsyncReadService, handle )))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
fileio->already = already;
|
||||
fileio->count = length;
|
||||
fileio->buffer = buffer;
|
||||
fileio->avail_mode = avail_mode;
|
||||
|
||||
SERVER_START_REQ( register_async )
|
||||
{
|
||||
req->type = ASYNC_TYPE_READ;
|
||||
req->count = length;
|
||||
req->async = server_async( handle, &fileio->io, event, apc, apc_user, iosb );
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtReadFile [NTDLL.@]
|
||||
|
@ -657,196 +367,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
|
|||
PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
|
||||
PLARGE_INTEGER offset, PULONG key)
|
||||
{
|
||||
int result, unix_handle, needs_close;
|
||||
unsigned int options;
|
||||
struct io_timeouts timeouts;
|
||||
NTSTATUS status, ret_status;
|
||||
ULONG total = 0;
|
||||
enum server_fd_type type;
|
||||
ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
|
||||
BOOL send_completion = FALSE, async_read, timeout_init_done = FALSE;
|
||||
|
||||
TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p)\n",
|
||||
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
|
||||
|
||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
status = unix_funcs->server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
if (status && status != STATUS_BAD_DEVICE_TYPE) return status;
|
||||
|
||||
if (!unix_funcs->virtual_check_buffer_for_write( buffer, length )) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
if (status == STATUS_BAD_DEVICE_TYPE)
|
||||
return server_read_file( hFile, hEvent, apc, apc_user, io_status, buffer, length, offset, key );
|
||||
|
||||
async_read = !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
|
||||
|
||||
if (type == FD_TYPE_FILE)
|
||||
{
|
||||
if (async_read && (!offset || offset->QuadPart < 0))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (offset && offset->QuadPart != FILE_USE_FILE_POINTER_POSITION)
|
||||
{
|
||||
/* async I/O doesn't make sense on regular files */
|
||||
while ((result = unix_funcs->virtual_locked_pread( unix_handle, buffer, length, offset->QuadPart )) == -1)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
{
|
||||
status = FILE_GetNtStatus();
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (!async_read)
|
||||
/* update file pointer position */
|
||||
lseek( unix_handle, offset->QuadPart + result, SEEK_SET );
|
||||
|
||||
total = result;
|
||||
status = (total || !length) ? STATUS_SUCCESS : STATUS_END_OF_FILE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else if (type == FD_TYPE_SERIAL || type == FD_TYPE_DEVICE)
|
||||
{
|
||||
if (async_read && (!offset || offset->QuadPart < 0))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == FD_TYPE_SERIAL && async_read && length)
|
||||
{
|
||||
/* an asynchronous serial port read with a read interval timeout needs to
|
||||
skip the synchronous read to make sure that the server starts the read
|
||||
interval timer after the first read */
|
||||
if ((status = get_io_timeouts( hFile, type, length, TRUE, &timeouts ))) goto err;
|
||||
if (timeouts.interval)
|
||||
{
|
||||
status = register_async_file_read( hFile, hEvent, apc, apc_user, io_status,
|
||||
buffer, total, length, FALSE );
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ((result = unix_funcs->virtual_locked_read( unix_handle, (char *)buffer + total, length - total )) >= 0)
|
||||
{
|
||||
total += result;
|
||||
if (!result || total == length)
|
||||
{
|
||||
if (total)
|
||||
{
|
||||
status = STATUS_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case FD_TYPE_FILE:
|
||||
case FD_TYPE_CHAR:
|
||||
case FD_TYPE_DEVICE:
|
||||
status = length ? STATUS_END_OF_FILE : STATUS_SUCCESS;
|
||||
goto done;
|
||||
case FD_TYPE_SERIAL:
|
||||
if (!length)
|
||||
{
|
||||
status = STATUS_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = STATUS_PIPE_BROKEN;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else if (type == FD_TYPE_FILE) continue; /* no async I/O on regular files */
|
||||
}
|
||||
else if (errno != EAGAIN)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
if (!total) status = FILE_GetNtStatus();
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (async_read)
|
||||
{
|
||||
BOOL avail_mode;
|
||||
|
||||
if ((status = get_io_avail_mode( hFile, type, &avail_mode )))
|
||||
goto err;
|
||||
if (total && avail_mode)
|
||||
{
|
||||
status = STATUS_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
status = register_async_file_read( hFile, hEvent, apc, apc_user, io_status,
|
||||
buffer, total, length, avail_mode );
|
||||
goto err;
|
||||
}
|
||||
else /* synchronous read, wait for the fd to become ready */
|
||||
{
|
||||
struct pollfd pfd;
|
||||
int ret, timeout;
|
||||
|
||||
if (!timeout_init_done)
|
||||
{
|
||||
timeout_init_done = TRUE;
|
||||
if ((status = get_io_timeouts( hFile, type, length, TRUE, &timeouts )))
|
||||
goto err;
|
||||
if (hEvent) NtResetEvent( hEvent, NULL );
|
||||
}
|
||||
timeout = get_next_io_timeout( &timeouts, total );
|
||||
|
||||
pfd.fd = unix_handle;
|
||||
pfd.events = POLLIN;
|
||||
|
||||
if (!timeout || !(ret = poll( &pfd, 1, timeout )))
|
||||
{
|
||||
if (total) /* return with what we got so far */
|
||||
status = STATUS_SUCCESS;
|
||||
else
|
||||
status = (type == FD_TYPE_MAILSLOT) ? STATUS_IO_TIMEOUT : STATUS_TIMEOUT;
|
||||
goto done;
|
||||
}
|
||||
if (ret == -1 && errno != EINTR)
|
||||
{
|
||||
status = FILE_GetNtStatus();
|
||||
goto done;
|
||||
}
|
||||
/* will now restart the read */
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
send_completion = cvalue != 0;
|
||||
|
||||
err:
|
||||
if (needs_close) close( unix_handle );
|
||||
if (status == STATUS_SUCCESS || (status == STATUS_END_OF_FILE && (!async_read || type == FD_TYPE_FILE)))
|
||||
{
|
||||
io_status->u.Status = status;
|
||||
io_status->Information = total;
|
||||
TRACE("= SUCCESS (%u)\n", total);
|
||||
if (hEvent) NtSetEvent( hEvent, NULL );
|
||||
if (apc && (!status || async_read)) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
|
||||
(ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("= 0x%08x\n", status);
|
||||
if (status != STATUS_PENDING && hEvent) NtResetEvent( hEvent, NULL );
|
||||
}
|
||||
|
||||
ret_status = async_read && type == FD_TYPE_FILE && (status == STATUS_SUCCESS || status == STATUS_END_OF_FILE)
|
||||
? STATUS_PENDING : status;
|
||||
|
||||
if (send_completion) NTDLL_AddCompletion( hFile, cvalue, status, total, ret_status == STATUS_PENDING );
|
||||
return ret_status;
|
||||
return unix_funcs->NtReadFile( hFile, hEvent, apc, apc_user, io_status, buffer, length, offset, key );
|
||||
}
|
||||
|
||||
|
||||
|
@ -858,144 +379,11 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
|
|||
PIO_STATUS_BLOCK io_status, FILE_SEGMENT_ELEMENT *segments,
|
||||
ULONG length, PLARGE_INTEGER offset, PULONG key )
|
||||
{
|
||||
int result, unix_handle, needs_close;
|
||||
unsigned int options;
|
||||
NTSTATUS status;
|
||||
ULONG pos = 0, total = 0;
|
||||
enum server_fd_type type;
|
||||
ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
|
||||
BOOL send_completion = FALSE;
|
||||
|
||||
TRACE( "(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
|
||||
file, event, apc, apc_user, io_status, segments, length, offset, key);
|
||||
|
||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
status = unix_funcs->server_get_unix_fd( file, FILE_READ_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
if (status) return status;
|
||||
|
||||
if ((type != FD_TYPE_FILE) ||
|
||||
(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) ||
|
||||
!(options & FILE_NO_INTERMEDIATE_BUFFERING))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto error;
|
||||
}
|
||||
|
||||
while (length)
|
||||
{
|
||||
if (offset && offset->QuadPart != FILE_USE_FILE_POINTER_POSITION)
|
||||
result = pread( unix_handle, (char *)segments->Buffer + pos,
|
||||
min( length - pos, page_size - pos ), offset->QuadPart + total );
|
||||
else
|
||||
result = read( unix_handle, (char *)segments->Buffer + pos, min( length - pos, page_size - pos ) );
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
status = FILE_GetNtStatus();
|
||||
break;
|
||||
}
|
||||
if (!result) break;
|
||||
total += result;
|
||||
length -= result;
|
||||
if ((pos += result) == page_size)
|
||||
{
|
||||
pos = 0;
|
||||
segments++;
|
||||
}
|
||||
}
|
||||
|
||||
if (total == 0) status = STATUS_END_OF_FILE;
|
||||
|
||||
send_completion = cvalue != 0;
|
||||
|
||||
if (needs_close) close( unix_handle );
|
||||
|
||||
io_status->u.Status = status;
|
||||
io_status->Information = total;
|
||||
TRACE("= 0x%08x (%u)\n", status, total);
|
||||
if (event) NtSetEvent( event, NULL );
|
||||
if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
|
||||
(ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
|
||||
if (send_completion) NTDLL_AddCompletion( file, cvalue, status, total, TRUE );
|
||||
|
||||
return STATUS_PENDING;
|
||||
|
||||
error:
|
||||
if (needs_close) close( unix_handle );
|
||||
|
||||
TRACE("= 0x%08x\n", status);
|
||||
if (event) NtResetEvent( event, NULL );
|
||||
|
||||
return status;
|
||||
return unix_funcs->NtReadFileScatter( file, event, apc, apc_user, io_status,
|
||||
segments, length, offset, key );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_AsyncWriteService (INTERNAL)
|
||||
*/
|
||||
static NTSTATUS FILE_AsyncWriteService( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status )
|
||||
{
|
||||
struct async_fileio_write *fileio = user;
|
||||
int result, fd, needs_close;
|
||||
enum server_fd_type type;
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case STATUS_ALERTED:
|
||||
/* write some data (non-blocking) */
|
||||
if ((status = unix_funcs->server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd,
|
||||
&needs_close, &type, NULL )))
|
||||
break;
|
||||
|
||||
if (!fileio->count && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_SOCKET))
|
||||
result = send( fd, fileio->buffer, 0, 0 );
|
||||
else
|
||||
result = write( fd, &fileio->buffer[fileio->already], fileio->count - fileio->already );
|
||||
|
||||
if (needs_close) close( fd );
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EINTR) status = STATUS_PENDING;
|
||||
else status = FILE_GetNtStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
fileio->already += result;
|
||||
status = (fileio->already < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATUS_TIMEOUT:
|
||||
case STATUS_IO_TIMEOUT:
|
||||
if (fileio->already) status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
if (status != STATUS_PENDING)
|
||||
{
|
||||
iosb->u.Status = status;
|
||||
iosb->Information = fileio->already;
|
||||
release_fileio( &fileio->io );
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS set_pending_write( HANDLE device )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
SERVER_START_REQ( set_serial_info )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( device );
|
||||
req->flags = SERIALINFO_PENDING_WRITE;
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* NtWriteFile [NTDLL.@]
|
||||
|
@ -1025,223 +413,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
|
|||
const void* buffer, ULONG length,
|
||||
PLARGE_INTEGER offset, PULONG key)
|
||||
{
|
||||
int result, unix_handle, needs_close;
|
||||
unsigned int options;
|
||||
struct io_timeouts timeouts;
|
||||
NTSTATUS status, ret_status;
|
||||
ULONG total = 0;
|
||||
enum server_fd_type type;
|
||||
ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
|
||||
BOOL send_completion = FALSE, async_write, append_write = FALSE, timeout_init_done = FALSE;
|
||||
LARGE_INTEGER offset_eof;
|
||||
|
||||
TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p)\n",
|
||||
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
|
||||
|
||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
status = unix_funcs->server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
if (status == STATUS_ACCESS_DENIED)
|
||||
{
|
||||
status = unix_funcs->server_get_unix_fd( hFile, FILE_APPEND_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
append_write = TRUE;
|
||||
}
|
||||
if (status && status != STATUS_BAD_DEVICE_TYPE) return status;
|
||||
|
||||
async_write = !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
|
||||
|
||||
if (!unix_funcs->virtual_check_buffer_for_read( buffer, length ))
|
||||
{
|
||||
status = STATUS_INVALID_USER_BUFFER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (status == STATUS_BAD_DEVICE_TYPE)
|
||||
return server_write_file( hFile, hEvent, apc, apc_user, io_status, buffer, length, offset, key );
|
||||
|
||||
if (type == FD_TYPE_FILE)
|
||||
{
|
||||
if (async_write &&
|
||||
(!offset || (offset->QuadPart < 0 && offset->QuadPart != FILE_WRITE_TO_END_OF_FILE)))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (append_write)
|
||||
{
|
||||
offset_eof.QuadPart = FILE_WRITE_TO_END_OF_FILE;
|
||||
offset = &offset_eof;
|
||||
}
|
||||
|
||||
if (offset && offset->QuadPart != FILE_USE_FILE_POINTER_POSITION)
|
||||
{
|
||||
off_t off = offset->QuadPart;
|
||||
|
||||
if (offset->QuadPart == FILE_WRITE_TO_END_OF_FILE)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (fstat( unix_handle, &st ) == -1)
|
||||
{
|
||||
status = FILE_GetNtStatus();
|
||||
goto done;
|
||||
}
|
||||
off = st.st_size;
|
||||
}
|
||||
else if (offset->QuadPart < 0)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* async I/O doesn't make sense on regular files */
|
||||
while ((result = pwrite( unix_handle, buffer, length, off )) == -1)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
{
|
||||
if (errno == EFAULT) status = STATUS_INVALID_USER_BUFFER;
|
||||
else status = FILE_GetNtStatus();
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!async_write)
|
||||
/* update file pointer position */
|
||||
lseek( unix_handle, off + result, SEEK_SET );
|
||||
|
||||
total = result;
|
||||
status = STATUS_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else if (type == FD_TYPE_SERIAL || type == FD_TYPE_DEVICE)
|
||||
{
|
||||
if (async_write &&
|
||||
(!offset || (offset->QuadPart < 0 && offset->QuadPart != FILE_WRITE_TO_END_OF_FILE)))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* zero-length writes on sockets may not work with plain write(2) */
|
||||
if (!length && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_SOCKET))
|
||||
result = send( unix_handle, buffer, 0, 0 );
|
||||
else
|
||||
result = write( unix_handle, (const char *)buffer + total, length - total );
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
total += result;
|
||||
if (total == length)
|
||||
{
|
||||
status = STATUS_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
if (type == FD_TYPE_FILE) continue; /* no async I/O on regular files */
|
||||
}
|
||||
else if (errno != EAGAIN)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
if (!total)
|
||||
{
|
||||
if (errno == EFAULT) status = STATUS_INVALID_USER_BUFFER;
|
||||
else status = FILE_GetNtStatus();
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (async_write)
|
||||
{
|
||||
struct async_fileio_write *fileio;
|
||||
|
||||
fileio = (struct async_fileio_write *)alloc_fileio( sizeof(*fileio), FILE_AsyncWriteService, hFile );
|
||||
if (!fileio)
|
||||
{
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
fileio->already = total;
|
||||
fileio->count = length;
|
||||
fileio->buffer = buffer;
|
||||
|
||||
SERVER_START_REQ( register_async )
|
||||
{
|
||||
req->type = ASYNC_TYPE_WRITE;
|
||||
req->count = length;
|
||||
req->async = server_async( hFile, &fileio->io, hEvent, apc, apc_user, io_status );
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
|
||||
goto err;
|
||||
}
|
||||
else /* synchronous write, wait for the fd to become ready */
|
||||
{
|
||||
struct pollfd pfd;
|
||||
int ret, timeout;
|
||||
|
||||
if (!timeout_init_done)
|
||||
{
|
||||
timeout_init_done = TRUE;
|
||||
if ((status = get_io_timeouts( hFile, type, length, FALSE, &timeouts )))
|
||||
goto err;
|
||||
if (hEvent) NtResetEvent( hEvent, NULL );
|
||||
}
|
||||
timeout = get_next_io_timeout( &timeouts, total );
|
||||
|
||||
pfd.fd = unix_handle;
|
||||
pfd.events = POLLOUT;
|
||||
|
||||
if (!timeout || !(ret = poll( &pfd, 1, timeout )))
|
||||
{
|
||||
/* return with what we got so far */
|
||||
status = total ? STATUS_SUCCESS : STATUS_TIMEOUT;
|
||||
goto done;
|
||||
}
|
||||
if (ret == -1 && errno != EINTR)
|
||||
{
|
||||
status = FILE_GetNtStatus();
|
||||
goto done;
|
||||
}
|
||||
/* will now restart the write */
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
send_completion = cvalue != 0;
|
||||
|
||||
err:
|
||||
if (needs_close) close( unix_handle );
|
||||
|
||||
if (type == FD_TYPE_SERIAL && (status == STATUS_SUCCESS || status == STATUS_PENDING))
|
||||
set_pending_write( hFile );
|
||||
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
io_status->u.Status = status;
|
||||
io_status->Information = total;
|
||||
TRACE("= SUCCESS (%u)\n", total);
|
||||
if (hEvent) NtSetEvent( hEvent, NULL );
|
||||
if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
|
||||
(ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("= 0x%08x\n", status);
|
||||
if (status != STATUS_PENDING && hEvent) NtResetEvent( hEvent, NULL );
|
||||
}
|
||||
|
||||
ret_status = async_write && type == FD_TYPE_FILE && status == STATUS_SUCCESS ? STATUS_PENDING : status;
|
||||
if (send_completion) NTDLL_AddCompletion( hFile, cvalue, status, total, ret_status == STATUS_PENDING );
|
||||
|
||||
return ret_status;
|
||||
return unix_funcs->NtWriteFile( hFile, hEvent, apc, apc_user, io_status, buffer, length, offset, key );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1253,87 +425,8 @@ NTSTATUS WINAPI NtWriteFileGather( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
|
|||
PIO_STATUS_BLOCK io_status, FILE_SEGMENT_ELEMENT *segments,
|
||||
ULONG length, PLARGE_INTEGER offset, PULONG key )
|
||||
{
|
||||
int result, unix_handle, needs_close;
|
||||
unsigned int options;
|
||||
NTSTATUS status;
|
||||
ULONG pos = 0, total = 0;
|
||||
enum server_fd_type type;
|
||||
ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
|
||||
BOOL send_completion = FALSE;
|
||||
|
||||
TRACE( "(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
|
||||
file, event, apc, apc_user, io_status, segments, length, offset, key);
|
||||
|
||||
if (length % page_size) return STATUS_INVALID_PARAMETER;
|
||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
status = unix_funcs->server_get_unix_fd( file, FILE_WRITE_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
if (status) return status;
|
||||
|
||||
if ((type != FD_TYPE_FILE) ||
|
||||
(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) ||
|
||||
!(options & FILE_NO_INTERMEDIATE_BUFFERING))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto error;
|
||||
}
|
||||
|
||||
while (length)
|
||||
{
|
||||
if (offset && offset->QuadPart != FILE_USE_FILE_POINTER_POSITION)
|
||||
result = pwrite( unix_handle, (char *)segments->Buffer + pos,
|
||||
page_size - pos, offset->QuadPart + total );
|
||||
else
|
||||
result = write( unix_handle, (char *)segments->Buffer + pos, page_size - pos );
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
if (errno == EFAULT)
|
||||
{
|
||||
status = STATUS_INVALID_USER_BUFFER;
|
||||
goto error;
|
||||
}
|
||||
status = FILE_GetNtStatus();
|
||||
break;
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
status = STATUS_DISK_FULL;
|
||||
break;
|
||||
}
|
||||
total += result;
|
||||
length -= result;
|
||||
if ((pos += result) == page_size)
|
||||
{
|
||||
pos = 0;
|
||||
segments++;
|
||||
}
|
||||
}
|
||||
|
||||
send_completion = cvalue != 0;
|
||||
|
||||
error:
|
||||
if (needs_close) close( unix_handle );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
io_status->u.Status = status;
|
||||
io_status->Information = total;
|
||||
TRACE("= SUCCESS (%u)\n", total);
|
||||
if (event) NtSetEvent( event, NULL );
|
||||
if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
|
||||
(ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("= 0x%08x\n", status);
|
||||
if (status != STATUS_PENDING && event) NtResetEvent( event, NULL );
|
||||
}
|
||||
|
||||
if (send_completion) NTDLL_AddCompletion( file, cvalue, status, total, FALSE );
|
||||
|
||||
return status;
|
||||
return unix_funcs->NtWriteFileGather( file, event, apc, apc_user, io_status,
|
||||
segments, length, offset, key );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -150,10 +150,6 @@ extern void virtual_fill_image_information( const pe_image_info_t *pe_info,
|
|||
SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN;
|
||||
extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN;
|
||||
|
||||
/* completion */
|
||||
extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue,
|
||||
NTSTATUS CompletionStatus, ULONG Information, BOOL async) DECLSPEC_HIDDEN;
|
||||
|
||||
/* locale */
|
||||
extern LCID user_lcid, system_lcid;
|
||||
extern DWORD ntdll_umbstowcs( const char* src, DWORD srclen, WCHAR* dst, DWORD dstlen ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -582,24 +582,6 @@ NTSTATUS WINAPI NtQueryIoCompletion( HANDLE handle, IO_COMPLETION_INFORMATION_CL
|
|||
return unix_funcs->NtQueryIoCompletion( handle, class, buffer, len, ret_len );
|
||||
}
|
||||
|
||||
NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue,
|
||||
NTSTATUS CompletionStatus, ULONG Information, BOOL async )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
SERVER_START_REQ( add_fd_completion )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( hFile );
|
||||
req->cvalue = CompletionValue;
|
||||
req->status = CompletionStatus;
|
||||
req->information = Information;
|
||||
req->async = async;
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* RtlRunOnceInitialize (NTDLL.@)
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -878,6 +878,8 @@ static struct unix_funcs unix_funcs =
|
|||
NtQueryVirtualMemory,
|
||||
NtQueueApcThread,
|
||||
NtRaiseException,
|
||||
NtReadFile,
|
||||
NtReadFileScatter,
|
||||
NtReadVirtualMemory,
|
||||
NtReleaseKeyedEvent,
|
||||
NtReleaseMutant,
|
||||
|
@ -906,6 +908,8 @@ static struct unix_funcs unix_funcs =
|
|||
NtWaitForKeyedEvent,
|
||||
NtWaitForMultipleObjects,
|
||||
NtWaitForSingleObject,
|
||||
NtWriteFile,
|
||||
NtWriteFileGather,
|
||||
NtWriteVirtualMemory,
|
||||
NtYieldExecution,
|
||||
DbgUiIssueRemoteBreakin,
|
||||
|
@ -939,10 +943,7 @@ static struct unix_funcs unix_funcs =
|
|||
virtual_create_builtin_view,
|
||||
virtual_alloc_thread_stack,
|
||||
virtual_locked_server_call,
|
||||
virtual_locked_read,
|
||||
virtual_locked_pread,
|
||||
virtual_locked_recvmsg,
|
||||
virtual_check_buffer_for_read,
|
||||
virtual_check_buffer_for_write,
|
||||
virtual_release_address_space,
|
||||
virtual_set_large_address_space,
|
||||
|
|
|
@ -54,6 +54,8 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
|
|||
return (struct ntdll_thread_data *)&NtCurrentTeb()->GdiTebBatch;
|
||||
}
|
||||
|
||||
static const UINT_PTR page_size = 0x1000;
|
||||
|
||||
NTSTATUS WINAPI KiUserExceptionDispatcher(EXCEPTION_RECORD*,CONTEXT*);
|
||||
void WINAPI LdrInitializeThunk(CONTEXT*,void**,ULONG_PTR,ULONG_PTR);
|
||||
|
||||
|
@ -89,10 +91,7 @@ extern void CDECL virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECL
|
|||
extern NTSTATUS CDECL virtual_create_builtin_view( void *module ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_size, SIZE_T commit_size, SIZE_T *pthread_size ) DECLSPEC_HIDDEN;
|
||||
extern unsigned int CDECL virtual_locked_server_call( void *req_ptr ) DECLSPEC_HIDDEN;
|
||||
extern ssize_t CDECL virtual_locked_read( int fd, void *addr, size_t size ) DECLSPEC_HIDDEN;
|
||||
extern ssize_t CDECL virtual_locked_pread( int fd, void *addr, size_t size, off_t offset ) DECLSPEC_HIDDEN;
|
||||
extern ssize_t CDECL virtual_locked_recvmsg( int fd, struct msghdr *hdr, int flags ) DECLSPEC_HIDDEN;
|
||||
extern BOOL CDECL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ) DECLSPEC_HIDDEN;
|
||||
extern BOOL CDECL virtual_check_buffer_for_write( void *ptr, SIZE_T size ) DECLSPEC_HIDDEN;
|
||||
extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN;
|
||||
extern void CDECL virtual_set_large_address_space(void) DECLSPEC_HIDDEN;
|
||||
|
@ -174,8 +173,11 @@ extern NTSTATUS virtual_alloc_teb( TEB **ret_teb ) DECLSPEC_HIDDEN;
|
|||
extern void virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN;
|
||||
extern void virtual_map_user_shared_data(void) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack ) DECLSPEC_HIDDEN;
|
||||
extern ssize_t virtual_locked_read( int fd, void *addr, size_t size ) DECLSPEC_HIDDEN;
|
||||
extern ssize_t virtual_locked_pread( int fd, void *addr, size_t size, off_t offset ) DECLSPEC_HIDDEN;
|
||||
extern BOOL virtual_is_valid_code_address( const void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
|
||||
extern int virtual_handle_stack_fault( void *addr ) DECLSPEC_HIDDEN;
|
||||
extern BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ) DECLSPEC_HIDDEN;
|
||||
extern SIZE_T virtual_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T size ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_T size ) DECLSPEC_HIDDEN;
|
||||
extern void virtual_set_force_exec( BOOL enable ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -134,7 +134,6 @@ static RTL_CRITICAL_SECTION csVirtual = { &critsect_debug, -1, 0, 0, 0, 0 };
|
|||
|
||||
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
|
||||
static const UINT page_shift = 12;
|
||||
static const UINT_PTR page_size = 0x1000;
|
||||
static const UINT_PTR page_mask = 0xfff;
|
||||
static const UINT_PTR granularity_mask = 0xffff;
|
||||
|
||||
|
@ -2866,7 +2865,7 @@ unsigned int CDECL virtual_locked_server_call( void *req_ptr )
|
|||
/***********************************************************************
|
||||
* virtual_locked_read
|
||||
*/
|
||||
ssize_t CDECL virtual_locked_read( int fd, void *addr, size_t size )
|
||||
ssize_t virtual_locked_read( int fd, void *addr, size_t size )
|
||||
{
|
||||
sigset_t sigset;
|
||||
BOOL has_write_watch = FALSE;
|
||||
|
@ -2891,7 +2890,7 @@ ssize_t CDECL virtual_locked_read( int fd, void *addr, size_t size )
|
|||
/***********************************************************************
|
||||
* virtual_locked_pread
|
||||
*/
|
||||
ssize_t CDECL virtual_locked_pread( int fd, void *addr, size_t size, off_t offset )
|
||||
ssize_t virtual_locked_pread( int fd, void *addr, size_t size, off_t offset )
|
||||
{
|
||||
sigset_t sigset;
|
||||
BOOL has_write_watch = FALSE;
|
||||
|
@ -3007,7 +3006,7 @@ int virtual_handle_stack_fault( void *addr )
|
|||
*
|
||||
* Check if a memory buffer can be read, triggering page faults if needed for DIB section access.
|
||||
*/
|
||||
BOOL CDECL virtual_check_buffer_for_read( const void *ptr, SIZE_T size )
|
||||
BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size )
|
||||
{
|
||||
if (!size) return TRUE;
|
||||
if (!ptr) return FALSE;
|
||||
|
|
|
@ -28,7 +28,7 @@ struct ldt_copy;
|
|||
struct msghdr;
|
||||
|
||||
/* increment this when you change the function table */
|
||||
#define NTDLL_UNIXLIB_VERSION 48
|
||||
#define NTDLL_UNIXLIB_VERSION 49
|
||||
|
||||
struct unix_funcs
|
||||
{
|
||||
|
@ -159,6 +159,13 @@ struct unix_funcs
|
|||
NTSTATUS (WINAPI *NtQueueApcThread)( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1,
|
||||
ULONG_PTR arg2, ULONG_PTR arg3 );
|
||||
NTSTATUS (WINAPI *NtRaiseException)( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance );
|
||||
NTSTATUS (WINAPI *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 );
|
||||
NTSTATUS (WINAPI *NtReadFileScatter)( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc,
|
||||
void *apc_user, IO_STATUS_BLOCK *io,
|
||||
FILE_SEGMENT_ELEMENT *segments, ULONG length,
|
||||
LARGE_INTEGER *offset, ULONG *key );
|
||||
NTSTATUS (WINAPI *NtReadVirtualMemory)( HANDLE process, const void *addr, void *buffer,
|
||||
SIZE_T size, SIZE_T *bytes_read );
|
||||
NTSTATUS (WINAPI *NtReleaseKeyedEvent)( HANDLE handle, const void *key,
|
||||
|
@ -204,6 +211,13 @@ struct unix_funcs
|
|||
const LARGE_INTEGER *timeout );
|
||||
NTSTATUS (WINAPI *NtWaitForSingleObject)( HANDLE handle, BOOLEAN alertable,
|
||||
const LARGE_INTEGER *timeout );
|
||||
NTSTATUS (WINAPI *NtWriteFile)( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
|
||||
IO_STATUS_BLOCK *io, const void *buffer, ULONG length,
|
||||
LARGE_INTEGER *offset, ULONG *key );
|
||||
NTSTATUS (WINAPI *NtWriteFileGather)( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc,
|
||||
void *apc_user, IO_STATUS_BLOCK *io,
|
||||
FILE_SEGMENT_ELEMENT *segments, ULONG length,
|
||||
LARGE_INTEGER *offset, ULONG *key );
|
||||
NTSTATUS (WINAPI *NtWriteVirtualMemory)( HANDLE process, void *addr, const void *buffer,
|
||||
SIZE_T size, SIZE_T *bytes_written );
|
||||
NTSTATUS (WINAPI *NtYieldExecution)(void);
|
||||
|
@ -253,10 +267,7 @@ struct unix_funcs
|
|||
NTSTATUS (CDECL *virtual_create_builtin_view)( void *module );
|
||||
NTSTATUS (CDECL *virtual_alloc_thread_stack)( INITIAL_TEB *stack, SIZE_T reserve_size, SIZE_T commit_size, SIZE_T *pthread_size );
|
||||
unsigned int (CDECL *virtual_locked_server_call)( void *req_ptr );
|
||||
ssize_t (CDECL *virtual_locked_read)( int fd, void *addr, size_t size );
|
||||
ssize_t (CDECL *virtual_locked_pread)( int fd, void *addr, size_t size, off_t offset );
|
||||
ssize_t (CDECL *virtual_locked_recvmsg)( int fd, struct msghdr *hdr, int flags );
|
||||
BOOL (CDECL *virtual_check_buffer_for_read)( const void *ptr, SIZE_T size );
|
||||
BOOL (CDECL *virtual_check_buffer_for_write)( void *ptr, SIZE_T size );
|
||||
void (CDECL *virtual_release_address_space)(void);
|
||||
void (CDECL *virtual_set_large_address_space)(void);
|
||||
|
|
Loading…
Reference in New Issue