server: Add support for object counts in the object type information.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-02-04 14:08:23 +01:00
parent c6f2aacb57
commit dc4e881834
10 changed files with 122 additions and 37 deletions

View File

@ -6596,37 +6596,37 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
case ObjectTypeInformation:
{
OBJECT_TYPE_INFORMATION *p = ptr;
char buffer[sizeof(struct object_type_info) + 64];
struct object_type_info *info = (struct object_type_info *)buffer;
SERVER_START_REQ( get_object_type )
{
req->handle = wine_server_obj_handle( handle );
if (len > sizeof(*p)) wine_server_set_reply( req, p + 1, len - sizeof(*p) );
wine_server_set_reply( req, buffer, sizeof(buffer) );
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->TypeName.Buffer = (WCHAR *)(p + 1);
p->TypeName.Length = res;
p->TypeName.MaximumLength = res + sizeof(WCHAR);
p->TypeName.Buffer[res / sizeof(WCHAR)] = 0;
if (used_len) *used_len = sizeof(*p) + p->TypeName.MaximumLength;
}
}
}
SERVER_END_REQ;
if (status) break;
if (sizeof(*p) + info->name_len + sizeof(WCHAR) <= len)
{
memset( p, 0, sizeof(*p) );
p->TypeName.Buffer = (WCHAR *)(p + 1);
p->TypeName.Length = info->name_len;
p->TypeName.MaximumLength = info->name_len + sizeof(WCHAR);
p->TotalNumberOfObjects = info->obj_count;
p->TotalNumberOfHandles = info->handle_count;
p->HighWaterNumberOfObjects = info->obj_max;
p->HighWaterNumberOfHandles = info->handle_max;
p->TypeIndex = info->index + 2;
memcpy( p->TypeName.Buffer, info + 1, info->name_len );
p->TypeName.Buffer[info->name_len / sizeof(WCHAR)] = 0;
if (used_len) *used_len = sizeof(*p) + p->TypeName.MaximumLength;
}
else
{
if (used_len) *used_len = sizeof(*p) + info->name_len + sizeof(WCHAR);
status = STATUS_INFO_LENGTH_MISMATCH;
}
break;
}

View File

