Commit 9ddb9294 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Added a server_get_unix_fd function that avoids doing a dup() of the fd when not required.

parent 7c38ff6a
...@@ -2014,7 +2014,7 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice, ...@@ -2014,7 +2014,7 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
{ {
DWORD sz = 0; DWORD sz = 0;
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
int fd, dev; int fd, needs_close, dev;
TRACE("%p %s %p %d %p %d %p\n", TRACE("%p %s %p %d %p %d %p\n",
hDevice, iocodex(dwIoControlCode), lpInBuffer, nInBufferSize, hDevice, iocodex(dwIoControlCode), lpInBuffer, nInBufferSize,
...@@ -2022,10 +2022,10 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice, ...@@ -2022,10 +2022,10 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
piosb->Information = 0; piosb->Information = 0;
if ((status = wine_server_handle_to_fd( hDevice, 0, &fd, NULL ))) goto error; if ((status = server_get_unix_fd( hDevice, 0, &fd, &needs_close, NULL ))) goto error;
if ((status = CDROM_Open(fd, &dev))) if ((status = CDROM_Open(fd, &dev)))
{ {
wine_server_release_fd( hDevice, fd ); if (needs_close) close( fd );
goto error; goto error;
} }
...@@ -2281,7 +2281,7 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice, ...@@ -2281,7 +2281,7 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
status = STATUS_INVALID_PARAMETER; status = STATUS_INVALID_PARAMETER;
break; break;
} }
wine_server_release_fd( hDevice, fd ); if (needs_close) close( fd );
error: error:
piosb->u.Status = status; piosb->u.Status = status;
piosb->Information = sz; piosb->Information = sz;
......
...@@ -1284,7 +1284,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, ...@@ -1284,7 +1284,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event,
PUNICODE_STRING mask, PUNICODE_STRING mask,
BOOLEAN restart_scan ) BOOLEAN restart_scan )
{ {
int cwd, fd; int cwd, fd, needs_close;
static const WCHAR wszWildcards[] = { '*','?',0 }; static const WCHAR wszWildcards[] = { '*','?',0 };
TRACE("(%p %p %p %p %p %p 0x%08x 0x%08x 0x%08x %s 0x%08x\n", TRACE("(%p %p %p %p %p %p 0x%08x 0x%08x 0x%08x %s 0x%08x\n",
...@@ -1305,7 +1305,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, ...@@ -1305,7 +1305,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event,
return io->u.Status = STATUS_NOT_IMPLEMENTED; return io->u.Status = STATUS_NOT_IMPLEMENTED;
} }
if ((io->u.Status = wine_server_handle_to_fd( handle, FILE_LIST_DIRECTORY, &fd, NULL )) != STATUS_SUCCESS) if ((io->u.Status = server_get_unix_fd( handle, FILE_LIST_DIRECTORY, &fd, &needs_close, NULL )) != STATUS_SUCCESS)
return io->u.Status; return io->u.Status;
io->Information = 0; io->Information = 0;
...@@ -1336,7 +1336,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, ...@@ -1336,7 +1336,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event,
RtlLeaveCriticalSection( &dir_section ); RtlLeaveCriticalSection( &dir_section );
wine_server_release_fd( handle, fd ); if (needs_close) close( fd );
if (cwd != -1) close( cwd ); if (cwd != -1) close( cwd );
TRACE( "=> %x (%ld)\n", io->u.Status, io->Information ); TRACE( "=> %x (%ld)\n", io->u.Status, io->Information );
return io->u.Status; return io->u.Status;
...@@ -1819,7 +1819,7 @@ BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR file_name) ...@@ -1819,7 +1819,7 @@ BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR file_name)
NTSTATUS DIR_unmount_device( HANDLE handle ) NTSTATUS DIR_unmount_device( HANDLE handle )
{ {
NTSTATUS status; NTSTATUS status;
int unix_fd; int unix_fd, needs_close;
SERVER_START_REQ( unmount_device ) SERVER_START_REQ( unmount_device )
{ {
...@@ -1829,7 +1829,7 @@ NTSTATUS DIR_unmount_device( HANDLE handle ) ...@@ -1829,7 +1829,7 @@ NTSTATUS DIR_unmount_device( HANDLE handle )
SERVER_END_REQ; SERVER_END_REQ;
if (status) return status; if (status) return status;
if (!(status = wine_server_handle_to_fd( handle, 0, &unix_fd, NULL ))) if (!(status = server_get_unix_fd( handle, 0, &unix_fd, &needs_close, NULL )))
{ {
struct stat st; struct stat st;
char *mount_point = NULL; char *mount_point = NULL;
...@@ -1861,7 +1861,7 @@ NTSTATUS DIR_unmount_device( HANDLE handle ) ...@@ -1861,7 +1861,7 @@ NTSTATUS DIR_unmount_device( HANDLE handle )
RtlFreeHeap( GetProcessHeap(), 0, mount_point ); RtlFreeHeap( GetProcessHeap(), 0, mount_point );
} }
} }
wine_server_release_fd( handle, unix_fd ); if (needs_close) close( unix_fd );
} }
return status; return status;
} }
...@@ -1875,7 +1875,7 @@ NTSTATUS DIR_unmount_device( HANDLE handle ) ...@@ -1875,7 +1875,7 @@ NTSTATUS DIR_unmount_device( HANDLE handle )
*/ */
NTSTATUS DIR_get_unix_cwd( char **cwd ) NTSTATUS DIR_get_unix_cwd( char **cwd )
{ {
int old_cwd, unix_fd; int old_cwd, unix_fd, needs_close;
CURDIR *curdir; CURDIR *curdir;
HANDLE handle; HANDLE handle;
NTSTATUS status; NTSTATUS status;
...@@ -1911,7 +1911,7 @@ NTSTATUS DIR_get_unix_cwd( char **cwd ) ...@@ -1911,7 +1911,7 @@ NTSTATUS DIR_get_unix_cwd( char **cwd )
if (status != STATUS_SUCCESS) goto done; if (status != STATUS_SUCCESS) goto done;
} }
if ((status = wine_server_handle_to_fd( handle, 0, &unix_fd, NULL )) == STATUS_SUCCESS) if ((status = server_get_unix_fd( handle, 0, &unix_fd, &needs_close, NULL )) == STATUS_SUCCESS)
{ {
RtlEnterCriticalSection( &dir_section ); RtlEnterCriticalSection( &dir_section );
...@@ -1940,7 +1940,7 @@ NTSTATUS DIR_get_unix_cwd( char **cwd ) ...@@ -1940,7 +1940,7 @@ NTSTATUS DIR_get_unix_cwd( char **cwd )
else status = FILE_GetNtStatus(); else status = FILE_GetNtStatus();
RtlLeaveCriticalSection( &dir_section ); RtlLeaveCriticalSection( &dir_section );
wine_server_release_fd( handle, unix_fd ); if (needs_close) close( unix_fd );
} }
if (!curdir->Handle) NtClose( handle ); if (!curdir->Handle) NtClose( handle );
......
...@@ -62,6 +62,8 @@ extern void DECLSPEC_NORETURN server_protocol_perror( const char *err ); ...@@ -62,6 +62,8 @@ extern void DECLSPEC_NORETURN server_protocol_perror( const char *err );
extern void DECLSPEC_NORETURN server_exit_thread( int status ); extern void DECLSPEC_NORETURN server_exit_thread( int status );
extern void DECLSPEC_NORETURN server_abort_thread( int status ); extern void DECLSPEC_NORETURN server_abort_thread( int status );
extern int server_remove_fd_from_cache( obj_handle_t handle ); extern int server_remove_fd_from_cache( obj_handle_t handle );
extern int server_get_unix_fd( obj_handle_t handle, unsigned int access, int *unix_fd,
int *flags, int *needs_close );
/* module handling */ /* module handling */
extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved ); extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved );
......
...@@ -980,13 +980,9 @@ static DWORD WINAPI check_events(int fd, DWORD mask, ...@@ -980,13 +980,9 @@ static DWORD WINAPI check_events(int fd, DWORD mask,
static DWORD CALLBACK wait_for_event(LPVOID arg) static DWORD CALLBACK wait_for_event(LPVOID arg)
{ {
async_commio *commio = (async_commio*) arg; async_commio *commio = (async_commio*) arg;
int fd; int fd, needs_close;
if (wine_server_handle_to_fd( commio->hDevice, FILE_READ_DATA | FILE_WRITE_DATA, &fd, NULL )) if (!server_get_unix_fd( commio->hDevice, FILE_READ_DATA | FILE_WRITE_DATA, &fd, &needs_close, NULL ))
{
fd = -1;
}
else
{ {
serial_irq_info new_irq_info; serial_irq_info new_irq_info;
DWORD new_mstat, new_evtmask; DWORD new_mstat, new_evtmask;
...@@ -1020,10 +1016,9 @@ static DWORD CALLBACK wait_for_event(LPVOID arg) ...@@ -1020,10 +1016,9 @@ static DWORD CALLBACK wait_for_event(LPVOID arg)
break; break;
} }
} }
if (needs_close) close( fd );
} }
if (commio->hEvent != INVALID_HANDLE_VALUE) if (commio->hEvent) NtSetEvent(commio->hEvent, NULL);
NtSetEvent(commio->hEvent, NULL);
if (fd != -1) wine_server_release_fd( commio->hDevice, fd );
RtlFreeHeap(GetProcessHeap(), 0, commio); RtlFreeHeap(GetProcessHeap(), 0, commio);
return 0; return 0;
} }
...@@ -1126,7 +1121,7 @@ static inline NTSTATUS io_control(HANDLE hDevice, ...@@ -1126,7 +1121,7 @@ static inline NTSTATUS io_control(HANDLE hDevice,
{ {
DWORD sz = 0, access = FILE_READ_DATA; DWORD sz = 0, access = FILE_READ_DATA;
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
int fd = -1; int fd = -1, needs_close = 0;
TRACE("%p %s %p %d %p %d %p\n", TRACE("%p %s %p %d %p %d %p\n",
hDevice, iocode2str(dwIoControlCode), lpInBuffer, nInBufferSize, hDevice, iocode2str(dwIoControlCode), lpInBuffer, nInBufferSize,
...@@ -1135,7 +1130,7 @@ static inline NTSTATUS io_control(HANDLE hDevice, ...@@ -1135,7 +1130,7 @@ static inline NTSTATUS io_control(HANDLE hDevice,
piosb->Information = 0; piosb->Information = 0;
if (dwIoControlCode != IOCTL_SERIAL_GET_TIMEOUTS) if (dwIoControlCode != IOCTL_SERIAL_GET_TIMEOUTS)
if ((status = wine_server_handle_to_fd( hDevice, access, &fd, NULL ))) if ((status = server_get_unix_fd( hDevice, access, &fd, &needs_close, NULL )))
goto error; goto error;
switch (dwIoControlCode) switch (dwIoControlCode)
...@@ -1343,7 +1338,7 @@ static inline NTSTATUS io_control(HANDLE hDevice, ...@@ -1343,7 +1338,7 @@ static inline NTSTATUS io_control(HANDLE hDevice,
status = STATUS_INVALID_PARAMETER; status = STATUS_INVALID_PARAMETER;
break; break;
} }
if (fd != -1) wine_server_release_fd( hDevice, fd ); if (needs_close) close( fd );
error: error:
piosb->u.Status = status; piosb->u.Status = status;
piosb->Information = sz; piosb->Information = sz;
......
...@@ -525,6 +525,58 @@ int server_remove_fd_from_cache( obj_handle_t handle ) ...@@ -525,6 +525,58 @@ int server_remove_fd_from_cache( obj_handle_t handle )
/*********************************************************************** /***********************************************************************
* server_get_unix_fd
*
* The returned unix_fd should be closed iff needs_close is non-zero.
*/
int server_get_unix_fd( obj_handle_t handle, unsigned int access, int *unix_fd,
int *needs_close, int *flags )
{
obj_handle_t fd_handle;
int ret = 0, removable = 0, fd;
*unix_fd = -1;
*needs_close = 0;
RtlEnterCriticalSection( &fd_cache_section );
fd = get_cached_fd( handle );
if (fd != -1 && !flags) goto done;
SERVER_START_REQ( get_handle_fd )
{
req->handle = handle;
req->access = access;
req->cached = (fd != -1);
if (!(ret = wine_server_call( req )))
{
removable = reply->flags & FD_FLAG_REMOVABLE;
if (flags) *flags = reply->flags;
}
}
SERVER_END_REQ;
if (!ret && fd == -1)
{
/* it wasn't in the cache, get it from the server */
fd = receive_fd( &fd_handle );
if (fd == -1)
{
ret = STATUS_TOO_MANY_OPENED_FILES;
goto done;
}
assert( fd_handle == handle );
*needs_close = removable || !add_fd_to_cache( handle, fd );
}
done:
RtlLeaveCriticalSection( &fd_cache_section );
if (!ret) *unix_fd = fd;
return ret;
}
/***********************************************************************
* wine_server_fd_to_handle (NTDLL.@) * wine_server_fd_to_handle (NTDLL.@)
* *
* Allocate a file handle for a Unix file descriptor. * Allocate a file handle for a Unix file descriptor.
...@@ -573,59 +625,12 @@ int wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attribut ...@@ -573,59 +625,12 @@ int wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attribut
*/ */
int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, int *flags ) int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, int *flags )
{ {
obj_handle_t fd_handle; int needs_close, ret = server_get_unix_fd( handle, access, unix_fd, &needs_close, flags );
int ret = 0, removable = 0, fd = -1;
RtlEnterCriticalSection( &fd_cache_section ); if (!ret && !needs_close)
*unix_fd = -1;
fd = get_cached_fd( handle );
if (fd != -1 && !flags)
{ {
if ((fd = dup(fd)) == -1) ret = FILE_GetNtStatus(); if ((*unix_fd = dup(*unix_fd)) == -1) ret = FILE_GetNtStatus();
goto done;
} }
SERVER_START_REQ( get_handle_fd )
{
req->handle = handle;
req->access = access;
req->cached = (fd != -1);
if (!(ret = wine_server_call( req )))
{
removable = reply->flags & FD_FLAG_REMOVABLE;
if (flags) *flags = reply->flags;
}
}
SERVER_END_REQ;
if (ret) goto done;
if (fd != -1)
{
if ((fd = dup(fd)) == -1) ret = FILE_GetNtStatus();
goto done;
}
/* it wasn't in the cache, get it from the server */
fd = receive_fd( &fd_handle );
if (fd == -1)
{
ret = STATUS_TOO_MANY_OPENED_FILES;
goto done;
}
assert( fd_handle == handle );
if (removable) goto done; /* don't cache it */
if (add_fd_to_cache( handle, fd ))
{
if ((fd = dup(fd)) == -1) ret = FILE_GetNtStatus();
}
done:
RtlLeaveCriticalSection( &fd_cache_section );
if (!ret) *unix_fd = fd;
return ret; return ret;
} }
......
...@@ -512,14 +512,14 @@ NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event, ...@@ -512,14 +512,14 @@ NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
{ {
DWORD sz = 0; DWORD sz = 0;
NTSTATUS status = STATUS_INVALID_PARAMETER; NTSTATUS status = STATUS_INVALID_PARAMETER;
int fd; int fd, needs_close;
TRACE( "%p %s %p %d %p %d %p\n", device, io2str(io_control), TRACE( "%p %s %p %d %p %d %p\n", device, io2str(io_control),
in_buffer, in_size, out_buffer, out_size, io_status ); in_buffer, in_size, out_buffer, out_size, io_status );
io_status->Information = 0; io_status->Information = 0;
if ((status = wine_server_handle_to_fd( device, 0, &fd, NULL ))) if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL )))
goto error; goto error;
switch (io_control) switch (io_control)
...@@ -569,7 +569,7 @@ NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event, ...@@ -569,7 +569,7 @@ NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
break; break;
} }
wine_server_release_fd( device, fd ); if (needs_close) close( fd );
error: error:
io_status->u.Status = status; io_status->u.Status = status;
......
...@@ -1767,11 +1767,10 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p ...@@ -1767,11 +1767,10 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr,
SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect ) SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect )
{ {
FILE_FS_DEVICE_INFORMATION device_info;
NTSTATUS res; NTSTATUS res;
SIZE_T size = 0; SIZE_T size = 0;
SIZE_T mask = get_mask( zero_bits ); SIZE_T mask = get_mask( zero_bits );
int unix_handle = -1; int unix_handle = -1, flags, needs_close;
int prot; int prot;
void *base; void *base;
struct file_view *view; struct file_view *view;
...@@ -1811,22 +1810,20 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p ...@@ -1811,22 +1810,20 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
SERVER_END_REQ; SERVER_END_REQ;
if (res) return res; if (res) return res;
if ((res = wine_server_handle_to_fd( handle, 0, &unix_handle, NULL ))) return res; if ((res = server_get_unix_fd( handle, 0, &unix_handle, &needs_close, &flags ))) return res;
removable = (flags & FD_FLAG_REMOVABLE) != 0;
if (FILE_GetDeviceInfo( unix_handle, &device_info ) == STATUS_SUCCESS)
removable = device_info.Characteristics & FILE_REMOVABLE_MEDIA;
if (prot & VPROT_IMAGE) if (prot & VPROT_IMAGE)
{ {
if (shared_file) if (shared_file)
{ {
int shared_fd; int shared_fd, shared_needs_close;
if ((res = wine_server_handle_to_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA, if ((res = server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA,
&shared_fd, NULL ))) goto done; &shared_fd, &shared_needs_close, NULL ))) goto done;
res = map_image( handle, unix_handle, base, size_low, mask, header_size, res = map_image( handle, unix_handle, base, size_low, mask, header_size,
shared_fd, removable, addr_ptr ); shared_fd, removable, addr_ptr );
wine_server_release_fd( shared_file, shared_fd ); if (shared_needs_close) close( shared_fd );
NtClose( shared_file ); NtClose( shared_file );
} }
else else
...@@ -1834,7 +1831,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p ...@@ -1834,7 +1831,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
res = map_image( handle, unix_handle, base, size_low, mask, header_size, res = map_image( handle, unix_handle, base, size_low, mask, header_size,
-1, removable, addr_ptr ); -1, removable, addr_ptr );
} }
wine_server_release_fd( handle, unix_handle ); if (needs_close) close( unix_handle );
if (!res) *size_ptr = size_low; if (!res) *size_ptr = size_low;
return res; return res;
} }
...@@ -1921,7 +1918,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p ...@@ -1921,7 +1918,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
RtlLeaveCriticalSection( &csVirtual ); RtlLeaveCriticalSection( &csVirtual );
done: done:
wine_server_release_fd( handle, unix_handle ); if (needs_close) close( unix_handle );
return res; return res;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment