From 8d1550d1c63b5f01545ec0b0c4da678850c2c905 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 23 Mar 2002 18:48:12 +0000 Subject: [PATCH] Export the FILE_GetUnixHandle functionality from ntdll. --- dlls/ntdll/ntdll.spec | 1 + files/file.c | 36 ++++-------------------- include/wine/server.h | 3 +- scheduler/client.c | 65 +++++++++++++++++++++++++++++++++---------- 4 files changed, 59 insertions(+), 46 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index a36457a8e44..2914d24674f 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1041,6 +1041,7 @@ debug_channels (atom cdrom console debug delayhlp dll dosfs dosmem file fixup # Server interface @ cdecl -norelay wine_server_call(ptr) wine_server_call +@ cdecl wine_server_handle_to_fd(long long ptr ptr ptr) wine_server_handle_to_fd # Codepages @ cdecl __wine_init_codepages(ptr ptr) __wine_init_codepages diff --git a/files/file.c b/files/file.c index 0bc85acd25b..87953dc246f 100644 --- a/files/file.c +++ b/files/file.c @@ -227,36 +227,12 @@ HANDLE FILE_DupUnixHandle( int fd, DWORD access, BOOL inherit ) * 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, DWORD *flags ) +static int FILE_GetUnixHandleType( HANDLE handle, DWORD access, enum fd_type *type, int *flags ) { int ret, fd = -1; - do - { - SERVER_START_REQ( get_handle_fd ) - { - req->handle = handle; - req->access = access; - if (!(ret = wine_server_call_err( req ))) - { - fd = reply->fd; - } - if (type) *type = reply->type; - if (flags) *flags = reply->flags; - } - SERVER_END_REQ; - if (ret) return -1; - - if (fd == -1) /* it wasn't in the cache, get it from the server */ - fd = wine_server_recv_fd( handle ); - - } while (fd == -2); /* -2 means race condition, so restart from scratch */ - - if (fd != -1) - { - if ((fd = dup(fd)) == -1) - SetLastError( ERROR_TOO_MANY_OPEN_FILES ); - } + ret = wine_server_handle_to_fd( handle, access, &fd, type, flags ); + if (ret) SetLastError( RtlNtStatusToDosError(ret) ); return fd; } @@ -1467,9 +1443,8 @@ static BOOL FILE_TimeoutRead(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPD BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped ) { - int unix_handle, result; + int unix_handle, result, flags; enum fd_type type; - DWORD flags; TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToRead, bytesRead, overlapped ); @@ -1693,9 +1668,8 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, LPDWORD bytesWritten, LPOVERLAPPED overlapped ) { - int unix_handle, result; + int unix_handle, result, flags; enum fd_type type; - DWORD flags; TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToWrite, bytesWritten, overlapped ); diff --git a/include/wine/server.h b/include/wine/server.h index 1280a62a509..c8fc370d2bc 100644 --- a/include/wine/server.h +++ b/include/wine/server.h @@ -51,7 +51,8 @@ struct __server_request_info extern unsigned int wine_server_call( void *req_ptr ); extern void wine_server_send_fd( int fd ); -extern int wine_server_recv_fd( handle_t handle ); +extern int wine_server_handle_to_fd( handle_t handle, unsigned int access, int *unix_fd, + enum fd_type *type, int *flags ); /* do a server call and set the last error code */ inline static unsigned int wine_server_call_err( void *req_ptr ) diff --git a/scheduler/client.c b/scheduler/client.c index 0da699a23e5..c8523eeb408 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -330,23 +330,17 @@ static int receive_fd( handle_t *handle ) /*********************************************************************** - * wine_server_recv_fd + * store_cached_fd * - * Receive a file descriptor passed from the server. - * The file descriptor must not be closed. - * Return -2 if a race condition stole our file descriptor. + * Store the cached fd value for a given handle back into the server. + * Returns the new fd, which can be different if there was already an + * fd in the cache for that handle. */ -int wine_server_recv_fd( handle_t handle ) +inline static int store_cached_fd( int fd, handle_t handle ) { - handle_t fd_handle; - - int fd = receive_fd( &fd_handle ); - - /* now store it in the server fd cache for this handle */ - SERVER_START_REQ( set_handle_info ) { - req->handle = fd_handle; + req->handle = handle; req->flags = 0; req->mask = 0; req->fd = fd; @@ -366,12 +360,55 @@ int wine_server_recv_fd( handle_t handle ) } } SERVER_END_REQ; - - if (handle != fd_handle) fd = -2; /* not the one we expected */ return fd; } +/*********************************************************************** + * wine_server_handle_to_fd (NTDLL.@) + * + * Retrieve the Unix fd corresponding to a file handle. + */ +int wine_server_handle_to_fd( handle_t handle, unsigned int access, int *unix_fd, + enum fd_type *type, int *flags ) +{ + handle_t fd_handle; + int ret, fd = -1; + + *unix_fd = -1; + for (;;) + { + SERVER_START_REQ( get_handle_fd ) + { + req->handle = handle; + req->access = access; + if (!(ret = wine_server_call( req ))) fd = reply->fd; + if (type) *type = reply->type; + if (flags) *flags = reply->flags; + } + SERVER_END_REQ; + if (ret) return ret; + + if (fd != -1) break; + + /* 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 ); + + if (fd_handle == handle) break; + /* if we received a different handle this means there was + * a race with another thread; we restart everything from + * scratch in this case. + */ + } + + if ((fd != -1) && ((fd = dup(fd)) == -1)) return STATUS_TOO_MANY_OPENED_FILES; + *unix_fd = fd; + return STATUS_SUCCESS; +} + + /*********************************************************************** * get_config_dir *