@ -399,6 +399,17 @@ struct object_attributes
};
struct object_type_info
{
data_size_t name_len;
unsigned int index;
unsigned int obj_count;
unsigned int handle_count;
unsigned int obj_max;
unsigned int handle_max;
};
struct token_groups
{
unsigned int count;
@ -4740,9 +4751,7 @@ struct get_object_type_request
struct get_object_type_reply
{
struct reply_header __header;
data_size_t total;
/* VARARG(type,unicode_str); */
char __pad_12[4];
/* VARARG(info,object_type_info); */
};
@ -6234,7 +6243,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 665
#define SERVER_PROTOCOL_VERSION 666
/* ### protocol_version end ### */

View File

@ -1599,7 +1599,28 @@ typedef struct _OBJECT_NAME_INFORMATION {
typedef struct __OBJECT_TYPE_INFORMATION {
UNICODE_STRING TypeName;
ULONG Reserved [22];
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccessMask;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
UCHAR TypeIndex;
CHAR ReservedByte;
ULONG PoolType;
ULONG DefaultPagedPoolCharge;
ULONG DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
typedef struct _PROCESS_BASIC_INFORMATION {

View File

@ -553,11 +553,25 @@ DECL_HANDLER(get_object_type)
{
struct object *obj;
struct type_descr *type;
struct object_type_info *info;
if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
type = obj->ops->type;
reply->total = type->name.len;
set_reply_data( type->name.str, min( reply->total, get_reply_max_size() ) );
if (sizeof(*info) + type->name.len <= get_reply_max_size())
{
if ((info = set_reply_data_size( sizeof(*info) + type->name.len )))
{
info->name_len = type->name.len;
info->index = type->index;
info->obj_count = type->obj_count;
info->handle_count = type->handle_count;
info->obj_max = type->obj_max;
info->handle_max = type->handle_max;
memcpy( info + 1, type->name.str, type->name.len );
}
}
else set_error( STATUS_BUFFER_OVERFLOW );
release_object( obj );
}

View File

@ -101,6 +101,8 @@ static inline obj_handle_t handle_global_to_local( obj_handle_t handle )
static struct object *grab_object_for_handle( struct object *obj )
{
obj->handle_count++;
obj->ops->type->handle_count++;
obj->ops->type->handle_max = max( obj->ops->type->handle_max, obj->ops->type->handle_count );
return grab_object( obj );
}
@ -108,6 +110,7 @@ static struct object *grab_object_for_handle( struct object *obj )
static void release_object_from_handle( struct object *obj )
{
assert( obj->handle_count );
obj->ops->type->handle_count--;
obj->handle_count--;
release_object( obj );
}

View File

@ -199,6 +199,8 @@ void *alloc_object( const struct object_ops *ops )
#ifdef DEBUG_OBJECTS
list_add_head( &object_list, &obj->obj_list );
#endif
obj->ops->type->obj_count++;
obj->ops->type->obj_max = max( obj->ops->type->obj_max, obj->ops->type->obj_count );
return obj;
}
return NULL;
@ -208,6 +210,7 @@ void *alloc_object( const struct object_ops *ops )
static void free_object( struct object *obj )
{
free( obj->sd );
obj->ops->type->obj_count--;
#ifdef DEBUG_OBJECTS
list_remove( &obj->obj_list );
memset( obj, 0xaa, obj->ops->size );

View File

@ -58,6 +58,10 @@ struct type_descr
{
struct unicode_str name; /* type name */
unsigned int index; /* index in global array of types */
unsigned int obj_count; /* count of objects of this type */
unsigned int handle_count; /* count of handles of this type */
unsigned int obj_max; /* max count of objects of this type */
unsigned int handle_max; /* max count of handles of this type */
};
/* operations valid on all objects */

View File

@ -415,6 +415,17 @@ struct object_attributes
/* VARARG(name,unicode_str); */
};
struct object_type_info
{
data_size_t name_len; /* length of the name string */
unsigned int index; /* type index in global table */
unsigned int obj_count; /* count of objects of this type */
unsigned int handle_count; /* count of handles of this type */
unsigned int obj_max; /* max count of objects of this type */
unsigned int handle_max; /* max count of handles of this type */
/* VARARG(name,unicode_str); */
};
struct token_groups
{
unsigned int count;
@ -3309,8 +3320,7 @@ struct handle_info
@REQ(get_object_type)
obj_handle_t handle; /* handle to the object */
@REPLY
data_size_t total; /* needed size for type name */
VARARG(type,unicode_str); /* type name */
VARARG(info,object_type_info); /* type information */
@END

View File

@ -2055,8 +2055,7 @@ C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, total) == 20 );
C_ASSERT( sizeof(struct get_object_info_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_object_type_request, handle) == 12 );
C_ASSERT( sizeof(struct get_object_type_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_object_type_reply, total) == 8 );
C_ASSERT( sizeof(struct get_object_type_reply) == 16 );
C_ASSERT( sizeof(struct get_object_type_reply) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_token_impersonation_level_request, handle) == 12 );
C_ASSERT( sizeof(struct get_token_impersonation_level_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_token_impersonation_level_reply, impersonation_level) == 8 );

View File

@ -1214,6 +1214,29 @@ static void dump_varargs_object_attributes( const char *prefix, data_size_t size
fputc( '}', stderr );
}
static void dump_varargs_object_type_info( const char *prefix, data_size_t size )
{
const struct object_type_info *info = cur_data;
fprintf( stderr,"%s{", prefix );
if (size)
{
if (size < sizeof(*info) || (size - sizeof(*info) < info->name_len))
{
fprintf( stderr, "***invalid***}" );
remove_data( size );
return;
}
fprintf( stderr, "index=%u,obj_count=%u,handle_count=%u,obj_max=%u,handle_max=%u,name=L\"",
info->index,info->obj_count, info->handle_count, info->obj_max, info->handle_max );
dump_strW( (const WCHAR *)(info + 1), info->name_len, stderr, "\"\"" );
fputc( '\"', stderr );
remove_data( min( size, sizeof(*info) + ((info->name_len + 2) & ~3 )));
}
fputc( '}', stderr );
}
static void dump_varargs_filesystem_event( const char *prefix, data_size_t size )
{
static const char * const actions[] = {
@ -4021,8 +4044,7 @@ static void dump_get_object_type_request( const struct get_object_type_request *
static void dump_get_object_type_reply( const struct get_object_type_reply *req )
{
fprintf( stderr, " total=%u", req->total );
dump_varargs_unicode_str( ", type=", cur_size );
dump_varargs_object_type_info( " info=", cur_size );
}
static void dump_get_token_impersonation_level_request( const struct get_token_impersonation_level_request *req )