server: Add support for returning the object name in NtQueryObject.

This commit is contained in:
Alexandre Julliard 2010-01-08 13:01:50 +01:00
parent 2e03013fc0
commit 658dae988d
9 changed files with 133 additions and 2 deletions

View File

@ -85,6 +85,42 @@ NTSTATUS WINAPI NtQueryObject(IN HANDLE handle,
SERVER_END_REQ;
}
break;
case ObjectNameInformation:
{
OBJECT_NAME_INFORMATION* p = ptr;
SERVER_START_REQ( get_object_info )
{
req->handle = wine_server_obj_handle( handle );
if (len > sizeof(*p)) wine_server_set_reply( req, p + 1, len - sizeof(*p) );
status = wine_server_call( req );
if (status == STATUS_SUCCESS)
{
if (!reply->total) /* no name */
{
if (sizeof(*p) > len) status = STATUS_INFO_LENGTH_MISMATCH;
else memset( p, 0, sizeof(*p) );
if (used_len) *used_len = sizeof(*p);
}
else if (sizeof(*p) + reply->total + sizeof(WCHAR) > len)
{
if (used_len) *used_len = sizeof(*p) + reply->total + sizeof(WCHAR);
status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
ULONG res = wine_server_reply_size( reply );
p->Name.Buffer = (WCHAR *)(p + 1);
p->Name.Length = res;
p->Name.MaximumLength = res + sizeof(WCHAR);
p->Name.Buffer[res / sizeof(WCHAR)] = 0;
if (used_len) *used_len = sizeof(*p) + p->Name.MaximumLength;
}
}
}
SERVER_END_REQ;
}
break;
case ObjectDataInformation:
{
OBJECT_DATA_INFORMATION* p = ptr;

View File

@ -44,6 +44,7 @@ static NTSTATUS (WINAPI *pNtOpenDirectoryObject)(PHANDLE, ACCESS_MASK, POBJECT_A
static NTSTATUS (WINAPI *pNtCreateDirectoryObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
static NTSTATUS (WINAPI *pNtOpenSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
static NTSTATUS (WINAPI *pNtCreateSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PUNICODE_STRING);
static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
static void test_case_sensitive (void)
@ -617,6 +618,57 @@ static void test_symboliclink(void)
pNtClose(dir);
}
static void test_query_object(void)
{
static const WCHAR name[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
'\\','t','e','s','t','_','e','v','e','n','t'};
HANDLE handle;
char buffer[1024];
NTSTATUS status;
ULONG len;
UNICODE_STRING *str;
handle = CreateEventA( NULL, FALSE, FALSE, "test_event" );
len = 0;
status = pNtQueryObject( handle, ObjectNameInformation, buffer, 0, &len );
ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
len = 0;
status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
len = 0;
status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
str = (UNICODE_STRING *)buffer;
ok( sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR) == len, "unexpected len %u\n", len );
ok( str->Length >= sizeof(name), "unexpected len %u\n", str->Length );
/* there can be a \\Sessions prefix in the name */
ok( !memcmp( str->Buffer + (str->Length - sizeof(name)) / sizeof(WCHAR), name, sizeof(name) ),
"wrong name %s\n", wine_dbgstr_w(str->Buffer) );
len -= sizeof(WCHAR);
status = pNtQueryObject( handle, ObjectNameInformation, buffer, len, &len );
ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
pNtClose( handle );
handle = CreateEventA( NULL, FALSE, FALSE, NULL );
len = 0;
status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
ok( len == sizeof(UNICODE_STRING), "unexpected len %u\n", len );
str = (UNICODE_STRING *)buffer;
ok( str->Length == 0, "unexpected len %u\n", len );
ok( str->Buffer == NULL, "unexpected ptr %p\n", str->Buffer );
pNtClose( handle );
}
START_TEST(om)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@ -646,10 +698,12 @@ START_TEST(om)
pNtCreateSemaphore = (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
pNtCreateTimer = (void *)GetProcAddress(hntdll, "NtCreateTimer");
pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
test_case_sensitive();
test_namespace_pipe();
test_name_collisions();
test_directory();
test_symboliclink();
test_query_object();
}

View File

@ -4349,6 +4349,9 @@ struct get_object_info_reply
struct reply_header __header;
unsigned int access;
unsigned int ref_count;
data_size_t total;
/* VARARG(name,unicode_str); */
char __pad_20[4];
};
@ -5394,6 +5397,6 @@ union generic_reply
struct free_user_handle_reply free_user_handle_reply;
};
#define SERVER_PROTOCOL_VERSION 394
#define SERVER_PROTOCOL_VERSION 395
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -593,11 +593,14 @@ DECL_HANDLER(dup_handle)
DECL_HANDLER(get_object_info)
{
struct object *obj;
WCHAR *name;
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;
if ((name = get_object_full_name( obj, &reply->total )))
set_reply_data_ptr( name, min( reply->total, get_reply_max_size() ));
release_object( obj );
}

View File

@ -171,6 +171,35 @@ const WCHAR *get_object_name( struct object *obj, data_size_t *len )
return ptr->name;
}
/* get the full path name of an existing object */
WCHAR *get_object_full_name( struct object *obj, data_size_t *ret_len )
{
static const WCHAR backslash = '\\';
struct object *ptr = obj;
data_size_t len = 0;
char *ret;
while (ptr && ptr->name)
{
struct object_name *name = ptr->name;
len += name->len + sizeof(WCHAR);
ptr = name->parent;
}
if (!len) return NULL;
if (!(ret = malloc( len ))) return NULL;
*ret_len = len;
while (obj && obj->name)
{
struct object_name *name = obj->name;
memcpy( ret + len - name->len, name->name, name->len );
len -= name->len + sizeof(WCHAR);
memcpy( ret + len, &backslash, sizeof(WCHAR) );
obj = name->parent;
}
return (WCHAR *)ret;
}
/* allocate and initialize an object */
void *alloc_object( const struct object_ops *ops )
{

View File

@ -115,6 +115,7 @@ extern void *mem_alloc( size_t size ); /* malloc wrapper */
extern void *memdup( const void *data, size_t len );
extern void *alloc_object( const struct object_ops *ops );
extern const WCHAR *get_object_name( struct object *obj, data_size_t *len );
extern WCHAR *get_object_full_name( struct object *obj, data_size_t *ret_len );
extern void dump_object_name( struct object *obj );
extern void *create_object( struct namespace *namespace, const struct object_ops *ops,
const struct unicode_str *name, struct object *parent );

View File

@ -3061,6 +3061,8 @@ enum message_type
@REPLY
unsigned int access; /* granted access mask */
unsigned int ref_count; /* object ref count */
data_size_t total; /* total needed size for name */
VARARG(name,unicode_str); /* object name */
@END

View File

@ -1817,7 +1817,8 @@ C_ASSERT( sizeof(struct query_symlink_reply) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_object_info_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, access) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, ref_count) == 12 );
C_ASSERT( sizeof(struct get_object_info_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, total) == 16 );
C_ASSERT( sizeof(struct get_object_info_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct unlink_object_request, handle) == 12 );
C_ASSERT( sizeof(struct unlink_object_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_token_impersonation_level_request, handle) == 12 );

View File

@ -3600,6 +3600,8 @@ static void dump_get_object_info_reply( const struct get_object_info_reply *req
{
fprintf( stderr, " access=%08x", req->access );
fprintf( stderr, ", ref_count=%08x", req->ref_count );
fprintf( stderr, ", total=%u", req->total );
dump_varargs_unicode_str( ", name=", cur_size );
}
static void dump_unlink_object_request( const struct unlink_object_request *req )