Process Hacker
phsup.h
Go to the documentation of this file.
1 #ifndef _PH_PHSUP_H
2 #define _PH_PHSUP_H
3 
4 // This header file provides some useful definitions specific to phlib.
5 
6 #include <intrin.h>
7 #include <wchar.h>
8 #include <assert.h>
9 #include <stdio.h>
10 
11 // Memory
12 
13 #define PTR_ADD_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset)))
14 #define PTR_SUB_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) - (ULONG_PTR)(Offset)))
15 #define ALIGN_UP_BY(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1))
16 #define ALIGN_UP_POINTER_BY(Pointer, Align) ((PVOID)ALIGN_UP_BY(Pointer, Align))
17 #define ALIGN_UP(Address, Type) ALIGN_UP_BY(Address, sizeof(Type))
18 #define ALIGN_UP_POINTER(Pointer, Type) ((PVOID)ALIGN_UP(Pointer, Type))
19 
20 #define PAGE_SIZE 0x1000
21 
22 #define PH_LARGE_BUFFER_SIZE (256 * 1024 * 1024)
23 
24 // Exceptions
25 
26 #define PhRaiseStatus(Status) RtlRaiseStatus(Status)
27 
28 #define SIMPLE_EXCEPTION_FILTER(Condition) \
29  ((Condition) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
30 
31 // Compiler
32 
33 #ifdef DEBUG
34 #define ASSUME_ASSERT(Expression) assert(Expression)
35 #define ASSUME_NO_DEFAULT assert(FALSE)
36 #else
37 #define ASSUME_ASSERT(Expression) __assume(Expression)
38 #define ASSUME_NO_DEFAULT __assume(FALSE)
39 #endif
40 
41 // Time
42 
43 #define PH_TICKS_PER_NS ((LONG64)1 * 10)
44 #define PH_TICKS_PER_MS (PH_TICKS_PER_NS * 1000)
45 #define PH_TICKS_PER_SEC (PH_TICKS_PER_MS * 1000)
46 #define PH_TICKS_PER_MIN (PH_TICKS_PER_SEC * 60)
47 #define PH_TICKS_PER_HOUR (PH_TICKS_PER_MIN * 60)
48 #define PH_TICKS_PER_DAY (PH_TICKS_PER_HOUR * 24)
49 
50 #define PH_TICKS_PARTIAL_MS(Ticks) (((ULONG64)(Ticks) / PH_TICKS_PER_MS) % 1000)
51 #define PH_TICKS_PARTIAL_SEC(Ticks) (((ULONG64)(Ticks) / PH_TICKS_PER_SEC) % 60)
52 #define PH_TICKS_PARTIAL_MIN(Ticks) (((ULONG64)(Ticks) / PH_TICKS_PER_MIN) % 60)
53 #define PH_TICKS_PARTIAL_HOURS(Ticks) (((ULONG64)(Ticks) / PH_TICKS_PER_HOUR) % 24)
54 #define PH_TICKS_PARTIAL_DAYS(Ticks) ((ULONG64)(Ticks) / PH_TICKS_PER_DAY)
55 
56 #define PH_TIMEOUT_MS PH_TICKS_PER_MS
57 #define PH_TIMEOUT_SEC PH_TICKS_PER_SEC
58 
59 // Annotations
60 
74 #define _Assume_refs_(count)
75 
76 #define _Callback_
77 
86 #define _May_raise_
87 
92 #define _Needs_align_(align)
93 
94 // Casts
95 
96 // Zero extension and sign extension macros
97 #define C_1uTo2(x) ((unsigned short)(unsigned char)(x))
98 #define C_1sTo2(x) ((unsigned short)(signed char)(x))
99 #define C_1uTo4(x) ((unsigned int)(unsigned char)(x))
100 #define C_1sTo4(x) ((unsigned int)(signed char)(x))
101 #define C_2uTo4(x) ((unsigned int)(unsigned short)(x))
102 #define C_2sTo4(x) ((unsigned int)(signed short)(x))
103 #define C_4uTo8(x) ((unsigned __int64)(unsigned int)(x))
104 #define C_4sTo8(x) ((unsigned __int64)(signed int)(x))
105 
106 // Sorting
107 
108 typedef enum _PH_SORT_ORDER
109 {
114 
115 FORCEINLINE LONG PhModifySort(
116  _In_ LONG Result,
117  _In_ PH_SORT_ORDER Order
118  )
119 {
120  if (Order == AscendingSortOrder)
121  return Result;
122  else if (Order == DescendingSortOrder)
123  return -Result;
124  else
125  return Result;
126 }
127 
128 #define PH_BUILTIN_COMPARE(value1, value2) \
129  if (value1 > value2) \
130  return 1; \
131  else if (value1 < value2) \
132  return -1; \
133  \
134  return 0
135 
136 FORCEINLINE int charcmp(
137  _In_ signed char value1,
138  _In_ signed char value2
139  )
140 {
141  return C_1sTo4(value1 - value2);
142 }
143 
144 FORCEINLINE int ucharcmp(
145  _In_ unsigned char value1,
146  _In_ unsigned char value2
147  )
148 {
149  PH_BUILTIN_COMPARE(value1, value2);
150 }
151 
152 FORCEINLINE int shortcmp(
153  _In_ signed short value1,
154  _In_ signed short value2
155  )
156 {
157  return C_2sTo4(value1 - value2);
158 }
159 
160 FORCEINLINE int ushortcmp(
161  _In_ unsigned short value1,
162  _In_ unsigned short value2
163  )
164 {
165  PH_BUILTIN_COMPARE(value1, value2);
166 }
167 
168 FORCEINLINE int intcmp(
169  _In_ int value1,
170  _In_ int value2
171  )
172 {
173  return value1 - value2;
174 }
175 
176 FORCEINLINE int uintcmp(
177  _In_ unsigned int value1,
178  _In_ unsigned int value2
179  )
180 {
181  PH_BUILTIN_COMPARE(value1, value2);
182 }
183 
184 FORCEINLINE int int64cmp(
185  _In_ __int64 value1,
186  _In_ __int64 value2
187  )
188 {
189  PH_BUILTIN_COMPARE(value1, value2);
190 }
191 
192 FORCEINLINE int uint64cmp(
193  _In_ unsigned __int64 value1,
194  _In_ unsigned __int64 value2
195  )
196 {
197  PH_BUILTIN_COMPARE(value1, value2);
198 }
199 
200 FORCEINLINE int intptrcmp(
201  _In_ LONG_PTR value1,
202  _In_ LONG_PTR value2
203  )
204 {
205  PH_BUILTIN_COMPARE(value1, value2);
206 }
207 
208 FORCEINLINE int uintptrcmp(
209  _In_ ULONG_PTR value1,
210  _In_ ULONG_PTR value2
211  )
212 {
213  PH_BUILTIN_COMPARE(value1, value2);
214 }
215 
216 FORCEINLINE int singlecmp(
217  _In_ float value1,
218  _In_ float value2
219  )
220 {
221  PH_BUILTIN_COMPARE(value1, value2);
222 }
223 
224 FORCEINLINE int doublecmp(
225  _In_ double value1,
226  _In_ double value2
227  )
228 {
229  PH_BUILTIN_COMPARE(value1, value2);
230 }
231 
232 FORCEINLINE int wcsicmp2(
233  _In_opt_ PWSTR Value1,
234  _In_opt_ PWSTR Value2
235  )
236 {
237  if (Value1 && Value2)
238  return wcsicmp(Value1, Value2);
239  else if (!Value1)
240  return !Value2 ? 0 : -1;
241  else
242  return 1;
243 }
244 
245 typedef int (__cdecl *PC_COMPARE_FUNCTION)(void *, const void *, const void *);
246 
247 // Synchronization
248 
249 #ifndef _WIN64
250 
251 #ifndef _InterlockedCompareExchangePointer
253  void *volatile *Destination,
254  void *Exchange,
255  void *Comparand
256  );
257 #endif
258 
259 #ifndef _InterlockedExchangePointer
260 FORCEINLINE void *_InterlockedExchangePointer(
261  void *volatile *Destination,
262  void *Exchange
263  )
264 {
265  return (PVOID)_InterlockedExchange(
266  (PLONG_PTR)Destination,
267  (LONG_PTR)Exchange
268  );
269 }
270 #endif
271 
272 #endif
273 
274 FORCEINLINE LONG_PTR _InterlockedExchangeAddPointer(
275  _Inout_ _Interlocked_operand_ LONG_PTR volatile *Addend,
276  _In_ LONG_PTR Value
277  )
278 {
279 #ifdef _WIN64
280  return (LONG_PTR)_InterlockedExchangeAdd64((PLONG64)Addend, (LONG64)Value);
281 #else
282  return (LONG_PTR)_InterlockedExchangeAdd((PLONG)Addend, (LONG)Value);
283 #endif
284 }
285 
286 FORCEINLINE LONG_PTR _InterlockedIncrementPointer(
287  _Inout_ _Interlocked_operand_ LONG_PTR volatile *Addend
288  )
289 {
290 #ifdef _WIN64
291  return (LONG_PTR)_InterlockedIncrement64((PLONG64)Addend);
292 #else
293  return (LONG_PTR)_InterlockedIncrement((PLONG)Addend);
294 #endif
295 }
296 
297 FORCEINLINE LONG_PTR _InterlockedDecrementPointer(
298  _Inout_ _Interlocked_operand_ LONG_PTR volatile *Addend
299  )
300 {
301 #ifdef _WIN64
302  return (LONG_PTR)_InterlockedDecrement64((PLONG64)Addend);
303 #else
304  return (LONG_PTR)_InterlockedDecrement((PLONG)Addend);
305 #endif
306 }
307 
309  _Inout_ _Interlocked_operand_ LONG_PTR volatile *Base,
310  _In_ LONG_PTR Bit
311  )
312 {
313 #ifdef _WIN64
314  return _interlockedbittestandreset64((PLONG64)Base, (LONG64)Bit);
315 #else
316  return _interlockedbittestandreset((PLONG)Base, (LONG)Bit);
317 #endif
318 }
319 
321  _Inout_ _Interlocked_operand_ LONG_PTR volatile *Base,
322  _In_ LONG_PTR Bit
323  )
324 {
325 #ifdef _WIN64
326  return _interlockedbittestandset64((PLONG64)Base, (LONG64)Bit);
327 #else
328  return _interlockedbittestandset((PLONG)Base, (LONG)Bit);
329 #endif
330 }
331 
332 FORCEINLINE BOOLEAN _InterlockedIncrementNoZero(
333  _Inout_ _Interlocked_operand_ LONG volatile *Addend
334  )
335 {
336  LONG value;
337  LONG newValue;
338 
339  value = *Addend;
340 
341  while (TRUE)
342  {
343  if (value == 0)
344  return FALSE;
345 
346  if ((newValue = _InterlockedCompareExchange(
347  Addend,
348  value + 1,
349  value
350  )) == value)
351  {
352  return TRUE;
353  }
354 
355  value = newValue;
356  }
357 }
358 
359 // Strings
360 
361 #define PH_INT32_STR_LEN 12
362 #define PH_INT32_STR_LEN_1 (PH_INT32_STR_LEN + 1)
363 
364 #define PH_INT64_STR_LEN 50
365 #define PH_INT64_STR_LEN_1 (PH_INT64_STR_LEN + 1)
366 
367 #define PH_PTR_STR_LEN 24
368 #define PH_PTR_STR_LEN_1 (PH_PTR_STR_LEN + 1)
369 
370 FORCEINLINE VOID PhPrintInt32(
371  _Out_writes_(PH_INT32_STR_LEN_1) PWSTR Destination,
372  _In_ LONG Int32
373  )
374 {
375  _ltow(Int32, Destination, 10);
376 }
377 
378 FORCEINLINE VOID PhPrintUInt32(
379  _Out_writes_(PH_INT32_STR_LEN_1) PWSTR Destination,
380  _In_ ULONG UInt32
381  )
382 {
383  _ultow(UInt32, Destination, 10);
384 }
385 
386 FORCEINLINE VOID PhPrintInt64(
387  _Out_writes_(PH_INT64_STR_LEN_1) PWSTR Destination,
388  _In_ LONG64 Int64
389  )
390 {
391  _i64tow(Int64, Destination, 10);
392 }
393 
394 FORCEINLINE VOID PhPrintUInt64(
395  _Out_writes_(PH_INT64_STR_LEN_1) PWSTR Destination,
396  _In_ ULONG64 UInt64
397  )
398 {
399  _ui64tow(UInt64, Destination, 10);
400 }
401 
402 FORCEINLINE VOID PhPrintPointer(
403  _Out_writes_(PH_PTR_STR_LEN_1) PWSTR Destination,
404  _In_ PVOID Pointer
405  )
406 {
407  Destination[0] = '0';
408  Destination[1] = 'x';
409 #ifdef _WIN64
410  _ui64tow((ULONG64)Pointer, &Destination[2], 16);
411 #else
412  _ultow((ULONG)Pointer, &Destination[2], 16);
413 #endif
414 }
415 
416 // Misc.
417 
418 FORCEINLINE ULONG PhCountBits(
419  _In_ ULONG Value
420  )
421 {
422  ULONG count = 0;
423 
424  while (Value)
425  {
426  count++;
427  Value &= Value - 1;
428  }
429 
430  return count;
431 }
432 
433 FORCEINLINE ULONG PhRoundNumber(
434  _In_ ULONG Value,
435  _In_ ULONG Multiplier
436  )
437 {
438  ULONG newValue;
439 
440  newValue = Value / Multiplier * Multiplier;
441 
442  // This new value has the multiplier truncated.
443  // E.g. 1099 / 100 * 100 = 1000.
444  // If the difference is less than half the multiplier,
445  // use the new value.
446  // E.g.
447  // 1099 -> 1000 (100). 1099 - 1000 >= 50, so use
448  // the new value plus the multiplier.
449  // 1010 -> 1000 (100). 1010 - 1000 < 50, so use
450  // the new value.
451 
452  if (Value - newValue < Multiplier / 2)
453  return newValue;
454  else
455  return newValue + Multiplier;
456 }
457 
458 FORCEINLINE VOID PhProbeAddress(
459  _In_ PVOID UserAddress,
460  _In_ SIZE_T UserLength,
461  _In_ PVOID BufferAddress,
462  _In_ SIZE_T BufferLength,
463  _In_ ULONG Alignment
464  )
465 {
466  if (UserLength != 0)
467  {
468  if (((ULONG_PTR)UserAddress & (Alignment - 1)) != 0)
469  PhRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
470 
471  if (
472  ((ULONG_PTR)UserAddress + UserLength < (ULONG_PTR)UserAddress) ||
473  ((ULONG_PTR)UserAddress < (ULONG_PTR)BufferAddress) ||
474  ((ULONG_PTR)UserAddress + UserLength > (ULONG_PTR)BufferAddress + BufferLength)
475  )
476  PhRaiseStatus(STATUS_ACCESS_VIOLATION);
477  }
478 }
479 
480 FORCEINLINE PLARGE_INTEGER PhTimeoutFromMilliseconds(
481  _Out_ PLARGE_INTEGER Timeout,
482  _In_ ULONG Milliseconds
483  )
484 {
485  if (Milliseconds == INFINITE)
486  return NULL;
487 
488  Timeout->QuadPart = -(LONGLONG)UInt32x32To64(Milliseconds, PH_TIMEOUT_MS);
489 
490  return Timeout;
491 }
492 
493 FORCEINLINE NTSTATUS PhGetLastWin32ErrorAsNtStatus()
494 {
495  ULONG win32Result;
496 
497  // This is needed because NTSTATUS_FROM_WIN32 uses the argument multiple times.
498  win32Result = GetLastError();
499 
500  return NTSTATUS_FROM_WIN32(win32Result);
501 }
502 
503 FORCEINLINE PVOID PhGetModuleProcAddress(
504  _In_ PWSTR ModuleName,
505  _In_ PSTR ProcName
506  )
507 {
508  HMODULE module;
509 
510  module = GetModuleHandle(ModuleName);
511 
512  if (module)
513  return GetProcAddress(module, ProcName);
514  else
515  return NULL;
516 }
517 
518 #endif