1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef CRASHPAD_UTIL_WIN_PROCESS_STRUCTS_H_
16 #define CRASHPAD_UTIL_WIN_PROCESS_STRUCTS_H_
17 
18 #include <windows.h>
19 
20 namespace crashpad {
21 namespace process_types {
22 
23 namespace internal {
24 
25 struct Traits32 {
26   using Pad = DWORD;
27   using UnsignedIntegral = DWORD;
28   using Pointer = DWORD;
29 };
30 
31 struct Traits64 {
32   using Pad = DWORD64;
33   using UnsignedIntegral = DWORD64;
34   using Pointer = DWORD64;
35 };
36 
37 }  // namespace internal
38 
39 //! \{
40 
41 //! \brief Selected structures from winternl.h, ntddk.h, and `dt ntdll!xxx`,
42 //!     customized to have both x86 and x64 sizes available.
43 //!
44 //! The structure and field names follow the Windows names for clarity. We do,
45 //! however, use plain integral types rather than pointer types. This is both
46 //! easier to define, and avoids accidentally treating them as pointers into the
47 //! current address space.
48 //!
49 //! The templates below should be instantiated with either internal::Traits32
50 //! for structures targeting x86, or internal::Traits64 for x64.
51 
52 // We set packing to 1 so that we can explicitly control the layout to make it
53 // match the OS defined structures.
54 #pragma pack(push, 1)
55 
56 template <class Traits>
57 struct PROCESS_BASIC_INFORMATION {
58   union {
59     DWORD ExitStatus;
60     typename Traits::Pad padding_for_x64_0;
61   };
62   typename Traits::Pointer PebBaseAddress;
63   typename Traits::UnsignedIntegral AffinityMask;
64   union {
65     DWORD BasePriority;
66     typename Traits::Pad padding_for_x64_1;
67   };
68   typename Traits::UnsignedIntegral UniqueProcessId;
69   typename Traits::UnsignedIntegral InheritedFromUniqueProcessId;
70 };
71 
72 template <class Traits>
73 struct LIST_ENTRY {
74   typename Traits::Pointer Flink;
75   typename Traits::Pointer Blink;
76 };
77 
78 template <class Traits>
79 struct UNICODE_STRING {
80   union {
81     struct {
82       USHORT Length;
83       USHORT MaximumLength;
84     };
85     typename Traits::Pad padding_for_x64;
86   };
87   typename Traits::Pointer Buffer;
88 };
89 
90 template <class Traits>
91 struct PEB_LDR_DATA {
92   ULONG Length;
93   DWORD Initialized;
94   typename Traits::Pointer SsHandle;
95   LIST_ENTRY<Traits> InLoadOrderModuleList;
96   LIST_ENTRY<Traits> InMemoryOrderModuleList;
97   LIST_ENTRY<Traits> InInitializationOrderModuleList;
98 };
99 
100 template <class Traits>
101 struct LDR_DATA_TABLE_ENTRY {
102   LIST_ENTRY<Traits> InLoadOrderLinks;
103   LIST_ENTRY<Traits> InMemoryOrderLinks;
104   LIST_ENTRY<Traits> InInitializationOrderLinks;
105   typename Traits::Pointer DllBase;
106   typename Traits::Pointer EntryPoint;
107   union {
108     ULONG SizeOfImage;
109     typename Traits::Pad padding_for_x64;
110   };
111   UNICODE_STRING<Traits> FullDllName;
112   UNICODE_STRING<Traits> BaseDllName;
113   ULONG Flags;
114   USHORT ObsoleteLoadCount;
115   USHORT TlsIndex;
116   LIST_ENTRY<Traits> HashLinks;
117   ULONG TimeDateStamp;
118 };
119 
120 template <class Traits>
121 struct CURDIR {
122   UNICODE_STRING<Traits> DosPath;
123   typename Traits::Pointer Handle;
124 };
125 
126 template <class Traits>
127 struct STRING {
128   union {
129     struct {
130       USHORT Length;
131       USHORT MaximumLength;
132     };
133     typename Traits::Pad padding_for_x64;
134   };
135   typename Traits::Pointer Buffer;
136 };
137 
138 template <class Traits>
139 struct RTL_DRIVE_LETTER_CURDIR {
140   WORD Flags;
141   WORD Length;
142   DWORD TimeStamp;
143   STRING<Traits> DosPath;
144 };
145 
146 template <class Traits>
147 struct RTL_USER_PROCESS_PARAMETERS {
148   DWORD MaximumLength;
149   DWORD Length;
150   DWORD Flags;
151   DWORD DebugFlags;
152   typename Traits::Pointer ConsoleHandle;
153   union {
154     DWORD ConsoleFlags;
155     typename Traits::Pad padding_for_x64_0;
156   };
157   typename Traits::Pointer StandardInput;
158   typename Traits::Pointer StandardOutput;
159   typename Traits::Pointer StandardError;
160   CURDIR<Traits> CurrentDirectory;
161   UNICODE_STRING<Traits> DllPath;
162   UNICODE_STRING<Traits> ImagePathName;
163   UNICODE_STRING<Traits> CommandLine;
164   typename Traits::Pointer Environment;
165   DWORD StartingX;
166   DWORD StartingY;
167   DWORD CountX;
168   DWORD CountY;
169   DWORD CountCharsX;
170   DWORD CountCharsY;
171   DWORD FillAttribute;
172   DWORD WindowFlags;
173   union {
174     DWORD ShowWindowFlags;
175     typename Traits::Pad padding_for_x64_1;
176   };
177   UNICODE_STRING<Traits> WindowTitle;
178   UNICODE_STRING<Traits> DesktopInfo;
179   UNICODE_STRING<Traits> ShellInfo;
180   UNICODE_STRING<Traits> RuntimeData;
181   RTL_DRIVE_LETTER_CURDIR<Traits> CurrentDirectores[32];  // sic.
182   ULONG EnvironmentSize;
183 };
184 
185 template <class T>
186 struct GdiHandleBufferCountForBitness;
187 
188 template <>
189 struct GdiHandleBufferCountForBitness<internal::Traits32> {
190   enum { value = 34 };
191 };
192 template <>
193 struct GdiHandleBufferCountForBitness<internal::Traits64> {
194   enum { value = 60 };
195 };
196 
197 template <class Traits>
198 struct PEB {
199   union {
200     struct {
201       BYTE InheritedAddressSpace;
202       BYTE ReadImageFileExecOptions;
203       BYTE BeingDebugged;
204       BYTE BitField;
205     };
206     typename Traits::Pad padding_for_x64_0;
207   };
208   typename Traits::Pointer Mutant;
209   typename Traits::Pointer ImageBaseAddress;
210   typename Traits::Pointer Ldr;
211   typename Traits::Pointer ProcessParameters;
212   typename Traits::Pointer SubSystemData;
213   typename Traits::Pointer ProcessHeap;
214   typename Traits::Pointer FastPebLock;
215   typename Traits::Pointer AtlThunkSListPtr;
216   typename Traits::Pointer IFEOKey;
217   union {
218     DWORD CrossProcessFlags;
219     typename Traits::Pad padding_for_x64_1;
220   };
221   typename Traits::Pointer KernelCallbackTable;
222   DWORD SystemReserved;
223   DWORD AtlThunkSListPtr32;
224   typename Traits::Pointer ApiSetMap;
225   union {
226     DWORD TlsExpansionCounter;
227     typename Traits::Pad padding_for_x64_2;
228   };
229   typename Traits::Pointer TlsBitmap;
230   DWORD TlsBitmapBits[2];
231   typename Traits::Pointer ReadOnlySharedMemoryBase;
232   typename Traits::Pointer SparePvoid0;
233   typename Traits::Pointer ReadOnlyStaticServerData;
234   typename Traits::Pointer AnsiCodePageData;
235   typename Traits::Pointer OemCodePageData;
236   typename Traits::Pointer UnicodeCaseTableData;
237   DWORD NumberOfProcessors;
238   DWORD NtGlobalFlag;
239   DWORD alignment_for_x86;
240   LARGE_INTEGER CriticalSectionTimeout;
241   typename Traits::UnsignedIntegral HeapSegmentReserve;
242   typename Traits::UnsignedIntegral HeapSegmentCommit;
243   typename Traits::UnsignedIntegral HeapDeCommitTotalFreeThreshold;
244   typename Traits::UnsignedIntegral HeapDeCommitFreeBlockThreshold;
245   DWORD NumberOfHeaps;
246   DWORD MaximumNumberOfHeaps;
247   typename Traits::Pointer ProcessHeaps;
248   typename Traits::Pointer GdiSharedHandleTable;
249   typename Traits::Pointer ProcessStarterHelper;
250   DWORD GdiDCAttributeList;
251   typename Traits::Pointer LoaderLock;
252   DWORD OSMajorVersion;
253   DWORD OSMinorVersion;
254   WORD OSBuildNumber;
255   WORD OSCSDVersion;
256   DWORD OSPlatformId;
257   DWORD ImageSubsystem;
258   DWORD ImageSubsystemMajorVersion;
259   union {
260     DWORD ImageSubsystemMinorVersion;
261     typename Traits::Pad padding_for_x64_3;
262   };
263   typename Traits::UnsignedIntegral ActiveProcessAffinityMask;
264   DWORD GdiHandleBuffer[GdiHandleBufferCountForBitness<Traits>::value];
265   typename Traits::Pointer PostProcessInitRoutine;
266   typename Traits::Pointer TlsExpansionBitmap;
267   DWORD TlsExpansionBitmapBits[32];
268   union {
269     DWORD SessionId;
270     typename Traits::Pad padding_for_x64_4;
271   };
272   ULARGE_INTEGER AppCompatFlags;
273   ULARGE_INTEGER AppCompatFlagsUser;
274   typename Traits::Pointer pShimData;
275   typename Traits::Pointer AppCompatInfo;
276   UNICODE_STRING<Traits> CSDVersion;
277   typename Traits::Pointer ActivationContextData;
278   typename Traits::Pointer ProcessAssemblyStorageMap;
279   typename Traits::Pointer SystemDefaultActivationContextData;
280   typename Traits::Pointer SystemAssemblyStorageMap;
281   typename Traits::UnsignedIntegral MinimumStackCommit;
282   typename Traits::Pointer FlsCallback;
283   LIST_ENTRY<Traits> FlsListHead;
284   typename Traits::Pointer FlsBitmap;
285   DWORD FlsBitmapBits[4];
286   DWORD FlsHighIndex;
287 };
288 
289 template <class Traits>
290 struct NT_TIB {
291   union {
292     // See https://msdn.microsoft.com/library/dn424783.aspx.
293     typename Traits::Pointer Wow64Teb;
294     struct {
295       typename Traits::Pointer ExceptionList;
296       typename Traits::Pointer StackBase;
297       typename Traits::Pointer StackLimit;
298       typename Traits::Pointer SubSystemTib;
299       union {
300         typename Traits::Pointer FiberData;
301         BYTE Version[4];
302       };
303       typename Traits::Pointer ArbitraryUserPointer;
304       typename Traits::Pointer Self;
305     };
306   };
307 };
308 
309 // See https://msdn.microsoft.com/library/gg750647.aspx.
310 template <class Traits>
311 struct CLIENT_ID {
312   typename Traits::Pointer UniqueProcess;
313   typename Traits::Pointer UniqueThread;
314 };
315 
316 // This is a partial definition of the TEB, as we do not currently use many
317 // fields of it. See https://nirsoft.net/kernel_struct/vista/TEB.html, and the
318 // (arch-specific) definition of _TEB in winternl.h.
319 template <class Traits>
320 struct TEB {
321   NT_TIB<Traits> NtTib;
322   typename Traits::Pointer EnvironmentPointer;
323   CLIENT_ID<Traits> ClientId;
324   typename Traits::Pointer ActiveRpcHandle;
325   typename Traits::Pointer ThreadLocalStoragePointer;
326   typename Traits::Pointer ProcessEnvironmentBlock;
327   typename Traits::Pointer RemainderOfReserved2[399];
328   BYTE Reserved3[1952];
329   typename Traits::Pointer TlsSlots[64];
330   BYTE Reserved4[8];
331   typename Traits::Pointer Reserved5[26];
332   typename Traits::Pointer ReservedForOle;
333   typename Traits::Pointer Reserved6[4];
334   typename Traits::Pointer TlsExpansionSlots;
335 };
336 
337 // See https://msdn.microsoft.com/library/gg750724.aspx.
338 template <class Traits>
339 struct SYSTEM_THREAD_INFORMATION {
340   union {
341     struct {
342       LARGE_INTEGER KernelTime;
343       LARGE_INTEGER UserTime;
344       LARGE_INTEGER CreateTime;
345       union {
346         ULONG WaitTime;
347         typename Traits::Pad padding_for_x64_0;
348       };
349       typename Traits::Pointer StartAddress;
350       CLIENT_ID<Traits> ClientId;
351       LONG Priority;
352       LONG BasePriority;
353       ULONG ContextSwitches;
354       ULONG ThreadState;
355       union {
356         ULONG WaitReason;
357         typename Traits::Pad padding_for_x64_1;
358       };
359     };
360     LARGE_INTEGER alignment_for_x86[8];
361   };
362 };
363 
364 // There's an extra field in the x64 VM_COUNTERS (or maybe it's VM_COUNTERS_EX,
365 // it's not clear), so we just make separate specializations for 32/64.
366 template <class Traits>
367 struct VM_COUNTERS {};
368 
369 template <>
370 struct VM_COUNTERS<internal::Traits32> {
371   SIZE_T PeakVirtualSize;
372   SIZE_T VirtualSize;
373   ULONG PageFaultCount;
374   SIZE_T PeakWorkingSetSize;
375   SIZE_T WorkingSetSize;
376   SIZE_T QuotaPeakPagedPoolUsage;
377   SIZE_T QuotaPagedPoolUsage;
378   SIZE_T QuotaPeakNonPagedPoolUsage;
379   SIZE_T QuotaNonPagedPoolUsage;
380   SIZE_T PagefileUsage;
381   SIZE_T PeakPagefileUsage;
382 };
383 
384 template <>
385 struct VM_COUNTERS<internal::Traits64> {
386   SIZE_T PeakVirtualSize;
387   SIZE_T VirtualSize;
388   union {
389     ULONG PageFaultCount;
390     internal::Traits64::Pad padding_for_x64;
391   };
392   SIZE_T PeakWorkingSetSize;
393   SIZE_T WorkingSetSize;
394   SIZE_T QuotaPeakPagedPoolUsage;
395   SIZE_T QuotaPagedPoolUsage;
396   SIZE_T QuotaPeakNonPagedPoolUsage;
397   SIZE_T QuotaNonPagedPoolUsage;
398   SIZE_T PagefileUsage;
399   SIZE_T PeakPagefileUsage;
400   SIZE_T PrivateUsage;
401 };
402 
403 // https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/System%20Information/Structures/SYSTEM_PROCESS_INFORMATION.html
404 template <class Traits>
405 struct SYSTEM_PROCESS_INFORMATION {
406   ULONG NextEntryOffset;
407   ULONG NumberOfThreads;
408   LARGE_INTEGER WorkingSetPrivateSize;
409   ULONG HardFaultCount;
410   ULONG NumberOfThreadsHighWatermark;
411   ULONGLONG CycleTime;
412   LARGE_INTEGER CreateTime;
413   LARGE_INTEGER UserTime;
414   LARGE_INTEGER KernelTime;
415   UNICODE_STRING<Traits> ImageName;
416   union {
417     LONG BasePriority;
418     typename Traits::Pad padding_for_x64_0;
419   };
420   union {
421     DWORD UniqueProcessId;
422     typename Traits::Pad padding_for_x64_1;
423   };
424   union {
425     DWORD InheritedFromUniqueProcessId;
426     typename Traits::Pad padding_for_x64_2;
427   };
428   ULONG HandleCount;
429   ULONG SessionId;
430   typename Traits::Pointer UniqueProcessKey;
431   union {
432     VM_COUNTERS<Traits> VirtualMemoryCounters;
433     LARGE_INTEGER alignment_for_x86[6];
434   };
435   IO_COUNTERS IoCounters;
436   SYSTEM_THREAD_INFORMATION<Traits> Threads[1];
437 };
438 
439 // https://undocumented.ntinternals.net/source/usermode/structures/THREAD_BASIC_INFORMATION.html
440 template <class Traits>
441 struct THREAD_BASIC_INFORMATION {
442   union {
443     LONG ExitStatus;
444     typename Traits::Pad padding_for_x64_0;
445   };
446   typename Traits::Pointer TebBaseAddress;
447   CLIENT_ID<Traits> ClientId;
448   typename Traits::Pointer AffinityMask;
449   ULONG Priority;
450   LONG BasePriority;
451 };
452 
453 template <class Traits>
454 struct EXCEPTION_POINTERS {
455   typename Traits::Pointer ExceptionRecord;
456   typename Traits::Pointer ContextRecord;
457 };
458 
459 using EXCEPTION_POINTERS32 = EXCEPTION_POINTERS<internal::Traits32>;
460 using EXCEPTION_POINTERS64 = EXCEPTION_POINTERS<internal::Traits64>;
461 
462 // This is defined in winnt.h, but not for cross-bitness.
463 template <class Traits>
464 struct RTL_CRITICAL_SECTION {
465   typename Traits::Pointer DebugInfo;
466   LONG LockCount;
467   LONG RecursionCount;
468   typename Traits::Pointer OwningThread;
469   typename Traits::Pointer LockSemaphore;
470   typename Traits::UnsignedIntegral SpinCount;
471 };
472 
473 template <class Traits>
474 struct RTL_CRITICAL_SECTION_DEBUG {
475   union {
476     struct {
477       WORD Type;
478       WORD CreatorBackTraceIndex;
479     };
480     typename Traits::Pad alignment_for_x64;
481   };
482   typename Traits::Pointer CriticalSection;
483   LIST_ENTRY<Traits> ProcessLocksList;
484   DWORD EntryCount;
485   DWORD ContentionCount;
486   DWORD Flags;
487   WORD CreatorBackTraceIndexHigh;
488   WORD SpareWORD;
489 };
490 
491 struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX {
492   void* Object;
493   ULONG_PTR UniqueProcessId;
494   HANDLE HandleValue;
495   ULONG GrantedAccess;
496   USHORT CreatorBackTraceIndex;
497   USHORT ObjectTypeIndex;
498   ULONG HandleAttributes;
499   ULONG Reserved;
500 };
501 
502 struct SYSTEM_HANDLE_INFORMATION_EX {
503   ULONG_PTR NumberOfHandles;
504   ULONG_PTR Reserved;
505   SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
506 };
507 
508 #pragma pack(pop)
509 
510 //! \}
511 
512 }  // namespace process_types
513 }  // namespace crashpad
514 
515 #endif  // CRASHPAD_UTIL_WIN_PROCESS_STRUCTS_H_
516