diff --git a/dlls/wow64/struct32.h b/dlls/wow64/struct32.h index a885884fc0a..419575c2ede 100644 --- a/dlls/wow64/struct32.h +++ b/dlls/wow64/struct32.h @@ -265,6 +265,35 @@ typedef struct PS_ATTRIBUTE32 Attributes[1]; } PS_ATTRIBUTE_LIST32; +typedef struct +{ + ULONG Section; + ULONG MappedBaseAddress; + ULONG ImageBaseAddress; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT NameOffset; + BYTE Name[MAXIMUM_FILENAME_LENGTH]; +} RTL_PROCESS_MODULE_INFORMATION32; + +typedef struct +{ + ULONG ModulesCount; + RTL_PROCESS_MODULE_INFORMATION32 Modules[1]; +} RTL_PROCESS_MODULES32; + +typedef struct +{ + USHORT NextOffset; + RTL_PROCESS_MODULE_INFORMATION32 BaseInfo; + ULONG ImageCheckSum; + ULONG TimeDateStamp; + ULONG DefaultBase; +} RTL_PROCESS_MODULE_INFORMATION_EX32; + typedef struct { ULONG BaseAddress; @@ -423,4 +452,185 @@ typedef struct } StateInfo; } DBGUI_WAIT_STATE_CHANGE32; +typedef struct +{ + ULONG unknown; + ULONG KeMaximumIncrement; + ULONG PageSize; + ULONG MmNumberOfPhysicalPages; + ULONG MmLowestPhysicalPage; + ULONG MmHighestPhysicalPage; + ULONG AllocationGranularity; + ULONG LowestUserAddress; + ULONG HighestUserAddress; + ULONG ActiveProcessorsAffinityMask; + BYTE NumberOfProcessors; +} SYSTEM_BASIC_INFORMATION32; + +typedef struct +{ + ULONG CurrentSize; + ULONG PeakSize; + ULONG PageFaultCount; + ULONG MinimumWorkingSet; + ULONG MaximumWorkingSet; + ULONG CurrentSizeIncludingTransitionInPages; + ULONG PeakSizeIncludingTransitionInPages; + ULONG TransitionRePurposeCount; + ULONG Flags; +} SYSTEM_CACHE_INFORMATION32; + +typedef struct +{ + ULONG OwnerPid; + BYTE ObjectType; + BYTE HandleFlags; + USHORT HandleValue; + ULONG ObjectPointer; + ULONG AccessMask; +} SYSTEM_HANDLE_ENTRY32; + +typedef struct +{ + ULONG Count; + SYSTEM_HANDLE_ENTRY32 Handle[1]; +} SYSTEM_HANDLE_INFORMATION32; + +typedef struct +{ + ULONG RegistryQuotaAllowed; + ULONG RegistryQuotaUsed; + ULONG Reserved1; +} SYSTEM_REGISTRY_QUOTA_INFORMATION32; + +typedef struct +{ + ULONG Object; + ULONG UniqueProcessId; + ULONG HandleValue; + ULONG GrantedAccess; + USHORT CreatorBackTraceIndex; + USHORT ObjectTypeIndex; + ULONG HandleAttributes; + ULONG Reserved; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX32; + +typedef struct +{ + ULONG NumberOfHandles; + ULONG Reserved; + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX32 Handles[1]; +} SYSTEM_HANDLE_INFORMATION_EX32; + +typedef struct +{ + ULONG ProcessorMask; + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + union + { + struct + { + BYTE Flags; + } ProcessorCore; + struct + { + DWORD NodeNumber; + } NumaNode; + CACHE_DESCRIPTOR Cache; + ULONGLONG Reserved[2]; + }; +} SYSTEM_LOGICAL_PROCESSOR_INFORMATION32; + +typedef struct +{ + BYTE Flags; + BYTE EfficiencyClass; + BYTE Reserved[20]; + WORD GroupCount; + GROUP_AFFINITY32 GroupMask[ANYSIZE_ARRAY]; +} PROCESSOR_RELATIONSHIP32; + +typedef struct +{ + DWORD NodeNumber; + BYTE Reserved[20]; + GROUP_AFFINITY32 GroupMask; +} NUMA_NODE_RELATIONSHIP32; + +typedef struct +{ + BYTE Level; + BYTE Associativity; + WORD LineSize; + DWORD CacheSize; + PROCESSOR_CACHE_TYPE Type; + BYTE Reserved[20]; + GROUP_AFFINITY32 GroupMask; +} CACHE_RELATIONSHIP32; + +typedef struct +{ + BYTE MaximumProcessorCount; + BYTE ActiveProcessorCount; + BYTE Reserved[38]; + ULONG ActiveProcessorMask; +} PROCESSOR_GROUP_INFO32; + +typedef struct +{ + WORD MaximumGroupCount; + WORD ActiveGroupCount; + BYTE Reserved[20]; + PROCESSOR_GROUP_INFO32 GroupInfo[ANYSIZE_ARRAY]; +} GROUP_RELATIONSHIP32; + +typedef struct +{ + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + DWORD Size; + union + { + PROCESSOR_RELATIONSHIP32 Processor; + NUMA_NODE_RELATIONSHIP32 NumaNode; + CACHE_RELATIONSHIP32 Cache; + GROUP_RELATIONSHIP32 Group; + }; +} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32; + +typedef struct +{ + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + DWORD dwTickCount; + ULONG StartAddress; + CLIENT_ID32 ClientId; + DWORD dwCurrentPriority; + DWORD dwBasePriority; + DWORD dwContextSwitches; + DWORD dwThreadState; + DWORD dwWaitReason; + DWORD dwUnknown; +} SYSTEM_THREAD_INFORMATION32; + +typedef struct +{ + ULONG NextEntryOffset; + DWORD dwThreadCount; + DWORD dwUnknown1[6]; + LARGE_INTEGER CreationTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING32 ProcessName; + DWORD dwBasePriority; + ULONG UniqueProcessId; + ULONG ParentProcessId; + ULONG HandleCount; + ULONG SessionId; + DWORD dwUnknown4; + VM_COUNTERS_EX32 vmCounters; + IO_COUNTERS ioCounters; + SYSTEM_THREAD_INFORMATION32 ti[1]; +} SYSTEM_PROCESS_INFORMATION32; + #endif /* __WOW64_STRUCT32_H */ diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h index 76772c91025..161acb83188 100644 --- a/dlls/wow64/syscall.h +++ b/dlls/wow64/syscall.h @@ -156,6 +156,8 @@ SYSCALL_ENTRY( NtQuerySymbolicLinkObject ) \ SYSCALL_ENTRY( NtQuerySystemEnvironmentValue ) \ SYSCALL_ENTRY( NtQuerySystemEnvironmentValueEx ) \ + SYSCALL_ENTRY( NtQuerySystemInformation ) \ + SYSCALL_ENTRY( NtQuerySystemInformationEx ) \ SYSCALL_ENTRY( NtQuerySystemTime ) \ SYSCALL_ENTRY( NtQueryTimer ) \ SYSCALL_ENTRY( NtQueryTimerResolution ) \ @@ -225,6 +227,7 @@ SYSCALL_ENTRY( NtWaitForMultipleObjects ) \ SYSCALL_ENTRY( NtWaitForSingleObject ) \ SYSCALL_ENTRY( NtWow64AllocateVirtualMemory64 ) \ + SYSCALL_ENTRY( NtWow64GetNativeSystemInformation ) \ SYSCALL_ENTRY( NtWow64ReadVirtualMemory64 ) \ SYSCALL_ENTRY( NtWow64WriteVirtualMemory64 ) \ SYSCALL_ENTRY( NtWriteFile ) \ diff --git a/dlls/wow64/system.c b/dlls/wow64/system.c index aa67fe484b7..2f4bb168601 100644 --- a/dlls/wow64/system.c +++ b/dlls/wow64/system.c @@ -31,6 +31,78 @@ WINE_DEFAULT_DEBUG_CHANNEL(wow); +static void put_system_basic_information( SYSTEM_BASIC_INFORMATION32 *info32, + const SYSTEM_BASIC_INFORMATION *info ) +{ + info32->unknown = info->unknown; + info32->KeMaximumIncrement = info->KeMaximumIncrement; + info32->PageSize = info->PageSize; + info32->MmNumberOfPhysicalPages = info->MmNumberOfPhysicalPages; + info32->MmLowestPhysicalPage = info->MmLowestPhysicalPage; + info32->MmHighestPhysicalPage = info->MmHighestPhysicalPage; + info32->AllocationGranularity = info->AllocationGranularity; + info32->LowestUserAddress = PtrToUlong( info->LowestUserAddress ); + info32->HighestUserAddress = PtrToUlong( info->HighestUserAddress ); + info32->ActiveProcessorsAffinityMask = info->ActiveProcessorsAffinityMask; + info32->NumberOfProcessors = info->NumberOfProcessors; +} + + +static void put_group_affinity( GROUP_AFFINITY32 *info32, const GROUP_AFFINITY *info ) +{ + info32->Mask = info->Mask; + info32->Group = info->Group; +} + + +static void put_logical_proc_info_ex( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32 *info32, + const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info ) +{ + ULONG i; + + info32->Relationship = info->Relationship; + info32->Size = offsetof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32, Processor ); + switch (info->Relationship) + { + case RelationProcessorCore: + case RelationProcessorPackage: + info32->Processor.Flags = info->Processor.Flags; + info32->Processor.EfficiencyClass = info->Processor.EfficiencyClass; + info32->Processor.GroupCount = info->Processor.GroupCount; + for (i = 0; i < info->Processor.GroupCount; i++) + put_group_affinity( &info32->Processor.GroupMask[i], &info->Processor.GroupMask[i] ); + info32->Size += offsetof( PROCESSOR_RELATIONSHIP32, GroupMask[i] ); + break; + case RelationNumaNode: + info32->NumaNode.NodeNumber = info->NumaNode.NodeNumber; + put_group_affinity( &info32->NumaNode.GroupMask, &info->NumaNode.GroupMask ); + info32->Size += sizeof(info32->NumaNode); + break; + case RelationCache: + info32->Cache.Level = info->Cache.Level; + info32->Cache.Associativity = info->Cache.Associativity; + info32->Cache.LineSize = info->Cache.LineSize; + info32->Cache.CacheSize = info->Cache.CacheSize; + info32->Cache.Type = info->Cache.Type; + put_group_affinity( &info32->Cache.GroupMask, &info->Cache.GroupMask ); + info32->Size += sizeof(info32->Cache); + break; + case RelationGroup: + info32->Group.MaximumGroupCount = info->Group.MaximumGroupCount; + info32->Group.ActiveGroupCount = info->Group.ActiveGroupCount; + for (i = 0; i < info->Group.MaximumGroupCount; i++) + { + info32->Group.GroupInfo[i].MaximumProcessorCount = info->Group.GroupInfo[i].MaximumProcessorCount; + info32->Group.GroupInfo[i].ActiveProcessorCount = info->Group.GroupInfo[i].ActiveProcessorCount; + info32->Group.GroupInfo[i].ActiveProcessorMask = info->Group.GroupInfo[i].ActiveProcessorMask; + } + info32->Size += offsetof( GROUP_RELATIONSHIP32, GroupInfo[i] ); + break; + default: + break; + } +} + /********************************************************************** * wow64_NtDisplayString @@ -149,6 +221,420 @@ NTSTATUS WINAPI wow64_NtQuerySystemEnvironmentValueEx( UINT *args ) } +/********************************************************************** + * wow64_NtQuerySystemInformation + */ +NTSTATUS WINAPI wow64_NtQuerySystemInformation( UINT *args ) +{ + SYSTEM_INFORMATION_CLASS class = get_ulong( &args ); + void *ptr = get_ptr( &args ); + ULONG len = get_ulong( &args ); + ULONG *retlen = get_ptr( &args ); + + NTSTATUS status; + + switch (class) + { + case SystemPerformanceInformation: /* SYSTEM_PERFORMANCE_INFORMATION */ + case SystemTimeOfDayInformation: /* SYSTEM_TIMEOFDAY_INFORMATION */ + case SystemProcessorPerformanceInformation: /* SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION */ + case SystemInterruptInformation: /* SYSTEM_INTERRUPT_INFORMATION */ + case SystemTimeAdjustmentInformation: /* SYSTEM_TIME_ADJUSTMENT_QUERY */ + case SystemKernelDebuggerInformation: /* SYSTEM_KERNEL_DEBUGGER_INFORMATION */ + case SystemCurrentTimeZoneInformation: /* RTL_TIME_ZONE_INFORMATION */ + case SystemRecommendedSharedDataAlignment: /* ULONG */ + case SystemFirmwareTableInformation: /* SYSTEM_FIRMWARE_TABLE_INFORMATION */ + case SystemDynamicTimeZoneInformation: /* RTL_DYNAMIC_TIME_ZONE_INFORMATION */ + case SystemCodeIntegrityInformation: /* SYSTEM_CODEINTEGRITY_INFORMATION */ + case SystemKernelDebuggerInformationEx: /* SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX */ + case SystemCpuSetInformation: /* SYSTEM_CPU_SET_INFORMATION */ + case SystemWineVersionInformation: /* char[] */ + return NtQuerySystemInformation( class, ptr, len, retlen ); + + case SystemCpuInformation: /* SYSTEM_CPU_INFORMATION */ + case SystemEmulationProcessorInformation: /* SYSTEM_CPU_INFORMATION */ + return NtQuerySystemInformation( SystemEmulationProcessorInformation, ptr, len, retlen ); + + case SystemBasicInformation: /* SYSTEM_BASIC_INFORMATION */ + case SystemEmulationBasicInformation: /* SYSTEM_BASIC_INFORMATION */ + if (len == sizeof(SYSTEM_BASIC_INFORMATION32)) + { + SYSTEM_BASIC_INFORMATION info; + SYSTEM_BASIC_INFORMATION32 *info32 = ptr; + + if (!(status = NtQuerySystemInformation( SystemEmulationBasicInformation, &info, sizeof(info), NULL ))) + put_system_basic_information( info32, &info ); + } + else status = STATUS_INFO_LENGTH_MISMATCH; + if (retlen) *retlen = sizeof(SYSTEM_BASIC_INFORMATION32); + return status; + + case SystemProcessInformation: /* SYSTEM_PROCESS_INFORMATION */ + { + ULONG inpos = 0, outpos = 0, size = len * 2, i, retsize; + SYSTEM_PROCESS_INFORMATION32 *prev = NULL; + SYSTEM_PROCESS_INFORMATION *info = Wow64AllocateTemp( size ); + + status = NtQuerySystemInformation( class, info, size, &retsize ); + if (status) + { + if (status == STATUS_INFO_LENGTH_MISMATCH && retlen) *retlen = retsize; + return status; + } + for (;;) + { + SYSTEM_PROCESS_INFORMATION *proc = (SYSTEM_PROCESS_INFORMATION *)((char *)info + inpos); + SYSTEM_PROCESS_INFORMATION32 *proc32 = (SYSTEM_PROCESS_INFORMATION32 *)((char *)ptr + outpos); + ULONG proc_len = offsetof( SYSTEM_PROCESS_INFORMATION32, ti[proc->dwThreadCount] ); + + if (outpos + proc_len + proc->ProcessName.MaximumLength <= len) + { + memset( proc32, 0, proc_len ); + proc32->dwThreadCount = proc->dwThreadCount; + proc32->CreationTime = proc->CreationTime; + proc32->UserTime = proc->UserTime; + proc32->KernelTime = proc->KernelTime; + proc32->ProcessName.Length = proc->ProcessName.Length; + proc32->ProcessName.MaximumLength = proc->ProcessName.MaximumLength; + proc32->ProcessName.Buffer = PtrToUlong( (char *)proc32 + proc_len ); + proc32->dwBasePriority = proc->dwBasePriority; + proc32->UniqueProcessId = HandleToULong( proc->UniqueProcessId ); + proc32->ParentProcessId = HandleToULong( proc->ParentProcessId ); + proc32->HandleCount = proc->HandleCount; + proc32->SessionId = proc->SessionId; + proc32->ioCounters = proc->ioCounters; + put_vm_counters( &proc32->vmCounters, &proc->vmCounters, sizeof(proc32->vmCounters) ); + for (i = 0; i < proc->dwThreadCount; i++) + { + proc32->ti[i].KernelTime = proc->ti[i].KernelTime; + proc32->ti[i].UserTime = proc->ti[i].UserTime; + proc32->ti[i].CreateTime = proc->ti[i].CreateTime; + proc32->ti[i].dwTickCount = proc->ti[i].dwTickCount; + proc32->ti[i].StartAddress = PtrToUlong( proc->ti[i].StartAddress ); + proc32->ti[i].dwCurrentPriority = proc->ti[i].dwCurrentPriority; + proc32->ti[i].dwBasePriority = proc->ti[i].dwBasePriority; + proc32->ti[i].dwContextSwitches = proc->ti[i].dwContextSwitches; + proc32->ti[i].dwThreadState = proc->ti[i].dwThreadState; + proc32->ti[i].dwWaitReason = proc->ti[i].dwWaitReason; + put_client_id( &proc32->ti[i].ClientId, &proc->ti[i].ClientId ); + } + memcpy( (char *)proc32 + proc_len, proc->ProcessName.Buffer, + proc->ProcessName.MaximumLength ); + + if (prev) prev->NextEntryOffset = (char *)proc32 - (char *)prev; + prev = proc32; + } + outpos += proc_len + proc->ProcessName.MaximumLength; + inpos += proc->NextEntryOffset; + if (!proc->NextEntryOffset) break; + } + if (retlen) *retlen = outpos; + if (outpos <= len) return STATUS_SUCCESS; + else return STATUS_INFO_LENGTH_MISMATCH; + } + + case SystemModuleInformation: /* RTL_PROCESS_MODULES */ + if (len >= sizeof(RTL_PROCESS_MODULES32)) + { + RTL_PROCESS_MODULES *info; + RTL_PROCESS_MODULES32 *info32 = ptr; + ULONG count = (len - offsetof( RTL_PROCESS_MODULES32, Modules )) / sizeof(info32->Modules[0]); + ULONG i, size = offsetof( RTL_PROCESS_MODULES, Modules[count] ); + + info = Wow64AllocateTemp( size ); + if (!(status = NtQuerySystemInformation( class, info, size, retlen ))) + { + info32->ModulesCount = info->ModulesCount; + for (i = 0; i < info->ModulesCount; i++) + { + info32->Modules[i].Section = HandleToULong( info->Modules[i].Section ); + info32->Modules[i].MappedBaseAddress = 0; + info32->Modules[i].ImageBaseAddress = 0; + info32->Modules[i].ImageSize = info->Modules[i].ImageSize; + info32->Modules[i].Flags = info->Modules[i].Flags; + info32->Modules[i].LoadOrderIndex = info->Modules[i].LoadOrderIndex; + info32->Modules[i].InitOrderIndex = info->Modules[i].InitOrderIndex; + info32->Modules[i].LoadCount = info->Modules[i].LoadCount; + info32->Modules[i].NameOffset = info->Modules[i].NameOffset; + strcpy( (char *)info->Modules[i].Name, (char *)info32->Modules[i].Name ); + } + } + } + else status = NtQuerySystemInformation( class, NULL, 0, retlen ); + + if (retlen) + { + ULONG count = (*retlen - offsetof(RTL_PROCESS_MODULES, Modules)) / sizeof(RTL_PROCESS_MODULE_INFORMATION32); + *retlen = offsetof( RTL_PROCESS_MODULES32, Modules[count] ); + } + return status; + + case SystemHandleInformation: /* SYSTEM_HANDLE_INFORMATION */ + if (len >= sizeof(SYSTEM_HANDLE_INFORMATION32)) + { + SYSTEM_HANDLE_INFORMATION *info; + SYSTEM_HANDLE_INFORMATION32 *info32 = ptr; + ULONG count = (len - offsetof(SYSTEM_HANDLE_INFORMATION32, Handle)) / sizeof(SYSTEM_HANDLE_ENTRY32); + ULONG i, size = offsetof( SYSTEM_HANDLE_INFORMATION, Handle[count] ); + + info = Wow64AllocateTemp( size ); + if (!(status = NtQuerySystemInformation( class, info, size, retlen ))) + { + info32->Count = info->Count; + for (i = 0; i < info->Count; i++) + { + info32->Handle[i].OwnerPid = info->Handle[i].OwnerPid; + info32->Handle[i].ObjectType = info->Handle[i].ObjectType; + info32->Handle[i].HandleFlags = info->Handle[i].HandleFlags; + info32->Handle[i].HandleValue = info->Handle[i].HandleValue; + info32->Handle[i].ObjectPointer = PtrToUlong( info->Handle[i].ObjectPointer ); + info32->Handle[i].AccessMask = info->Handle[i].AccessMask; + } + } + if (retlen) + { + ULONG count = (*retlen - offsetof(SYSTEM_HANDLE_INFORMATION, Handle)) / sizeof(SYSTEM_HANDLE_ENTRY); + *retlen = offsetof( SYSTEM_HANDLE_INFORMATION32, Handle[count] ); + } + return status; + } + else return STATUS_INFO_LENGTH_MISMATCH; + + case SystemFileCacheInformation: /* SYSTEM_CACHE_INFORMATION */ + if (len >= sizeof(SYSTEM_CACHE_INFORMATION32)) + { + SYSTEM_CACHE_INFORMATION info; + SYSTEM_CACHE_INFORMATION32 *info32 = ptr; + + if (!(status = NtQuerySystemInformation( class, &info, sizeof(info), NULL ))) + { + info32->CurrentSize = info.CurrentSize; + info32->PeakSize = info.PeakSize; + info32->PageFaultCount = info.PageFaultCount; + info32->MinimumWorkingSet = info.MinimumWorkingSet; + info32->MaximumWorkingSet = info.MaximumWorkingSet; + info32->CurrentSizeIncludingTransitionInPages = info.CurrentSizeIncludingTransitionInPages; + info32->PeakSizeIncludingTransitionInPages = info.PeakSizeIncludingTransitionInPages; + info32->TransitionRePurposeCount = info.TransitionRePurposeCount; + info32->Flags = info.Flags; + } + } + else status = STATUS_INFO_LENGTH_MISMATCH; + if (retlen) *retlen = sizeof(SYSTEM_CACHE_INFORMATION32); + return status; + + case SystemRegistryQuotaInformation: /* SYSTEM_REGISTRY_QUOTA_INFORMATION */ + if (len >= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION32)) + { + SYSTEM_REGISTRY_QUOTA_INFORMATION info; + SYSTEM_REGISTRY_QUOTA_INFORMATION32 *info32 = ptr; + + if (!(status = NtQuerySystemInformation( class, &info, sizeof(info), NULL ))) + { + info32->RegistryQuotaAllowed = info.RegistryQuotaAllowed; + info32->RegistryQuotaUsed = info.RegistryQuotaUsed; + info32->Reserved1 = PtrToUlong( info.Reserved1 ); + } + } + else status = STATUS_INFO_LENGTH_MISMATCH; + if (retlen) *retlen = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION32); + return status; + + case SystemExtendedProcessInformation: + FIXME( "SystemExtendedProcessInformation, len %u, info %p, stub\n", len, ptr ); + memset( ptr, 0, len ); + return STATUS_SUCCESS; + + case SystemExtendedHandleInformation: /* SYSTEM_HANDLE_INFORMATION_EX */ + if (len >= sizeof(SYSTEM_HANDLE_INFORMATION_EX32)) + { + SYSTEM_HANDLE_INFORMATION_EX *info; + SYSTEM_HANDLE_INFORMATION_EX32 *info32 = ptr; + ULONG count = (len - offsetof(SYSTEM_HANDLE_INFORMATION_EX32, Handles)) / sizeof(info32->Handles[0]); + ULONG i, size = offsetof( SYSTEM_HANDLE_INFORMATION_EX, Handles[count] ); + + if (!ptr) return STATUS_ACCESS_VIOLATION; + info = Wow64AllocateTemp( size ); + if (!(status = NtQuerySystemInformation( class, info, size, retlen ))) + { + info32->NumberOfHandles = info->NumberOfHandles; + info32->Reserved = info->Reserved; + for (i = 0; i < info->NumberOfHandles; i++) + { + info32->Handles[i].Object = PtrToUlong( info->Handles[i].Object ); + info32->Handles[i].UniqueProcessId = info->Handles[i].UniqueProcessId; + info32->Handles[i].HandleValue = info->Handles[i].HandleValue; + info32->Handles[i].GrantedAccess = info->Handles[i].GrantedAccess; + info32->Handles[i].CreatorBackTraceIndex = info->Handles[i].CreatorBackTraceIndex; + info32->Handles[i].ObjectTypeIndex = info->Handles[i].ObjectTypeIndex; + info32->Handles[i].HandleAttributes = info->Handles[i].HandleAttributes; + info32->Handles[i].Reserved = info->Handles[i].Reserved; + } + } + if (retlen) + { + ULONG count = (*retlen - offsetof(SYSTEM_HANDLE_INFORMATION_EX, Handles)) / sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX); + *retlen = offsetof( SYSTEM_HANDLE_INFORMATION_EX32, Handles[count] ); + } + return status; + } + else return STATUS_INFO_LENGTH_MISMATCH; + + case SystemLogicalProcessorInformation: /* SYSTEM_LOGICAL_PROCESSOR_INFORMATION */ + { + SYSTEM_LOGICAL_PROCESSOR_INFORMATION *info; + SYSTEM_LOGICAL_PROCESSOR_INFORMATION32 *info32 = ptr; + ULONG i, size, count; + + info = Wow64AllocateTemp( len * 2 ); + status = NtQuerySystemInformation( class, info, len * 2, &size ); + if (status && status != STATUS_INFO_LENGTH_MISMATCH) return status; + count = size / sizeof(*info); + if (!status && len >= count * sizeof(*info32)) + { + for (i = 0; i < count; i++) + { + info32[i].ProcessorMask = info[i].ProcessorMask; + info32[i].Relationship = info[i].Relationship; + info32[i].Reserved[0] = info[i].Reserved[0]; + info32[i].Reserved[1] = info[i].Reserved[1]; + } + } + else status = STATUS_INFO_LENGTH_MISMATCH; + if (retlen) *retlen = count * sizeof(*info32); + return status; + } + + case SystemModuleInformationEx: /* RTL_PROCESS_MODULE_INFORMATION_EX */ + if (len >= sizeof(RTL_PROCESS_MODULE_INFORMATION_EX) + sizeof(USHORT)) + { + RTL_PROCESS_MODULE_INFORMATION_EX *info; + RTL_PROCESS_MODULE_INFORMATION_EX32 *info32 = ptr; + ULONG count = (len - sizeof(info32->NextOffset)) / sizeof(*info32); + ULONG i, size = count * sizeof(*info) + sizeof(info->NextOffset); + + info = Wow64AllocateTemp( size ); + if (!(status = NtQuerySystemInformation( class, info, size, retlen ))) + { + RTL_PROCESS_MODULE_INFORMATION_EX *mod = info; + for (i = 0; mod->NextOffset; i++) + { + info32[i].NextOffset = sizeof(*info32); + info32[i].BaseInfo.Section = HandleToULong( mod->BaseInfo.Section ); + info32[i].BaseInfo.MappedBaseAddress = 0; + info32[i].BaseInfo.ImageBaseAddress = 0; + info32[i].BaseInfo.ImageSize = mod->BaseInfo.ImageSize; + info32[i].BaseInfo.Flags = mod->BaseInfo.Flags; + info32[i].BaseInfo.LoadOrderIndex = mod->BaseInfo.LoadOrderIndex; + info32[i].BaseInfo.InitOrderIndex = mod->BaseInfo.InitOrderIndex; + info32[i].BaseInfo.LoadCount = mod->BaseInfo.LoadCount; + info32[i].BaseInfo.NameOffset = mod->BaseInfo.NameOffset; + info32[i].ImageCheckSum = mod->ImageCheckSum; + info32[i].TimeDateStamp = mod->TimeDateStamp; + info32[i].DefaultBase = 0; + strcpy( (char *)info32[i].BaseInfo.Name, (char *)mod->BaseInfo.Name ); + mod = (RTL_PROCESS_MODULE_INFORMATION_EX *)((char *)mod + mod->NextOffset); + } + info32[i].NextOffset = 0; + } + } + else status = NtQuerySystemInformation( class, NULL, 0, retlen ); + + if (retlen) + { + ULONG count = (*retlen - sizeof(USHORT)) / sizeof(RTL_PROCESS_MODULE_INFORMATION_EX); + *retlen = count * sizeof(RTL_PROCESS_MODULE_INFORMATION_EX32) + sizeof(USHORT); + } + return status; + + case SystemNativeBasicInformation: + return STATUS_INVALID_INFO_CLASS; + + default: + FIXME( "unsupported class %u\n", class ); + return STATUS_INVALID_INFO_CLASS; + } +} + + +/********************************************************************** + * wow64_NtQuerySystemInformationEx + */ +NTSTATUS WINAPI wow64_NtQuerySystemInformationEx( UINT *args ) +{ + SYSTEM_INFORMATION_CLASS class = get_ulong( &args ); + void *query = get_ptr( &args ); + ULONG query_len = get_ulong( &args ); + void *ptr = get_ptr( &args ); + ULONG len = get_ulong( &args ); + ULONG *retlen = get_ptr( &args ); + + HANDLE handle; + NTSTATUS status; + + if (!query || query_len < sizeof(LONG)) return STATUS_INVALID_PARAMETER; + handle = LongToHandle( *(LONG *)query ); + + switch (class) + { + case SystemLogicalProcessorInformationEx: /* SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX */ + { + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32 *ex32, *info32 = ptr; + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ex, *info; + ULONG size, size32, pos = 0, pos32 = 0; + + status = NtQuerySystemInformationEx( class, &handle, sizeof(handle), NULL, 0, &size ); + if (status != STATUS_INFO_LENGTH_MISMATCH) return status; + info = Wow64AllocateTemp( size ); + status = NtQuerySystemInformationEx( class, &handle, sizeof(handle), info, size, &size ); + if (!status) + { + for (pos = pos32 = 0; pos < size && pos32 < len; pos += ex->Size, pos32 += size32) + { + ex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)info + pos); + ex32 = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32 *)((char *)info32 + pos32); + + switch (ex->Relationship) + { + case RelationProcessorCore: + case RelationProcessorPackage: + size32 = offsetof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32, + Processor.GroupMask[ex->Processor.GroupCount] ); + break; + case RelationNumaNode: + size32 = offsetof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32, NumaNode ) + sizeof( ex32->NumaNode ); + break; + case RelationCache: + size32 = offsetof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32, Cache ) + sizeof( ex32->Cache ); + break; + case RelationGroup: + size32 = offsetof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX32, + Group.GroupInfo[ex->Group.MaximumGroupCount] ); + break; + default: + size32 = 0; + continue; + } + if (pos32 + size32 <= len) put_logical_proc_info_ex( ex32, ex ); + } + if (pos < size) status = STATUS_INFO_LENGTH_MISMATCH; + else size = pos32; + } + if (retlen) *retlen = size; + return status; + } + + case SystemCpuSetInformation: /* SYSTEM_CPU_SET_INFORMATION */ + case SystemSupportedProcessorArchitectures: /* ULONG */ + return NtQuerySystemInformationEx( class, &handle, sizeof(handle), ptr, len, retlen ); + + default: + FIXME( "unsupported class %u\n", class ); + return STATUS_INVALID_INFO_CLASS; + } +} + + /********************************************************************** * wow64_NtQuerySystemTime */ @@ -235,3 +721,42 @@ NTSTATUS WINAPI wow64_NtUnloadDriver( UINT *args ) return NtUnloadDriver( unicode_str_32to64( &str, str32 )); } + + +/********************************************************************** + * wow64_NtWow64GetNativeSystemInformation + */ +NTSTATUS WINAPI wow64_NtWow64GetNativeSystemInformation( UINT *args ) +{ + ULONG class = get_ulong( &args ); + void *ptr = get_ptr( &args ); + ULONG len = get_ulong( &args ); + ULONG *retlen = get_ptr( &args ); + + NTSTATUS status; + + switch (class) + { + case SystemBasicInformation: + case SystemEmulationBasicInformation: + if (len == sizeof(SYSTEM_BASIC_INFORMATION32)) + { + SYSTEM_BASIC_INFORMATION info; + SYSTEM_BASIC_INFORMATION32 *info32 = ptr; + + if (!(status = NtQuerySystemInformation( class, &info, sizeof(info), NULL ))) + put_system_basic_information( info32, &info ); + } + else status = STATUS_INFO_LENGTH_MISMATCH; + if (retlen) *retlen = sizeof(SYSTEM_BASIC_INFORMATION32); + return status; + + case SystemCpuInformation: + case SystemEmulationProcessorInformation: + case SystemNativeBasicInformation: + return NtQuerySystemInformation( class, ptr, len, retlen ); + + default: + return STATUS_INVALID_INFO_CLASS; + } +}