server: Add a request to return all object types.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d6ef9401b3
commit
b6f774df69
|
@ -6491,6 +6491,30 @@ NTSTATUS WINAPI NtSetEaFile( HANDLE handle, IO_STATUS_BLOCK *io, void *buffer, U
|
|||
}
|
||||
|
||||
|
||||
/* convert type information from server format; helper for NtQueryObject */
|
||||
static void *put_object_type_info( OBJECT_TYPE_INFORMATION *p, struct object_type_info *info )
|
||||
{
|
||||
const ULONG align = sizeof(DWORD_PTR) - 1;
|
||||
|
||||
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;
|
||||
p->GenericMapping.GenericRead = info->mapping.read;
|
||||
p->GenericMapping.GenericWrite = info->mapping.write;
|
||||
p->GenericMapping.GenericExecute = info->mapping.exec;
|
||||
p->GenericMapping.GenericAll = info->mapping.all;
|
||||
p->ValidAccessMask = info->valid_access;
|
||||
memcpy( p->TypeName.Buffer, info + 1, info->name_len );
|
||||
p->TypeName.Buffer[info->name_len / sizeof(WCHAR)] = 0;
|
||||
return (char *)(p + 1) + ((p->TypeName.MaximumLength + align) & ~align);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* NtQueryObject (NTDLL.@)
|
||||
*/
|
||||
|
@ -6609,22 +6633,7 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
|
|||
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;
|
||||
p->GenericMapping.GenericRead = info->mapping.read;
|
||||
p->GenericMapping.GenericWrite = info->mapping.write;
|
||||
p->GenericMapping.GenericExecute = info->mapping.exec;
|
||||
p->GenericMapping.GenericAll = info->mapping.all;
|
||||
p->ValidAccessMask = info->valid_access;
|
||||
memcpy( p->TypeName.Buffer, info + 1, info->name_len );
|
||||
p->TypeName.Buffer[info->name_len / sizeof(WCHAR)] = 0;
|
||||
put_object_type_info( p, info );
|
||||
if (used_len) *used_len = sizeof(*p) + p->TypeName.MaximumLength;
|
||||
}
|
||||
else
|
||||
|
@ -6635,6 +6644,44 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
|
|||
break;
|
||||
}
|
||||
|
||||
case ObjectTypesInformation:
|
||||
{
|
||||
OBJECT_TYPES_INFORMATION *types = ptr;
|
||||
OBJECT_TYPE_INFORMATION *p;
|
||||
struct object_type_info *buffer;
|
||||
/* assume at most 32 types, with an average 16-char name */
|
||||
ULONG size = 32 * (sizeof(struct object_type_info) + 16 * sizeof(WCHAR));
|
||||
ULONG i, count, pos, total, align = sizeof(DWORD_PTR) - 1;
|
||||
|
||||
buffer = malloc( size );
|
||||
SERVER_START_REQ( get_object_types )
|
||||
{
|
||||
wine_server_set_reply( req, buffer, size );
|
||||
status = wine_server_call( req );
|
||||
count = reply->count;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!status)
|
||||
{
|
||||
if (len >= sizeof(*types)) types->NumberOfTypes = count;
|
||||
total = (sizeof(*types) + align) & ~align;
|
||||
p = (OBJECT_TYPE_INFORMATION *)((char *)ptr + total);
|
||||
for (i = pos = 0; i < count; i++)
|
||||
{
|
||||
struct object_type_info *info = (struct object_type_info *)((char *)buffer + pos);
|
||||
pos += sizeof(*info) + ((info->name_len + 3) & ~3);
|
||||
total += sizeof(*p) + ((info->name_len + sizeof(WCHAR) + align) & ~align);
|
||||
if (total <= len) p = put_object_type_info( p, info );
|
||||
}
|
||||
if (used_len) *used_len = total;
|
||||
if (total > len) status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
else if (status == STATUS_BUFFER_OVERFLOW) FIXME( "size %u too small\n", size );
|
||||
|
||||
free( buffer );
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjectDataInformation:
|
||||
{
|
||||
OBJECT_DATA_INFORMATION* p = ptr;
|
||||
|
|
|
@ -4758,6 +4758,21 @@ struct get_object_type_reply
|
|||
|
||||
|
||||
|
||||
struct get_object_types_request
|
||||
{
|
||||
struct request_header __header;
|
||||
char __pad_12[4];
|
||||
};
|
||||
struct get_object_types_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
int count;
|
||||
/* VARARG(info,object_types_info); */
|
||||
char __pad_12[4];
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct get_token_impersonation_level_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -5635,6 +5650,7 @@ enum request
|
|||
REQ_query_symlink,
|
||||
REQ_get_object_info,
|
||||
REQ_get_object_type,
|
||||
REQ_get_object_types,
|
||||
REQ_get_token_impersonation_level,
|
||||
REQ_allocate_locally_unique_id,
|
||||
REQ_create_device_manager,
|
||||
|
@ -5918,6 +5934,7 @@ union generic_request
|
|||
struct query_symlink_request query_symlink_request;
|
||||
struct get_object_info_request get_object_info_request;
|
||||
struct get_object_type_request get_object_type_request;
|
||||
struct get_object_types_request get_object_types_request;
|
||||
struct get_token_impersonation_level_request get_token_impersonation_level_request;
|
||||
struct allocate_locally_unique_id_request allocate_locally_unique_id_request;
|
||||
struct create_device_manager_request create_device_manager_request;
|
||||
|
@ -6199,6 +6216,7 @@ union generic_reply
|
|||
struct query_symlink_reply query_symlink_reply;
|
||||
struct get_object_info_reply get_object_info_reply;
|
||||
struct get_object_type_reply get_object_type_reply;
|
||||
struct get_object_types_reply get_object_types_reply;
|
||||
struct get_token_impersonation_level_reply get_token_impersonation_level_reply;
|
||||
struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply;
|
||||
struct create_device_manager_reply create_device_manager_reply;
|
||||
|
@ -6245,7 +6263,7 @@ union generic_reply
|
|||
|
||||
/* ### protocol_version begin ### */
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 667
|
||||
#define SERVER_PROTOCOL_VERSION 668
|
||||
|
||||
/* ### protocol_version end ### */
|
||||
|
||||
|
|
|
@ -1160,7 +1160,7 @@ typedef enum _OBJECT_INFORMATION_CLASS {
|
|||
ObjectBasicInformation,
|
||||
ObjectNameInformation,
|
||||
ObjectTypeInformation,
|
||||
ObjectAllInformation,
|
||||
ObjectTypesInformation,
|
||||
ObjectDataInformation
|
||||
} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
|
||||
|
||||
|
@ -1623,6 +1623,11 @@ typedef struct __OBJECT_TYPE_INFORMATION {
|
|||
ULONG DefaultNonPagedPoolCharge;
|
||||
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
|
||||
|
||||
typedef struct _OBJECT_TYPES_INFORMATION
|
||||
{
|
||||
ULONG NumberOfTypes;
|
||||
} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION;
|
||||
|
||||
typedef struct _PROCESS_BASIC_INFORMATION {
|
||||
#ifdef __WINESRC__
|
||||
DWORD_PTR ExitStatus;
|
||||
|
|
|
@ -591,3 +591,42 @@ DECL_HANDLER(get_object_type)
|
|||
|
||||
release_object( obj );
|
||||
}
|
||||
|
||||
/* query type information for all types */
|
||||
DECL_HANDLER(get_object_types)
|
||||
{
|
||||
struct object_type_info *info;
|
||||
data_size_t size = ARRAY_SIZE(types) * sizeof(*info);
|
||||
unsigned int i;
|
||||
char *next;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(types); i++) size += (types[i]->name.len + 3) & ~3;
|
||||
|
||||
if (size <= get_reply_max_size())
|
||||
{
|
||||
if ((info = set_reply_data_size( size )))
|
||||
{
|
||||
for (i = 0; i < ARRAY_SIZE(types); i++)
|
||||
{
|
||||
info->name_len = types[i]->name.len;
|
||||
info->index = types[i]->index;
|
||||
info->obj_count = types[i]->obj_count;
|
||||
info->handle_count = types[i]->handle_count;
|
||||
info->obj_max = types[i]->obj_max;
|
||||
info->handle_max = types[i]->handle_max;
|
||||
info->valid_access = types[i]->valid_access;
|
||||
info->mapping = types[i]->mapping;
|
||||
memcpy( info + 1, types[i]->name.str, types[i]->name.len );
|
||||
next = (char *)(info + 1) + types[i]->name.len;
|
||||
if (types[i]->name.len & 3)
|
||||
{
|
||||
memset( next, 0, 4 - (types[i]->name.len & 3) );
|
||||
next += 4 - (types[i]->name.len & 3);
|
||||
}
|
||||
info = (struct object_type_info *)next;
|
||||
}
|
||||
reply->count = i;
|
||||
}
|
||||
}
|
||||
else set_error( STATUS_BUFFER_OVERFLOW );
|
||||
}
|
||||
|
|
|
@ -3326,6 +3326,14 @@ struct handle_info
|
|||
@END
|
||||
|
||||
|
||||
/* Query type information for all types */
|
||||
@REQ(get_object_types)
|
||||
@REPLY
|
||||
int count; /* total count of object types */
|
||||
VARARG(info,object_types_info); /* type information */
|
||||
@END
|
||||
|
||||
|
||||
/* Query the impersonation level of an impersonation token */
|
||||
@REQ(get_token_impersonation_level)
|
||||
obj_handle_t handle; /* handle to the object */
|
||||
|
|
|
@ -353,6 +353,7 @@ DECL_HANDLER(open_symlink);
|
|||
DECL_HANDLER(query_symlink);
|
||||
DECL_HANDLER(get_object_info);
|
||||
DECL_HANDLER(get_object_type);
|
||||
DECL_HANDLER(get_object_types);
|
||||
DECL_HANDLER(get_token_impersonation_level);
|
||||
DECL_HANDLER(allocate_locally_unique_id);
|
||||
DECL_HANDLER(create_device_manager);
|
||||
|
@ -635,6 +636,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_query_symlink,
|
||||
(req_handler)req_get_object_info,
|
||||
(req_handler)req_get_object_type,
|
||||
(req_handler)req_get_object_types,
|
||||
(req_handler)req_get_token_impersonation_level,
|
||||
(req_handler)req_allocate_locally_unique_id,
|
||||
(req_handler)req_create_device_manager,
|
||||
|
@ -2056,6 +2058,9 @@ 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( sizeof(struct get_object_type_reply) == 8 );
|
||||
C_ASSERT( sizeof(struct get_object_types_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_object_types_reply, count) == 8 );
|
||||
C_ASSERT( sizeof(struct get_object_types_reply) == 16 );
|
||||
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 );
|
||||
|
|
|
@ -1240,6 +1240,13 @@ static void dump_varargs_object_type_info( const char *prefix, data_size_t size
|
|||
fputc( '}', stderr );
|
||||
}
|
||||
|
||||
static void dump_varargs_object_types_info( const char *prefix, data_size_t size )
|
||||
{
|
||||
fprintf( stderr,"%s{", prefix );
|
||||
while (cur_size) dump_varargs_object_type_info( ",", cur_size );
|
||||
fputc( '}', stderr );
|
||||
}
|
||||
|
||||
static void dump_varargs_filesystem_event( const char *prefix, data_size_t size )
|
||||
{
|
||||
static const char * const actions[] = {
|
||||
|
@ -4050,6 +4057,16 @@ static void dump_get_object_type_reply( const struct get_object_type_reply *req
|
|||
dump_varargs_object_type_info( " info=", cur_size );
|
||||
}
|
||||
|
||||
static void dump_get_object_types_request( const struct get_object_types_request *req )
|
||||
{
|
||||
}
|
||||
|
||||
static void dump_get_object_types_reply( const struct get_object_types_reply *req )
|
||||
{
|
||||
fprintf( stderr, " count=%d", req->count );
|
||||
dump_varargs_object_types_info( ", info=", cur_size );
|
||||
}
|
||||
|
||||
static void dump_get_token_impersonation_level_request( const struct get_token_impersonation_level_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
|
@ -4677,6 +4694,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_query_symlink_request,
|
||||
(dump_func)dump_get_object_info_request,
|
||||
(dump_func)dump_get_object_type_request,
|
||||
(dump_func)dump_get_object_types_request,
|
||||
(dump_func)dump_get_token_impersonation_level_request,
|
||||
(dump_func)dump_allocate_locally_unique_id_request,
|
||||
(dump_func)dump_create_device_manager_request,
|
||||
|
@ -4956,6 +4974,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_query_symlink_reply,
|
||||
(dump_func)dump_get_object_info_reply,
|
||||
(dump_func)dump_get_object_type_reply,
|
||||
(dump_func)dump_get_object_types_reply,
|
||||
(dump_func)dump_get_token_impersonation_level_reply,
|
||||
(dump_func)dump_allocate_locally_unique_id_reply,
|
||||
(dump_func)dump_create_device_manager_reply,
|
||||
|
@ -5235,6 +5254,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"query_symlink",
|
||||
"get_object_info",
|
||||
"get_object_type",
|
||||
"get_object_types",
|
||||
"get_token_impersonation_level",
|
||||
"allocate_locally_unique_id",
|
||||
"create_device_manager",
|
||||
|
|
Loading…
Reference in New Issue