From ec851647e2a65f9f2c7e20091f44a9e7b95da855 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Fri, 21 Aug 2015 07:26:44 +0200 Subject: [PATCH] server: Implement open_file_object for rootdir pointing to file object. --- 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 4f58788cc40..d68be15d65f 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 86dc1283e65..fef4827cbea 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 e70304f0265..a07ca16af3c 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 b5e0ca71b56..b59de1c3c76 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 );