forked from Mirrors/wine-wine
ntdll: Move fd cache functions to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
8a63b688ac
commit
1a743c9af3
|
@ -2844,7 +2844,7 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
|
||||||
|
|
||||||
piosb->Information = 0;
|
piosb->Information = 0;
|
||||||
|
|
||||||
if ((status = server_get_unix_fd( hDevice, 0, &fd, &needs_close, NULL, NULL )))
|
if ((status = unix_funcs->server_get_unix_fd( hDevice, 0, &fd, &needs_close, NULL, NULL )))
|
||||||
{
|
{
|
||||||
if (status == STATUS_BAD_DEVICE_TYPE) return status; /* no associated fd */
|
if (status == STATUS_BAD_DEVICE_TYPE) return status; /* no associated fd */
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -1946,7 +1946,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH NtQueryDirectoryFile( HANDLE handle, HANDLE ev
|
||||||
}
|
}
|
||||||
if (!buffer) return STATUS_ACCESS_VIOLATION;
|
if (!buffer) return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
if ((status = server_get_unix_fd( handle, FILE_LIST_DIRECTORY, &fd, &needs_close, NULL, NULL )) != STATUS_SUCCESS)
|
if ((status = unix_funcs->server_get_unix_fd( handle, FILE_LIST_DIRECTORY, &fd, &needs_close, NULL, NULL )) != STATUS_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
io->Information = 0;
|
io->Information = 0;
|
||||||
|
@ -2436,7 +2436,7 @@ NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *
|
||||||
return STATUS_NO_MEMORY;
|
return STATUS_NO_MEMORY;
|
||||||
strcpy( unix_name->Buffer, "." );
|
strcpy( unix_name->Buffer, "." );
|
||||||
|
|
||||||
if ((status = server_get_unix_fd( attr->RootDirectory, 0, &root_fd, &needs_close, &type, NULL )))
|
if ((status = unix_funcs->server_get_unix_fd( attr->RootDirectory, 0, &root_fd, &needs_close, &type, NULL )))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (type != FD_TYPE_DIR)
|
if (type != FD_TYPE_DIR)
|
||||||
|
@ -2638,7 +2638,7 @@ NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *
|
||||||
return STATUS_NO_MEMORY;
|
return STATUS_NO_MEMORY;
|
||||||
unix_name[0] = '.';
|
unix_name[0] = '.';
|
||||||
|
|
||||||
if (!(status = server_get_unix_fd( attr->RootDirectory, 0, &root_fd, &needs_close, &type, NULL )))
|
if (!(status = unix_funcs->server_get_unix_fd( attr->RootDirectory, 0, &root_fd, &needs_close, &type, NULL )))
|
||||||
{
|
{
|
||||||
if (type != FD_TYPE_DIR)
|
if (type != FD_TYPE_DIR)
|
||||||
{
|
{
|
||||||
|
@ -2867,7 +2867,7 @@ NTSTATUS DIR_unmount_device( HANDLE handle )
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
int unix_fd, needs_close;
|
int unix_fd, needs_close;
|
||||||
|
|
||||||
if (!(status = server_get_unix_fd( handle, 0, &unix_fd, &needs_close, NULL, NULL )))
|
if (!(status = unix_funcs->server_get_unix_fd( handle, 0, &unix_fd, &needs_close, NULL, NULL )))
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *mount_point = NULL;
|
char *mount_point = NULL;
|
||||||
|
@ -2949,7 +2949,7 @@ NTSTATUS DIR_get_unix_cwd( char **cwd )
|
||||||
if (status != STATUS_SUCCESS) goto done;
|
if (status != STATUS_SUCCESS) goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status = server_get_unix_fd( handle, 0, &unix_fd, &needs_close, NULL, NULL )) == STATUS_SUCCESS)
|
if ((status = unix_funcs->server_get_unix_fd( handle, 0, &unix_fd, &needs_close, NULL, NULL )) == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
RtlEnterCriticalSection( &dir_section );
|
RtlEnterCriticalSection( &dir_section );
|
||||||
|
|
||||||
|
|
|
@ -542,8 +542,8 @@ static NTSTATUS FILE_AsyncReadService( void *user, IO_STATUS_BLOCK *iosb, NTSTAT
|
||||||
{
|
{
|
||||||
case STATUS_ALERTED: /* got some new data */
|
case STATUS_ALERTED: /* got some new data */
|
||||||
/* check to see if the data is ready (non-blocking) */
|
/* check to see if the data is ready (non-blocking) */
|
||||||
if ((status = server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd,
|
if ((status = unix_funcs->server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd,
|
||||||
&needs_close, NULL, NULL )))
|
&needs_close, NULL, NULL )))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
result = virtual_locked_read(fd, &fileio->buffer[fileio->already], fileio->count-fileio->already);
|
result = virtual_locked_read(fd, &fileio->buffer[fileio->already], fileio->count-fileio->already);
|
||||||
|
@ -862,8 +862,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
|
||||||
|
|
||||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
status = server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle,
|
status = unix_funcs->server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle,
|
||||||
&needs_close, &type, &options );
|
&needs_close, &type, &options );
|
||||||
if (status && status != STATUS_BAD_DEVICE_TYPE) return status;
|
if (status && status != STATUS_BAD_DEVICE_TYPE) return status;
|
||||||
|
|
||||||
if (!virtual_check_buffer_for_write( buffer, length )) return STATUS_ACCESS_VIOLATION;
|
if (!virtual_check_buffer_for_write( buffer, length )) return STATUS_ACCESS_VIOLATION;
|
||||||
|
@ -1062,8 +1062,8 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
|
||||||
|
|
||||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
status = server_get_unix_fd( file, FILE_READ_DATA, &unix_handle,
|
status = unix_funcs->server_get_unix_fd( file, FILE_READ_DATA, &unix_handle,
|
||||||
&needs_close, &type, &options );
|
&needs_close, &type, &options );
|
||||||
if (status) return status;
|
if (status) return status;
|
||||||
|
|
||||||
if ((type != FD_TYPE_FILE) ||
|
if ((type != FD_TYPE_FILE) ||
|
||||||
|
@ -1137,8 +1137,8 @@ static NTSTATUS FILE_AsyncWriteService( void *user, IO_STATUS_BLOCK *iosb, NTSTA
|
||||||
{
|
{
|
||||||
case STATUS_ALERTED:
|
case STATUS_ALERTED:
|
||||||
/* write some data (non-blocking) */
|
/* write some data (non-blocking) */
|
||||||
if ((status = server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd,
|
if ((status = unix_funcs->server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd,
|
||||||
&needs_close, &type, NULL )))
|
&needs_close, &type, NULL )))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!fileio->count && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_SOCKET))
|
if (!fileio->count && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_SOCKET))
|
||||||
|
@ -1231,12 +1231,12 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
|
||||||
|
|
||||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
status = server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle,
|
status = unix_funcs->server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle,
|
||||||
&needs_close, &type, &options );
|
&needs_close, &type, &options );
|
||||||
if (status == STATUS_ACCESS_DENIED)
|
if (status == STATUS_ACCESS_DENIED)
|
||||||
{
|
{
|
||||||
status = server_get_unix_fd( hFile, FILE_APPEND_DATA, &unix_handle,
|
status = unix_funcs->server_get_unix_fd( hFile, FILE_APPEND_DATA, &unix_handle,
|
||||||
&needs_close, &type, &options );
|
&needs_close, &type, &options );
|
||||||
append_write = TRUE;
|
append_write = TRUE;
|
||||||
}
|
}
|
||||||
if (status && status != STATUS_BAD_DEVICE_TYPE) return status;
|
if (status && status != STATUS_BAD_DEVICE_TYPE) return status;
|
||||||
|
@ -1458,8 +1458,8 @@ NTSTATUS WINAPI NtWriteFileGather( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
|
||||||
if (length % page_size) return STATUS_INVALID_PARAMETER;
|
if (length % page_size) return STATUS_INVALID_PARAMETER;
|
||||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
status = server_get_unix_fd( file, FILE_WRITE_DATA, &unix_handle,
|
status = unix_funcs->server_get_unix_fd( file, FILE_WRITE_DATA, &unix_handle,
|
||||||
&needs_close, &type, &options );
|
&needs_close, &type, &options );
|
||||||
if (status) return status;
|
if (status) return status;
|
||||||
|
|
||||||
if ((type != FD_TYPE_FILE) ||
|
if ((type != FD_TYPE_FILE) ||
|
||||||
|
@ -2459,7 +2459,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||||
if (len < info_sizes[class])
|
if (len < info_sizes[class])
|
||||||
return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
|
return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
|
||||||
if ((io->u.Status = server_get_unix_fd( hFile, 0, &fd, &needs_close, NULL, &options )))
|
if ((io->u.Status = unix_funcs->server_get_unix_fd( hFile, 0, &fd, &needs_close, NULL, &options )))
|
||||||
{
|
{
|
||||||
if (io->u.Status != STATUS_BAD_DEVICE_TYPE) return io->u.Status;
|
if (io->u.Status != STATUS_BAD_DEVICE_TYPE) return io->u.Status;
|
||||||
return server_get_file_info( hFile, io, ptr, len, class );
|
return server_get_file_info( hFile, io, ptr, len, class );
|
||||||
|
@ -2561,7 +2561,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||||
if (size > 0x10000) size = 0x10000;
|
if (size > 0x10000) size = 0x10000;
|
||||||
if ((tmpbuf = RtlAllocateHeap( GetProcessHeap(), 0, size )))
|
if ((tmpbuf = RtlAllocateHeap( GetProcessHeap(), 0, size )))
|
||||||
{
|
{
|
||||||
if (!server_get_unix_fd( hFile, FILE_READ_DATA, &fd, &needs_close, NULL, NULL ))
|
if (!unix_funcs->server_get_unix_fd( hFile, FILE_READ_DATA, &fd, &needs_close, NULL, NULL ))
|
||||||
{
|
{
|
||||||
int res = recv( fd, tmpbuf, size, MSG_PEEK );
|
int res = recv( fd, tmpbuf, size, MSG_PEEK );
|
||||||
info->MessagesAvailable = (res > 0);
|
info->MessagesAvailable = (res > 0);
|
||||||
|
@ -2693,7 +2693,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
||||||
const FILE_BASIC_INFORMATION *info = ptr;
|
const FILE_BASIC_INFORMATION *info = ptr;
|
||||||
LARGE_INTEGER mtime, atime;
|
LARGE_INTEGER mtime, atime;
|
||||||
|
|
||||||
if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
|
if ((io->u.Status = unix_funcs->server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
|
||||||
return io->u.Status;
|
return io->u.Status;
|
||||||
|
|
||||||
mtime.QuadPart = info->LastWriteTime.QuadPart == -1 ? 0 : info->LastWriteTime.QuadPart;
|
mtime.QuadPart = info->LastWriteTime.QuadPart == -1 ? 0 : info->LastWriteTime.QuadPart;
|
||||||
|
@ -2733,7 +2733,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
||||||
{
|
{
|
||||||
const FILE_POSITION_INFORMATION *info = ptr;
|
const FILE_POSITION_INFORMATION *info = ptr;
|
||||||
|
|
||||||
if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
|
if ((io->u.Status = unix_funcs->server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
|
||||||
return io->u.Status;
|
return io->u.Status;
|
||||||
|
|
||||||
if (lseek( fd, info->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1)
|
if (lseek( fd, info->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1)
|
||||||
|
@ -2750,7 +2750,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const FILE_END_OF_FILE_INFORMATION *info = ptr;
|
const FILE_END_OF_FILE_INFORMATION *info = ptr;
|
||||||
|
|
||||||
if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
|
if ((io->u.Status = unix_funcs->server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
|
||||||
return io->u.Status;
|
return io->u.Status;
|
||||||
|
|
||||||
/* first try normal truncate */
|
/* first try normal truncate */
|
||||||
|
@ -2869,7 +2869,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const FILE_VALID_DATA_LENGTH_INFORMATION *info = ptr;
|
const FILE_VALID_DATA_LENGTH_INFORMATION *info = ptr;
|
||||||
|
|
||||||
if ((io->u.Status = server_get_unix_fd( handle, FILE_WRITE_DATA, &fd, &needs_close, NULL, NULL )))
|
if ((io->u.Status = unix_funcs->server_get_unix_fd( handle, FILE_WRITE_DATA, &fd, &needs_close, NULL, NULL )))
|
||||||
return io->u.Status;
|
return io->u.Status;
|
||||||
|
|
||||||
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
|
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||||
|
@ -3269,7 +3269,7 @@ NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, PIO_STATUS_BLOCK io
|
||||||
int fd, needs_close;
|
int fd, needs_close;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL );
|
io->u.Status = unix_funcs->server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL );
|
||||||
if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
|
if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
SERVER_START_REQ( get_volume_info )
|
SERVER_START_REQ( get_volume_info )
|
||||||
|
@ -3577,9 +3577,9 @@ NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK *io )
|
||||||
|
|
||||||
if (!io || !virtual_check_buffer_for_write( io, sizeof(*io) )) return STATUS_ACCESS_VIOLATION;
|
if (!io || !virtual_check_buffer_for_write( io, sizeof(*io) )) return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
ret = server_get_unix_fd( hFile, FILE_WRITE_DATA, &fd, &needs_close, &type, NULL );
|
ret = unix_funcs->server_get_unix_fd( hFile, FILE_WRITE_DATA, &fd, &needs_close, &type, NULL );
|
||||||
if (ret == STATUS_ACCESS_DENIED)
|
if (ret == STATUS_ACCESS_DENIED)
|
||||||
ret = server_get_unix_fd( hFile, FILE_APPEND_DATA, &fd, &needs_close, &type, NULL );
|
ret = unix_funcs->server_get_unix_fd( hFile, FILE_APPEND_DATA, &fd, &needs_close, &type, NULL );
|
||||||
|
|
||||||
if (!ret && type == FD_TYPE_SERIAL)
|
if (!ret && type == FD_TYPE_SERIAL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2340,7 +2340,7 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm,
|
||||||
return STATUS_DLL_NOT_FOUND;
|
return STATUS_DLL_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))
|
if (!unix_funcs->server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))
|
||||||
{
|
{
|
||||||
fstat( fd, st );
|
fstat( fd, st );
|
||||||
if (needs_close) close( fd );
|
if (needs_close) close( fd );
|
||||||
|
|
|
@ -127,9 +127,6 @@ extern unsigned int server_select( const select_op_t *select_op, data_size_t siz
|
||||||
extern unsigned int server_wait( const select_op_t *select_op, data_size_t size,
|
extern unsigned int server_wait( const select_op_t *select_op, data_size_t size,
|
||||||
UINT flags, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
UINT flags, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||||
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN;
|
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN;
|
||||||
extern int server_remove_fd_from_cache( HANDLE handle ) DECLSPEC_HIDDEN;
|
|
||||||
extern int server_get_unix_fd( HANDLE handle, unsigned int access, int *unix_fd,
|
|
||||||
int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN;
|
|
||||||
extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
|
extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
|
||||||
data_size_t *ret_len ) DECLSPEC_HIDDEN;
|
data_size_t *ret_len ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS validate_open_object_attributes( const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN;
|
extern NTSTATUS validate_open_object_attributes( const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -366,7 +366,7 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
|
||||||
if (dest) *dest = wine_server_ptr_handle( reply->handle );
|
if (dest) *dest = wine_server_ptr_handle( reply->handle );
|
||||||
if (reply->closed && reply->self)
|
if (reply->closed && reply->self)
|
||||||
{
|
{
|
||||||
int fd = server_remove_fd_from_cache( source );
|
int fd = unix_funcs->server_remove_fd_from_cache( source );
|
||||||
if (fd != -1) close( fd );
|
if (fd != -1) close( fd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +385,7 @@ static LONG WINAPI invalid_handle_exception_handler( EXCEPTION_POINTERS *eptr )
|
||||||
NTSTATUS close_handle( HANDLE handle )
|
NTSTATUS close_handle( HANDLE handle )
|
||||||
{
|
{
|
||||||
NTSTATUS ret;
|
NTSTATUS ret;
|
||||||
int fd = server_remove_fd_from_cache( handle );
|
int fd = unix_funcs->server_remove_fd_from_cache( handle );
|
||||||
|
|
||||||
SERVER_START_REQ( close_handle )
|
SERVER_START_REQ( close_handle )
|
||||||
{
|
{
|
||||||
|
|
|
@ -951,7 +951,7 @@ static DWORD CALLBACK wait_for_event(LPVOID arg)
|
||||||
async_commio *commio = arg;
|
async_commio *commio = arg;
|
||||||
int fd, needs_close;
|
int fd, needs_close;
|
||||||
|
|
||||||
if (!server_get_unix_fd( commio->hDevice, FILE_READ_DATA | FILE_WRITE_DATA, &fd, &needs_close, NULL, NULL ))
|
if (!unix_funcs->server_get_unix_fd( commio->hDevice, FILE_READ_DATA | FILE_WRITE_DATA, &fd, &needs_close, NULL, NULL ))
|
||||||
{
|
{
|
||||||
serial_irq_info new_irq_info;
|
serial_irq_info new_irq_info;
|
||||||
DWORD new_mstat, dummy, cookie;
|
DWORD new_mstat, dummy, cookie;
|
||||||
|
@ -1141,7 +1141,7 @@ static inline NTSTATUS io_control(HANDLE hDevice,
|
||||||
|
|
||||||
piosb->Information = 0;
|
piosb->Information = 0;
|
||||||
|
|
||||||
if ((status = server_get_unix_fd( hDevice, access, &fd, &needs_close, &type, NULL )))
|
if ((status = unix_funcs->server_get_unix_fd( hDevice, access, &fd, &needs_close, &type, NULL )))
|
||||||
goto error;
|
goto error;
|
||||||
if (type != FD_TYPE_SERIAL)
|
if (type != FD_TYPE_SERIAL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,8 +93,6 @@
|
||||||
#include "ntdll_misc.h"
|
#include "ntdll_misc.h"
|
||||||
#include "ddk/wdm.h"
|
#include "ddk/wdm.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(server);
|
|
||||||
|
|
||||||
/* Some versions of glibc don't define this */
|
/* Some versions of glibc don't define this */
|
||||||
#ifndef SCM_RIGHTS
|
#ifndef SCM_RIGHTS
|
||||||
#define SCM_RIGHTS 1
|
#define SCM_RIGHTS 1
|
||||||
|
@ -118,27 +116,6 @@ timeout_t server_start_time = 0; /* time of server startup */
|
||||||
|
|
||||||
sigset_t server_block_set; /* signals to block during server calls */
|
sigset_t server_block_set; /* signals to block during server calls */
|
||||||
|
|
||||||
static RTL_CRITICAL_SECTION fd_cache_section;
|
|
||||||
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
|
|
||||||
{
|
|
||||||
0, 0, &fd_cache_section,
|
|
||||||
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
|
||||||
0, 0, { (DWORD_PTR)(__FILE__ ": fd_cache_section") }
|
|
||||||
};
|
|
||||||
static RTL_CRITICAL_SECTION fd_cache_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
|
||||||
|
|
||||||
/* atomically exchange a 64-bit value */
|
|
||||||
static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val )
|
|
||||||
{
|
|
||||||
#ifdef _WIN64
|
|
||||||
return (LONG64)InterlockedExchangePointer( (void **)dest, (void *)val );
|
|
||||||
#else
|
|
||||||
LONG64 tmp = *dest;
|
|
||||||
while (InterlockedCompareExchange64( dest, val, tmp ) != tmp) tmp = *dest;
|
|
||||||
return tmp;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* server_protocol_error
|
* server_protocol_error
|
||||||
*/
|
*/
|
||||||
|
@ -750,182 +727,6 @@ void CDECL wine_server_send_fd( int fd )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
/* fd cache support */
|
|
||||||
|
|
||||||
union fd_cache_entry
|
|
||||||
{
|
|
||||||
LONG64 data;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
enum server_fd_type type : 5;
|
|
||||||
unsigned int access : 3;
|
|
||||||
unsigned int options : 24;
|
|
||||||
} s;
|
|
||||||
};
|
|
||||||
|
|
||||||
C_ASSERT( sizeof(union fd_cache_entry) == sizeof(LONG64) );
|
|
||||||
|
|
||||||
#define FD_CACHE_BLOCK_SIZE (65536 / sizeof(union fd_cache_entry))
|
|
||||||
#define FD_CACHE_ENTRIES 128
|
|
||||||
|
|
||||||
static union fd_cache_entry *fd_cache[FD_CACHE_ENTRIES];
|
|
||||||
static union fd_cache_entry fd_cache_initial_block[FD_CACHE_BLOCK_SIZE];
|
|
||||||
|
|
||||||
static inline unsigned int handle_to_index( HANDLE handle, unsigned int *entry )
|
|
||||||
{
|
|
||||||
unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1;
|
|
||||||
*entry = idx / FD_CACHE_BLOCK_SIZE;
|
|
||||||
return idx % FD_CACHE_BLOCK_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* add_fd_to_cache
|
|
||||||
*
|
|
||||||
* Caller must hold fd_cache_section.
|
|
||||||
*/
|
|
||||||
static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
|
|
||||||
unsigned int access, unsigned int options )
|
|
||||||
{
|
|
||||||
unsigned int entry, idx = handle_to_index( handle, &entry );
|
|
||||||
union fd_cache_entry cache;
|
|
||||||
|
|
||||||
if (entry >= FD_CACHE_ENTRIES)
|
|
||||||
{
|
|
||||||
FIXME( "too many allocated handles, not caching %p\n", handle );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fd_cache[entry]) /* do we need to allocate a new block of entries? */
|
|
||||||
{
|
|
||||||
if (!entry) fd_cache[0] = fd_cache_initial_block;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
void *ptr = wine_anon_mmap( NULL, FD_CACHE_BLOCK_SIZE * sizeof(union fd_cache_entry),
|
|
||||||
PROT_READ | PROT_WRITE, 0 );
|
|
||||||
if (ptr == MAP_FAILED) return FALSE;
|
|
||||||
fd_cache[entry] = ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store fd+1 so that 0 can be used as the unset value */
|
|
||||||
cache.s.fd = fd + 1;
|
|
||||||
cache.s.type = type;
|
|
||||||
cache.s.access = access;
|
|
||||||
cache.s.options = options;
|
|
||||||
cache.data = interlocked_xchg64( &fd_cache[entry][idx].data, cache.data );
|
|
||||||
assert( !cache.s.fd );
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* get_cached_fd
|
|
||||||
*/
|
|
||||||
static inline NTSTATUS get_cached_fd( HANDLE handle, int *fd, enum server_fd_type *type,
|
|
||||||
unsigned int *access, unsigned int *options )
|
|
||||||
{
|
|
||||||
unsigned int entry, idx = handle_to_index( handle, &entry );
|
|
||||||
union fd_cache_entry cache;
|
|
||||||
|
|
||||||
if (entry >= FD_CACHE_ENTRIES || !fd_cache[entry]) return STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
cache.data = InterlockedCompareExchange64( &fd_cache[entry][idx].data, 0, 0 );
|
|
||||||
if (!cache.data) return STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
/* if fd type is invalid, fd stores an error value */
|
|
||||||
if (cache.s.type == FD_TYPE_INVALID) return cache.s.fd - 1;
|
|
||||||
|
|
||||||
*fd = cache.s.fd - 1;
|
|
||||||
if (type) *type = cache.s.type;
|
|
||||||
if (access) *access = cache.s.access;
|
|
||||||
if (options) *options = cache.s.options;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* server_remove_fd_from_cache
|
|
||||||
*/
|
|
||||||
int server_remove_fd_from_cache( HANDLE handle )
|
|
||||||
{
|
|
||||||
unsigned int entry, idx = handle_to_index( handle, &entry );
|
|
||||||
int fd = -1;
|
|
||||||
|
|
||||||
if (entry < FD_CACHE_ENTRIES && fd_cache[entry])
|
|
||||||
{
|
|
||||||
union fd_cache_entry cache;
|
|
||||||
cache.data = interlocked_xchg64( &fd_cache[entry][idx].data, 0 );
|
|
||||||
if (cache.s.type != FD_TYPE_INVALID) fd = cache.s.fd - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* server_get_unix_fd
|
|
||||||
*
|
|
||||||
* The returned unix_fd should be closed iff needs_close is non-zero.
|
|
||||||
*/
|
|
||||||
int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
|
|
||||||
int *needs_close, enum server_fd_type *type, unsigned int *options )
|
|
||||||
{
|
|
||||||
sigset_t sigset;
|
|
||||||
obj_handle_t fd_handle;
|
|
||||||
int ret, fd = -1;
|
|
||||||
unsigned int access = 0;
|
|
||||||
|
|
||||||
*unix_fd = -1;
|
|
||||||
*needs_close = 0;
|
|
||||||
wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA;
|
|
||||||
|
|
||||||
ret = get_cached_fd( handle, &fd, type, &access, options );
|
|
||||||
if (ret != STATUS_INVALID_HANDLE) goto done;
|
|
||||||
|
|
||||||
server_enter_uninterrupted_section( &fd_cache_section, &sigset );
|
|
||||||
ret = get_cached_fd( handle, &fd, type, &access, options );
|
|
||||||
if (ret == STATUS_INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
SERVER_START_REQ( get_handle_fd )
|
|
||||||
{
|
|
||||||
req->handle = wine_server_obj_handle( handle );
|
|
||||||
if (!(ret = wine_server_call( req )))
|
|
||||||
{
|
|
||||||
if (type) *type = reply->type;
|
|
||||||
if (options) *options = reply->options;
|
|
||||||
access = reply->access;
|
|
||||||
if ((fd = unix_funcs->receive_fd( &fd_handle )) != -1)
|
|
||||||
{
|
|
||||||
assert( wine_server_ptr_handle(fd_handle) == handle );
|
|
||||||
*needs_close = (!reply->cacheable ||
|
|
||||||
!add_fd_to_cache( handle, fd, reply->type,
|
|
||||||
reply->access, reply->options ));
|
|
||||||
}
|
|
||||||
else ret = STATUS_TOO_MANY_OPENED_FILES;
|
|
||||||
}
|
|
||||||
else if (reply->cacheable)
|
|
||||||
{
|
|
||||||
add_fd_to_cache( handle, ret, FD_TYPE_INVALID, 0, 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
}
|
|
||||||
server_leave_uninterrupted_section( &fd_cache_section, &sigset );
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (!ret && ((access & wanted_access) != wanted_access))
|
|
||||||
{
|
|
||||||
ret = STATUS_ACCESS_DENIED;
|
|
||||||
if (*needs_close) close( fd );
|
|
||||||
}
|
|
||||||
if (!ret) *unix_fd = fd;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* wine_server_fd_to_handle (NTDLL.@)
|
* wine_server_fd_to_handle (NTDLL.@)
|
||||||
*
|
*
|
||||||
|
@ -942,20 +743,7 @@ done:
|
||||||
*/
|
*/
|
||||||
int CDECL wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, HANDLE *handle )
|
int CDECL wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, HANDLE *handle )
|
||||||
{
|
{
|
||||||
int ret;
|
return unix_funcs->server_fd_to_handle( fd, access, attributes, handle );
|
||||||
|
|
||||||
*handle = 0;
|
|
||||||
wine_server_send_fd( fd );
|
|
||||||
|
|
||||||
SERVER_START_REQ( alloc_file_handle )
|
|
||||||
{
|
|
||||||
req->access = access;
|
|
||||||
req->attributes = attributes;
|
|
||||||
req->fd = fd;
|
|
||||||
if (!(ret = wine_server_call( req ))) *handle = wine_server_ptr_handle( reply->handle );
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -974,15 +762,9 @@ int CDECL wine_server_fd_to_handle( int fd, unsigned int access, unsigned int at
|
||||||
* NTSTATUS code
|
* NTSTATUS code
|
||||||
*/
|
*/
|
||||||
int CDECL wine_server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd,
|
int CDECL wine_server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd,
|
||||||
unsigned int *options )
|
unsigned int *options )
|
||||||
{
|
{
|
||||||
int needs_close, ret = server_get_unix_fd( handle, access, unix_fd, &needs_close, NULL, options );
|
return unix_funcs->server_handle_to_fd( handle, access, unix_fd, options );
|
||||||
|
|
||||||
if (!ret && !needs_close)
|
|
||||||
{
|
|
||||||
if ((*unix_fd = dup(*unix_fd)) == -1) ret = FILE_GetNtStatus();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1000,7 +782,7 @@ int CDECL wine_server_handle_to_fd( HANDLE handle, unsigned int access, int *uni
|
||||||
*/
|
*/
|
||||||
void CDECL wine_server_release_fd( HANDLE handle, int unix_fd )
|
void CDECL wine_server_release_fd( HANDLE handle, int unix_fd )
|
||||||
{
|
{
|
||||||
close( unix_fd );
|
unix_funcs->server_release_fd( handle, unix_fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -530,7 +530,7 @@ NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
|
||||||
|
|
||||||
io_status->Information = 0;
|
io_status->Information = 0;
|
||||||
|
|
||||||
if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )))
|
if ((status = unix_funcs->server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
switch (io_control)
|
switch (io_control)
|
||||||
|
|
|
@ -199,7 +199,7 @@ void map_user_shared_data(void)
|
||||||
MESSAGE( "wine: failed to open the USD section: %08x\n", status );
|
MESSAGE( "wine: failed to open the USD section: %08x\n", status );
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if ((res = server_get_unix_fd( section, 0, &fd, &needs_close, NULL, NULL )) ||
|
if ((res = unix_funcs->server_get_unix_fd( section, 0, &fd, &needs_close, NULL, NULL )) ||
|
||||||
(user_shared_data != mmap( user_shared_data, sizeof(*user_shared_data),
|
(user_shared_data != mmap( user_shared_data, sizeof(*user_shared_data),
|
||||||
PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0 )))
|
PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0 )))
|
||||||
{
|
{
|
||||||
|
|
|
@ -997,7 +997,11 @@ static struct unix_funcs unix_funcs =
|
||||||
mmap_is_in_reserved_area,
|
mmap_is_in_reserved_area,
|
||||||
mmap_enum_reserved_areas,
|
mmap_enum_reserved_areas,
|
||||||
server_send_fd,
|
server_send_fd,
|
||||||
receive_fd,
|
server_remove_fd_from_cache,
|
||||||
|
server_get_unix_fd,
|
||||||
|
server_fd_to_handle,
|
||||||
|
server_handle_to_fd,
|
||||||
|
server_release_fd,
|
||||||
server_pipe,
|
server_pipe,
|
||||||
server_init_process,
|
server_init_process,
|
||||||
server_init_process_done,
|
server_init_process_done,
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
#include "unix_private.h"
|
#include "unix_private.h"
|
||||||
#include "ddk/wdm.h"
|
#include "ddk/wdm.h"
|
||||||
|
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(server);
|
WINE_DEFAULT_DEBUG_CHANNEL(server);
|
||||||
|
|
||||||
#ifndef MSG_CMSG_CLOEXEC
|
#ifndef MSG_CMSG_CLOEXEC
|
||||||
#define MSG_CMSG_CLOEXEC 0
|
#define MSG_CMSG_CLOEXEC 0
|
||||||
|
@ -127,6 +127,27 @@ sigset_t server_block_set; /* signals to block during server calls */
|
||||||
static int fd_socket = -1; /* socket to exchange file descriptors with the server */
|
static int fd_socket = -1; /* socket to exchange file descriptors with the server */
|
||||||
static pid_t server_pid;
|
static pid_t server_pid;
|
||||||
|
|
||||||
|
static RTL_CRITICAL_SECTION fd_cache_section;
|
||||||
|
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
|
||||||
|
{
|
||||||
|
0, 0, &fd_cache_section,
|
||||||
|
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
||||||
|
0, 0, { (DWORD_PTR)(__FILE__ ": fd_cache_section") }
|
||||||
|
};
|
||||||
|
static RTL_CRITICAL_SECTION fd_cache_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
/* atomically exchange a 64-bit value */
|
||||||
|
static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val )
|
||||||
|
{
|
||||||
|
#ifdef _WIN64
|
||||||
|
return (LONG64)InterlockedExchangePointer( (void **)dest, (void *)val );
|
||||||
|
#else
|
||||||
|
LONG64 tmp = *dest;
|
||||||
|
while (InterlockedCompareExchange64( dest, val, tmp ) != tmp) tmp = *dest;
|
||||||
|
return tmp;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
|
static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
|
||||||
static void fatal_perror( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
|
static void fatal_perror( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
|
||||||
|
@ -184,6 +205,26 @@ static DECLSPEC_NORETURN void server_protocol_perror( const char *err )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* server_enter_uninterrupted_section
|
||||||
|
*/
|
||||||
|
void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset )
|
||||||
|
{
|
||||||
|
pthread_sigmask( SIG_BLOCK, &server_block_set, sigset );
|
||||||
|
RtlEnterCriticalSection( cs );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* server_leave_uninterrupted_section
|
||||||
|
*/
|
||||||
|
void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset )
|
||||||
|
{
|
||||||
|
RtlLeaveCriticalSection( cs );
|
||||||
|
pthread_sigmask( SIG_SETMASK, sigset, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* server_send_fd
|
* server_send_fd
|
||||||
*
|
*
|
||||||
|
@ -240,7 +281,7 @@ void CDECL server_send_fd( int fd )
|
||||||
*
|
*
|
||||||
* Receive a file descriptor passed from the server.
|
* Receive a file descriptor passed from the server.
|
||||||
*/
|
*/
|
||||||
int CDECL receive_fd( obj_handle_t *handle )
|
static int receive_fd( obj_handle_t *handle )
|
||||||
{
|
{
|
||||||
struct iovec vec;
|
struct iovec vec;
|
||||||
struct msghdr msghdr;
|
struct msghdr msghdr;
|
||||||
|
@ -295,6 +336,232 @@ int CDECL receive_fd( obj_handle_t *handle )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* fd cache support */
|
||||||
|
|
||||||
|
union fd_cache_entry
|
||||||
|
{
|
||||||
|
LONG64 data;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
enum server_fd_type type : 5;
|
||||||
|
unsigned int access : 3;
|
||||||
|
unsigned int options : 24;
|
||||||
|
} s;
|
||||||
|
};
|
||||||
|
|
||||||
|
C_ASSERT( sizeof(union fd_cache_entry) == sizeof(LONG64) );
|
||||||
|
|
||||||
|
#define FD_CACHE_BLOCK_SIZE (65536 / sizeof(union fd_cache_entry))
|
||||||
|
#define FD_CACHE_ENTRIES 128
|
||||||
|
|
||||||
|
static union fd_cache_entry *fd_cache[FD_CACHE_ENTRIES];
|
||||||
|
static union fd_cache_entry fd_cache_initial_block[FD_CACHE_BLOCK_SIZE];
|
||||||
|
|
||||||
|
static inline unsigned int handle_to_index( HANDLE handle, unsigned int *entry )
|
||||||
|
{
|
||||||
|
unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1;
|
||||||
|
*entry = idx / FD_CACHE_BLOCK_SIZE;
|
||||||
|
return idx % FD_CACHE_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* add_fd_to_cache
|
||||||
|
*
|
||||||
|
* Caller must hold fd_cache_section.
|
||||||
|
*/
|
||||||
|
static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
|
||||||
|
unsigned int access, unsigned int options )
|
||||||
|
{
|
||||||
|
unsigned int entry, idx = handle_to_index( handle, &entry );
|
||||||
|
union fd_cache_entry cache;
|
||||||
|
|
||||||
|
if (entry >= FD_CACHE_ENTRIES)
|
||||||
|
{
|
||||||
|
FIXME( "too many allocated handles, not caching %p\n", handle );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fd_cache[entry]) /* do we need to allocate a new block of entries? */
|
||||||
|
{
|
||||||
|
if (!entry) fd_cache[0] = fd_cache_initial_block;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
void *ptr = wine_anon_mmap( NULL, FD_CACHE_BLOCK_SIZE * sizeof(union fd_cache_entry),
|
||||||
|
PROT_READ | PROT_WRITE, 0 );
|
||||||
|
if (ptr == MAP_FAILED) return FALSE;
|
||||||
|
fd_cache[entry] = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store fd+1 so that 0 can be used as the unset value */
|
||||||
|
cache.s.fd = fd + 1;
|
||||||
|
cache.s.type = type;
|
||||||
|
cache.s.access = access;
|
||||||
|
cache.s.options = options;
|
||||||
|
cache.data = interlocked_xchg64( &fd_cache[entry][idx].data, cache.data );
|
||||||
|
assert( !cache.s.fd );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* get_cached_fd
|
||||||
|
*/
|
||||||
|
static inline NTSTATUS get_cached_fd( HANDLE handle, int *fd, enum server_fd_type *type,
|
||||||
|
unsigned int *access, unsigned int *options )
|
||||||
|
{
|
||||||
|
unsigned int entry, idx = handle_to_index( handle, &entry );
|
||||||
|
union fd_cache_entry cache;
|
||||||
|
|
||||||
|
if (entry >= FD_CACHE_ENTRIES || !fd_cache[entry]) return STATUS_INVALID_HANDLE;
|
||||||
|
|
||||||
|
cache.data = InterlockedCompareExchange64( &fd_cache[entry][idx].data, 0, 0 );
|
||||||
|
if (!cache.data) return STATUS_INVALID_HANDLE;
|
||||||
|
|
||||||
|
/* if fd type is invalid, fd stores an error value */
|
||||||
|
if (cache.s.type == FD_TYPE_INVALID) return cache.s.fd - 1;
|
||||||
|
|
||||||
|
*fd = cache.s.fd - 1;
|
||||||
|
if (type) *type = cache.s.type;
|
||||||
|
if (access) *access = cache.s.access;
|
||||||
|
if (options) *options = cache.s.options;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* server_remove_fd_from_cache
|
||||||
|
*/
|
||||||
|
int CDECL server_remove_fd_from_cache( HANDLE handle )
|
||||||
|
{
|
||||||
|
unsigned int entry, idx = handle_to_index( handle, &entry );
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
if (entry < FD_CACHE_ENTRIES && fd_cache[entry])
|
||||||
|
{
|
||||||
|
union fd_cache_entry cache;
|
||||||
|
cache.data = interlocked_xchg64( &fd_cache[entry][idx].data, 0 );
|
||||||
|
if (cache.s.type != FD_TYPE_INVALID) fd = cache.s.fd - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* server_get_unix_fd
|
||||||
|
*
|
||||||
|
* The returned unix_fd should be closed iff needs_close is non-zero.
|
||||||
|
*/
|
||||||
|
int CDECL server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
|
||||||
|
int *needs_close, enum server_fd_type *type, unsigned int *options )
|
||||||
|
{
|
||||||
|
sigset_t sigset;
|
||||||
|
obj_handle_t fd_handle;
|
||||||
|
int ret, fd = -1;
|
||||||
|
unsigned int access = 0;
|
||||||
|
|
||||||
|
*unix_fd = -1;
|
||||||
|
*needs_close = 0;
|
||||||
|
wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA;
|
||||||
|
|
||||||
|
ret = get_cached_fd( handle, &fd, type, &access, options );
|
||||||
|
if (ret != STATUS_INVALID_HANDLE) goto done;
|
||||||
|
|
||||||
|
server_enter_uninterrupted_section( &fd_cache_section, &sigset );
|
||||||
|
ret = get_cached_fd( handle, &fd, type, &access, options );
|
||||||
|
if (ret == STATUS_INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
SERVER_START_REQ( get_handle_fd )
|
||||||
|
{
|
||||||
|
req->handle = wine_server_obj_handle( handle );
|
||||||
|
if (!(ret = wine_server_call( req )))
|
||||||
|
{
|
||||||
|
if (type) *type = reply->type;
|
||||||
|
if (options) *options = reply->options;
|
||||||
|
access = reply->access;
|
||||||
|
if ((fd = receive_fd( &fd_handle )) != -1)
|
||||||
|
{
|
||||||
|
assert( wine_server_ptr_handle(fd_handle) == handle );
|
||||||
|
*needs_close = (!reply->cacheable ||
|
||||||
|
!add_fd_to_cache( handle, fd, reply->type,
|
||||||
|
reply->access, reply->options ));
|
||||||
|
}
|
||||||
|
else ret = STATUS_TOO_MANY_OPENED_FILES;
|
||||||
|
}
|
||||||
|
else if (reply->cacheable)
|
||||||
|
{
|
||||||
|
add_fd_to_cache( handle, ret, FD_TYPE_INVALID, 0, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
}
|
||||||
|
server_leave_uninterrupted_section( &fd_cache_section, &sigset );
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (!ret && ((access & wanted_access) != wanted_access))
|
||||||
|
{
|
||||||
|
ret = STATUS_ACCESS_DENIED;
|
||||||
|
if (*needs_close) close( fd );
|
||||||
|
}
|
||||||
|
if (!ret) *unix_fd = fd;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* server_fd_to_handle
|
||||||
|
*/
|
||||||
|
NTSTATUS CDECL server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, HANDLE *handle )
|
||||||
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
|
||||||
|
*handle = 0;
|
||||||
|
wine_server_send_fd( fd );
|
||||||
|
|
||||||
|
SERVER_START_REQ( alloc_file_handle )
|
||||||
|
{
|
||||||
|
req->access = access;
|
||||||
|
req->attributes = attributes;
|
||||||
|
req->fd = fd;
|
||||||
|
if (!(ret = wine_server_call( req ))) *handle = wine_server_ptr_handle( reply->handle );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* server_handle_to_fd
|
||||||
|
*
|
||||||
|
* Retrieve the file descriptor corresponding to a file handle.
|
||||||
|
*/
|
||||||
|
NTSTATUS CDECL server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd,
|
||||||
|
unsigned int *options )
|
||||||
|
{
|
||||||
|
int needs_close;
|
||||||
|
NTSTATUS ret = server_get_unix_fd( handle, access, unix_fd, &needs_close, NULL, options );
|
||||||
|
|
||||||
|
if (!ret && !needs_close)
|
||||||
|
{
|
||||||
|
if ((*unix_fd = dup(*unix_fd)) == -1) ret = STATUS_TOO_MANY_OPENED_FILES;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* server_release_fd
|
||||||
|
*/
|
||||||
|
void CDECL server_release_fd( HANDLE handle, int unix_fd )
|
||||||
|
{
|
||||||
|
close( unix_fd );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* server_pipe
|
* server_pipe
|
||||||
*
|
*
|
||||||
|
|
|
@ -61,7 +61,15 @@ extern void virtual_init(void) DECLSPEC_HIDDEN;
|
||||||
extern void CDECL dbg_init(void) DECLSPEC_HIDDEN;
|
extern void CDECL dbg_init(void) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern void CDECL server_send_fd( int fd ) DECLSPEC_HIDDEN;
|
extern void CDECL server_send_fd( int fd ) DECLSPEC_HIDDEN;
|
||||||
extern int CDECL receive_fd( obj_handle_t *handle ) DECLSPEC_HIDDEN;
|
extern int CDECL server_remove_fd_from_cache( HANDLE handle ) DECLSPEC_HIDDEN;
|
||||||
|
extern int CDECL server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
|
||||||
|
int *needs_close, enum server_fd_type *type,
|
||||||
|
unsigned int *options ) DECLSPEC_HIDDEN;
|
||||||
|
extern NTSTATUS CDECL server_fd_to_handle( int fd, unsigned int access, unsigned int attributes,
|
||||||
|
HANDLE *handle ) DECLSPEC_HIDDEN;
|
||||||
|
extern NTSTATUS CDECL server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd,
|
||||||
|
unsigned int *options ) DECLSPEC_HIDDEN;
|
||||||
|
extern void CDECL server_release_fd( HANDLE handle, int unix_fd ) DECLSPEC_HIDDEN;
|
||||||
extern int CDECL server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
|
extern int CDECL server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
|
||||||
extern void CDECL server_init_process(void) DECLSPEC_HIDDEN;
|
extern void CDECL server_init_process(void) DECLSPEC_HIDDEN;
|
||||||
extern void CDECL server_init_process_done(void) DECLSPEC_HIDDEN;
|
extern void CDECL server_init_process_done(void) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
/* increment this when you change the function table */
|
/* increment this when you change the function table */
|
||||||
#define NTDLL_UNIXLIB_VERSION 8
|
#define NTDLL_UNIXLIB_VERSION 9
|
||||||
|
|
||||||
struct unix_funcs
|
struct unix_funcs
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,14 @@ struct unix_funcs
|
||||||
|
|
||||||
/* server functions */
|
/* server functions */
|
||||||
void (CDECL *server_send_fd)( int fd );
|
void (CDECL *server_send_fd)( int fd );
|
||||||
int (CDECL *receive_fd)( obj_handle_t *handle );
|
int (CDECL *server_remove_fd_from_cache)( HANDLE handle );
|
||||||
|
int (CDECL *server_get_unix_fd)( HANDLE handle, unsigned int wanted_access, int *unix_fd,
|
||||||
|
int *needs_close, enum server_fd_type *type, unsigned int *options );
|
||||||
|
NTSTATUS (CDECL *server_fd_to_handle)( int fd, unsigned int access, unsigned int attributes,
|
||||||
|
HANDLE *handle );
|
||||||
|
NTSTATUS (CDECL *server_handle_to_fd)( HANDLE handle, unsigned int access, int *unix_fd,
|
||||||
|
unsigned int *options );
|
||||||
|
void (CDECL *server_release_fd)( HANDLE handle, int unix_fd );
|
||||||
int (CDECL *server_pipe)( int fd[2] );
|
int (CDECL *server_pipe)( int fd[2] );
|
||||||
void (CDECL *server_init_process)(void);
|
void (CDECL *server_init_process)(void);
|
||||||
void (CDECL *server_init_process_done)(void);
|
void (CDECL *server_init_process_done)(void);
|
||||||
|
|
|
@ -1815,7 +1815,7 @@ NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zer
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
|
|
||||||
if ((res = server_get_unix_fd( handle, 0, &unix_handle, &needs_close, NULL, NULL ))) goto done;
|
if ((res = unix_funcs->server_get_unix_fd( handle, 0, &unix_handle, &needs_close, NULL, NULL ))) goto done;
|
||||||
|
|
||||||
if (sec_flags & SEC_IMAGE)
|
if (sec_flags & SEC_IMAGE)
|
||||||
{
|
{
|
||||||
|
@ -1823,8 +1823,8 @@ NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zer
|
||||||
{
|
{
|
||||||
int shared_fd, shared_needs_close;
|
int shared_fd, shared_needs_close;
|
||||||
|
|
||||||
if ((res = server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA,
|
if ((res = unix_funcs->server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA,
|
||||||
&shared_fd, &shared_needs_close, NULL, NULL ))) goto done;
|
&shared_fd, &shared_needs_close, NULL, NULL ))) goto done;
|
||||||
res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits_64, image_info,
|
res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits_64, image_info,
|
||||||
shared_fd, needs_close, addr_ptr );
|
shared_fd, needs_close, addr_ptr );
|
||||||
if (shared_needs_close) close( shared_fd );
|
if (shared_needs_close) close( shared_fd );
|
||||||
|
|
Loading…
Reference in New Issue