[PATCH 2/3] ntdll: Use FileNameInformation to retrieve the object name for file objects.

Zebediah Figura z.figura12 at gmail.com
Mon Aug 3 20:14:43 CDT 2020


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/ntdll/unix/file.c | 45 ++++++++++++++++++++++++++++++++++++++++++
 server/fd.c            |  5 +++++
 server/file.h          |  1 +
 server/handle.c        | 16 ++++++++++++---
 server/protocol.def    |  1 +
 5 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 03e92a5c59e..26643dfdb3a 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -6496,6 +6496,7 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
         OBJECT_NAME_INFORMATION *p = ptr;
         char *unix_name;
         WCHAR *nt_name;
+        BOOL is_file = FALSE;
 
         /* first try as a file object */
 
@@ -6530,6 +6531,7 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
             status = wine_server_call( req );
             if (status == STATUS_SUCCESS)
             {
+                is_file = reply->is_file;
                 if (!reply->total)  /* no name */
                 {
                     if (sizeof(*p) > len) status = STATUS_INFO_LENGTH_MISMATCH;
@@ -6553,6 +6555,49 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
             }
         }
         SERVER_END_REQ;
+
+        if ((!status || status == STATUS_INFO_LENGTH_MISMATCH) && is_file)
+        {
+            FILE_NAME_INFORMATION *file_name;
+            IO_STATUS_BLOCK io;
+            NTSTATUS file_status;
+
+            if (!(file_name = malloc( sizeof(*file_name) + len ))) return STATUS_NO_MEMORY;
+
+            file_status = NtQueryInformationFile( handle, &io, file_name,
+                                                  sizeof(*file_name) + len, FileNameInformation );
+            switch (file_status)
+            {
+            case STATUS_SUCCESS:
+            case STATUS_BUFFER_OVERFLOW:
+                if (!status)
+                {
+                    ULONG file_size = file_name->FileNameLength;
+                    if (sizeof(*p) + p->Name.MaximumLength + file_name->FileNameLength > len)
+                    {
+                        file_size = len - (sizeof(*p) + p->Name.MaximumLength);
+                        status = STATUS_BUFFER_OVERFLOW;
+                    }
+                    memcpy( p->Name.Buffer + p->Name.Length / sizeof(WCHAR), file_name->FileName, file_size );
+                    p->Name.Length += file_size;
+                    p->Name.MaximumLength += file_size;
+                    p->Name.Buffer[p->Name.Length / sizeof(WCHAR)] = 0;
+                }
+                if (used_len) *used_len += file_name->FileNameLength;
+                break;
+
+            case STATUS_INVALID_DEVICE_REQUEST:
+            case STATUS_INVALID_PARAMETER:
+            case STATUS_NOT_IMPLEMENTED:
+                break;
+
+            default:
+                status = file_status;
+            }
+
+            free( file_name );
+        }
+
         break;
     }
 
diff --git a/server/fd.c b/server/fd.c
index 064defc34e8..52881b34dd6 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2592,6 +2592,11 @@ void fd_copy_completion( struct fd *src, struct fd *dst )
     dst->comp_flags = src->comp_flags;
 }
 
+struct object *get_fd_parent( struct fd *fd )
+{
+    return fd->fd_ops->get_parent( fd );
+}
+
 /* flush a file buffers */
 DECL_HANDLER(flush)
 {
diff --git a/server/file.h b/server/file.h
index b407c725db2..b24f0b943ec 100644
--- a/server/file.h
+++ b/server/file.h
@@ -103,6 +103,7 @@ 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 struct object *get_fd_parent( struct fd *fd );
 
 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 );
diff --git a/server/handle.c b/server/handle.c
index 9ae99cd0c63..8f371770bdf 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -38,6 +38,7 @@
 #include "thread.h"
 #include "security.h"
 #include "request.h"
+#include "file.h"
 
 struct handle_entry
 {
@@ -661,15 +662,24 @@ DECL_HANDLER(dup_handle)
 
 DECL_HANDLER(get_object_info)
 {
-    struct object *obj;
-    WCHAR *name;
+    struct object *obj, *parent = NULL;
+    struct fd *fd;
+    WCHAR *name = NULL;
 
     if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
 
     reply->access = get_handle_access( current->process, req->handle );
     reply->ref_count = obj->refcount;
     reply->handle_count = obj->handle_count;
-    if ((name = get_object_full_name( obj, &reply->total )))
+    if ((fd = get_obj_fd( obj )))
+    {
+        parent = get_fd_parent( fd );
+        release_object( fd );
+    }
+    else
+        clear_error();
+    reply->is_file = !!parent;
+    if ((name = get_object_full_name( parent ? parent : obj, &reply->total )))
         set_reply_data_ptr( name, min( reply->total, get_reply_max_size() ));
     release_object( obj );
 }
diff --git a/server/protocol.def b/server/protocol.def
index 1bbc8c5008f..d9944a24873 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3364,6 +3364,7 @@ struct handle_info
     unsigned int   ref_count;     /* object ref count */
     unsigned int   handle_count;  /* object handle count */
     data_size_t    total;         /* total needed size for name */
+    int            is_file;       /* is this object a file? */
     VARARG(name,unicode_str);     /* object name */
 @END
 
-- 
2.27.0




More information about the wine-devel mailing list