[PATCH v2 4/4] ntdll: Implement reading multiple entries in NtQueryDirectoryObject.

Jinoh Kang jinoh.kang.kr at gmail.com
Sat Apr 16 01:42:11 CDT 2022


On 4/13/22 12:00, Zebediah Figura wrote:
> diff --git a/server/directory.c b/server/directory.c
> index 23d7eb0a2b7..52033ca5e9e 100644
> --- a/server/directory.c
> +++ b/server/directory.c
> @@ -533,32 +533,76 @@ DECL_HANDLER(open_directory)
>  }
>  
>  /* get a directory entry by index */
> -DECL_HANDLER(get_directory_entry)
> +DECL_HANDLER(get_directory_entries)
>  {
>      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)
> +        struct directory_entry *entry;
> +        struct object *obj;
> +        data_size_t size;
> +        unsigned int i;
> +        char *buffer;
> +
> +        reply->total_len = 0;
> +
> +        size = 0;
> +        for (i = 0; i < req->max_count; ++i)
>          {
> +            const struct unicode_str *type_name;
>              data_size_t name_len;
> -            const struct unicode_str *type_name = &obj->ops->type->name;
> -            const WCHAR *name = get_object_name( obj, &name_len );
> +            size_t entry_size;
>  
> -            reply->total_len = name_len + type_name->len;
> +            if (!(obj = find_object_index( dir->entries, req->index + i )))
> +                break;
> +            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 (reply->total_len <= get_reply_max_size())
> +            if (size + entry_size > 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 );
> -                }
> +                set_error( STATUS_MORE_ENTRIES );
> +                break;
> +            }
> +            size += entry_size;
> +        }
> +        reply->count = i;
> +
> +        if (!(buffer = set_reply_data_size( size )))
> +        {
> +            release_object( dir );
> +            return;
> +        }
> +
> +        size = 0;
> +        for (i = 0; i < reply->count; ++i)
> +        {
> +            const struct unicode_str *type_name;
> +            data_size_t name_len;
> +            const WCHAR *name;
> +
> +            obj = find_object_index( dir->entries, req->index + i );
> +            assert( obj );
> +            type_name = &obj->ops->type->name;
> +            name = get_object_name( obj, &name_len );
> +
> +            entry = (struct directory_entry *)(buffer + size);
> +            entry->name_len = name_len;
> +            entry->type_len = type_name->len;
> +
> +            size += sizeof(entry);

s/sizeof(entry)/sizeof(*entry)/

> +            memcpy( buffer + size, name, name_len );
> +            size += name_len;
> +            memcpy( buffer + size, type_name->str, type_name->len );
> +            size += type_name->len;
> +            if (size & 3)
> +            {
> +                memset( buffer + size, 0, 4 - (size & 3) );
> +                size += 4 - (size & 3);
>              }
> -            else set_error( STATUS_BUFFER_TOO_SMALL );
>  
>              release_object( obj );
>          }
-- 
Sincerely,
Jinoh Kang



More information about the wine-devel mailing list