Files
Johnny Shaw 53fbbdc5b5 sync latest
2026-03-25 18:14:46 -06:00

838 lines
26 KiB
C

/*
* Windows on Windows support functions
*
* This file is part of System Informer.
*/
#ifndef _NTWOW64_H
#define _NTWOW64_H
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#ifdef __has_include
#if __has_include (<ntxcapi.h>)
#include <ntxcapi.h>
#endif // __has_include
#endif // __has_include
#endif // (PHNT_MODE != PHNT_MODE_KERNEL)
#define WOW64_SYSTEM_DIRECTORY "SysWOW64"
#define WOW64_SYSTEM_DIRECTORY_U L"SysWOW64"
#define WOW64_X86_TAG " (x86)"
#define WOW64_X86_TAG_U L" (x86)"
// In USER_SHARED_DATA
typedef enum _WOW64_SHARED_INFORMATION
{
SharedNtdll32LdrInitializeThunk,
SharedNtdll32KiUserExceptionDispatcher,
SharedNtdll32KiUserApcDispatcher,
SharedNtdll32KiUserCallbackDispatcher,
SharedNtdll32ExpInterlockedPopEntrySListFault,
SharedNtdll32ExpInterlockedPopEntrySListResume,
SharedNtdll32ExpInterlockedPopEntrySListEnd,
SharedNtdll32RtlUserThreadStart,
SharedNtdll32pQueryProcessDebugInformationRemote,
SharedNtdll32BaseAddress,
SharedNtdll32LdrSystemDllInitBlock,
Wow64SharedPageEntriesCount
} WOW64_SHARED_INFORMATION;
//
// 32-bit definitions
//
#define WOW64_POINTER(Type) ULONG
typedef struct _RTL_BALANCED_NODE32
{
union
{
WOW64_POINTER(struct _RTL_BALANCED_NODE *) Children[2];
struct
{
WOW64_POINTER(struct _RTL_BALANCED_NODE *) Left;
WOW64_POINTER(struct _RTL_BALANCED_NODE *) Right;
};
};
union
{
WOW64_POINTER(UCHAR) Red : 1;
WOW64_POINTER(UCHAR) Balance : 2;
WOW64_POINTER(ULONG_PTR) ParentValue;
};
} RTL_BALANCED_NODE32, *PRTL_BALANCED_NODE32;
typedef struct _RTL_RB_TREE32
{
WOW64_POINTER(PRTL_BALANCED_NODE) Root;
WOW64_POINTER(PRTL_BALANCED_NODE) Min;
} RTL_RB_TREE32, *PRTL_RB_TREE32;
typedef struct _PEB_LDR_DATA32
{
ULONG Length;
BOOLEAN Initialized;
WOW64_POINTER(HANDLE) SsHandle;
LIST_ENTRY32 InLoadOrderModuleList;
LIST_ENTRY32 InMemoryOrderModuleList;
LIST_ENTRY32 InInitializationOrderModuleList;
WOW64_POINTER(PVOID) EntryInProgress;
BOOLEAN ShutdownInProgress;
WOW64_POINTER(HANDLE) ShutdownThreadId;
} PEB_LDR_DATA32, *PPEB_LDR_DATA32;
typedef struct _LDR_SERVICE_TAG_RECORD32
{
WOW64_POINTER(struct _LDR_SERVICE_TAG_RECORD *) Next;
ULONG ServiceTag;
} LDR_SERVICE_TAG_RECORD32, *PLDR_SERVICE_TAG_RECORD32;
typedef struct _LDRP_CSLIST32
{
WOW64_POINTER(PSINGLE_LIST_ENTRY) Tail;
} LDRP_CSLIST32, *PLDRP_CSLIST32;
typedef struct _LDR_DDAG_NODE32
{
LIST_ENTRY32 Modules;
WOW64_POINTER(PLDR_SERVICE_TAG_RECORD) ServiceTagList;
ULONG LoadCount;
ULONG LoadWhileUnloadingCount;
ULONG LowestLink;
union
{
LDRP_CSLIST32 Dependencies;
SINGLE_LIST_ENTRY32 RemovalLink;
};
LDRP_CSLIST32 IncomingDependencies;
LDR_DDAG_STATE State;
SINGLE_LIST_ENTRY32 CondenseLink;
ULONG PreorderNumber;
} LDR_DDAG_NODE32, *PLDR_DDAG_NODE32;
#define LDR_DATA_TABLE_ENTRY_SIZE_WINXP_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, DdagNode)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN7_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, BaseNameHashValue)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN8_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, ImplicitPathOptions)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN10_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, SigningLevel)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN11_32 sizeof(LDR_DATA_TABLE_ENTRY32)
typedef struct _LDR_DATA_TABLE_ENTRY32
{
LIST_ENTRY32 InLoadOrderLinks;
LIST_ENTRY32 InMemoryOrderLinks;
union
{
LIST_ENTRY32 InInitializationOrderLinks;
LIST_ENTRY32 InProgressLinks;
};
WOW64_POINTER(PVOID) DllBase;
WOW64_POINTER(PVOID) EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING32 FullDllName;
UNICODE_STRING32 BaseDllName;
union
{
UCHAR FlagGroup[4];
ULONG Flags;
struct
{
ULONG PackagedBinary : 1;
ULONG MarkedForRemoval : 1;
ULONG ImageDll : 1;
ULONG LoadNotificationsSent : 1;
ULONG TelemetryEntryProcessed : 1;
ULONG ProcessStaticImport : 1;
ULONG InLegacyLists : 1;
ULONG InIndexes : 1;
ULONG ShimDll : 1;
ULONG InExceptionTable : 1;
ULONG ReservedFlags1 : 2;
ULONG LoadInProgress : 1;
ULONG LoadConfigProcessed : 1;
ULONG EntryProcessed : 1;
ULONG ProtectDelayLoad : 1;
ULONG ReservedFlags3 : 2;
ULONG DontCallForThreads : 1;
ULONG ProcessAttachCalled : 1;
ULONG ProcessAttachFailed : 1;
ULONG CorDeferredValidate : 1;
ULONG CorImage : 1;
ULONG DontRelocate : 1;
ULONG CorILOnly : 1;
ULONG ChpeImage : 1;
ULONG ReservedFlags5 : 2;
ULONG Redirected : 1;
ULONG ReservedFlags6 : 2;
ULONG CompatDatabaseProcessed : 1;
};
};
USHORT ObsoleteLoadCount;
USHORT TlsIndex;
LIST_ENTRY32 HashLinks;
ULONG TimeDateStamp;
WOW64_POINTER(struct _ACTIVATION_CONTEXT *) EntryPointActivationContext;
WOW64_POINTER(PVOID) Lock;
WOW64_POINTER(PLDR_DDAG_NODE) DdagNode;
LIST_ENTRY32 NodeModuleLink;
WOW64_POINTER(struct _LDRP_LOAD_CONTEXT *) LoadContext;
WOW64_POINTER(PVOID) ParentDllBase;
WOW64_POINTER(PVOID) SwitchBackContext;
RTL_BALANCED_NODE32 BaseAddressIndexNode;
RTL_BALANCED_NODE32 MappingInfoIndexNode;
WOW64_POINTER(ULONG_PTR) OriginalBase;
LARGE_INTEGER LoadTime;
ULONG BaseNameHashValue;
LDR_DLL_LOAD_REASON LoadReason;
ULONG ImplicitPathOptions;
ULONG ReferenceCount;
ULONG DependentLoadFlags;
UCHAR SigningLevel; // since REDSTONE2
ULONG CheckSum; // since 22H1
WOW64_POINTER(PVOID) ActivePatchImageBase;
LDR_HOT_PATCH_STATE HotPatchState;
} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;
typedef const LDR_DATA_TABLE_ENTRY32* PCLDR_DATA_TABLE_ENTRY32;
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, InMemoryOrderLinks) == 0x8, "LDR_DATA_TABLE_ENTRY32.InMemoryOrderLinks offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, InInitializationOrderLinks) == 0x10, "LDR_DATA_TABLE_ENTRY32.InInitializationOrderLinks offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, DllBase) == 0x18, "LDR_DATA_TABLE_ENTRY32.DllBase offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, EntryPoint) == 0x1c, "LDR_DATA_TABLE_ENTRY32.EntryPoint offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, SizeOfImage) == 0x20, "LDR_DATA_TABLE_ENTRY32.SizeOfImage offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, ObsoleteLoadCount) == 0x38, "LDR_DATA_TABLE_ENTRY32.ObsoleteLoadCount offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, TimeDateStamp) == 0x44, "LDR_DATA_TABLE_ENTRY32.TimeDateStamp offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, DdagNode) == 0x50, "LDR_DATA_TABLE_ENTRY32.DdagNode offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, ParentDllBase) == 0x60, "LDR_DATA_TABLE_ENTRY32.ParentDllBase offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, OriginalBase) == 0x80, "LDR_DATA_TABLE_ENTRY32.OriginalBase offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, BaseNameHashValue) == 0x90, "LDR_DATA_TABLE_ENTRY32.BaseNameHashValue offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, LoadReason) == 0x94, "LDR_DATA_TABLE_ENTRY32.LoadReason offset incorrect");
static_assert(UFIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, CheckSum) == 0xA8, "LDR_DATA_TABLE_ENTRY32.CheckSum offset incorrect");
static_assert(sizeof(LDR_DATA_TABLE_ENTRY32) == 0xB8, "LDR_DATA_TABLE_ENTRY32 incorrect size");
typedef struct _CURDIR32
{
UNICODE_STRING32 DosPath;
WOW64_POINTER(HANDLE) Handle;
} CURDIR32, *PCURDIR32;
typedef struct _RTL_DRIVE_LETTER_CURDIR32
{
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
STRING32 DosPath;
} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32;
typedef struct _RTL_USER_PROCESS_PARAMETERS32
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
WOW64_POINTER(HANDLE) ConsoleHandle;
ULONG ConsoleFlags;
WOW64_POINTER(HANDLE) StandardInput;
WOW64_POINTER(HANDLE) StandardOutput;
WOW64_POINTER(HANDLE) StandardError;
CURDIR32 CurrentDirectory;
UNICODE_STRING32 DllPath;
UNICODE_STRING32 ImagePathName;
UNICODE_STRING32 CommandLine;
WOW64_POINTER(PVOID) Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING32 WindowTitle;
UNICODE_STRING32 DesktopInfo;
UNICODE_STRING32 ShellInfo;
UNICODE_STRING32 RuntimeData;
RTL_DRIVE_LETTER_CURDIR32 CurrentDirectories[RTL_MAX_DRIVE_LETTERS];
WOW64_POINTER(ULONG_PTR) EnvironmentSize;
WOW64_POINTER(ULONG_PTR) EnvironmentVersion;
WOW64_POINTER(PVOID) PackageDependencyData;
ULONG ProcessGroupId;
ULONG LoaderThreads;
UNICODE_STRING32 RedirectionDllName; // REDSTONE4
UNICODE_STRING32 HeapPartitionName; // 19H1
WOW64_POINTER(ULONGLONG) DefaultThreadpoolCpuSetMasks;
ULONG DefaultThreadpoolCpuSetMaskCount;
ULONG DefaultThreadpoolThreadMaximum;
} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32;
typedef struct _LEAP_SECOND_DATA *PLEAP_SECOND_DATA;
typedef struct _PEB32
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN ImageUsesLargePages : 1;
BOOLEAN IsProtectedProcess : 1;
BOOLEAN IsImageDynamicallyRelocated : 1;
BOOLEAN SkipPatchingUser32Forwarders : 1;
BOOLEAN IsPackagedProcess : 1;
BOOLEAN IsAppContainer : 1;
BOOLEAN IsProtectedProcessLight : 1;
BOOLEAN IsLongPathAwareProcess : 1;
};
};
WOW64_POINTER(HANDLE) Mutant;
WOW64_POINTER(PVOID) ImageBaseAddress;
WOW64_POINTER(PPEB_LDR_DATA) Ldr;
WOW64_POINTER(PRTL_USER_PROCESS_PARAMETERS) ProcessParameters;
WOW64_POINTER(PVOID) SubSystemData;
WOW64_POINTER(PVOID) ProcessHeap;
WOW64_POINTER(PRTL_CRITICAL_SECTION) FastPebLock;
WOW64_POINTER(PVOID) AtlThunkSListPtr;
WOW64_POINTER(PVOID) IFEOKey;
union
{
ULONG CrossProcessFlags;
struct
{
ULONG ProcessInJob : 1;
ULONG ProcessInitializing : 1;
ULONG ProcessUsingVEH : 1;
ULONG ProcessUsingVCH : 1;
ULONG ProcessUsingFTH : 1;
ULONG ProcessPreviouslyThrottled : 1; // The process was previously throttled.
ULONG ProcessCurrentlyThrottled : 1; // The process is currently throttled.
ULONG ProcessImagesHotPatched : 1; // The process images are hot patched. // RS5
ULONG ReservedBits0 : 24;
};
};
union
{
WOW64_POINTER(PVOID) KernelCallbackTable;
WOW64_POINTER(PVOID) UserSharedInfoPtr;
};
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
WOW64_POINTER(PVOID) ApiSetMap;
ULONG TlsExpansionCounter;
WOW64_POINTER(PVOID) TlsBitmap;
ULONG TlsBitmapBits[2];
WOW64_POINTER(PVOID) ReadOnlySharedMemoryBase;
WOW64_POINTER(PVOID) SharedData;
WOW64_POINTER(PVOID *) ReadOnlyStaticServerData;
WOW64_POINTER(PVOID) AnsiCodePageData;
WOW64_POINTER(PVOID) OemCodePageData;
WOW64_POINTER(PVOID) UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
LARGE_INTEGER CriticalSectionTimeout;
WOW64_POINTER(SIZE_T) HeapSegmentReserve;
WOW64_POINTER(SIZE_T) HeapSegmentCommit;
WOW64_POINTER(SIZE_T) HeapDeCommitTotalFreeThreshold;
WOW64_POINTER(SIZE_T) HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
WOW64_POINTER(PVOID *) ProcessHeaps;
WOW64_POINTER(PVOID) GdiSharedHandleTable;
WOW64_POINTER(PVOID) ProcessStarterHelper;
ULONG GdiDCAttributeList;
WOW64_POINTER(PRTL_CRITICAL_SECTION) LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
USHORT OSBuildNumber;
USHORT OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
WOW64_POINTER(ULONG_PTR) ActiveProcessAffinityMask;
GDI_HANDLE_BUFFER32 GdiHandleBuffer;
WOW64_POINTER(PVOID) PostProcessInitRoutine;
WOW64_POINTER(PVOID) TlsExpansionBitmap;
ULONG TlsExpansionBitmapBits[32];
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
WOW64_POINTER(PVOID) pShimData;
WOW64_POINTER(PVOID) AppCompatInfo;
UNICODE_STRING32 CSDVersion;
WOW64_POINTER(PACTIVATION_CONTEXT_DATA) ActivationContextData;
WOW64_POINTER(PVOID) ProcessAssemblyStorageMap;
WOW64_POINTER(PACTIVATION_CONTEXT_DATA) SystemDefaultActivationContextData;
WOW64_POINTER(PVOID) SystemAssemblyStorageMap;
WOW64_POINTER(SIZE_T) MinimumStackCommit;
WOW64_POINTER(PVOID) SparePointers[2]; // 19H1 (previously FlsCallback to FlsHighIndex)
WOW64_POINTER(PVOID) PatchLoaderData;
WOW64_POINTER(PVOID) ChpeV2ProcessInfo; // _CHPEV2_PROCESS_INFO
ULONG AppModelFeatureState;
ULONG SpareUlongs[2];
USHORT ActiveCodePage;
USHORT OemCodePage;
USHORT UseCaseMapping;
USHORT UnusedNlsField;
WOW64_POINTER(PVOID) WerRegistrationData;
WOW64_POINTER(PVOID) WerShipAssertPtr;
union
{
WOW64_POINTER(PVOID) pContextData; // WIN7
WOW64_POINTER(PVOID) pUnused; // WIN10
WOW64_POINTER(PVOID) EcCodeBitMap; // WIN11
};
WOW64_POINTER(PVOID) pImageHeaderHash;
union
{
ULONG TracingFlags;
struct
{
ULONG HeapTracingEnabled : 1;
ULONG CritSecTracingEnabled : 1;
ULONG LibLoaderTracingEnabled : 1;
ULONG SpareTracingBits : 29;
};
};
ULONGLONG CsrServerReadOnlySharedMemoryBase;
WOW64_POINTER(PVOID) TppWorkerpListLock;
LIST_ENTRY32 TppWorkerpList;
WOW64_POINTER(PVOID) WaitOnAddressHashTable[128];
WOW64_POINTER(PVOID) TelemetryCoverageHeader; // REDSTONE3
ULONG CloudFileFlags;
ULONG CloudFileDiagFlags; // REDSTONE4
CHAR PlaceholderCompatibilityMode;
CHAR PlaceholderCompatibilityModeReserved[7];
WOW64_POINTER(PLEAP_SECOND_DATA) LeapSecondData; // REDSTONE5
union
{
ULONG LeapSecondFlags;
struct
{
ULONG SixtySecondEnabled : 1;
ULONG Reserved : 31;
};
};
ULONG NtGlobalFlag2;
ULONGLONG ExtendedFeatureDisableMask; // since WIN11
} PEB32, *PPEB32;
static_assert(sizeof(PEB32) == 0x488, "sizeof(PEB32) is incorrect"); // WIN11
// Note: Use PhGetProcessPeb32 instead. (dmex)
//#define WOW64_GET_PEB32(peb64) \
// ((PPEB32)RtlOffsetToPointer((peb64), ALIGN_UP_BY(sizeof(PEB), PAGE_SIZE)))
#define GDI_BATCH_BUFFER_SIZE 310
typedef struct _GDI_TEB_BATCH32
{
ULONG Offset;
WOW64_POINTER(ULONG_PTR) HDC;
ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
} GDI_TEB_BATCH32, *PGDI_TEB_BATCH32;
typedef struct tagSOleTlsData32
{
WOW64_POINTER(PVOID) ThreadBase;
WOW64_POINTER(PVOID) SmAllocator;
ULONG ApartmentID;
ULONG Flags; // OLETLSFLAGS
LONG TlsMapIndex;
WOW64_POINTER(PVOID *) TlsSlot;
ULONG ComInits;
ULONG OleInits;
ULONG Calls;
WOW64_POINTER(PVOID) ServerCall; // was CallInfo before TH1
WOW64_POINTER(PVOID) CallObjectCache; // was FreeAsyncCall before TH1
WOW64_POINTER(PVOID) ContextStack; // was FreeClientCall before TH1
WOW64_POINTER(PVOID) ObjServer;
ULONG TIDCaller;
// ... (other fields are version-dependant)
} SOleTlsData32, *PSOleTlsData32;
// rev
#define RPC_THREAD_POINTER_KEY32 0xABABABAB
typedef struct _TEB32
{
NT_TIB32 NtTib;
WOW64_POINTER(PVOID) EnvironmentPointer;
CLIENT_ID32 ClientId;
WOW64_POINTER(PVOID) ActiveRpcHandle;
WOW64_POINTER(PVOID) ThreadLocalStoragePointer;
WOW64_POINTER(PPEB) ProcessEnvironmentBlock;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
WOW64_POINTER(PVOID) CsrClientThread;
WOW64_POINTER(PVOID) Win32ThreadInfo;
ULONG User32Reserved[26];
ULONG UserReserved[5];
WOW64_POINTER(PVOID) WOW32Reserved;
LCID CurrentLocale;
ULONG FpSoftwareStatusRegister;
WOW64_POINTER(PVOID) ReservedForDebuggerInstrumentation[16];
WOW64_POINTER(PVOID) SystemReserved1[36];
UCHAR WorkingOnBehalfTicket[8];
NTSTATUS ExceptionCode;
WOW64_POINTER(PVOID) ActivationContextStackPointer;
WOW64_POINTER(ULONG_PTR) InstrumentationCallbackSp;
WOW64_POINTER(ULONG_PTR) InstrumentationCallbackPreviousPc;
WOW64_POINTER(ULONG_PTR) InstrumentationCallbackPreviousSp;
BOOLEAN InstrumentationCallbackDisabled;
UCHAR SpareBytes[23];
ULONG TxFsContext;
GDI_TEB_BATCH32 GdiTebBatch;
CLIENT_ID32 RealClientId;
WOW64_POINTER(HANDLE) GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
WOW64_POINTER(PVOID) GdiThreadLocalInfo;
WOW64_POINTER(ULONG_PTR) Win32ClientInfo[62];
WOW64_POINTER(PVOID) glDispatchTable[233];
WOW64_POINTER(ULONG_PTR) glReserved1[29];
WOW64_POINTER(PVOID) glReserved2;
WOW64_POINTER(PVOID) glSectionInfo;
WOW64_POINTER(PVOID) glSection;
WOW64_POINTER(PVOID) glTable;
WOW64_POINTER(PVOID) glCurrentRC;
WOW64_POINTER(PVOID) glContext;
NTSTATUS LastStatusValue;
UNICODE_STRING32 StaticUnicodeString;
WCHAR StaticUnicodeBuffer[261];
WOW64_POINTER(PVOID) DeallocationStack;
WOW64_POINTER(PVOID) TlsSlots[64];
LIST_ENTRY32 TlsLinks;
WOW64_POINTER(PVOID) Vdm;
WOW64_POINTER(PVOID) ReservedForNtRpc;
WOW64_POINTER(PVOID) DbgSsReserved[2];
ULONG HardErrorMode;
WOW64_POINTER(PVOID) Instrumentation[9];
GUID ActivityId;
WOW64_POINTER(PVOID) SubProcessTag;
WOW64_POINTER(PVOID) PerflibData;
WOW64_POINTER(PVOID) EtwTraceData;
WOW64_POINTER(PVOID) WinSockData;
ULONG GdiBatchCount;
union
{
PROCESSOR_NUMBER CurrentIdealProcessor;
ULONG IdealProcessorValue;
struct
{
UCHAR ReservedPad0;
UCHAR ReservedPad1;
UCHAR ReservedPad2;
UCHAR IdealProcessor;
};
};
ULONG GuaranteedStackBytes;
WOW64_POINTER(PVOID) ReservedForPerf;
WOW64_POINTER(PSOleTlsData32) ReservedForOle;
ULONG WaitingOnLoaderLock;
WOW64_POINTER(PVOID) SavedPriorityState;
WOW64_POINTER(ULONG_PTR) ReservedForCodeCoverage;
WOW64_POINTER(PVOID) ThreadPoolData;
WOW64_POINTER(PVOID *) TlsExpansionSlots;
ULONG MuiGeneration;
ULONG IsImpersonating;
WOW64_POINTER(PVOID) NlsCache;
WOW64_POINTER(PVOID) pShimData;
USHORT HeapVirtualAffinity;
USHORT LowFragHeapDataSlot;
WOW64_POINTER(HANDLE) CurrentTransactionHandle;
WOW64_POINTER(PTEB_ACTIVE_FRAME) ActiveFrame;
WOW64_POINTER(PVOID) FlsData;
WOW64_POINTER(PVOID) PreferredLanguages;
WOW64_POINTER(PVOID) UserPrefLanguages;
WOW64_POINTER(PVOID) MergedPrefLanguages;
ULONG MuiImpersonation;
union
{
USHORT CrossTebFlags;
USHORT SpareCrossTebBits : 16;
};
union
{
USHORT SameTebFlags;
struct
{
USHORT SafeThunkCall : 1;
USHORT InDebugPrint : 1;
USHORT HasFiberData : 1;
USHORT SkipThreadAttach : 1;
USHORT WerInShipAssertCode : 1;
USHORT RanProcessInit : 1;
USHORT ClonedThread : 1;
USHORT SuppressDebugMsg : 1;
USHORT DisableUserStackWalk : 1;
USHORT RtlExceptionAttached : 1;
USHORT InitialThread : 1;
USHORT SessionAware : 1;
USHORT LoadOwner : 1;
USHORT LoaderWorker : 1;
USHORT SpareSameTebBits : 2;
};
};
WOW64_POINTER(PVOID) TxnScopeEnterCallback;
WOW64_POINTER(PVOID) TxnScopeExitCallback;
WOW64_POINTER(PVOID) TxnScopeContext;
ULONG LockCount;
LONG WowTebOffset;
WOW64_POINTER(PVOID) ResourceRetValue;
WOW64_POINTER(PVOID) ReservedForWdf;
ULONGLONG ReservedForCrt;
GUID EffectiveContainerId;
} TEB32, *PTEB32;
static_assert(FIELD_OFFSET(TEB32, ProcessEnvironmentBlock) == 0x030, "FIELD_OFFSET(TEB32, ProcessEnvironmentBlock) is incorrect");
static_assert(FIELD_OFFSET(TEB32, ExceptionCode) == 0x1a4, "FIELD_OFFSET(TEB32, ExceptionCode) is incorrect");
static_assert(FIELD_OFFSET(TEB32, StaticUnicodeBuffer) == 0xc00, "FIELD_OFFSET(TEB32, StaticUnicodeBuffer) is incorrect");
static_assert(FIELD_OFFSET(TEB32, TlsLinks) == 0xf10, "FIELD_OFFSET(TEB32, TlsLinks) is incorrect");
static_assert(FIELD_OFFSET(TEB32, TlsExpansionSlots) == 0xf94, "FIELD_OFFSET(TEB32, TlsExpansionSlots) is incorrect");
static_assert(FIELD_OFFSET(TEB32, FlsData) == 0xfb4, "FIELD_OFFSET(TEB32, FlsData) is incorrect");
static_assert(FIELD_OFFSET(TEB32, MuiImpersonation) == 0xfc4, "FIELD_OFFSET(TEB32, MuiImpersonation) is incorrect");
static_assert(FIELD_OFFSET(TEB32, EffectiveContainerId) == 0xff0, "FIELD_OFFSET(TEB32, EffectiveContainerId) is incorrect");
static_assert(sizeof(TEB32) == 0x1000, "sizeof(TEB32) is incorrect");
//
// Conversion
//
FORCEINLINE VOID UStr32ToUStr(
_Out_ PUNICODE_STRING Destination,
_In_ PCUNICODE_STRING32 Source
)
{
Destination->Length = Source->Length;
Destination->MaximumLength = Source->MaximumLength;
Destination->Buffer = (PWCH)UlongToPtr(Source->Buffer);
}
FORCEINLINE VOID UStrToUStr32(
_Out_ PUNICODE_STRING32 Destination,
_In_ PCUNICODE_STRING Source
)
{
Destination->Length = Source->Length;
Destination->MaximumLength = Source->MaximumLength;
Destination->Buffer = PtrToUlong(Source->Buffer);
}
// The Wow64Info structure follows the PEB32/TEB32 structures and is shared between 32-bit and 64-bit modules inside a Wow64 process.
// from SDK/10.0.10240.0/um/minwin/wow64t.h (dmex)
//
// Page size on x86 NT
//
#define PAGE_SIZE_X86NT 0x1000
#define PAGE_SHIFT_X86NT 12L
#define WOW64_SPLITS_PER_PAGE (PAGE_SIZE_X86NT / PAGE_SIZE_X86NT)
//
// Convert the number of native pages to sub x86-pages
//
#define Wow64GetNumberOfX86Pages(NativePages) \
((NativePages) * (PAGE_SIZE_X86NT >> PAGE_SHIFT_X86NT))
//
// Macro to round to the nearest page size
//
#define WOW64_ROUND_TO_PAGES(Size) \
(((ULONG_PTR)(Size) + PAGE_SIZE_X86NT - 1) & ~(PAGE_SIZE_X86NT - 1))
//
// Get number of native pages
//
#define WOW64_BYTES_TO_PAGES(Size) \
(((ULONG)(Size) >> WOW64_ROUND_TO_PAGES) + (((ULONG)(Size) & (PAGE_SIZE_X86NT - 1)) != 0))
//
// Get the 32-bit TEB without doing a memory reference.
//
#define WOW64_GET_TEB32(teb64) ((PTEB32)(((ULONG_PTR)(teb64)) + ((ULONG_PTR)WOW64_ROUND_TO_PAGES(sizeof(TEB)))))
#define WOW64_TEB32_POINTER_ADDRESS(teb64) ((PVOID)&(((PTEB)(teb64))->NtTib.ExceptionList))
//
// Get the 32-bit execute options.
//
typedef union _WOW64_EXECUTE_OPTIONS
{
ULONG Flags;
struct
{
ULONG StackReserveSize : 8;
ULONG StackCommitSize : 4;
ULONG Deprecated0 : 1;
ULONG DisableWowAssert : 1;
ULONG DisableTurboDispatch : 1;
ULONG Unused : 13;
ULONG Reserved0 : 1;
ULONG Reserved1 : 1;
ULONG Reserved2 : 1;
ULONG Reserved3 : 1;
};
} WOW64_EXECUTE_OPTIONS, *PWOW64_EXECUTE_OPTIONS;
#define WOW64_CPUFLAGS_MSFT64 0x00000001
#define WOW64_CPUFLAGS_SOFTWARE 0x00000002
#define WOW64_CPUFLAGS_IA64 0x00000004
typedef struct _WOW64INFO
{
ULONG NativeSystemPageSize;
ULONG CpuFlags;
WOW64_EXECUTE_OPTIONS Wow64ExecuteFlags;
ULONG InstrumentationCallback;
} WOW64INFO, *PWOW64INFO;
typedef struct _PEB32_WITH_WOW64INFO
{
PEB32 Peb32;
WOW64INFO Wow64Info;
} PEB32_WITH_WOW64INFO, *PPEB32_WITH_WOW64INFO;
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#ifdef _M_X64
FORCEINLINE
TEB32*
POINTER_UNSIGNED
Wow64CurrentGuestTeb(
VOID
)
{
TEB* POINTER_UNSIGNED Teb;
TEB32* POINTER_UNSIGNED Teb32;
Teb = NtCurrentTeb();
if (Teb->WowTebOffset == 0)
{
//
// Not running under or over WoW, so there is no "guest teb"
//
return NULL;
}
if (Teb->WowTebOffset < 0)
{
//
// Was called while running under WoW. The current teb is the guest teb.
//
Teb32 = (PTEB32)Teb;
#if defined(RTL_ASSERT)
RTL_ASSERT(&Teb32->WowTebOffset == &Teb->WowTebOffset);
#endif
}
else
{
//
// Called by the WoW Host, so calculate the position of the guest teb
// relative to the current (host) teb.
//
Teb32 = (PTEB32)RtlOffsetToPointer(Teb, Teb->WowTebOffset);
}
#if defined(RTL_ASSERT)
RTL_ASSERT(Teb32->NtTib.Self == PtrToUlong(Teb32));
#endif
return Teb32;
}
FORCEINLINE
VOID*
POINTER_UNSIGNED
Wow64CurrentNativeTeb(
VOID
)
{
TEB* POINTER_UNSIGNED Teb;
VOID* POINTER_UNSIGNED HostTeb;
Teb = NtCurrentTeb();
if (Teb->WowTebOffset >= 0)
{
//
// Not running under WoW, so it it either not running on WoW at all, or
// it is the host. Return the current teb as native teb.
//
HostTeb = (PVOID)Teb;
}
else
{
//
// Called while running under WoW Host, so calculate the position of the
// host teb relative to the current (guest) teb.
//
HostTeb = (PVOID)RtlOffsetToPointer(Teb, Teb->WowTebOffset);
}
#if defined(RTL_ASSERT)
RTL_ASSERT((((PTEB32)HostTeb)->NtTib.Self == PtrToUlong(HostTeb)) || ((ULONG_PTR)((PTEB)HostTeb)->NtTib.Self == (ULONG_PTR)HostTeb));
#endif
return HostTeb;
}
#define NtCurrentTeb32() (Wow64CurrentGuestTeb())
#define NtCurrentPeb32() ((PPEB32)(UlongToPtr((NtCurrentTeb32()->ProcessEnvironmentBlock))))
#define Wow64GetNativeTebField(teb, field) (((ULONG)(teb) == ((PTEB32)(teb))->NtTib.Self) ? (((PTEB32)(teb))->##field) : (((PTEB)(teb))->##field) )
#define Wow64SetNativeTebField(teb, field, value) { if ((ULONG)(teb) == ((PTEB32)(teb))->NtTib.Self) {(((PTEB32)(teb))->##field) = (value);} else {(((PTEB)(teb))->##field) = (value);} }
#endif // _M_X64
#endif // (PHNT_MODE != PHNT_MODE_KERNEL)
#endif // _NTWOW64_H