Added wine_server_release_fd function to release the fd returned by

wine_server_handle_to_fd. Fixed a couple of potential fd leaks.
This commit is contained in:
Alexandre Julliard 2003-12-01 23:01:12 +00:00
parent 854e59d9ec
commit f3f435ffa1
9 changed files with 90 additions and 85 deletions

View File

@ -200,28 +200,6 @@ static void fileio_async_cleanup( struct async_private *ovp )
RtlFreeHeap( ntdll_get_process_heap(), 0, ovp ); RtlFreeHeap( ntdll_get_process_heap(), 0, ovp );
} }
/***********************************************************************
* FILE_GetUnixHandleType
*
* Retrieve the Unix handle corresponding to a file handle.
* Returns -1 on failure.
*/
static int FILE_GetUnixHandleType( HANDLE handle, DWORD access, enum fd_type *type, int *flags_ptr, int *fd )
{
int ret, flags;
*fd = -1;
ret = wine_server_handle_to_fd( handle, access, fd, type, &flags );
if (flags_ptr) *flags_ptr = flags;
if (!ret && (((access & GENERIC_READ) && (flags & FD_FLAG_RECV_SHUTDOWN)) ||
((access & GENERIC_WRITE) && (flags & FD_FLAG_SEND_SHUTDOWN))))
{
close(*fd);
ret = STATUS_PIPE_DISCONNECTED;
}
return ret;
}
/*********************************************************************** /***********************************************************************
* FILE_GetNtStatus(void) * FILE_GetNtStatus(void)
* *
@ -351,19 +329,30 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key); hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
io_status->Information = 0; io_status->Information = 0;
io_status->u.Status = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type, &flags, &unix_handle ); io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_READ, &unix_handle, &type, &flags );
if (io_status->u.Status) return io_status->u.Status; if (io_status->u.Status) return io_status->u.Status;
if (flags & FD_FLAG_RECV_SHUTDOWN)
{
wine_server_release_fd( hFile, unix_handle );
return STATUS_PIPE_DISCONNECTED;
}
if (flags & FD_FLAG_TIMEOUT) if (flags & FD_FLAG_TIMEOUT)
{ {
if (hEvent) if (hEvent)
{ {
/* this shouldn't happen, but check it */ /* this shouldn't happen, but check it */
FIXME("NIY-hEvent\n"); FIXME("NIY-hEvent\n");
wine_server_release_fd( hFile, unix_handle );
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
io_status->u.Status = NtCreateEvent(&hEvent, SYNCHRONIZE, NULL, 0, 0); io_status->u.Status = NtCreateEvent(&hEvent, SYNCHRONIZE, NULL, 0, 0);
if (io_status->u.Status) return io_status->u.Status; if (io_status->u.Status)
{
wine_server_release_fd( hFile, unix_handle );
return io_status->u.Status;
}
} }
if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT)) if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
@ -371,14 +360,14 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
async_fileio* ovp; async_fileio* ovp;
NTSTATUS ret; NTSTATUS ret;
if (unix_handle < 0) return STATUS_INVALID_HANDLE; if (!(ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio))))
{
ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio)); wine_server_release_fd( hFile, unix_handle );
if (!ovp) return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
}
ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops ); ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
ovp->async.handle = hFile; ovp->async.handle = hFile;
ovp->async.fd = unix_handle; ovp->async.fd = unix_handle; /* FIXME */
ovp->async.type = ASYNC_TYPE_READ; ovp->async.type = ASYNC_TYPE_READ;
ovp->async.func = FILE_AsyncReadService; ovp->async.func = FILE_AsyncReadService;
ovp->async.event = hEvent; ovp->async.event = hEvent;
@ -419,19 +408,18 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
{ {
case FD_TYPE_SMB: case FD_TYPE_SMB:
FIXME("NIY-SMB\n"); FIXME("NIY-SMB\n");
close(unix_handle);
/* FIXME */ /* FIXME */
/* return SMB_ReadFile(hFile, buffer, length, io_status); */ /* return SMB_ReadFile(hFile, unix_handle, buffer, length, io_status); */
wine_server_release_fd( hFile, unix_handle );
return STATUS_INVALID_HANDLE; return STATUS_INVALID_HANDLE;
case FD_TYPE_DEFAULT: case FD_TYPE_DEFAULT:
/* normal unix files */ /* normal unix file */
if (unix_handle == -1) return STATUS_INVALID_HANDLE;
break; break;
default: default:
FIXME("Unsupported type of fd %d\n", type); FIXME("Unsupported type of fd %d\n", type);
if (unix_handle == -1) close(unix_handle); wine_server_release_fd( hFile, unix_handle );
return STATUS_INVALID_HANDLE; return STATUS_INVALID_HANDLE;
} }
@ -444,7 +432,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
FilePositionInformation); FilePositionInformation);
if (io_status->u.Status) if (io_status->u.Status)
{ {
close(unix_handle); wine_server_release_fd( hFile, unix_handle );
return io_status->u.Status; return io_status->u.Status;
} }
} }
@ -456,7 +444,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
io_status->u.Status = FILE_GetNtStatus(); io_status->u.Status = FILE_GetNtStatus();
break; break;
} }
close( unix_handle ); wine_server_release_fd( hFile, unix_handle );
return io_status->u.Status; return io_status->u.Status;
} }
@ -543,23 +531,28 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key); hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
io_status->Information = 0; io_status->Information = 0;
io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &unix_handle, &type, &flags );
io_status->u.Status = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type, &flags, &unix_handle );
if (io_status->u.Status) return io_status->u.Status; if (io_status->u.Status) return io_status->u.Status;
if (flags & FD_FLAG_SEND_SHUTDOWN)
{
wine_server_release_fd( hFile, unix_handle );
return STATUS_PIPE_DISCONNECTED;
}
if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT)) if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
{ {
async_fileio* ovp; async_fileio* ovp;
NTSTATUS ret; NTSTATUS ret;
if (unix_handle < 0) return STATUS_INVALID_HANDLE; if (!(ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio))))
{
ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio)); wine_server_release_fd( hFile, unix_handle );
if (!ovp) return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
}
ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops ); ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
ovp->async.handle = hFile; ovp->async.handle = hFile;
ovp->async.fd = unix_handle; ovp->async.fd = unix_handle; /* FIXME */
ovp->async.type = ASYNC_TYPE_WRITE; ovp->async.type = ASYNC_TYPE_WRITE;
ovp->async.func = FILE_AsyncWriteService; ovp->async.func = FILE_AsyncWriteService;
ovp->async.event = hEvent; ovp->async.event = hEvent;
@ -595,7 +588,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
{ {
case FD_TYPE_SMB: case FD_TYPE_SMB:
FIXME("NIY-SMB\n"); FIXME("NIY-SMB\n");
close(unix_handle); wine_server_release_fd( hFile, unix_handle );
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
case FD_TYPE_DEFAULT: case FD_TYPE_DEFAULT:
@ -605,7 +598,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
default: default:
FIXME("Unsupported type of fd %d\n", type); FIXME("Unsupported type of fd %d\n", type);
if (unix_handle == -1) close(unix_handle); wine_server_release_fd( hFile, unix_handle );
return STATUS_INVALID_HANDLE; return STATUS_INVALID_HANDLE;
} }
@ -618,7 +611,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
FilePositionInformation); FilePositionInformation);
if (io_status->u.Status) if (io_status->u.Status)
{ {
close(unix_handle); wine_server_release_fd( hFile, unix_handle );
return io_status->u.Status; return io_status->u.Status;
} }
} }
@ -632,7 +625,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
else io_status->u.Status = FILE_GetNtStatus(); else io_status->u.Status = FILE_GetNtStatus();
break; break;
} }
close( unix_handle ); wine_server_release_fd( hFile, unix_handle );
return io_status->u.Status; return io_status->u.Status;
} }

