[4/4] server: Implement open_file_object for rootdir pointing to file object.

Sebastian Lackner sebastian at fds-team.de
Fri Aug 21 00:26:44 CDT 2015


---
 dlls/ntdll/tests/file.c |   16 ++++++++--------
 server/fd.c             |   29 ++++++++++++++++++++---------
 server/file.c           |   23 ++++++++++++++++++++++-
 server/file.h           |    1 +
 4 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 4f58788..d68be15 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -466,8 +466,8 @@ static void open_file_test(void)
     attr.ObjectName = &nameW;
     status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
                          FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
-    todo_wine ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
-                  "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
+    ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
+        "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
 
     nameW.Length = 0;
     nameW.Buffer = NULL;
@@ -475,24 +475,24 @@ static void open_file_test(void)
     attr.ObjectName = &nameW;
     status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
                           FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
-    todo_wine ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
+    ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
 
     numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
     ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
     numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
-    todo_wine ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
+    ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
 
     numbytes = 0xdeadbeef;
     memset( data, 0, sizeof(data) );
     ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
-    todo_wine ok( ret, "ReadFile failed with error %u\n", GetLastError() );
-    todo_wine ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
-    todo_wine ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
+    ok( ret, "ReadFile failed with error %u\n", GetLastError() );
+    ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
+    ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
 
     numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
     ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
     numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
-    todo_wine ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
+    ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
 
     CloseHandle( file );
     CloseHandle( root );
diff --git a/server/fd.c b/server/fd.c
index 86dc128..fef4827 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1717,7 +1717,7 @@ void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *u
     fd->user   = user;
 }
 
-static char *dup_fd_name( struct fd *root, const char *name )
+char *dup_fd_name( struct fd *root, const char *name )
 {
     char *ret;
 
@@ -2386,19 +2386,30 @@ DECL_HANDLER(open_file_object)
 
     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 )))
     {
-        if ((result = obj->ops->open_file( obj, req->access, req->sharing, req->options )))
+        if (get_error() != STATUS_OBJECT_TYPE_MISMATCH) return;
+        if (!(obj = (struct object *)get_file_obj( current->process, req->rootdir, 0 ))) return;
+        if (name.len)
         {
-            reply->handle = alloc_handle( current->process, result, req->access, req->attributes );
-            release_object( result );
+            release_object( obj );
+            set_error( STATUS_OBJECT_PATH_NOT_FOUND );
+            return;
         }
-        release_object( obj );
+        clear_error();
+    }
+    else
+    {
+        obj = open_object_dir( root, &name, req->attributes, NULL );
+        if (root) release_object( root );
+        if (!obj) return;
     }
 
-    if (root) release_object( root );
+    if ((result = obj->ops->open_file( obj, req->access, req->sharing, req->options )))
+    {
+        reply->handle = alloc_handle( current->process, result, req->access, req->attributes );
+        release_object( result );
+    }
+    release_object( obj );
 }
 
 /* get the Unix name from a file handle */
diff --git a/server/file.c b/server/file.c
index e70304f..a07ca16 100644
--- a/server/file.c
+++ b/server/file.c
@@ -68,6 +68,8 @@ static struct object_type *file_get_type( struct object *obj );
 static struct fd *file_get_fd( struct object *obj );
 static struct security_descriptor *file_get_sd( struct object *obj );
 static int file_set_sd( struct object *obj, const struct security_descriptor *sd, unsigned int set_info );
+static struct object *file_open_file( struct object *obj, unsigned int access,
+                                      unsigned int sharing, unsigned int options );
 static void file_destroy( struct object *obj );
 
 static int file_get_poll_events( struct fd *fd );
@@ -89,7 +91,7 @@ static const struct object_ops file_ops =
     file_get_sd,                  /* get_sd */
     file_set_sd,                  /* set_sd */
     no_lookup_name,               /* lookup_name */
-    no_open_file,                 /* open_file */
+    file_open_file,               /* open_file */
     fd_close_handle,              /* close_handle */
     file_destroy                  /* destroy */
 };
@@ -605,6 +607,25 @@ static int file_set_sd( struct object *obj, const struct security_descriptor *sd
     return 1;
 }
 
+static struct object *file_open_file( struct object *obj, unsigned int access,
+                                      unsigned int sharing, unsigned int options )
+{
+    struct file *file = (struct file *)obj;
+    struct object *new_file = NULL;
+    char *unix_name;
+
+    assert( obj->ops == &file_ops );
+
+    if ((unix_name = dup_fd_name( file->fd, "" )))
+    {
+        new_file = create_file( NULL, unix_name, strlen(unix_name), access,
+                                sharing, FILE_OPEN, options, 0, NULL );
+        free( unix_name );
+    }
+    else set_error( STATUS_OBJECT_TYPE_MISMATCH );
+    return new_file;
+}
+
 static void file_destroy( struct object *obj )
 {
     struct file *file = (struct file *)obj;
diff --git a/server/file.h b/server/file.h
index b5e0ca7..b59de1c 100644
--- a/server/file.h
+++ b/server/file.h
@@ -81,6 +81,7 @@ extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count );
 extern void allow_fd_caching( struct fd *fd );
 extern void set_fd_signaled( struct fd *fd, int signaled );
 extern int is_fd_signaled( struct fd *fd );
+extern char *dup_fd_name( struct fd *root, const char *name );
 
 extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry );
 extern unsigned int default_fd_map_access( struct object *obj, unsigned int access );
-- 
2.5.0



More information about the wine-patches mailing list