server: Add support for returning the object name in NtQueryObject.
This commit is contained in:
parent
2e03013fc0
commit
658dae988d
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue