// Copyright 2015 The Crashpad Authors. All rights reserved. // // 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 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 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 struct LIST_ENTRY { typename Traits::Pointer Flink; typename Traits::Pointer Blink; }; template struct UNICODE_STRING { union { struct { USHORT Length; USHORT MaximumLength; }; typename Traits::Pad padding_for_x64; }; typename Traits::Pointer Buffer; }; template struct PEB_LDR_DATA { ULONG Length; DWORD Initialized; typename Traits::Pointer SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; }; template struct LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; typename Traits::Pointer DllBase; typename Traits::Pointer EntryPoint; union { ULONG SizeOfImage; typename Traits::Pad padding_for_x64; }; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT ObsoleteLoadCount; USHORT TlsIndex; LIST_ENTRY HashLinks; ULONG TimeDateStamp; }; template struct CURDIR { UNICODE_STRING DosPath; typename Traits::Pointer Handle; }; template struct STRING { union { struct { DWORD Length; DWORD MaximumLength; }; typename Traits::Pad padding_for_x64; }; typename Traits::Pointer Buffer; }; template struct RTL_DRIVE_LETTER_CURDIR { WORD Flags; WORD Length; DWORD TimeStamp; STRING DosPath; }; template 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; }; typename Traits::Pointer StandardInput; typename Traits::Pointer StandardOutput; typename Traits::Pointer StandardError; CURDIR CurrentDirectory; UNICODE_STRING DllPath; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; typename Traits::Pointer Environment; DWORD StartingX; DWORD StartingY; DWORD CountX; DWORD CountY; DWORD CountCharsX; DWORD CountCharsY; DWORD FillAttribute; DWORD WindowFlags; DWORD ShowWindowFlags; UNICODE_STRING WindowTitle; UNICODE_STRING DesktopInfo; UNICODE_STRING ShellInfo; UNICODE_STRING RuntimeData; RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32]; // sic. }; template struct GdiHandleBufferCountForBitness; template <> struct GdiHandleBufferCountForBitness { enum { value = 34 }; }; template <> struct GdiHandleBufferCountForBitness { enum { value = 60 }; }; template 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::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 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 FlsListHead; typename Traits::Pointer FlsBitmap; DWORD FlsBitmapBits[4]; DWORD FlsHighIndex; }; template struct NT_TIB { union { // See https://msdn.microsoft.com/en-us/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/en-us/library/gg750647.aspx. template 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 http://www.nirsoft.net/kernel_struct/vista/TEB.html, and // the (arch-specific) definition of _TEB in winternl.h. template struct TEB { NT_TIB NtTib; typename Traits::Pointer ProcessEnvironmentBlock; CLIENT_ID ClientId; // Not identical to Reserved2 in winternl's _TEB because we define ClientId. typename Traits::Pointer RemainderOfReserved2[397]; 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/en-us/library/gg750724.aspx. template 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 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 struct VM_COUNTERS {}; template <> struct VM_COUNTERS { 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 { 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; }; // See http://undocumented.ntinternals.net/source/usermode/undocumented%20functions/system%20information/structures/system_process_information.html template 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 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 VirtualMemoryCounters; LARGE_INTEGER alignment_for_x86[6]; }; IO_COUNTERS IoCounters; SYSTEM_THREAD_INFORMATION Threads[1]; }; // http://undocumented.ntinternals.net/source/usermode/structures/thread_basic_information.html template struct THREAD_BASIC_INFORMATION { union { LONG ExitStatus; typename Traits::Pad padding_for_x64_0; }; typename Traits::Pointer TebBaseAddress; CLIENT_ID ClientId; typename Traits::Pointer AffinityMask; ULONG Priority; LONG BasePriority; }; template struct EXCEPTION_POINTERS { typename Traits::Pointer ExceptionRecord; typename Traits::Pointer ContextRecord; }; using EXCEPTION_POINTERS32 = EXCEPTION_POINTERS; using EXCEPTION_POINTERS64 = EXCEPTION_POINTERS; // This is defined in winnt.h, but not for cross-bitness. template 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 struct RTL_CRITICAL_SECTION_DEBUG { union { struct { WORD Type; WORD CreatorBackTraceIndex; }; typename Traits::Pad alignment_for_x64; }; typename Traits::Pointer CriticalSection; LIST_ENTRY 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_