Commit dc4e8818 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent c6f2aacb
...@@ -6596,37 +6596,37 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas ...@@ -6596,37 +6596,37 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
case ObjectTypeInformation: case ObjectTypeInformation:
{ {
OBJECT_TYPE_INFORMATION *p = ptr; 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 ) SERVER_START_REQ( get_object_type )
{ {
req->handle = wine_server_obj_handle( handle ); 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 ); 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; 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; break;
} }
......
...@@ -399,6 +399,17 @@ struct object_attributes ...@@ -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 struct token_groups
{ {
unsigned int count; unsigned int count;
...@@ -4740,9 +4751,7 @@ struct get_object_type_request ...@@ -4740,9 +4751,7 @@ struct get_object_type_request
struct get_object_type_reply struct get_object_type_reply
{ {
struct reply_header __header; struct reply_header __header;
data_size_t total; /* VARARG(info,object_type_info); */
/* VARARG(type,unicode_str); */
char __pad_12[4];
}; };
...@@ -6234,7 +6243,7 @@ union generic_reply ...@@ -6234,7 +6243,7 @@ union generic_reply
/* ### protocol_version begin ### */ /* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 665 #define SERVER_PROTOCOL_VERSION 666
/* ### protocol_version end ### */ /* ### protocol_version end ### */
......
...@@ -1599,7 +1599,28 @@ typedef struct _OBJECT_NAME_INFORMATION { ...@@ -1599,7 +1599,28 @@ typedef struct _OBJECT_NAME_INFORMATION {
typedef struct __OBJECT_TYPE_INFORMATION { typedef struct __OBJECT_TYPE_INFORMATION {
UNICODE_STRING TypeName; 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; } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
typedef struct _PROCESS_BASIC_INFORMATION { typedef struct _PROCESS_BASIC_INFORMATION {
......
...@@ -553,11 +553,25 @@ DECL_HANDLER(get_object_type) ...@@ -553,11 +553,25 @@ DECL_HANDLER(get_object_type)
{ {
struct object *obj; struct object *obj;
struct type_descr *type; struct type_descr *type;
struct object_type_info *info;
if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return; if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
type = obj->ops->type; type = obj->ops->type;
reply->total = type->name.len; if (sizeof(*info) + type->name.len <= get_reply_max_size())
set_reply_data( type->name.str, min( reply->total, 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 ); release_object( obj );
} }
...@@ -101,6 +101,8 @@ static inline obj_handle_t handle_global_to_local( obj_handle_t handle ) ...@@ -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 ) static struct object *grab_object_for_handle( struct object *obj )
{ {
obj->handle_count++; 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 ); return grab_object( obj );
} }
...@@ -108,6 +110,7 @@ static struct object *grab_object_for_handle( struct 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 ) static void release_object_from_handle( struct object *obj )
{ {
assert( obj->handle_count ); assert( obj->handle_count );
obj->ops->type->handle_count--;
obj->handle_count--; obj->handle_count--;
release_object( obj ); release_object( obj );
} }
......
...@@ -199,6 +199,8 @@ void *alloc_object( const struct object_ops *ops ) ...@@ -199,6 +199,8 @@ void *alloc_object( const struct object_ops *ops )
#ifdef DEBUG_OBJECTS #ifdef DEBUG_OBJECTS
list_add_head( &object_list, &obj->obj_list ); list_add_head( &object_list, &obj->obj_list );
#endif #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 obj;
} }
return NULL; return NULL;
...@@ -208,6 +210,7 @@ void *alloc_object( const struct object_ops *ops ) ...@@ -208,6 +210,7 @@ void *alloc_object( const struct object_ops *ops )
static void free_object( struct object *obj ) static void free_object( struct object *obj )
{ {
free( obj->sd ); free( obj->sd );
obj->ops->type->obj_count--;
#ifdef DEBUG_OBJECTS #ifdef DEBUG_OBJECTS
list_remove( &obj->obj_list ); list_remove( &obj->obj_list );
memset( obj, 0xaa, obj->ops->size ); memset( obj, 0xaa, obj->ops->size );
......
...@@ -58,6 +58,10 @@ struct type_descr ...@@ -58,6 +58,10 @@ struct type_descr
{ {
struct unicode_str name; /* type name */ struct unicode_str name; /* type name */
unsigned int index; /* index in global array of types */ 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 */ /* operations valid on all objects */
......
...@@ -415,6 +415,17 @@ struct object_attributes ...@@ -415,6 +415,17 @@ struct object_attributes
/* VARARG(name,unicode_str); */ /* 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 struct token_groups
{ {
unsigned int count; unsigned int count;
...@@ -3309,8 +3320,7 @@ struct handle_info ...@@ -3309,8 +3320,7 @@ struct handle_info
@REQ(get_object_type) @REQ(get_object_type)
obj_handle_t handle; /* handle to the object */ obj_handle_t handle; /* handle to the object */
@REPLY @REPLY
data_size_t total; /* needed size for type name */ VARARG(info,object_type_info); /* type information */
VARARG(type,unicode_str); /* type name */
@END @END
......
...@@ -2055,8 +2055,7 @@ C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, total) == 20 ); ...@@ -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( sizeof(struct get_object_info_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_object_type_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_object_type_request, handle) == 12 );
C_ASSERT( sizeof(struct get_object_type_request) == 16 ); 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) == 8 );
C_ASSERT( sizeof(struct get_object_type_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_token_impersonation_level_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_token_impersonation_level_request, handle) == 12 );
C_ASSERT( sizeof(struct get_token_impersonation_level_request) == 16 ); C_ASSERT( sizeof(struct get_token_impersonation_level_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_token_impersonation_level_reply, impersonation_level) == 8 ); C_ASSERT( FIELD_OFFSET(struct get_token_impersonation_level_reply, impersonation_level) == 8 );
......
...@@ -1214,6 +1214,29 @@ static void dump_varargs_object_attributes( const char *prefix, data_size_t size ...@@ -1214,6 +1214,29 @@ static void dump_varargs_object_attributes( const char *prefix, data_size_t size
fputc( '}', stderr ); 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 void dump_varargs_filesystem_event( const char *prefix, data_size_t size )
{ {
static const char * const actions[] = { static const char * const actions[] = {
...@@ -4021,8 +4044,7 @@ static void dump_get_object_type_request( const struct get_object_type_request * ...@@ -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 ) static void dump_get_object_type_reply( const struct get_object_type_reply *req )
{ {
fprintf( stderr, " total=%u", req->total ); dump_varargs_object_type_info( " info=", cur_size );
dump_varargs_unicode_str( ", type=", cur_size );
} }
static void dump_get_token_impersonation_level_request( const struct get_token_impersonation_level_request *req ) static void dump_get_token_impersonation_level_request( const struct get_token_impersonation_level_request *req )
......
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