View File

@ -1067,6 +1067,7 @@
@ cdecl -norelay wine_server_call(ptr) @ cdecl -norelay wine_server_call(ptr)
@ cdecl wine_server_fd_to_handle(long long long ptr) @ cdecl wine_server_fd_to_handle(long long long ptr)
@ cdecl wine_server_handle_to_fd(long long ptr ptr ptr) @ cdecl wine_server_handle_to_fd(long long ptr ptr ptr)
@ cdecl wine_server_release_fd(long long)
@ cdecl wine_server_send_fd(long) @ cdecl wine_server_send_fd(long)
# Codepages # Codepages

View File

@ -360,31 +360,33 @@ static int receive_fd( obj_handle_t *handle )
* Returns the new fd, which can be different if there was already an * Returns the new fd, which can be different if there was already an
* fd in the cache for that handle. * fd in the cache for that handle.
*/ */
inline static int store_cached_fd( int fd, obj_handle_t handle ) inline static int store_cached_fd( int *fd, obj_handle_t handle )
{ {
int ret;
SERVER_START_REQ( set_handle_info ) SERVER_START_REQ( set_handle_info )
{ {
req->handle = handle; req->handle = handle;
req->flags = 0; req->flags = 0;
req->mask = 0; req->mask = 0;
req->fd = fd; req->fd = *fd;
if (!wine_server_call( req )) if (!(ret = wine_server_call( req )))
{ {
if (reply->cur_fd != fd) if (reply->cur_fd != *fd)
{ {
/* someone was here before us */ /* someone was here before us */
close( fd ); close( *fd );
fd = reply->cur_fd; *fd = reply->cur_fd;
} }
} }
else else
{ {
close( fd ); close( *fd );
fd = -1; *fd = -1;
} }
} }
SERVER_END_REQ; SERVER_END_REQ;
return fd; return ret;
} }
@ -442,7 +444,8 @@ int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *uni
/* it wasn't in the cache, get it from the server */ /* it wasn't in the cache, get it from the server */
fd = receive_fd( &fd_handle ); fd = receive_fd( &fd_handle );
/* and store it back into the cache */ /* and store it back into the cache */
fd = store_cached_fd( fd, fd_handle ); ret = store_cached_fd( &fd, fd_handle );
if (ret) return ret;
if (fd_handle == handle) break; if (fd_handle == handle) break;
/* if we received a different handle this means there was /* if we received a different handle this means there was
@ -457,6 +460,17 @@ int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *uni
} }
/***********************************************************************
* wine_server_release_fd (NTDLL.@)
*
* Release the Unix fd returned by wine_server_handle_to_fd.
*/
void wine_server_release_fd( obj_handle_t handle, int unix_fd )
{
close( unix_fd );
}
/*********************************************************************** /***********************************************************************
* start_server * start_server
* *

View File

@ -555,8 +555,7 @@ static int do_relocations( char *base, const IMAGE_DATA_DIRECTORY *dir,
* Map an executable (PE format) image into memory. * Map an executable (PE format) image into memory.
*/ */
static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, DWORD total_size, static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
DWORD header_size, int shared_fd, DWORD shared_size, DWORD header_size, int shared_fd, BOOL removable, PVOID *addr_ptr )
BOOL removable, PVOID *addr_ptr )
{ {
IMAGE_DOS_HEADER *dos; IMAGE_DOS_HEADER *dos;
IMAGE_NT_HEADERS *nt; IMAGE_NT_HEADERS *nt;
@ -756,13 +755,11 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, DWORD total_size
VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot ); VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
} }
close( fd );
*addr_ptr = ptr; *addr_ptr = ptr;
return STATUS_SUCCESS; return STATUS_SUCCESS;
error: error:
if (ptr != (char *)-1) munmap( ptr, total_size ); if (ptr != (char *)-1) munmap( ptr, total_size );
close( fd );
return status; return status;
} }
@ -1415,28 +1412,33 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
removable = reply->removable; removable = reply->removable;
} }
SERVER_END_REQ; SERVER_END_REQ;
if (res) goto error; if (res) return res;
if ((res = wine_server_handle_to_fd( handle, 0, &unix_handle, NULL, NULL ))) goto error; if ((res = wine_server_handle_to_fd( handle, 0, &unix_handle, NULL, NULL ))) return res;
if (prot & VPROT_IMAGE) if (prot & VPROT_IMAGE)
{ {
int shared_fd = -1;
if (shared_file) if (shared_file)
{ {
int shared_fd;
if ((res = wine_server_handle_to_fd( shared_file, GENERIC_READ, &shared_fd, if ((res = wine_server_handle_to_fd( shared_file, GENERIC_READ, &shared_fd,
NULL, NULL ))) goto error; NULL, NULL ))) goto error;
NtClose( shared_file ); /* we no longer need it */ res = map_image( handle, unix_handle, base, size_low, header_size,
shared_fd, removable, addr_ptr );
wine_server_release_fd( shared_file, shared_fd );
NtClose( shared_file );
} }
res = map_image( handle, unix_handle, base, size_low, header_size, else
shared_fd, shared_size, removable, addr_ptr ); {
if (shared_fd != -1) close( shared_fd ); res = map_image( handle, unix_handle, base, size_low, header_size,
-1, removable, addr_ptr );
}
wine_server_release_fd( handle, unix_handle );
if (!res) *size_ptr = size_low; if (!res) *size_ptr = size_low;
return res; return res;
} }
if (size_high) if (size_high)
ERR("Sizes larger than 4Gb not supported\n"); ERR("Sizes larger than 4Gb not supported\n");
@ -1507,12 +1509,12 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
res = STATUS_NO_MEMORY; res = STATUS_NO_MEMORY;
goto error; goto error;
} }
if (unix_handle != -1) close( unix_handle ); wine_server_release_fd( handle, unix_handle );
*size_ptr = size; *size_ptr = size;
return STATUS_SUCCESS; return STATUS_SUCCESS;
error: error:
if (unix_handle != -1) close( unix_handle ); wine_server_release_fd( handle, unix_handle );
if (ptr != (void *)-1) munmap( ptr, size ); if (ptr != (void *)-1) munmap( ptr, size );
return res; return res;
} }

