From ac5102602ffa37baba312b27031dc0c98ed7eea8 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 26 Jul 2021 12:35:33 +0200 Subject: [PATCH] wow64: Add thunks for the generic object syscalls. Signed-off-by: Alexandre Julliard --- dlls/wow64/struct32.h | 32 +++++++ dlls/wow64/sync.c | 197 ++++++++++++++++++++++++++++++++++++++++++ dlls/wow64/syscall.h | 4 + 3 files changed, 233 insertions(+) diff --git a/dlls/wow64/struct32.h b/dlls/wow64/struct32.h index 03a57fc2c27..b96fdae80ca 100644 --- a/dlls/wow64/struct32.h +++ b/dlls/wow64/struct32.h @@ -31,6 +31,38 @@ typedef struct ULONG SecurityQualityOfService; } OBJECT_ATTRIBUTES32; +typedef struct +{ + UNICODE_STRING32 Name; +} OBJECT_NAME_INFORMATION32; + +typedef struct +{ + UNICODE_STRING32 TypeName; + 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_INFORMATION32; + typedef struct { UNICODE_STRING32 ObjectName; diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index 0332f85e3ff..f386a7cdab3 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -32,6 +32,41 @@ WINE_DEFAULT_DEBUG_CHANNEL(wow); +static void put_object_type_info( OBJECT_TYPE_INFORMATION32 *info32, const OBJECT_TYPE_INFORMATION *info ) +{ + if (info->TypeName.Length) + { + memcpy( info32 + 1, info->TypeName.Buffer, info->TypeName.Length + sizeof(WCHAR) ); + info32->TypeName.Length = info->TypeName.Length; + info32->TypeName.MaximumLength = info->TypeName.Length + sizeof(WCHAR); + info32->TypeName.Buffer = PtrToUlong( info32 + 1 ); + } + else memset( &info32->TypeName, 0, sizeof(info32->TypeName) ); + info32->TotalNumberOfObjects = info->TotalNumberOfObjects; + info32->TotalNumberOfHandles = info->TotalNumberOfHandles; + info32->TotalPagedPoolUsage = info->TotalPagedPoolUsage; + info32->TotalNonPagedPoolUsage = info->TotalNonPagedPoolUsage; + info32->TotalNamePoolUsage = info->TotalNamePoolUsage; + info32->TotalHandleTableUsage = info->TotalHandleTableUsage; + info32->HighWaterNumberOfObjects = info->HighWaterNumberOfObjects; + info32->HighWaterNumberOfHandles = info->HighWaterNumberOfHandles; + info32->HighWaterPagedPoolUsage = info->HighWaterPagedPoolUsage; + info32->HighWaterNonPagedPoolUsage = info->HighWaterNonPagedPoolUsage; + info32->HighWaterNamePoolUsage = info->HighWaterNamePoolUsage; + info32->HighWaterHandleTableUsage = info->HighWaterHandleTableUsage; + info32->InvalidAttributes = info->InvalidAttributes; + info32->GenericMapping = info->GenericMapping; + info32->ValidAccessMask = info->ValidAccessMask; + info32->SecurityRequired = info->SecurityRequired; + info32->MaintainHandleCount = info->MaintainHandleCount; + info32->TypeIndex = info->TypeIndex; + info32->ReservedByte = info->ReservedByte; + info32->PoolType = info->PoolType; + info32->DefaultPagedPoolCharge = info->DefaultPagedPoolCharge; + info32->DefaultNonPagedPoolCharge = info->DefaultNonPagedPoolCharge; +} + + void put_section_image_info( SECTION_IMAGE_INFORMATION32 *info32, const SECTION_IMAGE_INFORMATION *info ) { if (info->Machine == IMAGE_FILE_MACHINE_AMD64 || info->Machine == IMAGE_FILE_MACHINE_ARM64) @@ -349,6 +384,41 @@ NTSTATUS WINAPI wow64_NtDelayExecution( UINT *args ) } +/********************************************************************** + * wow64_NtDuplicateObject + */ +NTSTATUS WINAPI wow64_NtDuplicateObject( UINT *args ) +{ + HANDLE source_process = get_handle( &args ); + HANDLE source_handle = get_handle( &args ); + HANDLE dest_process = get_handle( &args ); + ULONG *handle_ptr = get_ptr( &args ); + ACCESS_MASK access = get_ulong( &args ); + ULONG attributes = get_ulong( &args ); + ULONG options = get_ulong( &args ); + + HANDLE handle = 0; + NTSTATUS status; + + if (handle_ptr) *handle_ptr = 0; + status = NtDuplicateObject( source_process, source_handle, dest_process, &handle, + access, attributes, options ); + if (handle_ptr) put_handle( handle_ptr, handle ); + return status; +} + + +/********************************************************************** + * wow64_NtMakeTemporaryObject + */ +NTSTATUS WINAPI wow64_NtMakeTemporaryObject( UINT *args ) +{ + HANDLE handle = get_handle( &args ); + + return NtMakeTemporaryObject( handle ); +} + + /********************************************************************** * wow64_NtOpenDirectoryObject */ @@ -643,6 +713,111 @@ NTSTATUS WINAPI wow64_NtQueryMutant( UINT *args ) } +/********************************************************************** + * wow64_NtQueryObject + */ +NTSTATUS WINAPI wow64_NtQueryObject( UINT *args ) +{ + HANDLE handle = get_handle( &args ); + OBJECT_INFORMATION_CLASS class = get_ulong( &args ); + void *ptr = get_ptr( &args ); + ULONG len = get_ulong( &args ); + ULONG *retlen = get_ptr( &args ); + + NTSTATUS status; + ULONG ret_size; + + switch (class) + { + case ObjectBasicInformation: /* OBJECT_BASIC_INFORMATION */ + case ObjectDataInformation: /* OBJECT_DATA_INFORMATION */ + return NtQueryObject( handle, class, ptr, len, retlen ); + + case ObjectNameInformation: /* OBJECT_NAME_INFORMATION */ + { + ULONG size = len + sizeof(OBJECT_NAME_INFORMATION) - sizeof(OBJECT_NAME_INFORMATION32); + OBJECT_NAME_INFORMATION32 *info32 = ptr; + OBJECT_NAME_INFORMATION *info = RtlAllocateHeap( GetProcessHeap(), 0, size ); + + if (!(status = NtQueryObject( handle, class, info, size, &ret_size ))) + { + if (len >= sizeof(*info32) + info->Name.MaximumLength) + { + if (info->Name.Length) + { + memcpy( info32 + 1, info->Name.Buffer, info->Name.Length + sizeof(WCHAR) ); + info32->Name.Length = info->Name.Length; + info32->Name.MaximumLength = info->Name.Length + sizeof(WCHAR); + info32->Name.Buffer = PtrToUlong( info32 + 1 ); + } + else memset( &info32->Name, 0, sizeof(info32->Name) ); + } + else status = STATUS_INFO_LENGTH_MISMATCH; + if (retlen) *retlen = sizeof(*info32) + info->Name.MaximumLength; + } + else if (status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_BUFFER_OVERFLOW) + { + if (retlen) *retlen = ret_size - sizeof(*info) + sizeof(*info32); + } + RtlFreeHeap( GetProcessHeap(), 0, info ); + return status; + } + + case ObjectTypeInformation: /* OBJECT_TYPE_INFORMATION */ + { + ULONG_PTR buffer[(sizeof(OBJECT_TYPE_INFORMATION) + 64) / sizeof(ULONG_PTR)]; + OBJECT_TYPE_INFORMATION *info = (OBJECT_TYPE_INFORMATION *)buffer; + OBJECT_TYPE_INFORMATION32 *info32 = ptr; + + if (!(status = NtQueryObject( handle, class, info, sizeof(buffer), NULL ))) + { + if (len >= sizeof(*info32) + info->TypeName.MaximumLength) + put_object_type_info( info32, info ); + else + status = STATUS_INFO_LENGTH_MISMATCH; + if (retlen) *retlen = sizeof(*info32) + info->TypeName.Length + sizeof(WCHAR); + } + return status; + } + + case ObjectTypesInformation: /* OBJECT_TYPES_INFORMATION */ + { + OBJECT_TYPES_INFORMATION *info, *info32 = ptr; + /* assume at most 32 types, with an average 16-char name */ + ULONG ret_size, size = 32 * (sizeof(OBJECT_TYPE_INFORMATION) + 16 * sizeof(WCHAR)); + + info = RtlAllocateHeap( GetProcessHeap(), 0, size ); + if (!(status = NtQueryObject( handle, class, info, size, &ret_size ))) + { + OBJECT_TYPE_INFORMATION *type; + OBJECT_TYPE_INFORMATION32 *type32; + ULONG align = TYPE_ALIGNMENT( OBJECT_TYPE_INFORMATION ) - 1; + ULONG align32 = TYPE_ALIGNMENT( OBJECT_TYPE_INFORMATION32 ) - 1; + ULONG i, pos = (sizeof(*info) + align) & ~align, pos32 = (sizeof(*info32) + align32) & ~align32; + + if (pos32 <= len) info32->NumberOfTypes = info->NumberOfTypes; + for (i = 0; i < info->NumberOfTypes; i++) + { + type = (OBJECT_TYPE_INFORMATION *)((char *)info + pos); + type32 = (OBJECT_TYPE_INFORMATION32 *)((char *)ptr + pos32); + pos += sizeof(*type) + ((type->TypeName.MaximumLength + align) & ~align); + pos32 += sizeof(*type32) + ((type->TypeName.MaximumLength + align32) & ~align32); + if (pos32 <= len) put_object_type_info( type32, type ); + } + if (pos32 > len) status = STATUS_INFO_LENGTH_MISMATCH; + if (retlen) *retlen = pos32; + } + RtlFreeHeap( GetProcessHeap(), 0, info ); + return status; + } + + default: + FIXME( "unsupported class %u\n", class ); + return STATUS_NOT_IMPLEMENTED; + } +} + + /********************************************************************** * wow64_NtQueryPerformanceCounter */ @@ -847,6 +1022,28 @@ NTSTATUS WINAPI wow64_NtSetInformationDebugObject( UINT *args ) } +/********************************************************************** + * wow64_NtSetInformationObject + */ +NTSTATUS WINAPI wow64_NtSetInformationObject( UINT *args ) +{ + HANDLE handle = get_handle( &args ); + OBJECT_INFORMATION_CLASS class = get_ulong( &args ); + void *ptr = get_ptr( &args ); + ULONG len = get_ulong( &args ); + + switch (class) + { + case ObjectDataInformation: /* OBJECT_DATA_INFORMATION */ + return NtSetInformationObject( handle, class, ptr, len ); + + default: + FIXME( "unsupported class %u\n", class ); + return STATUS_NOT_IMPLEMENTED; + } +} + + /********************************************************************** * wow64_NtSetIoCompletion */ diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h index 3d57b6c3a15..26948446fd1 100644 --- a/dlls/wow64/syscall.h +++ b/dlls/wow64/syscall.h @@ -42,8 +42,10 @@ SYSCALL_ENTRY( NtDebugContinue ) \ SYSCALL_ENTRY( NtDelayExecution ) \ SYSCALL_ENTRY( NtDeleteAtom ) \ + SYSCALL_ENTRY( NtDuplicateObject ) \ SYSCALL_ENTRY( NtFindAtom ) \ SYSCALL_ENTRY( NtGetCurrentProcessorNumber ) \ + SYSCALL_ENTRY( NtMakeTemporaryObject ) \ SYSCALL_ENTRY( NtOpenDirectoryObject ) \ SYSCALL_ENTRY( NtOpenEvent ) \ SYSCALL_ENTRY( NtOpenIoCompletion ) \ @@ -63,6 +65,7 @@ SYSCALL_ENTRY( NtQueryInstallUILanguage ) \ SYSCALL_ENTRY( NtQueryIoCompletion ) \ SYSCALL_ENTRY( NtQueryMutant ) \ + SYSCALL_ENTRY( NtQueryObject ) \ SYSCALL_ENTRY( NtQueryPerformanceCounter ) \ SYSCALL_ENTRY( NtQuerySection ) \ SYSCALL_ENTRY( NtQuerySemaphore ) \ @@ -77,6 +80,7 @@ SYSCALL_ENTRY( NtSetDefaultUILanguage ) \ SYSCALL_ENTRY( NtSetEvent ) \ SYSCALL_ENTRY( NtSetInformationDebugObject ) \ + SYSCALL_ENTRY( NtSetInformationObject ) \ SYSCALL_ENTRY( NtSetIoCompletion ) \ SYSCALL_ENTRY( NtSetTimer ) \ SYSCALL_ENTRY( NtSetTimerResolution ) \