Signed-off-by: Zebediah Figura z.figura12@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