diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index d0229af4ab7..b1e22095249 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -439,6 +439,7 @@ static NTSTATUS get_io_timeouts( HANDLE handle, enum server_fd_type type, ULONG break; case FD_TYPE_SOCKET: case FD_TYPE_PIPE: + case FD_TYPE_CHAR: if (is_read) timeouts->interval = 0; /* return as soon as we got something */ break; default: @@ -491,6 +492,7 @@ static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL case FD_TYPE_MAILSLOT: case FD_TYPE_SOCKET: case FD_TYPE_PIPE: + case FD_TYPE_CHAR: *avail_mode = TRUE; break; default: diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 1fde1260779..5a1c721aa97 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1083,6 +1083,7 @@ enum server_fd_type FD_TYPE_SERIAL, FD_TYPE_PIPE, FD_TYPE_MAILSLOT, + FD_TYPE_CHAR, FD_TYPE_DEVICE, FD_TYPE_NB_TYPES }; @@ -4625,6 +4626,6 @@ union generic_reply struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply; }; -#define SERVER_PROTOCOL_VERSION 298 +#define SERVER_PROTOCOL_VERSION 299 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/file.c b/server/file.c index a45c340d362..7fc36b02b5e 100644 --- a/server/file.c +++ b/server/file.c @@ -58,6 +58,7 @@ struct file struct object obj; /* object header */ struct fd *fd; /* file descriptor for this file */ unsigned int access; /* file access (FILE_READ_DATA etc.) */ + mode_t mode; /* file stat.st_mode */ }; static unsigned int generic_file_map_access( unsigned int access ); @@ -110,9 +111,17 @@ static inline int is_overlapped( const struct file *file ) static struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing ) { struct file *file; + struct stat st; + + if (fstat( fd, &st ) == -1) + { + file_set_error(); + return NULL; + } if ((file = alloc_object( &file_ops ))) { + file->mode = st.st_mode; file->access = file_map_access( &file->obj, access ); if (!(file->fd = create_anonymous_fd( &file_fd_ops, fd, &file->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) @@ -124,12 +133,13 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in return file; } -static struct object *create_file_obj( struct fd *fd, unsigned int access ) +static struct object *create_file_obj( struct fd *fd, unsigned int access, mode_t mode ) { struct file *file = alloc_object( &file_ops ); if (!file) return NULL; file->access = access; + file->mode = mode; file->fd = fd; grab_object( fd ); set_fd_user( fd, &file_fd_ops, &file->obj ); @@ -178,7 +188,7 @@ static struct object *create_file( const char *nameptr, data_size_t len, unsigne else if (S_ISCHR(mode) && is_serial_fd( fd )) obj = create_serial( fd ); else - obj = create_file_obj( fd, access ); + obj = create_file_obj( fd, access, mode ); release_object( fd ); @@ -235,7 +245,11 @@ static void file_flush( struct fd *fd, struct event **event ) static enum server_fd_type file_get_fd_type( struct fd *fd ) { - return FD_TYPE_FILE; + struct file *file = get_fd_user( fd ); + + if (S_ISREG(file->mode) || S_ISBLK(file->mode)) return FD_TYPE_FILE; + if (S_ISDIR(file->mode)) return FD_TYPE_DIR; + return FD_TYPE_CHAR; } static struct fd *file_get_fd( struct object *obj ) diff --git a/server/protocol.def b/server/protocol.def index 02dee2def5f..8e501191d5d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -897,6 +897,7 @@ enum server_fd_type FD_TYPE_SERIAL, /* serial port */ FD_TYPE_PIPE, /* named pipe */ FD_TYPE_MAILSLOT, /* mailslot */ + FD_TYPE_CHAR, /* unspecified char device */ FD_TYPE_DEVICE, /* Windows device file */ FD_TYPE_NB_TYPES };