[PATCH 3/3] server: Generalize get_directory_entries to single_entry case.

Jinoh Kang jinoh.kang.kr at gmail.com
Sun May 8 08:49:37 CDT 2022


Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---

Notes:
    v3 -> v4: new patch

 dlls/ntdll/unix/sync.c | 50 ++++++++----------------------------------
 server/directory.c     | 40 ++++-----------------------------
 server/protocol.def    | 14 ++----------
 3 files changed, 15 insertions(+), 89 deletions(-)

diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index cce1ac6f264..1c7d8cb000d 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -1110,61 +1110,23 @@ NTSTATUS WINAPI NtQueryDirectoryObject( HANDLE handle, DIRECTORY_BASIC_INFORMATI
                                         ULONG size, BOOLEAN single_entry, BOOLEAN restart,
                                         ULONG *context, ULONG *ret_size )
 {
-    unsigned int i, count, pos, used_size, used_count;
+    unsigned int i, count, total_len, pos, used_size, used_count;
     ULONG index = restart ? 0 : *context;
     struct directory_entry *entries;
     NTSTATUS status;
     char *p;
 
-    if (single_entry)
-    {
-        SERVER_START_REQ( get_directory_entry )
-        {
-            req->handle = wine_server_obj_handle( handle );
-            req->index = index;
-            if (size >= 2 * sizeof(*buffer) + 2 * sizeof(WCHAR))
-                wine_server_set_reply( req, buffer + 2, size - 2 * sizeof(*buffer) - 2 * sizeof(WCHAR) );
-            if (!(status = wine_server_call( req )))
-            {
-                buffer->ObjectName.Buffer = (WCHAR *)(buffer + 2);
-                buffer->ObjectName.Length = reply->name_len;
-                buffer->ObjectName.MaximumLength = reply->name_len + sizeof(WCHAR);
-                buffer->ObjectTypeName.Buffer = (WCHAR *)(buffer + 2) + reply->name_len/sizeof(WCHAR) + 1;
-                buffer->ObjectTypeName.Length = wine_server_reply_size( reply ) - reply->name_len;
-                buffer->ObjectTypeName.MaximumLength = buffer->ObjectTypeName.Length + sizeof(WCHAR);
-                /* make room for the terminating null */
-                memmove( buffer->ObjectTypeName.Buffer, buffer->ObjectTypeName.Buffer - 1,
-                         buffer->ObjectTypeName.Length );
-                buffer->ObjectName.Buffer[buffer->ObjectName.Length/sizeof(WCHAR)] = 0;
-                buffer->ObjectTypeName.Buffer[buffer->ObjectTypeName.Length/sizeof(WCHAR)] = 0;
-
-                memset( &buffer[1], 0, sizeof(buffer[1]) );
-
-                *context = index + 1;
-            }
-            else if (status == STATUS_NO_MORE_ENTRIES)
-            {
-                if (size > sizeof(*buffer))
-                    memset( buffer, 0, sizeof(*buffer) );
-                if (ret_size) *ret_size = sizeof(*buffer);
-            }
-
-            if (ret_size && (!status || status == STATUS_BUFFER_TOO_SMALL))
-                *ret_size = 2 * sizeof(*buffer) + reply->total_len + 2 * sizeof(WCHAR);
-        }
-        SERVER_END_REQ;
-        return status;
-    }
-
     if (!(entries = malloc( size ))) return STATUS_NO_MEMORY;
 
     SERVER_START_REQ( get_directory_entries )
     {
         req->handle = wine_server_obj_handle( handle );
         req->index = index;
+        req->max_count = single_entry ? 1 : UINT_MAX;
         wine_server_set_reply( req, entries, size );
         status = wine_server_call( req );
         count = reply->count;
+        total_len = reply->total_len;
     }
     SERVER_END_REQ;
 
@@ -1224,6 +1186,12 @@ NTSTATUS WINAPI NtQueryDirectoryObject( HANDLE handle, DIRECTORY_BASIC_INFORMATI
         return STATUS_NO_MORE_ENTRIES;
     }
 
+    if (single_entry && !used_count)
+    {
+        if (ret_size) *ret_size = 2 * sizeof(*buffer) + 2 * sizeof(WCHAR) + total_len;
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+
     *context = index + used_count;
     if (ret_size) *ret_size = (char *)p - (char *)buffer;
     return status;
diff --git a/server/directory.c b/server/directory.c
index f35e5f35ede..2abac6c2fa7 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -545,8 +545,10 @@ DECL_HANDLER(get_directory_entries)
         unsigned int i;
         char *buffer;
 
+        reply->total_len = 0;
+
         size = 0;
-        for (i = 0; ; ++i)
+        for (i = 0; i < req->max_count; ++i)
         {
             const struct unicode_str *type_name;
             data_size_t name_len;
@@ -557,6 +559,7 @@ DECL_HANDLER(get_directory_entries)
             type_name = &obj->ops->type->name;
             get_object_name( obj, &name_len );
             entry_size = (sizeof(*entry) + name_len + type_name->len + 3) & ~3;
+            reply->total_len += name_len + type_name->len;
             release_object( obj );
 
             if (size + entry_size > get_reply_max_size())
@@ -607,41 +610,6 @@ DECL_HANDLER(get_directory_entries)
     }
 }
 
-/* get a directory entry by index */
-DECL_HANDLER(get_directory_entry)
-{
-    struct directory *dir = (struct directory *)get_handle_obj( current->process, req->handle,
-                                                                DIRECTORY_QUERY, &directory_ops );
-    if (dir)
-    {
-        struct object *obj = find_object_index( dir->entries, req->index );
-        if (obj)
-        {
-            data_size_t name_len;
-            const struct unicode_str *type_name = &obj->ops->type->name;
-            const WCHAR *name = get_object_name( obj, &name_len );
-
-            reply->total_len = name_len + type_name->len;
-
-            if (reply->total_len <= get_reply_max_size())
-            {
-                void *ptr = set_reply_data_size( reply->total_len );
-                if (ptr)
-                {
-                    reply->name_len = name_len;
-                    memcpy( ptr, name, name_len );
-                    memcpy( (char *)ptr + name_len, type_name->str, type_name->len );
-                }
-            }
-            else set_error( STATUS_BUFFER_TOO_SMALL );
-
-            release_object( obj );
-        }
-        else set_error( STATUS_NO_MORE_ENTRIES );
-        release_object( dir );
-    }
-}
-
 /* query object type name information */
 DECL_HANDLER(get_object_type)
 {
diff --git a/server/protocol.def b/server/protocol.def
index 7a06a6e8455..4530b172263 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3283,24 +3283,14 @@ struct handle_info
 @REQ(get_directory_entries)
     obj_handle_t   handle;             /* handle to the directory */
     unsigned int   index;              /* index of first entry */
+    unsigned int   max_count;          /* maximum number of entries to return */
 @REPLY
+    data_size_t    total_len;          /* total length needed for strings */
     unsigned int   count;              /* number of entries returned */
     VARARG(entries,directory_entries);
 @END
 
 
-/* Get a directory entry by index */
- at REQ(get_directory_entry)
-    obj_handle_t   handle;             /* handle to the directory */
-    unsigned int   index;              /* entry index */
- at REPLY
-    data_size_t    total_len;          /* total length needed for strings */
-    data_size_t    name_len;           /* length of the entry name in bytes */
-    VARARG(name,unicode_str,name_len); /* entry name */
-    VARARG(type,unicode_str);          /* entry type */
- at END
-
-
 /* Create a symbolic link object */
 @REQ(create_symlink)
     unsigned int   access;        /* access flags */
-- 
2.34.1




More information about the wine-devel mailing list