View File

@ -1580,10 +1580,9 @@ static NTSTATUS SMB_SetOffset(HANDLE hFile, DWORD offset)
return status; return status;
} }
NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, int fd, LPVOID buffer, DWORD bytesToRead,
PIO_STATUS_BLOCK io_status) PIO_STATUS_BLOCK io_status)
{ {
int fd;
DWORD count, offset; DWORD count, offset;
USHORT user_id, tree_id, dialect, file_id, read; USHORT user_id, tree_id, dialect, file_id, read;
@ -1594,9 +1593,6 @@ NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
io_status->u.Status = SMB_GetSmbInfo(hFile, &tree_id, &user_id, &dialect, &file_id, &offset); io_status->u.Status = SMB_GetSmbInfo(hFile, &tree_id, &user_id, &dialect, &file_id, &offset);
if (io_status->u.Status) return io_status->u.Status; if (io_status->u.Status) return io_status->u.Status;
fd = FILE_GetUnixHandle(hFile, GENERIC_READ);
if (fd<0) return io_status->u.Status = STATUS_INVALID_HANDLE;
while(1) while(1)
{ {
count = bytesToRead - io_status->Information; count = bytesToRead - io_status->Information;
@ -1615,8 +1611,6 @@ NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
if(io_status->Information >= bytesToRead) if(io_status->Information >= bytesToRead)
break; break;
} }
close(fd);
return io_status->u.Status = SMB_SetOffset(hFile, offset); return io_status->u.Status = SMB_SetOffset(hFile, offset);
} }

