Commit a5e38b33 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Partial implementation of NtQueryDirectoryObject.

parent d30b5742
...@@ -406,26 +406,62 @@ NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK Des ...@@ -406,26 +406,62 @@ NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK Des
* Read information from a namespace directory. * Read information from a namespace directory.
* *
* PARAMS * PARAMS
* DirectoryHandle [I] Handle to a directory object * handle [I] Handle to a directory object
* Buffer [O] Buffer to hold the read data * buffer [O] Buffer to hold the read data
* BufferLength [I] Size of the buffer in bytes * size [I] Size of the buffer in bytes
* ReturnSingleEntry [I] If TRUE, return a single entry, if FALSE, return as many as fit in the buffer * single_entry [I] If TRUE, return a single entry, if FALSE, return as many as fit in the buffer
* RestartScan [I] If TRUE, start scanning from the start, if FALSE, scan from Context * restart [I] If TRUE, start scanning from the start, if FALSE, scan from Context
* Context [I/O] Indicates what point of the directory the scan is at * context [I/O] Indicates what point of the directory the scan is at
* ReturnLength [O] Caller supplied storage for the number of bytes written (or NULL) * ret_size [O] Caller supplied storage for the number of bytes written (or NULL)
* *
* RETURNS * RETURNS
* Success: ERROR_SUCCESS. * Success: ERROR_SUCCESS.
* Failure: An NTSTATUS error code. * Failure: An NTSTATUS error code.
*/ */
NTSTATUS WINAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PDIRECTORY_BASIC_INFORMATION Buffer, NTSTATUS WINAPI NtQueryDirectoryObject(HANDLE handle, PDIRECTORY_BASIC_INFORMATION buffer,
IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, ULONG size, BOOLEAN single_entry, BOOLEAN restart,
IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL) PULONG context, PULONG ret_size)
{ {
FIXME("(%p,%p,0x%08x,0x%08x,0x%08x,%p,%p), stub\n", DirectoryHandle, Buffer, BufferLength, ReturnSingleEntry, NTSTATUS ret;
RestartScan, Context, ReturnLength);
if (restart) *context = 0;
return STATUS_NOT_IMPLEMENTED; if (single_entry)
{
if (size <= sizeof(*buffer) + 2*sizeof(WCHAR)) return STATUS_BUFFER_OVERFLOW;
SERVER_START_REQ( get_directory_entry )
{
req->handle = handle;
req->index = *context;
wine_server_set_reply( req, buffer + 1, size - sizeof(*buffer) - 2*sizeof(WCHAR) );
if (!(ret = wine_server_call( req )))
{
buffer->ObjectName.Buffer = (WCHAR *)(buffer + 1);
buffer->ObjectName.Length = reply->name_len;
buffer->ObjectName.MaximumLength = reply->name_len + sizeof(WCHAR);
buffer->ObjectTypeName.Buffer = (WCHAR *)(buffer + 1) + 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;
(*context)++;
}
}
SERVER_END_REQ;
if (ret_size)
*ret_size = buffer->ObjectName.MaximumLength + buffer->ObjectTypeName.MaximumLength + sizeof(*buffer);
}
else
{
FIXME("multiple entries not implemented\n");
ret = STATUS_NOT_IMPLEMENTED;
}
return ret;
} }
/* /*
......
...@@ -3950,6 +3950,22 @@ struct open_directory_reply ...@@ -3950,6 +3950,22 @@ struct open_directory_reply
struct get_directory_entry_request
{
struct request_header __header;
obj_handle_t handle;
unsigned int index;
};
struct get_directory_entry_reply
{
struct reply_header __header;
size_t name_len;
/* VARARG(name,unicode_str,name_len); */
/* VARARG(type,unicode_str); */
};
struct create_symlink_request struct create_symlink_request
{ {
struct request_header __header; struct request_header __header;
...@@ -4448,6 +4464,7 @@ enum request ...@@ -4448,6 +4464,7 @@ enum request
REQ_set_mailslot_info, REQ_set_mailslot_info,
REQ_create_directory, REQ_create_directory,
REQ_open_directory, REQ_open_directory,
REQ_get_directory_entry,
REQ_create_symlink, REQ_create_symlink,
REQ_open_symlink, REQ_open_symlink,
REQ_query_symlink, REQ_query_symlink,
...@@ -4685,6 +4702,7 @@ union generic_request ...@@ -4685,6 +4702,7 @@ union generic_request
struct set_mailslot_info_request set_mailslot_info_request; struct set_mailslot_info_request set_mailslot_info_request;
struct create_directory_request create_directory_request; struct create_directory_request create_directory_request;
struct open_directory_request open_directory_request; struct open_directory_request open_directory_request;
struct get_directory_entry_request get_directory_entry_request;
struct create_symlink_request create_symlink_request; struct create_symlink_request create_symlink_request;
struct open_symlink_request open_symlink_request; struct open_symlink_request open_symlink_request;
struct query_symlink_request query_symlink_request; struct query_symlink_request query_symlink_request;
...@@ -4920,6 +4938,7 @@ union generic_reply ...@@ -4920,6 +4938,7 @@ union generic_reply
struct set_mailslot_info_reply set_mailslot_info_reply; struct set_mailslot_info_reply set_mailslot_info_reply;
struct create_directory_reply create_directory_reply; struct create_directory_reply create_directory_reply;
struct open_directory_reply open_directory_reply; struct open_directory_reply open_directory_reply;
struct get_directory_entry_reply get_directory_entry_reply;
struct create_symlink_reply create_symlink_reply; struct create_symlink_reply create_symlink_reply;
struct open_symlink_reply open_symlink_reply; struct open_symlink_reply open_symlink_reply;
struct query_symlink_reply query_symlink_reply; struct query_symlink_reply query_symlink_reply;
...@@ -4941,6 +4960,6 @@ union generic_reply ...@@ -4941,6 +4960,6 @@ union generic_reply
struct add_fd_completion_reply add_fd_completion_reply; struct add_fd_completion_reply add_fd_completion_reply;
}; };
#define SERVER_PROTOCOL_VERSION 333 #define SERVER_PROTOCOL_VERSION 334
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -396,3 +396,38 @@ DECL_HANDLER(open_directory) ...@@ -396,3 +396,38 @@ DECL_HANDLER(open_directory)
if (root) release_object( root ); 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 );
}
}
...@@ -318,6 +318,24 @@ struct object *find_object( const struct namespace *namespace, const struct unic ...@@ -318,6 +318,24 @@ struct object *find_object( const struct namespace *namespace, const struct unic
return NULL; 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 */ /* allocate a namespace */
struct namespace *create_namespace( unsigned int hash_size ) struct namespace *create_namespace( unsigned int hash_size )
{ {
......
...@@ -126,6 +126,7 @@ extern struct object *grab_object( void *obj ); ...@@ -126,6 +126,7 @@ extern struct object *grab_object( void *obj );
extern void release_object( void *obj ); extern void release_object( void *obj );
extern struct object *find_object( const struct namespace *namespace, const struct unicode_str *name, extern struct object *find_object( const struct namespace *namespace, const struct unicode_str *name,
unsigned int attributes ); 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_add_queue( struct object *obj, struct wait_queue_entry *entry );
extern int no_satisfied( struct object *obj, struct thread *thread ); extern int no_satisfied( struct object *obj, struct thread *thread );
extern int no_signal( struct object *obj, unsigned int access ); extern int no_signal( struct object *obj, unsigned int access );
......
...@@ -2851,6 +2851,17 @@ enum message_type ...@@ -2851,6 +2851,17 @@ enum message_type
@END @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 */ /* Create a symbolic link object */
@REQ(create_symlink) @REQ(create_symlink)
unsigned int access; /* access flags */ unsigned int access; /* access flags */
......
...@@ -321,6 +321,7 @@ DECL_HANDLER(create_mailslot); ...@@ -321,6 +321,7 @@ DECL_HANDLER(create_mailslot);
DECL_HANDLER(set_mailslot_info); DECL_HANDLER(set_mailslot_info);
DECL_HANDLER(create_directory); DECL_HANDLER(create_directory);
DECL_HANDLER(open_directory); DECL_HANDLER(open_directory);
DECL_HANDLER(get_directory_entry);
DECL_HANDLER(create_symlink); DECL_HANDLER(create_symlink);
DECL_HANDLER(open_symlink); DECL_HANDLER(open_symlink);
DECL_HANDLER(query_symlink); DECL_HANDLER(query_symlink);
...@@ -557,6 +558,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -557,6 +558,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_set_mailslot_info, (req_handler)req_set_mailslot_info,
(req_handler)req_create_directory, (req_handler)req_create_directory,
(req_handler)req_open_directory, (req_handler)req_open_directory,
(req_handler)req_get_directory_entry,
(req_handler)req_create_symlink, (req_handler)req_create_symlink,
(req_handler)req_open_symlink, (req_handler)req_open_symlink,
(req_handler)req_query_symlink, (req_handler)req_query_symlink,
......
...@@ -3500,6 +3500,22 @@ static void dump_open_directory_reply( const struct open_directory_reply *req ) ...@@ -3500,6 +3500,22 @@ static void dump_open_directory_reply( const struct open_directory_reply *req )
fprintf( stderr, " handle=%p", req->handle ); 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 ) static void dump_create_symlink_request( const struct create_symlink_request *req )
{ {
fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " access=%08x,", req->access );
...@@ -3944,6 +3960,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -3944,6 +3960,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_set_mailslot_info_request, (dump_func)dump_set_mailslot_info_request,
(dump_func)dump_create_directory_request, (dump_func)dump_create_directory_request,
(dump_func)dump_open_directory_request, (dump_func)dump_open_directory_request,
(dump_func)dump_get_directory_entry_request,
(dump_func)dump_create_symlink_request, (dump_func)dump_create_symlink_request,
(dump_func)dump_open_symlink_request, (dump_func)dump_open_symlink_request,
(dump_func)dump_query_symlink_request, (dump_func)dump_query_symlink_request,
...@@ -4177,6 +4194,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -4177,6 +4194,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_set_mailslot_info_reply, (dump_func)dump_set_mailslot_info_reply,
(dump_func)dump_create_directory_reply, (dump_func)dump_create_directory_reply,
(dump_func)dump_open_directory_reply, (dump_func)dump_open_directory_reply,
(dump_func)dump_get_directory_entry_reply,
(dump_func)dump_create_symlink_reply, (dump_func)dump_create_symlink_reply,
(dump_func)dump_open_symlink_reply, (dump_func)dump_open_symlink_reply,
(dump_func)dump_query_symlink_reply, (dump_func)dump_query_symlink_reply,
...@@ -4410,6 +4428,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -4410,6 +4428,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"set_mailslot_info", "set_mailslot_info",
"create_directory", "create_directory",
"open_directory", "open_directory",
"get_directory_entry",
"create_symlink", "create_symlink",
"open_symlink", "open_symlink",
"query_symlink", "query_symlink",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment