Patch 2 in the series, a repost of my patch to wine-devel of 2002-01-03, Now incremental to the previous patch (i.e., also relies on Mike's patches being applied).
Patch file: 002-fd_type.diff Purpose: More general approach to file descriptor types and flags. Created: 2002-01-07 Applies: CVS 2002-01-07 (with 001-file_overlapped.diff applied)
If overlapped IO is to be allowed / implemented for several different types of file descriptors (regular files, serial ports, pipes, sockets, ...), a more general scheme must be found to obtain file descriptor types and flags or capabilities. The current scheme treats FD_TYPE_OVERLAPPED as a special type, making it impossible to distinguish between e.g. overlapped files and overlapped sockets.
This patch fixes this behaviour by modifying the meaning of return value of the get_file_info() function.
** NOTE ON BUILDING: tools/make_requests must be run ** ** after applying this patch **
server/protocol.def: The lowest byte of the type value is reserved for the type itself (macro FD_TYPE (type)the rest is available for miscellaneous flags.
New FD types: FD_TYPE_DEVICE, FD_TYPE_NAMED_PIPE, FD_TYPE_PIPE, FD_TYPE_SERIAL, FD_TYPE_SOCKET. New FD flags (were formerly FD types): FD_TYPE_FLAG_OVERLAPPED: The fd uses overlapped I/O. FD_TYPE_FLAG_TIMEOUT: The fd applies a timeout on its I/O operations New test macros: FD_TYPE_IS_OVERLAPPED (type), FD_TYPE_HAS_TIMEOUT (type)
server/device.c: device_get_info(): return FD_TYPE_DEVICE. server/file.c: file_get_info(): set FD_TYPE_FLAG_OVERLAPPED on overlapped files. server/named_pipe.c: named_pipe_get_info(): return FD_TYPE_NAMED_PIPE. server/pipe.c: named_pipe_get_info(): return FD_TYPE_PIPE. server/serial.c: serial_get_info(): return FD_TYPE_SERIAL, account for OVERLAPPED and TIMEOUT flags. server/serial.c: sock_get_info(): return FD_TYPE_SOCKET.
files/file.c: ReadFile(): Replace FD_TYPE_XYZ dependent switch statement with an equivalent if/elseif construct which will allow a morte fine-grained destinction of fd types and flags in the future. WriteFile(): dito.
Martin Wilck Martin.Wilck@Fujitsu-Siemens.com
diff -ruX diffignore CVS/wine/files/file.c MW/wine/files/file.c --- CVS/wine/files/file.c Mon Jan 7 16:04:31 2002 +++ MW/wine/files/file.c Mon Jan 7 16:00:33 2002 @@ -1467,9 +1467,8 @@
unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type );
- switch (type) + if ( FD_TYPE_IS_OVERLAPPED (type) ) { - case FD_TYPE_OVERLAPPED: if (unix_handle == -1) return FALSE; if ( (overlapped==NULL) || NtResetEvent( overlapped->hEvent, NULL ) ) { @@ -1512,15 +1511,21 @@ /* fail on return, with ERROR_IO_PENDING */ SetLastError(ERROR_IO_PENDING); return FALSE; + }
- case FD_TYPE_CONSOLE: + else if ( FD_TYPE (type) == FD_TYPE_CONSOLE ) + { return ReadConsoleA(hFile, buffer, bytesToRead, bytesRead, NULL); + }
- case FD_TYPE_TIMEOUT: + else if ( FD_TYPE_HAS_TIMEOUT (type) ) + { close(unix_handle); return FILE_TimeoutRead(hFile, buffer, bytesToRead, bytesRead); + }
- default: + else + { /* normal unix files */ if (unix_handle == -1) return FALSE; @@ -1530,7 +1535,6 @@ SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - break; }
/* code for synchronous reads */ @@ -1689,9 +1693,8 @@
unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type );
- switch (type) + if ( FD_TYPE_IS_OVERLAPPED (type) ) { - case FD_TYPE_OVERLAPPED: if (unix_handle == -1) return FALSE; if ( (overlapped==NULL) || NtResetEvent( overlapped->hEvent, NULL ) ) { @@ -1741,11 +1744,17 @@ SetLastError(ERROR_IO_PENDING); return FALSE;
- case FD_TYPE_CONSOLE: + } + + else if ( FD_TYPE (type) == FD_TYPE_CONSOLE ) + { TRACE("%d %s %ld %p %p\n", hFile, debugstr_an(buffer, bytesToWrite), bytesToWrite, bytesWritten, overlapped ); return WriteConsoleA(hFile, buffer, bytesToWrite, bytesWritten, NULL); - default: + } + + else + { if (unix_handle == -1) return FALSE; } diff -ruX diffignore CVS/wine/server/device.c MW/wine/server/device.c --- CVS/wine/server/device.c Mon Jan 7 15:45:26 2002 +++ MW/wine/server/device.c Mon Jan 7 16:00:33 2002 @@ -83,7 +83,7 @@ reply->index_low = 0; reply->serial = 0; } - return FD_TYPE_DEFAULT; + return FD_TYPE_DEVICE; }
/* create a device */ diff -ruX diffignore CVS/wine/server/file.c MW/wine/server/file.c --- CVS/wine/server/file.c Mon Jan 7 15:58:22 2002 +++ MW/wine/server/file.c Mon Jan 7 16:00:33 2002 @@ -308,6 +308,7 @@ { struct stat st; struct file *file = (struct file *)obj; + int fd_type = FD_TYPE_DEFAULT; assert( obj->ops == &file_ops );
if (reply) @@ -342,9 +343,10 @@ }
if (file->flags & FILE_FLAG_OVERLAPPED) - return FD_TYPE_OVERLAPPED; + fd_type |= FD_TYPE_FLAG_OVERLAPPED; + + return fd_type;
- return FD_TYPE_DEFAULT; }
static struct async_queue *file_queue_async(struct object *obj, struct async *async, int type, int count) diff -ruX diffignore CVS/wine/server/named_pipe.c MW/wine/server/named_pipe.c --- CVS/wine/server/named_pipe.c Mon Jan 7 15:45:26 2002 +++ MW/wine/server/named_pipe.c Mon Jan 7 16:00:33 2002 @@ -197,7 +197,7 @@ reply->index_low = 0; reply->serial = 0; } - return FD_TYPE_DEFAULT; + return FD_TYPE_NAMED_PIPE; }
static struct named_pipe *create_named_pipe( const WCHAR *name, size_t len ) diff -ruX diffignore CVS/wine/server/pipe.c MW/wine/server/pipe.c --- CVS/wine/server/pipe.c Mon Jan 7 15:45:26 2002 +++ MW/wine/server/pipe.c Mon Jan 7 16:00:33 2002 @@ -140,7 +140,7 @@ reply->index_low = 0; reply->serial = 0; } - return FD_TYPE_DEFAULT; + return FD_TYPE_PIPE; }
static void pipe_destroy( struct object *obj ) diff -ruX diffignore CVS/wine/server/protocol.def MW/wine/server/protocol.def --- CVS/wine/server/protocol.def Mon Jan 7 15:45:26 2002 +++ MW/wine/server/protocol.def Mon Jan 7 16:00:33 2002 @@ -544,12 +544,22 @@ int fd; /* file descriptor */ int type; /* the type of file */ @END +#define FD_TYPE(x) ((x) & 0xff) + #define FD_TYPE_INVALID 0 #define FD_TYPE_DEFAULT 1 #define FD_TYPE_CONSOLE 2 -#define FD_TYPE_OVERLAPPED 3 -#define FD_TYPE_TIMEOUT 4 +#define FD_TYPE_DEVICE 3 +#define FD_TYPE_NAMED_PIPE 4 +#define FD_TYPE_PIPE 5 +#define FD_TYPE_SERIAL 6 +#define FD_TYPE_SOCKET 7 + +#define FD_TYPE_FLAG_OVERLAPPED 0x100 +#define FD_TYPE_FLAG_TIMEOUT 0x200
+#define FD_TYPE_IS_OVERLAPPED(x) ((x) & FD_TYPE_FLAG_OVERLAPPED) +#define FD_TYPE_HAS_TIMEOUT(x) ((x) & FD_TYPE_FLAG_TIMEOUT)
/* Set a file current position */ @REQ(set_file_pointer) diff -ruX diffignore CVS/wine/server/serial.c MW/wine/server/serial.c --- CVS/wine/server/serial.c Mon Jan 7 15:45:26 2002 +++ MW/wine/server/serial.c Mon Jan 7 16:00:33 2002 @@ -192,6 +192,7 @@ static int serial_get_info( struct object *obj, struct get_file_info_reply *reply ) { struct serial *serial = (struct serial *) obj; + int fd_type = FD_TYPE_SERIAL; assert( obj->ops == &serial_ops );
if (reply) @@ -209,13 +210,13 @@ }
if(serial->attrib & FILE_FLAG_OVERLAPPED) - return FD_TYPE_OVERLAPPED; + fd_type |= FD_TYPE_FLAG_OVERLAPPED;
- if( (serial->readinterval == MAXDWORD) && - (serial->readmult == 0) && (serial->readconst == 0) ) - return FD_TYPE_DEFAULT; + else if( !((serial->readinterval == MAXDWORD) && + (serial->readmult == 0) && (serial->readconst == 0)) ) + fd_type |= FD_TYPE_FLAG_TIMEOUT;
- return FD_TYPE_TIMEOUT; + return fd_type; }
static void serial_poll_event(struct object *obj, int event) diff -ruX diffignore CVS/wine/server/sock.c MW/wine/server/sock.c --- CVS/wine/server/sock.c Mon Jan 7 15:45:26 2002 +++ MW/wine/server/sock.c Mon Jan 7 16:00:33 2002 @@ -288,7 +288,7 @@ reply->index_low = 0; reply->serial = 0; } - return FD_TYPE_DEFAULT; + return FD_TYPE_SOCKET; }
static void sock_destroy( struct object *obj )