// Copyright 2015 The Crashpad Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_UTIL_WIN_PROCESS_STRUCTS_H_
#define CRASHPAD_UTIL_WIN_PROCESS_STRUCTS_H_
#include <windows.h>
namespace crashpad {
namespace process_types {
namespace internal {
struct Traits32 {
using Pad = DWORD;
using UnsignedIntegral = DWORD;
using Pointer = DWORD;
};
struct Traits64 {
using Pad = DWORD64;
using UnsignedIntegral = DWORD64;
using Pointer = DWORD64;
};
} // namespace internal
//! \{
//! \brief Selected structures from winternl.h, ntddk.h, and `dt ntdll!xxx`,
//! customized to have both x86 and x64 sizes available.
//!
//! The structure and field names follow the Windows names for clarity. We do,
//! however, use plain integral types rather than pointer types. This is both
//! easier to define, and avoids accidentally treating them as pointers into the
//! current address space.
//!
//! The templates below should be instantiated with either internal::Traits32
//! for structures targeting x86, or internal::Traits64 for x64.
// We set packing to 1 so that we can explicitly control the layout to make it
// match the OS defined structures.
#pragma pack(push, 1)
template <class Traits>
struct PROCESS_BASIC_INFORMATION {
union {
DWORD ExitStatus;
typename Traits::Pad padding_for_x64_0;
};
typename Traits::Pointer PebBaseAddress;
typename Traits::UnsignedIntegral AffinityMask;
union {
DWORD BasePriority;
typename Traits::Pad padding_for_x64_1;
};
typename Traits::UnsignedIntegral UniqueProcessId;
typename Traits::UnsignedIntegral InheritedFromUniqueProcessId;
};
template <class Traits>
struct LIST_ENTRY {
typename Traits::Pointer Flink;
typename Traits::Pointer Blink;
};
template <class Traits>
struct UNICODE_STRING {
union {
struct {
USHORT Length;
USHORT MaximumLength;
};
typename Traits::Pad padding_for_x64;
};
typename Traits::Pointer Buffer;
};
template <class Traits>
struct PEB_LDR_DATA {
ULONG Length;
DWORD Initialized;
typename Traits::Pointer SsHandle;
LIST_ENTRY<Traits> InLoadOrderModuleList;
LIST_ENTRY<Traits> InMemoryOrderModuleList;
LIST_ENTRY<Traits> InInitializationOrderModuleList;
};
template <class Traits>
struct LDR_DATA_TABLE_ENTRY {
LIST_ENTRY<Traits> InLoadOrderLinks;
LIST_ENTRY<Traits> InMemoryOrderLinks;
LIST_ENTRY<Traits> InInitializationOrderLinks;
typename Traits::Pointer DllBase;
typename Traits::Pointer EntryPoint;
union {
ULONG SizeOfImage;
typename Traits::Pad padding_for_x64;
};
UNICODE_STRING<Traits> FullDllName;
UNICODE_STRING<Traits> BaseDllName;
ULONG Flags;
USHORT ObsoleteLoadCount;
USHORT TlsIndex;
LIST_ENTRY<Traits> HashLinks;
ULONG TimeDateStamp;
};
template <class Traits>
struct CURDIR {
UNICODE_STRING<Traits> DosPath;
typename Traits::Pointer Handle;
};
template <class Traits>
struct STRING {
union {
struct {
USHORT Length;
USHORT MaximumLength;
};
typename Traits::Pad padding_for_x64;
};
typename Traits::Pointer Buffer;
};
template <class Traits>
struct RTL_DRIVE_LETTER_CURDIR {
WORD Flags;
WORD Length;
DWORD TimeStamp;
STRING<Traits> DosPath;
};
template <class Traits>
struct RTL_USER_PROCESS_PARAMETERS {
DWORD MaximumLength;
DWORD Length;
DWORD Flags;
DWORD DebugFlags;
typename Traits::Pointer ConsoleHandle;
union {
DWORD ConsoleFlags;
typename Traits::Pad padding_for_x64_0;
};
typename Traits::Pointer StandardInput;
typename Traits::Pointer StandardOutput;
typename Traits::Pointer StandardError;
CURDIR<Traits> CurrentDirectory;
UNICODE_STRING<Traits> DllPath;
UNICODE_STRING<Traits> ImagePathName;
UNICODE_STRING<Traits> CommandLine;
typename Traits::Pointer Environment;
DWORD StartingX;
DWORD StartingY;
DWORD CountX;
DWORD CountY;
DWORD CountCharsX;
DWORD CountCharsY;
DWORD FillAttribute;
DWORD WindowFlags;
union {
DWORD ShowWindowFlags;
typename Traits::Pad padding_for_x64_1;
};
UNICODE_STRING<Traits> WindowTitle;
UNICODE_STRING<Traits> DesktopInfo;
UNICODE_STRING<Traits> ShellInfo;
UNICODE_STRING<Traits> RuntimeData;
RTL_DRIVE_LETTER_CURDIR<Traits> CurrentDirectores[32]; // sic.
ULONG EnvironmentSize;
};
template <class T>
struct GdiHandleBufferCountForBitness;
template <>
struct GdiHandleBufferCountForBitness<internal::Traits32> {
enum { value = 34 };
};
template <>
struct GdiHandleBufferCountForBitness<internal::Traits64> {
enum { value = 60 };
};
template <class Traits>
struct PEB {
union {
struct {
BYTE InheritedAddressSpace;
BYTE ReadImageFileExecOptions;
BYTE BeingDebugged;
BYTE BitField;
};
typename Traits::Pad padding_for_x64_0;
};
typename Traits::Pointer Mutant;
typename Traits::Pointer ImageBaseAddress;
typename Traits::Pointer Ldr;
typename Traits::Pointer ProcessParameters;
typename Traits::Pointer SubSystemData;
typename Traits::Pointer ProcessHeap;
typename Traits::Pointer FastPebLock;
typename Traits::Pointer AtlThunkSListPtr;
typename Traits::Pointer IFEOKey;
union {
DWORD CrossProcessFlags;
typename Traits::Pad padding_for_x64_1;
};
typename Traits::Pointer KernelCallbackTable;
DWORD SystemReserved;
DWORD AtlThunkSListPtr32;
typename Traits::Pointer ApiSetMap;
union {
DWORD TlsExpansionCounter;
typename Traits::Pad padding_for_x64_2;
};
typename Traits::Pointer TlsBitmap;
DWORD TlsBitmapBits[2];
typename Traits::Pointer ReadOnlySharedMemoryBase;
typename Traits::Pointer SparePvoid0;
typename Traits::Pointer ReadOnlyStaticServerData;
typename Traits::Pointer AnsiCodePageData;
typename Traits::Pointer OemCodePageData;
typename Traits::Pointer UnicodeCaseTableData;
DWORD NumberOfProcessors;
DWORD NtGlobalFlag;
DWORD alignment_for_x86;
LARGE_INTEGER CriticalSectionTimeout;
typename Traits::UnsignedIntegral HeapSegmentReserve;
typename Traits::UnsignedIntegral HeapSegmentCommit;
typename Traits::UnsignedIntegral HeapDeCommitTotalFreeThreshold;
typename Traits::UnsignedIntegral HeapDeCommitFreeBlockThreshold;
DWORD NumberOfHeaps;
DWORD MaximumNumberOfHeaps;
typename Traits::Pointer ProcessHeaps;
typename Traits::Pointer GdiSharedHandleTable;
typename Traits::Pointer ProcessStarterHelper;
DWORD GdiDCAttributeList;
typename Traits::Pointer LoaderLock;
DWORD OSMajorVersion;
DWORD OSMinorVersion;
WORD OSBuildNumber;
WORD OSCSDVersion;
DWORD OSPlatformId;
DWORD ImageSubsystem;
DWORD ImageSubsystemMajorVersion;
union {
DWORD ImageSubsystemMinorVersion;
typename Traits::Pad padding_for_x64_3;
};
typename Traits::UnsignedIntegral ActiveProcessAffinityMask;
DWORD GdiHandleBuffer[GdiHandleBufferCountForBitness<Traits>::value];
typename Traits::Pointer PostProcessInitRoutine;
typename Traits::Pointer TlsExpansionBitmap;
DWORD TlsExpansionBitmapBits[32];
union {
DWORD SessionId;
typename Traits::Pad padding_for_x64_4;
};
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
typename Traits::Pointer pShimData;
typename Traits::Pointer AppCompatInfo;
UNICODE_STRING<Traits> CSDVersion;
typename Traits::Pointer ActivationContextData;
typename Traits::Pointer ProcessAssemblyStorageMap;
typename Traits::Pointer SystemDefaultActivationContextData;
typename Traits::Pointer SystemAssemblyStorageMap;
typename Traits::UnsignedIntegral MinimumStackCommit;
typename Traits::Pointer FlsCallback;
LIST_ENTRY<Traits> FlsListHead;
typename Traits::Pointer FlsBitmap;
DWORD FlsBitmapBits[4];
DWORD FlsHighIndex;
};
template <class Traits>
struct NT_TIB {
union {
// See https://msdn.microsoft.com/library/dn424783.aspx.
typename Traits::Pointer Wow64Teb;
struct {
typename Traits::Pointer ExceptionList;
typename Traits::Pointer StackBase;
typename Traits::Pointer StackLimit;
typename Traits::Pointer SubSystemTib;
union {
typename Traits::Pointer FiberData;
BYTE Version[4];
};
typename Traits::Pointer ArbitraryUserPointer;
typename Traits::Pointer Self;
};
};
};
// See https://msdn.microsoft.com/library/gg750647.aspx.
template <class Traits>
struct CLIENT_ID {
typename Traits::Pointer UniqueProcess;
typename Traits::Pointer UniqueThread;
};
// This is a partial definition of the TEB, as we do not currently use many
// fields of it. See https://nirsoft.net/kernel_struct/vista/TEB.html, and the
// (arch-specific) definition of _TEB in winternl.h.
template <class Traits>
struct TEB {
NT_TIB<Traits> NtTib;
typename Traits::Pointer EnvironmentPointer;
CLIENT_ID<Traits> ClientId;
typename Traits::Pointer ActiveRpcHandle;
typename Traits::Pointer ThreadLocalStoragePointer;
typename Traits::Pointer ProcessEnvironmentBlock;
typename Traits::Pointer RemainderOfReserved2[399];
BYTE Reserved3[1952];
typename Traits::Pointer TlsSlots[64];
BYTE Reserved4[8];
typename Traits::Pointer Reserved5[26];
typename Traits::Pointer ReservedForOle;
typename Traits::Pointer Reserved6[4];
typename Traits::Pointer TlsExpansionSlots;
};
// See https://msdn.microsoft.com/library/gg750724.aspx.
template <class Traits>
struct SYSTEM_THREAD_INFORMATION {
union {
struct {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
union {
ULONG WaitTime;
typename Traits::Pad padding_for_x64_0;
};
typename Traits::Pointer StartAddress;
CLIENT_ID<Traits> ClientId;
LONG Priority;
LONG BasePriority;
ULONG ContextSwitches;
ULONG ThreadState;
union {
ULONG WaitReason;
typename Traits::Pad padding_for_x64_1;
};
};
LARGE_INTEGER alignment_for_x86[8];
};
};
// There's an extra field in the x64 VM_COUNTERS (or maybe it's VM_COUNTERS_EX,
// it's not clear), so we just make separate specializations for 32/64.
template <class Traits>
struct VM_COUNTERS {};
template <>
struct VM_COUNTERS<internal::Traits32> {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
};
template <>
struct VM_COUNTERS<internal::Traits64> {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
union {
ULONG PageFaultCount;
internal::Traits64::Pad padding_for_x64;
};
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivateUsage;
};
// https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/System%20Information/Structures/SYSTEM_PROCESS_INFORMATION.html
template <class Traits>
struct SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER WorkingSetPrivateSize;
ULONG HardFaultCount;
ULONG NumberOfThreadsHighWatermark;
ULONGLONG CycleTime;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING<Traits> ImageName;
union {
LONG BasePriority;
typename Traits::Pad padding_for_x64_0;
};
union {
DWORD UniqueProcessId;
typename Traits::Pad padding_for_x64_1;
};
union {
DWORD InheritedFromUniqueProcessId;
typename Traits::Pad padding_for_x64_2;
};
ULONG HandleCount;
ULONG SessionId;
typename Traits::Pointer UniqueProcessKey;
union {
VM_COUNTERS<Traits> VirtualMemoryCounters;
LARGE_INTEGER alignment_for_x86[6];
};
IO_COUNTERS IoCounters;
SYSTEM_THREAD_INFORMATION<Traits> Threads[1];
};
// https://undocumented.ntinternals.net/source/usermode/structures/THREAD_BASIC_INFORMATION.html
template <class Traits>
struct THREAD_BASIC_INFORMATION {
union {
LONG ExitStatus;
typename Traits::Pad padding_for_x64_0;
};
typename Traits::Pointer TebBaseAddress;
CLIENT_ID<Traits> ClientId;
typename Traits::Pointer AffinityMask;
ULONG Priority;
LONG BasePriority;
};
template <class Traits>
struct EXCEPTION_POINTERS {
typename Traits::Pointer ExceptionRecord;
typename Traits::Pointer ContextRecord;
};
using EXCEPTION_POINTERS32 = EXCEPTION_POINTERS<internal::Traits32>;
using EXCEPTION_POINTERS64 = EXCEPTION_POINTERS<internal::Traits64>;
// This is defined in winnt.h, but not for cross-bitness.
template <class Traits>
struct RTL_CRITICAL_SECTION {
typename Traits::Pointer DebugInfo;
LONG LockCount;
LONG RecursionCount;
typename Traits::Pointer OwningThread;
typename Traits::Pointer LockSemaphore;
typename Traits::UnsignedIntegral SpinCount;
};
template <class Traits>
struct RTL_CRITICAL_SECTION_DEBUG {
union {
struct {
WORD Type;
WORD CreatorBackTraceIndex;
};
typename Traits::Pad alignment_for_x64;
};
typename Traits::Pointer CriticalSection;
LIST_ENTRY<Traits> ProcessLocksList;
DWORD EntryCount;
DWORD ContentionCount;
DWORD Flags;
WORD CreatorBackTraceIndexHigh;
WORD SpareWORD;
};
struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX {
void* Object;
ULONG_PTR UniqueProcessId;
HANDLE HandleValue;
ULONG GrantedAccess;
USHORT CreatorBackTraceIndex;
USHORT ObjectTypeIndex;
ULONG HandleAttributes;
ULONG Reserved;
};
struct SYSTEM_HANDLE_INFORMATION_EX {
ULONG_PTR NumberOfHandles;
ULONG_PTR Reserved;
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
};
#pragma pack(pop)
//! \}
} // namespace process_types
} // namespace crashpad
#endif // CRASHPAD_UTIL_WIN_PROCESS_STRUCTS_H_