View File

@ -22,7 +22,7 @@
static inline int SMB_isSepW (WCHAR c) {return (c == '\\' || c == '/');} static inline int SMB_isSepW (WCHAR c) {return (c == '\\' || c == '/');}
static inline int SMB_isUNCW (LPCWSTR filename) {return (filename && SMB_isSepW (filename[0]) && SMB_isSepW (filename[1]));} static inline int SMB_isUNCW (LPCWSTR filename) {return (filename && SMB_isSepW (filename[0]) && SMB_isSepW (filename[1]));}
NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, int fd, LPVOID buffer, DWORD bytesToRead,
PIO_STATUS_BLOCK io_status); PIO_STATUS_BLOCK io_status);
extern HANDLE WINAPI SMB_CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, extern HANDLE WINAPI SMB_CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation, LPSECURITY_ATTRIBUTES sa, DWORD creation,

View File

@ -77,7 +77,7 @@ inline static void finish_async( async_private *ovp )
ovp->next = ovp->prev = NULL; ovp->next = ovp->prev = NULL;
close(ovp->fd); wine_server_release_fd( ovp->handle, ovp->fd );
if ( ovp->event != INVALID_HANDLE_VALUE ) if ( ovp->event != INVALID_HANDLE_VALUE )
NtSetEvent( ovp->event, NULL ); NtSetEvent( ovp->event, NULL );

View File

@ -55,6 +55,7 @@ extern void wine_server_send_fd( int fd );
extern int wine_server_fd_to_handle( int fd, unsigned int access, int inherit, obj_handle_t *handle ); extern int wine_server_fd_to_handle( int fd, unsigned int access, int inherit, obj_handle_t *handle );
extern int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, extern int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd,
enum fd_type *type, int *flags ); enum fd_type *type, int *flags );
extern void wine_server_release_fd( obj_handle_t handle, int unix_fd );
/* do a server call and set the last error code */ /* do a server call and set the last error code */
inline static unsigned int wine_server_call_err( void *req_ptr ) inline static unsigned int wine_server_call_err( void *req_ptr )

View File

@ -1040,8 +1040,8 @@ DECL_HANDLER(get_handle_fd)
if (unix_fd != -1) reply->fd = unix_fd; if (unix_fd != -1) reply->fd = unix_fd;
else if (!get_error()) else if (!get_error())
{ {
unix_fd = fd->unix_fd; assert( fd->unix_fd != -1 );
if (unix_fd != -1) send_client_fd( current->process, unix_fd, req->handle ); send_client_fd( current->process, fd->unix_fd, req->handle );
} }
reply->type = fd->fd_ops->get_file_info( fd, NULL, &reply->flags ); reply->type = fd->fd_ops->get_file_info( fd, NULL, &reply->flags );
release_object( fd ); release_object( fd );