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 );
}
/***********************************************************************
* 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)
*
@ -351,19 +329,30 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
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 (flags & FD_FLAG_RECV_SHUTDOWN)
{
wine_server_release_fd( hFile, unix_handle );
return STATUS_PIPE_DISCONNECTED;
}
if (flags & FD_FLAG_TIMEOUT)
{
if (hEvent)
{
/* this shouldn't happen, but check it */
FIXME("NIY-hEvent\n");
wine_server_release_fd( hFile, unix_handle );
return STATUS_NOT_IMPLEMENTED;
}
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))
@ -371,14 +360,14 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
async_fileio* ovp;
NTSTATUS ret;
if (unix_handle < 0) return STATUS_INVALID_HANDLE;
ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio));
if (!ovp) return STATUS_NO_MEMORY;
if (!(ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio))))
{
wine_server_release_fd( hFile, unix_handle );
return STATUS_NO_MEMORY;
}
ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
ovp->async.handle = hFile;
ovp->async.fd = unix_handle;
ovp->async.fd = unix_handle; /* FIXME */
ovp->async.type = ASYNC_TYPE_READ;
ovp->async.func = FILE_AsyncReadService;
ovp->async.event = hEvent;
@ -419,19 +408,18 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
{
case FD_TYPE_SMB:
FIXME("NIY-SMB\n");
close(unix_handle);
/* 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;
case FD_TYPE_DEFAULT:
/* normal unix files */
if (unix_handle == -1) return STATUS_INVALID_HANDLE;
/* normal unix file */
break;
default:
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;
}
@ -444,7 +432,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
FilePositionInformation);
if (io_status->u.Status)
{
close(unix_handle);
wine_server_release_fd( hFile, unix_handle );
return io_status->u.Status;
}
}
@ -456,7 +444,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
io_status->u.Status = FILE_GetNtStatus();
break;
}
close( unix_handle );
wine_server_release_fd( hFile, unix_handle );
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);
io_status->Information = 0;
io_status->u.Status = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type, &flags, &unix_handle );
io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &unix_handle, &type, &flags );
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))
{
async_fileio* ovp;
NTSTATUS ret;
if (unix_handle < 0) return STATUS_INVALID_HANDLE;
ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio));
if (!ovp) return STATUS_NO_MEMORY;
if (!(ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio))))
{
wine_server_release_fd( hFile, unix_handle );
return STATUS_NO_MEMORY;
}
ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
ovp->async.handle = hFile;
ovp->async.fd = unix_handle;
ovp->async.fd = unix_handle; /* FIXME */
ovp->async.type = ASYNC_TYPE_WRITE;
ovp->async.func = FILE_AsyncWriteService;
ovp->async.event = hEvent;
@ -595,7 +588,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
{
case FD_TYPE_SMB:
FIXME("NIY-SMB\n");
close(unix_handle);
wine_server_release_fd( hFile, unix_handle );
return STATUS_NOT_IMPLEMENTED;
case FD_TYPE_DEFAULT:
@ -605,7 +598,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
default:
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;
}
@ -618,7 +611,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
FilePositionInformation);
if (io_status->u.Status)
{
close(unix_handle);
wine_server_release_fd( hFile, unix_handle );
return io_status->u.Status;
}
}
@ -632,7 +625,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
else io_status->u.Status = FILE_GetNtStatus();
break;
}
close( unix_handle );
wine_server_release_fd( hFile, unix_handle );
return io_status->u.Status;
}

View File

@ -1067,6 +1067,7 @@
@ cdecl -norelay wine_server_call(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_release_fd(long long)
@ cdecl wine_server_send_fd(long)
# 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
* 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 )
{
req->handle = handle;
req->flags = 0;
req->mask = 0;
req->fd = fd;
if (!wine_server_call( req ))
req->fd = *fd;
if (!(ret = wine_server_call( req )))
{
if (reply->cur_fd != fd)
if (reply->cur_fd != *fd)
{
/* someone was here before us */
close( fd );
fd = reply->cur_fd;
close( *fd );
*fd = reply->cur_fd;
}
}
else
{
close( fd );
fd = -1;
close( *fd );
*fd = -1;
}
}
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 */
fd = receive_fd( &fd_handle );
/* 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 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
*

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.
*/
static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
DWORD header_size, int shared_fd, DWORD shared_size,
BOOL removable, PVOID *addr_ptr )
DWORD header_size, int shared_fd, BOOL removable, PVOID *addr_ptr )
{
IMAGE_DOS_HEADER *dos;
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 );
}
close( fd );
*addr_ptr = ptr;
return STATUS_SUCCESS;
error:
if (ptr != (char *)-1) munmap( ptr, total_size );
close( fd );
return status;
}
@ -1415,28 +1412,33 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
removable = reply->removable;
}
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)
{
int shared_fd = -1;
if (shared_file)
{
int shared_fd;
if ((res = wine_server_handle_to_fd( shared_file, GENERIC_READ, &shared_fd,
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,
shared_fd, shared_size, removable, addr_ptr );
if (shared_fd != -1) close( shared_fd );
else
{
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;
return res;
}
if (size_high)
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;
goto error;
}
if (unix_handle != -1) close( unix_handle );
wine_server_release_fd( handle, unix_handle );
*size_ptr = size;
return STATUS_SUCCESS;
error:
if (unix_handle != -1) close( unix_handle );
wine_server_release_fd( handle, unix_handle );
if (ptr != (void *)-1) munmap( ptr, size );
return res;
}

View File

@ -1580,10 +1580,9 @@ static NTSTATUS SMB_SetOffset(HANDLE hFile, DWORD offset)
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)
{
int fd;
DWORD count, offset;
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);
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)
{
count = bytesToRead - io_status->Information;
@ -1615,8 +1611,6 @@ NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
if(io_status->Information >= bytesToRead)
break;
}
close(fd);
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_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);
extern HANDLE WINAPI SMB_CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation,

View File

@ -77,7 +77,7 @@ inline static void finish_async( async_private *ovp )
ovp->next = ovp->prev = NULL;
close(ovp->fd);
wine_server_release_fd( ovp->handle, ovp->fd );
if ( ovp->event != INVALID_HANDLE_VALUE )
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_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd,
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 */
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;
else if (!get_error())
{
unix_fd = fd->unix_fd;
if (unix_fd != -1) send_client_fd( current->process, unix_fd, req->handle );
assert( fd->unix_fd != -1 );
send_client_fd( current->process, fd->unix_fd, req->handle );
}
reply->type = fd->fd_ops->get_file_info( fd, NULL, &reply->flags );
release_object( fd );