server: Partial implementation of NtQueryDirectoryObject.
diff --git a/server/directory.c b/server/directory.c
index f53ffe5..3e199f0 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -396,3 +396,38 @@
if (root) release_object( root );
}
+
+/* get a directory entry by index */
+DECL_HANDLER(get_directory_entry)
+{
+ static const WCHAR objectW[] = {'O','b','j','e','c','t',0 };
+ static const WCHAR dirW[] = {'D','i','r','e','c','t','o','r','y',0 };
+
+ struct directory *dir = get_directory_obj( current->process, req->handle, DIRECTORY_QUERY );
+ if (dir)
+ {
+ struct object *obj = find_object_index( dir->entries, req->index );
+ if (obj)
+ {
+ size_t name_len, type_len;
+ const WCHAR *name = get_object_name( obj, &name_len );
+ const WCHAR *type = obj->ops == &directory_ops ? dirW : objectW;
+
+ type_len = strlenW(type) * sizeof(WCHAR);
+ if (name_len + type_len <= get_reply_max_size())
+ {
+ void *ptr = set_reply_data_size( name_len + type_len );
+ if (ptr)
+ {
+ reply->name_len = name_len;
+ memcpy( ptr, name, name_len );
+ memcpy( (char *)ptr + name_len, type, type_len );
+ }
+ }
+ else set_error( STATUS_BUFFER_OVERFLOW );
+
+ release_object( obj );
+ }
+ release_object( dir );
+ }
+}
diff --git a/server/object.c b/server/object.c
index eb21ef1..7b7a5e3 100644
--- a/server/object.c
+++ b/server/object.c
@@ -318,6 +318,24 @@
return NULL;
}
+/* find an object by its index; the refcount is incremented */
+struct object *find_object_index( const struct namespace *namespace, unsigned int index )
+{
+ unsigned int i;
+
+ /* FIXME: not efficient at all */
+ for (i = 0; i < namespace->hash_size; i++)
+ {
+ const struct object_name *ptr;
+ LIST_FOR_EACH_ENTRY( ptr, &namespace->names[i], const struct object_name, entry )
+ {
+ if (!index--) return grab_object( ptr->obj );
+ }
+ }
+ set_error( STATUS_NO_MORE_ENTRIES );
+ return NULL;
+}
+
/* allocate a namespace */
struct namespace *create_namespace( unsigned int hash_size )
{
diff --git a/server/object.h b/server/object.h
index d1af7f2..543b9ba 100644
--- a/server/object.h
+++ b/server/object.h
@@ -126,6 +126,7 @@
extern void release_object( void *obj );
extern struct object *find_object( const struct namespace *namespace, const struct unicode_str *name,
unsigned int attributes );
+extern struct object *find_object_index( const struct namespace *namespace, unsigned int index );
extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry );
extern int no_satisfied( struct object *obj, struct thread *thread );
extern int no_signal( struct object *obj, unsigned int access );
diff --git a/server/protocol.def b/server/protocol.def
index a63b0cb..aa10f89 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2851,6 +2851,17 @@
@END
+/* Get a directory entry by index */
+@REQ(get_directory_entry)
+ obj_handle_t handle; /* handle to the directory */
+ unsigned int index; /* entry index */
+@REPLY
+ 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 */
+@END
+
+
/* Create a symbolic link object */
@REQ(create_symlink)
unsigned int access; /* access flags */
diff --git a/server/request.h b/server/request.h
index c84c6e9..cc1d3d1 100644
--- a/server/request.h
+++ b/server/request.h
@@ -321,6 +321,7 @@
DECL_HANDLER(set_mailslot_info);
DECL_HANDLER(create_directory);
DECL_HANDLER(open_directory);
+DECL_HANDLER(get_directory_entry);
DECL_HANDLER(create_symlink);
DECL_HANDLER(open_symlink);
DECL_HANDLER(query_symlink);
@@ -557,6 +558,7 @@
(req_handler)req_set_mailslot_info,
(req_handler)req_create_directory,
(req_handler)req_open_directory,
+ (req_handler)req_get_directory_entry,
(req_handler)req_create_symlink,
(req_handler)req_open_symlink,
(req_handler)req_query_symlink,
diff --git a/server/trace.c b/server/trace.c
index da4a0c7..4bcd545 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3500,6 +3500,22 @@
fprintf( stderr, " handle=%p", req->handle );
}
+static void dump_get_directory_entry_request( const struct get_directory_entry_request *req )
+{
+ fprintf( stderr, " handle=%p,", req->handle );
+ fprintf( stderr, " index=%08x", req->index );
+}
+
+static void dump_get_directory_entry_reply( const struct get_directory_entry_reply *req )
+{
+ fprintf( stderr, " name_len=%lu,", (unsigned long)req->name_len );
+ fprintf( stderr, " name=" );
+ dump_varargs_unicode_str( min(cur_size,req->name_len) );
+ fputc( ',', stderr );
+ fprintf( stderr, " type=" );
+ dump_varargs_unicode_str( cur_size );
+}
+
static void dump_create_symlink_request( const struct create_symlink_request *req )
{
fprintf( stderr, " access=%08x,", req->access );
@@ -3944,6 +3960,7 @@
(dump_func)dump_set_mailslot_info_request,
(dump_func)dump_create_directory_request,
(dump_func)dump_open_directory_request,
+ (dump_func)dump_get_directory_entry_request,
(dump_func)dump_create_symlink_request,
(dump_func)dump_open_symlink_request,
(dump_func)dump_query_symlink_request,
@@ -4177,6 +4194,7 @@
(dump_func)dump_set_mailslot_info_reply,
(dump_func)dump_create_directory_reply,
(dump_func)dump_open_directory_reply,
+ (dump_func)dump_get_directory_entry_reply,
(dump_func)dump_create_symlink_reply,
(dump_func)dump_open_symlink_reply,
(dump_func)dump_query_symlink_reply,
@@ -4410,6 +4428,7 @@
"set_mailslot_info",
"create_directory",
"open_directory",
+ "get_directory_entry",
"create_symlink",
"open_symlink",
"query_symlink",