>>>>> "Hans" == Hans Leidekker <hans@xxxxxxxx> writes: Hans> On Tuesday 13 January 2004 23:57, Uwe Bonnes wrote: >> +HANDLE DEVICE_Open( LPCWSTR filenameW, DWORD access, DWORD >> attributes, LPSECURITY_ATTRIBUTES sa ) { const struct VxDInfo >> *info; char filename[MAX_PATH]; @@ -283,7 +283,7 @@ for >> (info = VxDList; info->name; info++) if (!strncasecmp( >> info->name, filename, strlen(info->name) )) - return >> FILE_CreateDevice( info->id | 0x10000, access, sa ); + >> return FILE_CreateDevice( info->id | 0x10000, access, access, sa ); Hans> Hans> ^^^^^^ I think you want to pass 'attributes' here, right? For sure! Thanks. Alexandre, please use this patch. Now also server/protocol.def instead of include/wine/server_protocol.h is changed. Run make_request after applying. Changelog: wine/server/protocol.def, wine/include/file.h,wine/files/file.c, wine/files/dos_fs.c,wine/dlls/kernel/device.c, wine/server/device.c, wine/server/fd.c, wine/server/file.c, wine/server/file.h, wine/server/named_pipe.c, wine/server/process.c, wine/server/request.c,wine/server/serial.c, wine/server/signal.c, wine/server/smb.c, wine/server/sock.c , wine/server/trace.c, wine/server/thread.c Handle the device file connected to a device Bye -- Uwe Bonnes bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt --------- Tel. 06151 162516 -------- Fax. 06151 164321 ---------- Index: wine/server/protocol.def =================================================================== RCS file: /home/wine/wine/server/protocol.def,v retrieving revision 1.92 diff -u -w -r1.92 protocol.def --- wine/server/protocol.def 3 Jan 2004 00:38:30 -0000 1.92 +++ wine/server/protocol.def 14 Jan 2004 16:20:35 -0000 @@ -1109,6 +1109,7 @@ /* Create a device */ @REQ(create_device) unsigned int access; /* wanted access rights */ + unsigned int attributes; int inherit; /* inherit flag */ int id; /* client private id */ @REPLY Index: wine/include/file.h =================================================================== RCS file: /home/wine/wine/include/file.h,v retrieving revision 1.62 diff -u -w -r1.62 file.h --- wine/include/file.h 2 Dec 2003 04:19:56 -0000 1.62 +++ wine/include/file.h 14 Jan 2004 16:20:36 -0000 @@ -76,7 +76,7 @@ LPSECURITY_ATTRIBUTES sa, DWORD creation, DWORD attributes, HANDLE template, BOOL fail_read_only, UINT drive_type ); -extern HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa ); +extern HANDLE FILE_CreateDevice( int client_id, DWORD access, DWORD attributes, LPSECURITY_ATTRIBUTES sa ); extern LONG WINAPI WIN16_hread(HFILE16,SEGPTR,LONG); @@ -98,6 +98,6 @@ DOS_FULL_NAME *full ); /* win32/device.c */ -extern HANDLE DEVICE_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa ); +extern HANDLE DEVICE_Open( LPCWSTR filename, DWORD access, DWORD attributes, LPSECURITY_ATTRIBUTES sa ); #endif /* __WINE_FILE_H */ Index: wine/files/file.c =================================================================== RCS file: /home/wine/wine/files/file.c,v retrieving revision 1.198 diff -u -w -r1.198 file.c --- wine/files/file.c 6 Jan 2004 22:08:33 -0000 1.198 +++ wine/files/file.c 14 Jan 2004 16:20:38 -0000 @@ -271,14 +271,17 @@ * Same as FILE_CreateFile but for a device * Returns 0 on failure. */ -HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa ) +HANDLE FILE_CreateDevice( int client_id, DWORD access, DWORD attributes, LPSECURITY_ATTRIBUTES sa ) { + const char * devicename = DRIVE_GetDevice( client_id&0xff); HANDLE ret; SERVER_START_REQ( create_device ) { req->access = access; req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle); + req->attributes = attributes; req->id = client_id; + wine_server_add_data( req, devicename, (devicename)?strlen(devicename):0 ); SetLastError(0); wine_server_call_err( req ); ret = reply->handle; @@ -393,12 +396,12 @@ } else if (isalphaW(filename[4]) && filename[5] == ':' && filename[6] == '\0') { - ret = FILE_CreateDevice( (toupperW(filename[4]) - 'A') | 0x20000, access, sa ); + ret = FILE_CreateDevice( (toupperW(filename[4]) - 'A') | 0x20000, access, attributes, sa ); goto done; } else if (!DOSFS_GetDevice( filename )) { - ret = DEVICE_Open( filename+4, access, sa ); + ret = DEVICE_Open( filename+4, access, attributes, sa ); goto done; } else Index: wine/files/dos_fs.c =================================================================== RCS file: /home/wine/wine/files/dos_fs.c,v retrieving revision 1.144 diff -u -w -r1.144 dos_fs.c --- wine/files/dos_fs.c 5 Jan 2004 23:42:09 -0000 1.144 +++ wine/files/dos_fs.c 14 Jan 2004 16:20:40 -0000 @@ -973,7 +973,7 @@ !strcmpiW(DOSFS_Devices[i].name, hpscanW) || !strcmpiW(DOSFS_Devices[i].name, emmxxxx0W)) { - return FILE_CreateDevice( i, access, sa ); + return FILE_CreateDevice( i, access, attributes, sa ); } if( (handle=DOSFS_CreateCommPort(DOSFS_Devices[i].name,access,attributes,sa)) ) Index: wine/dlls/kernel/device.c =================================================================== RCS file: /home/wine/wine/dlls/kernel/device.c,v retrieving revision 1.7 diff -u -w -r1.7 device.c --- wine/dlls/kernel/device.c 2 Jan 2004 03:55:35 -0000 1.7 +++ wine/dlls/kernel/device.c 14 Jan 2004 16:20:41 -0000 @@ -270,7 +270,7 @@ { NULL, 0, NULL } }; -HANDLE DEVICE_Open( LPCWSTR filenameW, DWORD access, LPSECURITY_ATTRIBUTES sa ) +HANDLE DEVICE_Open( LPCWSTR filenameW, DWORD access, DWORD attributes, LPSECURITY_ATTRIBUTES sa ) { const struct VxDInfo *info; char filename[MAX_PATH]; @@ -283,7 +283,7 @@ for (info = VxDList; info->name; info++) if (!strncasecmp( info->name, filename, strlen(info->name) )) - return FILE_CreateDevice( info->id | 0x10000, access, sa ); + return FILE_CreateDevice( info->id | 0x10000, access, attributes, sa ); FIXME( "Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.\n", filename); Index: wine/server/device.c =================================================================== RCS file: /home/wine/wine/server/device.c,v retrieving revision 1.18 diff -u -w -r1.18 device.c --- wine/server/device.c 5 Sep 2003 23:15:41 -0000 1.18 +++ wine/server/device.c 14 Jan 2004 16:20:42 -0000 @@ -24,16 +24,23 @@ * client-side device support. */ +#include "config.h" + #include <assert.h> #include <fcntl.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/ioctl.h> #include "windef.h" #include "winbase.h" +#include "file.h" #include "handle.h" #include "thread.h" #include "request.h" @@ -42,37 +49,150 @@ { struct object obj; /* object header */ int id; /* client identifier */ + struct fd *fd; /* accociated device file */ }; static void device_dump( struct object *obj, int verbose ); +static struct fd *device_get_fd( struct object *obj ); +static void device_destroy(struct object *obj); +static int device_get_file_info( struct fd *fd, struct get_file_info_reply *reply, int *flags ); +static int device_set_file_pointer( struct fd *fd, unsigned int *low, int *high, int whence ); static const struct object_ops device_ops = { sizeof(struct device), /* size */ device_dump, /* dump */ - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ - NULL, /* satisfied */ - no_get_fd, /* get_fd */ - no_destroy /* destroy */ + default_fd_add_queue, /* add_queue */ + default_fd_remove_queue, /* remove_queue */ + default_fd_signaled, /* signaled */ + no_satisfied, /* satisfied */ + device_get_fd, /* get_fd */ + device_destroy /* destroy */ }; -static struct device *create_device( int id ) +static const struct fd_ops device_fd_ops = +{ + NULL, /* get_poll_events */ + default_poll_event, /* poll_event */ + no_flush, /* flush */ + device_get_file_info, /* get_file_info */ + device_set_file_pointer, /* device_set_file_pointer*/ + no_queue_async /* queue_async */ +}; + +static struct device *create_device( int id, unsigned int access, unsigned int attributes, + const char *nameptr, size_t len ) { struct device *dev; + int fd=-1, flags = 0, myerr; + char *name; + + if ((len) && (name = mem_alloc( len + 1 )) && (access/*!=QUERY_ACCESS*/)) + { + memcpy( name, nameptr, len ); + name[len] = 0; + + switch(access & (GENERIC_READ | GENERIC_WRITE)) + { + case GENERIC_READ: flags |= O_RDONLY; break; + case GENERIC_WRITE: flags |= O_WRONLY; break; + case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break; + default: break; + } + + flags |= O_NONBLOCK; + + fd = open( name, flags ); + myerr = errno; + if ((fd == -1) && ((myerr == EROFS) ||(myerr == EACCES))) + { + flags &= ~O_RDWR; + flags &= ~O_WRONLY; + fd = open( name, flags ); + } + free( name ); + } + if ((dev = alloc_object( &device_ops ))) { dev->id = id; + if (fd != -1) + { + dev->fd = create_anonymous_fd( &device_fd_ops, fd, &dev->obj ); + } + else + dev->fd = 0; } return dev; } +static struct fd *device_get_fd( struct object *obj ) +{ + struct device *dev = (struct device *)obj; + assert( obj->ops == &device_ops ); + return ( dev->fd )?(struct fd *)grab_object( dev->fd ):0; +} + +static void device_destroy( struct object *obj) +{ + struct device *dev = (struct device *)obj; + if (dev->fd) + release_object( dev->fd ); +} + static void device_dump( struct object *obj, int verbose ) { struct device *dev = (struct device *)obj; assert( obj->ops == &device_ops ); - fprintf( stderr, "Device id=%08x\n", dev->id ); + fprintf( stderr, "Device id=%08x fd=%p\n", dev->id , dev->fd); +} + +static int device_get_file_info( struct fd *fd, struct get_file_info_reply *reply, int *flags ) +{ + struct file *file = get_fd_user( fd ); + if (reply) + { + if (file) + reply->type = FILE_TYPE_DISK; + else + reply->type = FD_TYPE_INVALID; + reply->attr = 0; + reply->access_time = 0; + reply->write_time = 0; + reply->size_high = 0; + reply->size_low = 0; + reply->links = 0; + reply->index_high = 0; + reply->index_low = 0; + reply->serial = 0; + } + *flags = 0; + return FD_TYPE_DEFAULT; +} + +static int device_set_file_pointer( struct fd *fd, unsigned int *low, int *high, int whence ) +{ + struct file *file = get_fd_user( fd ); + off_t result,xto; + int unix_fd = get_unix_fd( fd ); + + xto = *low+((off_t)*high<<32); + if (!(file)) return 0; + if ((result = lseek( unix_fd, xto, whence))==-1) + { + /* Check for seek before start of file */ + + /* also check EPERM due to SuSE7 2.2.16 lseek() EPERM kernel bug */ + if (((errno == EINVAL) || (errno == EPERM)) + && (whence != SEEK_SET) && (*high < 0)) + set_error( 0xc0010000 | ERROR_NEGATIVE_SEEK /* FIXME */ ); + else + file_set_error(); + return 0; + } + *low = result & 0xffffffff; + *high = result >> 32; + return 1; } /* create a device */ @@ -81,7 +201,7 @@ struct device *dev; reply->handle = 0; - if ((dev = create_device( req->id ))) + if ((dev = create_device( req->id , req->access, req->attributes, get_req_data(), get_req_data_size()))) { reply->handle = alloc_handle( current->process, dev, req->access, req->inherit ); release_object( dev ); Index: wine/server/fd.c =================================================================== RCS file: /home/wine/wine/server/fd.c,v retrieving revision 1.15 diff -u -w -r1.15 fd.c --- wine/server/fd.c 2 Jan 2004 20:11:35 -0000 1.15 +++ wine/server/fd.c 14 Jan 2004 16:20:44 -0000 @@ -990,6 +990,15 @@ return FD_TYPE_INVALID; } +/* default get_file_info() routine */ +int no_set_file_pointer( struct fd *fd, unsigned int *low, int *high, int whence ) +{ + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + *low = 0xffffffff; + *high = 0xffffffff; + return 0; +} + /* default queue_async() routine */ void no_queue_async( struct fd *fd, void* ptr, unsigned int status, int type, int count ) { @@ -1050,7 +1059,7 @@ } } -/* get a file information */ +/* set a file information */ DECL_HANDLER(get_file_info) { struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); @@ -1060,6 +1069,28 @@ int flags; fd->fd_ops->get_file_info( fd, reply, &flags ); release_object( fd ); + } +} + +/* get a file information */ +DECL_HANDLER(set_file_pointer) +{ + struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); + int high = req->high; + int low = req->low; + + + if (fd) + { + fd->fd_ops->set_file_pointer( fd, &low, &high, req->whence); + release_object( fd ); + reply->new_low = low; + reply->new_high = high; + } + else + { + reply->new_low = 0xffffffff; + reply->new_high = 0xffffffff; } } Index: wine/server/file.c =================================================================== RCS file: /home/wine/wine/server/file.c,v retrieving revision 1.74 diff -u -w -r1.74 file.c --- wine/server/file.c 2 Jan 2004 20:11:35 -0000 1.74 +++ wine/server/file.c 14 Jan 2004 16:20:46 -0000 @@ -76,6 +76,7 @@ static void file_poll_event( struct fd *fd, int event ); static int file_flush( struct fd *fd, struct event **event ); static int file_get_info( struct fd *fd, struct get_file_info_reply *reply, int *flags ); +static int file_set_file_pointer( struct fd *fd, unsigned int *low, int *high, int whence ); static void file_queue_async( struct fd *fd, void *ptr, unsigned int status, int type, int count ); static const struct object_ops file_ops = @@ -96,6 +97,7 @@ file_poll_event, /* poll_event */ file_flush, /* flush */ file_get_info, /* get_file_info */ + file_set_file_pointer, /* set_file_pointer */ file_queue_async /* queue_async */ }; @@ -358,6 +360,32 @@ return FD_TYPE_DEFAULT; } +static int file_set_file_pointer( struct fd *fd, unsigned int *low, int *high, int whence ) +{ + struct file *file; + off_t result,xto; + int unix_fd = get_unix_fd( fd ); + + file= get_fd_user( fd ); + xto = *low+((off_t)*high<<32); + if (!(file)) return 0; + if ((result = lseek( unix_fd, xto, whence))==-1) + { + /* Check for seek before start of file */ + + /* also check EPERM due to SuSE7 2.2.16 lseek() EPERM kernel bug */ + if (((errno == EINVAL) || (errno == EPERM)) + && (whence != SEEK_SET) && (*high < 0)) + set_error( 0xc0010000 | ERROR_NEGATIVE_SEEK /* FIXME */ ); + else + file_set_error(); + return 0; + } + *low = result & 0xffffffff; + *high = result >> 32; + return 1; +} + static void file_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count) { struct file *file = get_fd_user( fd ); @@ -479,33 +507,6 @@ return get_unix_fd( file->fd ); } -static int set_file_pointer( obj_handle_t handle, unsigned int *low, int *high, int whence ) -{ - struct file *file; - off_t result,xto; - - xto = *low+((off_t)*high<<32); - if (!(file = get_file_obj( current->process, handle, 0 ))) - return 0; - if ((result = lseek( get_file_unix_fd(file), xto, whence))==-1) - { - /* Check for seek before start of file */ - - /* also check EPERM due to SuSE7 2.2.16 lseek() EPERM kernel bug */ - if (((errno == EINVAL) || (errno == EPERM)) - && (whence != SEEK_SET) && (*high < 0)) - set_win32_error( ERROR_NEGATIVE_SEEK ); - else - file_set_error(); - release_object( file ); - return 0; - } - *low = result & 0xffffffff; - *high = result >> 32; - release_object( file ); - return 1; -} - /* extend a file beyond the current end of file */ static int extend_file( struct file *file, off_t size ) { @@ -625,16 +626,6 @@ reply->handle = alloc_handle( current->process, file, req->access, req->inherit ); release_object( file ); } -} - -/* set a file current position */ -DECL_HANDLER(set_file_pointer) -{ - int high = req->high; - int low = req->low; - set_file_pointer( req->handle, &low, &high, req->whence ); - reply->new_low = low; - reply->new_high = high; } /* truncate (or extend) a file */ Index: wine/server/file.h =================================================================== RCS file: /home/wine/wine/server/file.h,v retrieving revision 1.10 diff -u -w -r1.10 file.h --- wine/server/file.h 8 Oct 2003 00:25:33 -0000 1.10 +++ wine/server/file.h 14 Jan 2004 16:20:49 -0000 @@ -38,6 +38,8 @@ int (*flush)(struct fd *, struct event **); /* get file information */ int (*get_file_info)(struct fd *,struct get_file_info_reply *, int *flags); + /* set file pointer (if appropriate)*/ + int (*set_file_pointer)(struct fd *, unsigned int *low, int *high, int whence ); /* queue an async operation - see register_async handler in async.c*/ void (*queue_async)(struct fd *, void* ptr, unsigned int status, int type, int count); }; @@ -63,6 +65,7 @@ extern void default_poll_event( struct fd *fd, int event ); extern int no_flush( struct fd *fd, struct event **event ); extern int no_get_file_info( struct fd *fd, struct get_file_info_reply *info, int *flags ); +extern int no_set_file_pointer( struct fd *fd, unsigned int *low, int *high, int whence ); extern void no_queue_async( struct fd *fd, void* ptr, unsigned int status, int type, int count ); extern void main_loop(void); Index: wine/server/named_pipe.c =================================================================== RCS file: /home/wine/wine/server/named_pipe.c,v retrieving revision 1.27 diff -u -w -r1.27 named_pipe.c --- wine/server/named_pipe.c 5 Sep 2003 23:15:41 -0000 1.27 +++ wine/server/named_pipe.c 14 Jan 2004 16:20:51 -0000 @@ -152,6 +152,7 @@ default_poll_event, /* poll_event */ pipe_server_flush, /* flush */ pipe_end_get_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ no_queue_async /* queue_async */ }; @@ -179,6 +180,7 @@ default_poll_event, /* poll_event */ pipe_client_flush, /* flush */ pipe_end_get_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ no_queue_async /* queue_async */ }; Index: wine/server/process.c =================================================================== RCS file: /home/wine/wine/server/process.c,v retrieving revision 1.115 diff -u -w -r1.115 process.c --- wine/server/process.c 10 Dec 2003 04:08:06 -0000 1.115 +++ wine/server/process.c 14 Jan 2004 16:21:02 -0000 @@ -76,6 +76,7 @@ process_poll_event, /* poll_event */ no_flush, /* flush */ no_get_file_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ no_queue_async /* queue_async */ }; Index: wine/server/request.c =================================================================== RCS file: /home/wine/wine/server/request.c,v retrieving revision 1.80 diff -u -w -r1.80 request.c --- wine/server/request.c 18 Jun 2003 19:45:22 -0000 1.80 +++ wine/server/request.c 14 Jan 2004 16:21:13 -0000 @@ -100,6 +100,7 @@ master_socket_poll_event, /* poll_event */ no_flush, /* flush */ no_get_file_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ no_queue_async /* queue_async */ }; Index: wine/server/serial.c =================================================================== RCS file: /home/wine/wine/server/serial.c,v retrieving revision 1.31 diff -u -w -r1.31 serial.c --- wine/server/serial.c 5 Sep 2003 23:15:41 -0000 1.31 +++ wine/server/serial.c 14 Jan 2004 16:21:23 -0000 @@ -107,6 +107,7 @@ serial_poll_event, /* poll_event */ serial_flush, /* flush */ serial_get_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ serial_queue_async /* queue_async */ }; Index: wine/server/signal.c =================================================================== RCS file: /home/wine/wine/server/signal.c,v retrieving revision 1.6 diff -u -w -r1.6 signal.c --- wine/server/signal.c 24 Oct 2003 04:29:01 -0000 1.6 +++ wine/server/signal.c 14 Jan 2004 16:21:33 -0000 @@ -71,6 +71,7 @@ handler_poll_event, /* poll_event */ no_flush, /* flush */ no_get_file_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ no_queue_async /* queue_async */ }; Index: wine/server/smb.c =================================================================== RCS file: /home/wine/wine/server/smb.c,v retrieving revision 1.10 diff -u -w -r1.10 smb.c --- wine/server/smb.c 5 Sep 2003 23:15:41 -0000 1.10 +++ wine/server/smb.c 14 Jan 2004 16:21:37 -0000 @@ -89,6 +89,7 @@ default_poll_event, /* poll_event */ no_flush, /* flush */ smb_get_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ no_queue_async /* queue_async */ }; Index: wine/server/sock.c =================================================================== RCS file: /home/wine/wine/server/sock.c,v retrieving revision 1.46 diff -u -w -r1.46 sock.c --- wine/server/sock.c 5 Sep 2003 23:15:41 -0000 1.46 +++ wine/server/sock.c 14 Jan 2004 16:21:42 -0000 @@ -117,6 +117,7 @@ sock_poll_event, /* poll_event */ no_flush, /* flush */ sock_get_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ sock_queue_async /* queue_async */ }; Index: wine/server/trace.c =================================================================== RCS file: /home/wine/wine/server/trace.c,v retrieving revision 1.191 diff -u -w -r1.191 trace.c --- wine/server/trace.c 3 Jan 2004 00:38:30 -0000 1.191 +++ wine/server/trace.c 14 Jan 2004 16:21:53 -0000 @@ -1349,6 +1349,7 @@ static void dump_create_device_request( const struct create_device_request *req ) { fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " attributes=%08x,", req->attributes ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " id=%d", req->id ); } Index: wine/server/thread.c =================================================================== RCS file: /home/wine/wine/server/thread.c,v retrieving revision 1.103 diff -u -w -r1.103 thread.c --- wine/server/thread.c 27 Oct 2003 22:10:22 -0000 1.103 +++ wine/server/thread.c 14 Jan 2004 16:21:55 -0000 @@ -100,6 +100,7 @@ thread_poll_event, /* poll_event */ no_flush, /* flush */ no_get_file_info, /* get_file_info */ + no_set_file_pointer, /* set_file_pointer*/ no_queue_async /* queue_async */ };