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;
|
||||
|
||||
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 */
|
||||
goto error;
|
||||
|
|
|
@ -1946,7 +1946,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH NtQueryDirectoryFile( HANDLE handle, HANDLE ev
|
|||
}
|
||||
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;
|
||||
|
||||
io->Information = 0;
|
||||
|
@ -2436,7 +2436,7 @@ NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *
|
|||
return STATUS_NO_MEMORY;
|
||||
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;
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
|
@ -2867,7 +2867,7 @@ NTSTATUS DIR_unmount_device( HANDLE handle )
|
|||
NTSTATUS status;
|
||||
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;
|
||||
char *mount_point = NULL;
|
||||
|
@ -2949,7 +2949,7 @@ NTSTATUS DIR_get_unix_cwd( char **cwd )
|
|||
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 );
|
||||
|
||||
|
|
|
@ -542,8 +542,8 @@ static NTSTATUS FILE_AsyncReadService( void *user, IO_STATUS_BLOCK *iosb, NTSTAT
|
|||
{
|
||||
case STATUS_ALERTED: /* got some new data */
|
||||
/* check to see if the data is ready (non-blocking) */
|
||||
if ((status = server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd,
|
||||
&needs_close, NULL, NULL )))
|
||||
if ((status = unix_funcs->server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd,
|
||||
&needs_close, NULL, NULL )))
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
status = server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
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 (!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;
|
||||
|
||||
status = server_get_unix_fd( file, FILE_READ_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
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) ||
|
||||
|
@ -1137,8 +1137,8 @@ static NTSTATUS FILE_AsyncWriteService( void *user, IO_STATUS_BLOCK *iosb, NTSTA
|
|||
{
|
||||
case STATUS_ALERTED:
|
||||
/* write some data (non-blocking) */
|
||||
if ((status = server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd,
|
||||
&needs_close, &type, NULL )))
|
||||
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))
|
||||
|
@ -1231,12 +1231,12 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
|
|||
|
||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
status = server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
status = unix_funcs->server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
if (status == STATUS_ACCESS_DENIED)
|
||||
{
|
||||
status = server_get_unix_fd( hFile, FILE_APPEND_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
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;
|
||||
|
@ -1458,8 +1458,8 @@ NTSTATUS WINAPI NtWriteFileGather( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
|
|||
if (length % page_size) return STATUS_INVALID_PARAMETER;
|
||||
if (!io_status) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
status = server_get_unix_fd( file, FILE_WRITE_DATA, &unix_handle,
|
||||
&needs_close, &type, &options );
|
||||
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) ||
|
||||
|
@ -2459,7 +2459,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
|||
if (len < info_sizes[class])
|
||||
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;
|
||||
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 ((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 );
|
||||
info->MessagesAvailable = (res > 0);
|
||||
|
@ -2693,7 +2693,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
|||
const FILE_BASIC_INFORMATION *info = ptr;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
/* first try normal truncate */
|
||||
|
@ -2869,7 +2869,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
|||
struct stat st;
|
||||
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;
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -2340,7 +2340,7 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm,
|
|||
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 );
|
||||
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,
|
||||
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 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,
|
||||
data_size_t *ret_len ) 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 (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 );
|
||||
}
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ static LONG WINAPI invalid_handle_exception_handler( EXCEPTION_POINTERS *eptr )
|
|||
NTSTATUS close_handle( HANDLE handle )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
|
|
|
@ -951,7 +951,7 @@ static DWORD CALLBACK wait_for_event(LPVOID arg)
|
|||
async_commio *commio = arg;
|
||||
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;
|
||||
DWORD new_mstat, dummy, cookie;
|
||||
|
@ -1141,7 +1141,7 @@ static inline NTSTATUS io_control(HANDLE hDevice,
|
|||
|
||||
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;
|
||||
if (type != FD_TYPE_SERIAL)
|
||||
{
|
||||
|
|
|
@ -93,8 +93,6 @@
|
|||
#include "ntdll_misc.h"
|
||||
#include "ddk/wdm.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(server);
|
||||
|
||||
/* Some versions of glibc don't define this */
|
||||
#ifndef SCM_RIGHTS
|
||||
#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 */
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -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.@)
|
||||
*
|
||||
|
@ -942,20 +743,7 @@ done:
|
|||
*/
|
||||
int CDECL wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, HANDLE *handle )
|
||||
{
|
||||
int 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;
|
||||
return unix_funcs->server_fd_to_handle( fd, access, attributes, handle );
|
||||
}
|
||||
|
||||
|
||||
|
@ -974,15 +762,9 @@ int CDECL wine_server_fd_to_handle( int fd, unsigned int access, unsigned int at
|
|||
* NTSTATUS code
|
||||
*/
|
||||
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 );
|
||||
|
||||
if (!ret && !needs_close)
|
||||
{
|
||||
if ((*unix_fd = dup(*unix_fd)) == -1) ret = FILE_GetNtStatus();
|
||||
}
|
||||
return ret;
|
||||
return unix_funcs->server_handle_to_fd( handle, access, unix_fd, options );
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
switch (io_control)
|
||||
|
|
|
@ -199,7 +199,7 @@ void map_user_shared_data(void)
|
|||
MESSAGE( "wine: failed to open the USD section: %08x\n", status );
|
||||
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),
|
||||
PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0 )))
|
||||
{
|
||||
|
|
|
@ -997,7 +997,11 @@ static struct unix_funcs unix_funcs =
|
|||
mmap_is_in_reserved_area,
|
||||
mmap_enum_reserved_areas,
|
||||
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_init_process,
|
||||
server_init_process_done,
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
#include "unix_private.h"
|
||||
#include "ddk/wdm.h"
|
||||
|
||||
WINE_DECLARE_DEBUG_CHANNEL(server);
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(server);
|
||||
|
||||
#ifndef MSG_CMSG_CLOEXEC
|
||||
#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 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__
|
||||
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)));
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -240,7 +281,7 @@ void CDECL server_send_fd( int fd )
|
|||
*
|
||||
* 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 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
|
||||
*
|
||||
|
|
|
@ -61,7 +61,15 @@ extern void virtual_init(void) DECLSPEC_HIDDEN;
|
|||
extern void CDECL dbg_init(void) 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 void CDECL server_init_process(void) DECLSPEC_HIDDEN;
|
||||
extern void CDECL server_init_process_done(void) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "wine/debug.h"
|
||||
|
||||
/* increment this when you change the function table */
|
||||
#define NTDLL_UNIXLIB_VERSION 8
|
||||
#define NTDLL_UNIXLIB_VERSION 9
|
||||
|
||||
struct unix_funcs
|
||||
{
|
||||
|
@ -52,7 +52,14 @@ struct unix_funcs
|
|||
|
||||
/* server functions */
|
||||
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] );
|
||||
void (CDECL *server_init_process)(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;
|
||||
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)
|
||||
{
|
||||
|
@ -1823,8 +1823,8 @@ NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zer
|
|||
{
|
||||
int shared_fd, shared_needs_close;
|
||||
|
||||
if ((res = server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA,
|
||||
&shared_fd, &shared_needs_close, NULL, NULL ))) goto done;
|
||||
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;
|
||||
res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits_64, image_info,
|
||||
shared_fd, needs_close, addr_ptr );
|
||||
if (shared_needs_close) close( shared_fd );
|
||||
|
|
Loading…
Reference in New Issue