[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