server: Support for opening devices.
Added support for opening devices directly with the server when they
don't correspond to a Unix file.
diff --git a/dlls/kernel/file.c b/dlls/kernel/file.c
index 5f8d128..a9edd35 100644
--- a/dlls/kernel/file.c
+++ b/dlls/kernel/file.c
@@ -1296,6 +1296,10 @@
{
dosdev += MAKELONG( 0, 4*sizeof(WCHAR) ); /* adjust position to start of filename */
}
+ else if (!(GetVersion() & 0x80000000))
+ {
+ dosdev = 0;
+ }
else if (filename[4])
{
ret = VXD_Open( filename+4, access, sa );
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index a50de84..023674d 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -1337,7 +1337,7 @@
/* make sure the device name is ASCII */
for (i = 0; i < name_len; i++)
- if (name[i] <= 32 || name[i] >= 127) return STATUS_OBJECT_NAME_NOT_FOUND;
+ if (name[i] <= 32 || name[i] >= 127) return STATUS_BAD_DEVICE_TYPE;
unix_len = strlen(config_dir) + sizeof("/dosdevices/") + name_len + 1;
@@ -1405,7 +1405,7 @@
dev = NULL; /* last try */
}
RtlFreeHeap( GetProcessHeap(), 0, unix_name );
- return STATUS_OBJECT_NAME_NOT_FOUND;
+ return STATUS_BAD_DEVICE_TYPE;
}
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 2e70296..f9363fa 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -202,6 +202,22 @@
io->u.Status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, disposition,
!(attr->Attributes & OBJ_CASE_INSENSITIVE) );
+ if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
+ {
+ SERVER_START_REQ( open_file_object )
+ {
+ req->access = access;
+ req->attributes = attr->Attributes;
+ req->rootdir = attr->RootDirectory;
+ req->sharing = sharing;
+ wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
+ io->u.Status = wine_server_call( req );
+ *handle = reply->handle;
+ }
+ SERVER_END_REQ;
+ return io->u.Status;
+ }
+
if (io->u.Status == STATUS_NO_SUCH_FILE &&
disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
{
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 46af45f..1391b08 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -772,6 +772,23 @@
+struct open_file_object_request
+{
+ struct request_header __header;
+ unsigned int access;
+ unsigned int attributes;
+ obj_handle_t rootdir;
+ unsigned int sharing;
+ /* VARARG(filename,unicode_str); */
+};
+struct open_file_object_reply
+{
+ struct reply_header __header;
+ obj_handle_t handle;
+};
+
+
+
struct alloc_file_handle_request
{
struct request_header __header;
@@ -3716,6 +3733,7 @@
REQ_release_semaphore,
REQ_open_semaphore,
REQ_create_file,
+ REQ_open_file_object,
REQ_alloc_file_handle,
REQ_get_handle_fd,
REQ_set_handle_fd,
@@ -3933,6 +3951,7 @@
struct release_semaphore_request release_semaphore_request;
struct open_semaphore_request open_semaphore_request;
struct create_file_request create_file_request;
+ struct open_file_object_request open_file_object_request;
struct alloc_file_handle_request alloc_file_handle_request;
struct get_handle_fd_request get_handle_fd_request;
struct set_handle_fd_request set_handle_fd_request;
@@ -4148,6 +4167,7 @@
struct release_semaphore_reply release_semaphore_reply;
struct open_semaphore_reply open_semaphore_reply;
struct create_file_reply create_file_reply;
+ struct open_file_object_reply open_file_object_reply;
struct alloc_file_handle_reply alloc_file_handle_reply;
struct get_handle_fd_reply get_handle_fd_reply;
struct set_handle_fd_reply set_handle_fd_reply;
@@ -4325,6 +4345,6 @@
struct query_symlink_reply query_symlink_reply;
};
-#define SERVER_PROTOCOL_VERSION 215
+#define SERVER_PROTOCOL_VERSION 216
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/fd.c b/server/fd.c
index 4ab7cbc..07ae40e 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -145,7 +145,8 @@
unsigned int access; /* file access (GENERIC_READ/WRITE) */
unsigned int sharing; /* file sharing mode */
int unix_fd; /* unix file descriptor */
- int fs_locks; /* can we use filesystem locks for this fd? */
+ int fs_locks :1; /* can we use filesystem locks for this fd? */
+ int unmounted :1;/* has the device been unmounted? */
int poll_index; /* index of fd in poll array */
struct list read_q; /* async readers of this fd */
struct list write_q; /* async writers of this fd */
@@ -1210,6 +1211,7 @@
if (fd->unix_fd != -1) close( fd->unix_fd );
fd->unix_fd = -1;
+ fd->unmounted = 1;
fd->closed->unix_fd = -1;
fd->closed->unlink[0] = 0;
@@ -1232,6 +1234,7 @@
fd->sharing = 0;
fd->unix_fd = -1;
fd->fs_locks = 1;
+ fd->unmounted = 0;
fd->poll_index = -1;
list_init( &fd->inode_entry );
list_init( &fd->locks );
@@ -1246,6 +1249,30 @@
return fd;
}
+/* allocate a pseudo fd object, for objects that need to behave like files but don't have a unix fd */
+struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *user )
+{
+ struct fd *fd = alloc_object( &fd_ops );
+
+ if (!fd) return NULL;
+
+ fd->fd_ops = fd_user_ops;
+ fd->user = user;
+ fd->inode = NULL;
+ fd->closed = NULL;
+ fd->access = 0;
+ fd->sharing = 0;
+ fd->unix_fd = -1;
+ fd->fs_locks = 0;
+ fd->unmounted = 0;
+ fd->poll_index = -1;
+ list_init( &fd->inode_entry );
+ list_init( &fd->locks );
+ list_init( &fd->read_q );
+ list_init( &fd->write_q );
+ return fd;
+}
+
/* check if the desired access is possible without violating */
/* the sharing mode of other opens of the same file */
static int check_sharing( struct fd *fd, unsigned int access, unsigned int sharing )
@@ -1409,7 +1436,11 @@
/* retrieve the unix fd for an object */
int get_unix_fd( struct fd *fd )
{
- if (fd->unix_fd == -1) set_error( STATUS_VOLUME_DISMOUNTED );
+ if (fd->unix_fd == -1)
+ {
+ if (fd->unmounted) set_error( STATUS_VOLUME_DISMOUNTED );
+ else set_error( STATUS_BAD_DEVICE_TYPE );
+ }
return fd->unix_fd;
}
@@ -1595,8 +1626,11 @@
struct device *device;
struct inode *inode;
struct fd *fd;
+ int unix_fd = get_unix_fd( device_fd );
- if (device_fd->unix_fd == -1 || fstat( device_fd->unix_fd, &st ) == -1 || !S_ISBLK( st.st_mode ))
+ if (unix_fd == -1) return;
+
+ if (fstat( unix_fd, &st ) == -1 || !S_ISBLK( st.st_mode ))
{
set_error( STATUS_INVALID_PARAMETER );
return;
@@ -1653,6 +1687,32 @@
}
}
+/* open a file object */
+DECL_HANDLER(open_file_object)
+{
+ struct unicode_str name;
+ struct directory *root = NULL;
+ struct object *obj;
+
+ get_req_unicode_str( &name );
+ if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+ return;
+
+ if ((obj = open_object_dir( root, &name, req->attributes, NULL )))
+ {
+ /* make sure this is a valid file object */
+ struct fd *fd = get_obj_fd( obj );
+ if (fd)
+ {
+ reply->handle = alloc_handle( current->process, obj, req->access, req->attributes );
+ release_object( fd );
+ }
+ release_object( obj );
+ }
+
+ if (root) release_object( root );
+}
+
/* get a Unix fd to access a file */
DECL_HANDLER(get_handle_fd)
{
diff --git a/server/file.h b/server/file.h
index f89940b..4419998 100644
--- a/server/file.h
+++ b/server/file.h
@@ -47,6 +47,7 @@
/* file descriptor functions */
extern struct fd *alloc_fd( const struct fd_ops *fd_user_ops, struct object *user );
+extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *user );
extern struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
unsigned int access, unsigned int sharing, unsigned int options );
extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
diff --git a/server/protocol.def b/server/protocol.def
index 3d055cb..2aa4f0e 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -604,6 +604,18 @@
@END
+/* Open a file object */
+@REQ(open_file_object)
+ unsigned int access; /* wanted access rights */
+ unsigned int attributes; /* open attributes */
+ obj_handle_t rootdir; /* root directory */
+ unsigned int sharing; /* sharing flags */
+ VARARG(filename,unicode_str); /* file name */
+@REPLY
+ obj_handle_t handle; /* handle to the file */
+@END
+
+
/* Allocate a file handle for a Unix fd */
@REQ(alloc_file_handle)
unsigned int access; /* wanted access rights */
diff --git a/server/request.h b/server/request.h
index 016e390..1fecb0f 100644
--- a/server/request.h
+++ b/server/request.h
@@ -145,6 +145,7 @@
DECL_HANDLER(release_semaphore);
DECL_HANDLER(open_semaphore);
DECL_HANDLER(create_file);
+DECL_HANDLER(open_file_object);
DECL_HANDLER(alloc_file_handle);
DECL_HANDLER(get_handle_fd);
DECL_HANDLER(set_handle_fd);
@@ -361,6 +362,7 @@
(req_handler)req_release_semaphore,
(req_handler)req_open_semaphore,
(req_handler)req_create_file,
+ (req_handler)req_open_file_object,
(req_handler)req_alloc_file_handle,
(req_handler)req_get_handle_fd,
(req_handler)req_set_handle_fd,
diff --git a/server/trace.c b/server/trace.c
index fb1be68..016b007 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1025,6 +1025,21 @@
fprintf( stderr, " handle=%p", req->handle );
}
+static void dump_open_file_object_request( const struct open_file_object_request *req )
+{
+ fprintf( stderr, " access=%08x,", req->access );
+ fprintf( stderr, " attributes=%08x,", req->attributes );
+ fprintf( stderr, " rootdir=%p,", req->rootdir );
+ fprintf( stderr, " sharing=%08x,", req->sharing );
+ fprintf( stderr, " filename=" );
+ dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_open_file_object_reply( const struct open_file_object_reply *req )
+{
+ fprintf( stderr, " handle=%p", req->handle );
+}
+
static void dump_alloc_file_handle_request( const struct alloc_file_handle_request *req )
{
fprintf( stderr, " access=%08x,", req->access );
@@ -3223,6 +3238,7 @@
(dump_func)dump_release_semaphore_request,
(dump_func)dump_open_semaphore_request,
(dump_func)dump_create_file_request,
+ (dump_func)dump_open_file_object_request,
(dump_func)dump_alloc_file_handle_request,
(dump_func)dump_get_handle_fd_request,
(dump_func)dump_set_handle_fd_request,
@@ -3436,6 +3452,7 @@
(dump_func)dump_release_semaphore_reply,
(dump_func)dump_open_semaphore_reply,
(dump_func)dump_create_file_reply,
+ (dump_func)dump_open_file_object_reply,
(dump_func)dump_alloc_file_handle_reply,
(dump_func)dump_get_handle_fd_reply,
(dump_func)dump_set_handle_fd_reply,
@@ -3649,6 +3666,7 @@
"release_semaphore",
"open_semaphore",
"create_file",
+ "open_file_object",
"alloc_file_handle",
"get_handle_fd",
"set_handle_fd",
@@ -3835,6 +3853,7 @@
{ "ACCESS_DENIED", STATUS_ACCESS_DENIED },
{ "ACCESS_VIOLATION", STATUS_ACCESS_VIOLATION },
{ "ALIAS_EXISTS", STATUS_ALIAS_EXISTS },
+ { "BAD_DEVICE_TYPE", STATUS_BAD_DEVICE_TYPE },
{ "BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW },
{ "BUFFER_TOO_SMALL", STATUS_BUFFER_TOO_SMALL },
{ "CHILD_MUST_BE_VOLATILE", STATUS_CHILD_MUST_BE_VOLATILE },