Process Hacker
phbase.h
Go to the documentation of this file.
1 #ifndef _PH_PHBASE_H
2 #define _PH_PHBASE_H
3 
4 #pragma once
5 
6 #ifndef PHLIB_NO_DEFAULT_LIB
7 #pragma comment(lib, "ntdll.lib")
8 
9 #pragma comment(lib, "comctl32.lib")
10 #pragma comment(lib, "version.lib")
11 #endif
12 
13 // nonstandard extension used : nameless struct/union
14 #pragma warning(disable: 4201)
15 // nonstandard extension used : bit field types other than int
16 #pragma warning(disable: 4214)
17 // 'function': attributes not present on previous declaration
18 #pragma warning(disable: 4985)
19 // 'function': was declared deprecated
20 #pragma warning(disable: 4996)
21 
22 #ifndef UNICODE
23 #define UNICODE
24 #endif
25 
26 #if defined(PHLIB_EXPORT)
27 #define PHLIBAPI __declspec(dllexport)
28 #elif defined(PHLIB_IMPORT)
29 #define PHLIBAPI __declspec(dllimport)
30 #else
31 #define PHLIBAPI
32 #endif
33 
34 #include <ntwin.h>
35 #include <ntbasic.h>
36 #include <phnt.h>
37 #include <phsup.h>
38 #include <ref.h>
39 #include <fastlock.h>
40 #include <queuedlock.h>
41 
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45 
46 struct _PH_STRING;
47 typedef struct _PH_STRING *PPH_STRING;
48 
49 struct _PH_PROVIDER_THREAD;
51 
54 
55 #define _User_set_
56 
58 
60 PHLIBAPI extern ULONG PhCurrentSessionId;
62 PHLIBAPI extern BOOLEAN PhElevated;
63 PHLIBAPI extern TOKEN_ELEVATION_TYPE PhElevationType;
64 PHLIBAPI extern PVOID PhHeapHandle;
65 PHLIBAPI extern RTL_OSVERSIONINFOEXW PhOsVersion;
67 PHLIBAPI extern ULONG WindowsVersion;
68 
69 PHLIBAPI extern ACCESS_MASK ProcessQueryAccess;
70 PHLIBAPI extern ACCESS_MASK ProcessAllAccess;
71 PHLIBAPI extern ACCESS_MASK ThreadQueryAccess;
72 PHLIBAPI extern ACCESS_MASK ThreadSetAccess;
73 PHLIBAPI extern ACCESS_MASK ThreadAllAccess;
74 
75 #define WINDOWS_ANCIENT 0
76 #define WINDOWS_XP 51
77 #define WINDOWS_SERVER_2003 52
78 #define WINDOWS_VISTA 60
79 #define WINDOWS_7 61
80 #define WINDOWS_8 62
81 #define WINDOWS_8_1 63
82 #define WINDOWS_10 100
83 #define WINDOWS_NEW MAXLONG
84 
85 #define WINDOWS_HAS_CONSOLE_HOST (WindowsVersion >= WINDOWS_7)
86 #define WINDOWS_HAS_CYCLE_TIME (WindowsVersion >= WINDOWS_VISTA)
87 #define WINDOWS_HAS_IFILEDIALOG (WindowsVersion >= WINDOWS_VISTA)
88 #define WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID (WindowsVersion >= WINDOWS_VISTA)
89 #define WINDOWS_HAS_IMMERSIVE (WindowsVersion >= WINDOWS_8)
90 #define WINDOWS_HAS_LIMITED_ACCESS (WindowsVersion >= WINDOWS_VISTA)
91 #define WINDOWS_HAS_PSSUSPENDRESUMEPROCESS (WindowsVersion >= WINDOWS_VISTA)
92 #define WINDOWS_HAS_SERVICE_TAGS (WindowsVersion >= WINDOWS_VISTA)
93 #define WINDOWS_HAS_UAC (WindowsVersion >= WINDOWS_VISTA)
94 
95 // Debugging
96 
97 #ifdef DEBUG
98 #define dprintf(format, ...) DbgPrint(format, __VA_ARGS__)
99 #else
100 #define dprintf(format, ...)
101 #endif
102 
103 // global
104 
105 // Initialization flags
106 
107 // Features
108 
109 // Imports
110 
111 #define PHLIB_INIT_MODULE_RESERVED1 0x1
112 #define PHLIB_INIT_MODULE_RESERVED2 0x2
113 
114 #define PHLIB_INIT_MODULE_WORK_QUEUE 0x4
115 
116 #define PHLIB_INIT_MODULE_HANDLE_TABLE 0x8
117 
118 #define PHLIB_INIT_MODULE_IO_SUPPORT 0x10
119 
120 #define PHLIB_INIT_MODULE_SYMBOL_PROVIDER 0x20
121 #define PHLIB_INIT_MODULE_RESERVED3 0x40
122 
123 // Misc.
125 #define PHLIB_INIT_TOKEN_INFO 0x100000
126 
127 NTSTATUS
129  VOID
130  );
131 
132 NTSTATUS
134  _In_ ULONG Flags,
135  _In_opt_ SIZE_T HeapReserveSize,
136  _In_opt_ SIZE_T HeapCommitSize
137  );
138 
139 #ifdef _WIN64
140 FORCEINLINE
141 BOOLEAN
143  VOID
144  )
145 {
146  return FALSE;
147 }
148 #else
149 BOOLEAN
151  VOID
152  );
153 #endif
154 
155 // basesup
156 
157 struct _PH_OBJECT_TYPE;
159 
160 BOOLEAN
162  _In_ ULONG Flags
163  );
164 
165 // Threads
166 
167 #ifdef DEBUG
168 struct _PH_AUTO_POOL;
169 typedef struct _PH_AUTO_POOL *PPH_AUTO_POOL;
170 
171 typedef struct _PHP_BASE_THREAD_DBG
172 {
173  CLIENT_ID ClientId;
174  LIST_ENTRY ListEntry;
175  PVOID StartAddress;
176  PVOID Parameter;
177 
178  PPH_AUTO_POOL CurrentAutoPool;
179 } PHP_BASE_THREAD_DBG, *PPHP_BASE_THREAD_DBG;
180 
181 extern ULONG PhDbgThreadDbgTlsIndex;
182 extern LIST_ENTRY PhDbgThreadListHead;
183 extern PH_QUEUED_LOCK PhDbgThreadListLock;
184 #endif
185 
186 PHLIBAPI
187 HANDLE
188 NTAPI
190  _In_opt_ SIZE_T StackSize,
191  _In_ PUSER_THREAD_START_ROUTINE StartAddress,
192  _In_opt_ PVOID Parameter
193  );
194 
195 // DLLs
196 
197 FORCEINLINE
198 PVOID
200  _In_ PWSTR DllName
201  )
202 {
203  UNICODE_STRING dllName;
204  PVOID dllHandle;
205 
206  RtlInitUnicodeString(&dllName, DllName);
207 
208  if (NT_SUCCESS(LdrGetDllHandle(NULL, NULL, &dllName, &dllHandle)))
209  return dllHandle;
210  else
211  return NULL;
212 }
213 
214 FORCEINLINE
215 PVOID
217  _In_ PVOID DllHandle,
218  _In_opt_ PSTR ProcedureName,
219  _In_opt_ ULONG ProcedureNumber
220  )
221 {
222  NTSTATUS status;
223  ANSI_STRING procedureName;
224  PVOID procedureAddress;
225 
226  if (ProcedureName)
227  {
228  RtlInitAnsiString(&procedureName, ProcedureName);
229  status = LdrGetProcedureAddress(
230  DllHandle,
231  &procedureName,
232  0,
233  &procedureAddress
234  );
235  }
236  else
237  {
238  status = LdrGetProcedureAddress(
239  DllHandle,
240  NULL,
241  ProcedureNumber,
242  &procedureAddress
243  );
244  }
245 
246  if (!NT_SUCCESS(status))
247  return NULL;
248 
249  return procedureAddress;
250 }
251 
252 // Misc. system
253 
254 PHLIBAPI
255 VOID
256 NTAPI
258  _Out_ PLARGE_INTEGER SystemTime
259  );
260 
261 PHLIBAPI
262 VOID
263 NTAPI
265  _Out_ PLARGE_INTEGER TimeZoneBias
266  );
267 
268 PHLIBAPI
269 VOID
270 NTAPI
272  _In_ PLARGE_INTEGER SystemTime,
273  _Out_ PLARGE_INTEGER LocalTime
274  );
275 
276 PHLIBAPI
277 VOID
278 NTAPI
280  _In_ PLARGE_INTEGER LocalTime,
281  _Out_ PLARGE_INTEGER SystemTime
282  );
283 
284 // Heap
285 
287 _Check_return_
288 _Ret_notnull_
290 PHLIBAPI
291 PVOID
292 NTAPI
293 PhAllocate(
294  _In_ SIZE_T Size
295  );
296 
297 PHLIBAPI
298 PVOID
299 NTAPI
301  _In_ SIZE_T Size
302  );
303 
304 PHLIBAPI
305 PVOID
306 NTAPI
308  _In_ SIZE_T Size,
309  _In_ ULONG Flags
310  );
311 
312 PHLIBAPI
313 VOID
314 NTAPI
315 PhFree(
316  _Frees_ptr_opt_ PVOID Memory
317  );
318 
321 PHLIBAPI
322 PVOID
323 NTAPI
324 PhReAllocate(
325  _Frees_ptr_opt_ PVOID Memory,
326  _In_ SIZE_T Size
327  );
328 
329 PHLIBAPI
330 PVOID
331 NTAPI
333  _In_ PVOID Memory,
334  _In_ SIZE_T Size
335  );
336 
337 _Check_return_
338 _Ret_maybenull_
339 PHLIBAPI
340 PVOID
341 NTAPI
343  _In_ SIZE_T Size,
344  _Out_opt_ PSIZE_T NewSize
345  );
346 
347 PHLIBAPI
348 VOID
349 NTAPI
350 PhFreePage(
351  _Frees_ptr_opt_ PVOID Memory
352  );
353 
354 FORCEINLINE
355 PVOID
357  _In_ PVOID Data,
358  _In_ SIZE_T Size
359  )
360 {
361  PVOID copy;
362 
363  copy = PhAllocate(Size);
364  memcpy(copy, Data, Size);
365 
366  return copy;
367 }
368 
369 // Event
370 
371 #define PH_EVENT_SET 0x1
372 #define PH_EVENT_SET_SHIFT 0
373 #define PH_EVENT_REFCOUNT_SHIFT 1
374 #define PH_EVENT_REFCOUNT_INC 0x2
375 #define PH_EVENT_REFCOUNT_MASK (((ULONG_PTR)1 << 15) - 1)
376 
385 typedef struct _PH_EVENT
386 {
387  union
388  {
389  ULONG_PTR Value;
390  struct
391  {
392  USHORT Set : 1;
393  USHORT RefCount : 15;
394  UCHAR Reserved;
396 #ifdef _WIN64
397  ULONG Spare;
398 #endif
399  };
400  };
401  HANDLE EventHandle;
402 } PH_EVENT, *PPH_EVENT;
403 
404 C_ASSERT(sizeof(PH_EVENT) == sizeof(ULONG_PTR) + sizeof(HANDLE));
405 
406 #define PH_EVENT_INIT { { PH_EVENT_REFCOUNT_INC }, NULL }
407 
408 PHLIBAPI
409 VOID
410 FASTCALL
412  _Out_ PPH_EVENT Event
413  );
414 
415 #define PhSetEvent PhfSetEvent
416 PHLIBAPI
417 VOID
418 FASTCALL
420  _Inout_ PPH_EVENT Event
421  );
422 
423 PHLIBAPI
424 BOOLEAN
425 FASTCALL
427  _Inout_ PPH_EVENT Event,
428  _In_opt_ PLARGE_INTEGER Timeout
429  );
430 
431 FORCEINLINE
432 BOOLEAN
434  _Inout_ PPH_EVENT Event,
435  _In_opt_ PLARGE_INTEGER Timeout
436  )
437 {
438  if (Event->Set)
439  return TRUE;
440 
441  return PhfWaitForEvent(Event, Timeout);
442 }
443 
444 #define PhResetEvent PhfResetEvent
445 PHLIBAPI
446 VOID
447 FASTCALL
449  _Inout_ PPH_EVENT Event
450  );
451 
452 FORCEINLINE
453 VOID
455  _Out_ PPH_EVENT Event
456  )
457 {
458  Event->Value = PH_EVENT_REFCOUNT_INC;
459  Event->EventHandle = NULL;
460 }
461 
469 FORCEINLINE
470 BOOLEAN
472  _In_ PPH_EVENT Event
473  )
474 {
475  return (BOOLEAN)Event->Set;
476 }
477 
478 // Barrier
479 
480 #define PH_BARRIER_COUNT_SHIFT 0
481 #define PH_BARRIER_COUNT_MASK (((LONG_PTR)1 << (sizeof(ULONG_PTR) * 8 / 2 - 1)) - 1)
482 #define PH_BARRIER_COUNT_INC ((LONG_PTR)1 << PH_BARRIER_COUNT_SHIFT)
483 #define PH_BARRIER_TARGET_SHIFT (sizeof(ULONG_PTR) * 8 / 2)
484 #define PH_BARRIER_TARGET_MASK (((LONG_PTR)1 << (sizeof(ULONG_PTR) * 8 / 2 - 1)) - 1)
485 #define PH_BARRIER_TARGET_INC ((LONG_PTR)1 << PH_BARRIER_TARGET_SHIFT)
486 #define PH_BARRIER_WAKING ((LONG_PTR)1 << (sizeof(ULONG_PTR) * 8 - 1))
487 
488 #define PH_BARRIER_MASTER 1
489 #define PH_BARRIER_SLAVE 2
490 #define PH_BARRIER_OBSERVER 3
491 
492 typedef struct _PH_BARRIER
493 {
494  ULONG_PTR Value;
497 
498 #define PH_BARRIER_INIT(Target) { (ULONG_PTR)(Target) << PH_BARRIER_TARGET_SHIFT, PH_QUEUED_LOCK_INIT }
499 
500 PHLIBAPI
501 VOID
502 FASTCALL
504  _Out_ PPH_BARRIER Barrier,
505  _In_ ULONG_PTR Target
506  );
507 
508 #define PhWaitForBarrier PhfWaitForBarrier
509 PHLIBAPI
510 BOOLEAN
511 FASTCALL
513  _Inout_ PPH_BARRIER Barrier,
514  _In_ BOOLEAN Spin
515  );
516 
517 FORCEINLINE
518 VOID
520  _Out_ PPH_BARRIER Barrier,
521  _In_ ULONG_PTR Target
522  )
523 {
524  Barrier->Value = Target << PH_BARRIER_TARGET_SHIFT;
525  PhInitializeQueuedLock(&Barrier->WakeEvent);
526 }
527 
528 // Rundown protection
529 
530 #define PH_RUNDOWN_ACTIVE 0x1
531 #define PH_RUNDOWN_REF_SHIFT 1
532 #define PH_RUNDOWN_REF_INC 0x2
533 
534 typedef struct _PH_RUNDOWN_PROTECT
535 {
536  ULONG_PTR Value;
538 
539 #define PH_RUNDOWN_PROTECT_INIT { 0 }
540 
542 {
543  ULONG_PTR Count;
546 
547 PHLIBAPI
548 VOID
549 FASTCALL
551  _Out_ PPH_RUNDOWN_PROTECT Protection
552  );
553 
554 PHLIBAPI
555 BOOLEAN
556 FASTCALL
558  _Inout_ PPH_RUNDOWN_PROTECT Protection
559  );
560 
561 PHLIBAPI
562 VOID
563 FASTCALL
565  _Inout_ PPH_RUNDOWN_PROTECT Protection
566  );
567 
568 PHLIBAPI
569 VOID
570 FASTCALL
572  _Inout_ PPH_RUNDOWN_PROTECT Protection
573  );
574 
575 FORCEINLINE
576 VOID
578  _Out_ PPH_RUNDOWN_PROTECT Protection
579  )
580 {
581  Protection->Value = 0;
582 }
583 
584 FORCEINLINE
585 BOOLEAN
587  _Inout_ PPH_RUNDOWN_PROTECT Protection
588  )
589 {
590  ULONG_PTR value;
591 
592  value = Protection->Value & ~PH_RUNDOWN_ACTIVE; // fail fast path when rundown is active
593 
594  if ((ULONG_PTR)_InterlockedCompareExchangePointer(
595  (PVOID *)&Protection->Value,
596  (PVOID)(value + PH_RUNDOWN_REF_INC),
597  (PVOID)value
598  ) == value)
599  {
600  return TRUE;
601  }
602  else
603  {
604  return PhfAcquireRundownProtection(Protection);
605  }
606 }
607 
608 FORCEINLINE
609 VOID
611  _Inout_ PPH_RUNDOWN_PROTECT Protection
612  )
613 {
614  ULONG_PTR value;
615 
616  value = Protection->Value & ~PH_RUNDOWN_ACTIVE; // Fail fast path when rundown is active
617 
618  if ((ULONG_PTR)_InterlockedCompareExchangePointer(
619  (PVOID *)&Protection->Value,
620  (PVOID)(value - PH_RUNDOWN_REF_INC),
621  (PVOID)value
622  ) != value)
623  {
624  PhfReleaseRundownProtection(Protection);
625  }
626 }
627 
628 FORCEINLINE
629 VOID
631  _Inout_ PPH_RUNDOWN_PROTECT Protection
632  )
633 {
634  ULONG_PTR value;
635 
636  value = (ULONG_PTR)_InterlockedCompareExchangePointer(
637  (PVOID *)&Protection->Value,
638  (PVOID)PH_RUNDOWN_ACTIVE,
639  (PVOID)0
640  );
641 
642  if (value != 0 && value != PH_RUNDOWN_ACTIVE)
643  PhfWaitForRundownProtection(Protection);
644 }
645 
646 // One-time initialization
647 
648 #define PH_INITONCE_SHIFT 31
649 #define PH_INITONCE_INITIALIZING (0x1 << PH_INITONCE_SHIFT)
650 #define PH_INITONCE_INITIALIZING_SHIFT PH_INITONCE_SHIFT
651 
652 typedef struct _PH_INITONCE
653 {
656 
657 C_ASSERT(PH_INITONCE_SHIFT >= FIELD_OFFSET(PH_EVENT, AvailableForUse) * 8);
658 
659 #define PH_INITONCE_INIT { PH_EVENT_INIT }
660 
661 #define PhInitializeInitOnce PhfInitializeInitOnce
662 PHLIBAPI
663 VOID
664 FASTCALL
666  _Out_ PPH_INITONCE InitOnce
667  );
668 
669 PHLIBAPI
670 BOOLEAN
671 FASTCALL
673  _Inout_ PPH_INITONCE InitOnce
674  );
675 
676 #define PhEndInitOnce PhfEndInitOnce
677 PHLIBAPI
678 VOID
679 FASTCALL
681  _Inout_ PPH_INITONCE InitOnce
682  );
683 
684 FORCEINLINE
685 BOOLEAN
687  _Inout_ PPH_INITONCE InitOnce
688  )
689 {
690  if (InitOnce->Event.Set)
691  return FALSE;
692  else
693  return PhfBeginInitOnce(InitOnce);
694 }
695 
696 FORCEINLINE
697 BOOLEAN
699  _In_ PPH_INITONCE InitOnce
700  )
701 {
702  return (BOOLEAN)InitOnce->Event.Set;
703 }
704 
705 // String
706 
707 PHLIBAPI
708 SIZE_T
709 NTAPI
711  _In_ PWSTR String
712  );
713 
714 PHLIBAPI
715 PSTR
716 NTAPI
718  _In_ PSTR String
719  );
720 
721 PHLIBAPI
722 PSTR
723 NTAPI
725  _In_ PSTR String
726  );
727 
728 PHLIBAPI
729 PWSTR
730 NTAPI
732  _In_ PWSTR String
733  );
734 
735 PHLIBAPI
736 BOOLEAN
737 NTAPI
739  _In_ PSTR InputBuffer,
740  _In_ SIZE_T InputCount,
741  _Out_writes_opt_z_(OutputCount) PSTR OutputBuffer,
742  _In_ SIZE_T OutputCount,
743  _Out_opt_ PSIZE_T ReturnCount
744  );
745 
746 PHLIBAPI
747 BOOLEAN
748 NTAPI
750  _In_ PWSTR InputBuffer,
751  _In_ SIZE_T InputCount,
752  _Out_writes_opt_z_(OutputCount) PWSTR OutputBuffer,
753  _In_ SIZE_T OutputCount,
754  _Out_opt_ PSIZE_T ReturnCount
755  );
756 
757 PHLIBAPI
758 BOOLEAN
759 NTAPI
761  _In_ PSTR InputBuffer,
762  _In_ SIZE_T InputCount,
763  _Out_writes_opt_z_(OutputCount) PWSTR OutputBuffer,
764  _In_ SIZE_T OutputCount,
765  _Out_opt_ PSIZE_T ReturnCount
766  );
767 
768 PHLIBAPI
769 BOOLEAN
770 NTAPI
772  _In_ PSTR InputBuffer,
773  _In_ SIZE_T InputCount,
774  _Out_writes_opt_z_(OutputCount) PWSTR OutputBuffer,
775  _In_ SIZE_T OutputCount,
776  _Out_opt_ PSIZE_T ReturnCount
777  );
778 
779 PHLIBAPI
780 LONG
781 NTAPI
783  _In_ PWSTR A,
784  _In_ PWSTR B,
785  _In_ BOOLEAN IgnoreCase
786  );
787 
788 FORCEINLINE
789 BOOLEAN
791  _In_ WCHAR Char1,
792  _In_ WCHAR Char2
793  )
794 {
795  WCHAR d;
796 
797  d = Char1 ^ Char2;
798 
799  // We ignore bits beyond bit 5 because bit 6 is the case bit, and also we
800  // don't support localization here.
801  if (d & 0x1f)
802  return TRUE;
803 
804  return FALSE;
805 }
806 
807 FORCEINLINE
808 BOOLEAN
810  _In_ WCHAR Char
811  )
812 {
813  return (USHORT)(Char - '0') < 10;
814 }
815 
816 FORCEINLINE
817 LONG
819  _In_ PSTR String1,
820  _In_ PSTR String2,
821  _In_ BOOLEAN IgnoreCase
822  )
823 {
824  if (!IgnoreCase)
825  return strcmp(String1, String2);
826  else
827  return stricmp(String1, String2);
828 }
829 
830 FORCEINLINE
831 BOOLEAN
833  _In_ PSTR String1,
834  _In_ PSTR String2,
835  _In_ BOOLEAN IgnoreCase
836  )
837 {
838  if (!IgnoreCase)
839  return strcmp(String1, String2) == 0;
840  else
841  return stricmp(String1, String2) == 0;
842 }
843 
844 FORCEINLINE
845 LONG
847  _In_ PWSTR String1,
848  _In_ PWSTR String2,
849  _In_ BOOLEAN IgnoreCase
850  )
851 {
852  if (!IgnoreCase)
853  return wcscmp(String1, String2);
854  else
855  return wcsicmp(String1, String2);
856 }
857 
858 FORCEINLINE
859 BOOLEAN
861  _In_ PWSTR String1,
862  _In_ PWSTR String2,
863  _In_ BOOLEAN IgnoreCase
864  )
865 {
866  if (!IgnoreCase)
867  {
868  return wcscmp(String1, String2) == 0;
869  }
870  else
871  {
872  // wcsicmp is very expensive, so we do a quick check for negatives first.
873  if (PhAreCharactersDifferent(String1[0], String2[0]))
874  return FALSE;
875 
876  return wcsicmp(String1, String2) == 0;
877  }
878 }
879 
880 typedef struct _PH_STRINGREF
881 {
883  SIZE_T Length;
885  PWCH Buffer;
887 
888 typedef struct _PH_BYTESREF
889 {
891  SIZE_T Length;
893  PCH Buffer;
895 
896 typedef struct _PH_RELATIVE_BYTESREF
897 {
899  ULONG Length;
901  ULONG Offset;
903 
904 #define PH_STRINGREF_INIT(String) { sizeof(String) - sizeof(WCHAR), (String) }
905 #define PH_BYTESREF_INIT(String) { sizeof(String) - sizeof(CHAR), (String) }
906 
907 FORCEINLINE
908 VOID
910  _Out_ PPH_STRINGREF String,
911  _In_ PWSTR Buffer
912  )
913 {
914  String->Length = wcslen(Buffer) * sizeof(WCHAR);
915  String->Buffer = Buffer;
916 }
917 
918 FORCEINLINE
919 VOID
921  _Out_ PPH_STRINGREF String,
922  _In_ PWSTR Buffer
923  )
924 {
925  String->Length = PhCountStringZ(Buffer) * sizeof(WCHAR);
926  String->Buffer = Buffer;
927 }
928 
929 FORCEINLINE
930 VOID
932  _Out_ PPH_BYTESREF Bytes,
933  _In_ PSTR Buffer
934  )
935 {
936  Bytes->Length = strlen(Buffer) * sizeof(CHAR);
937  Bytes->Buffer = Buffer;
938 }
939 
940 FORCEINLINE
941 VOID
943  _Out_ PPH_STRINGREF String
944  )
945 {
946  String->Length = 0;
947  String->Buffer = NULL;
948 }
949 
950 FORCEINLINE
951 BOOLEAN
953  _In_ PPH_STRINGREF String,
954  _Out_ PUNICODE_STRING UnicodeString
955  )
956 {
957  UnicodeString->Length = (USHORT)String->Length;
958  UnicodeString->MaximumLength = (USHORT)String->Length;
959  UnicodeString->Buffer = String->Buffer;
960 
961  return String->Length <= UNICODE_STRING_MAX_BYTES;
962 }
963 
964 FORCEINLINE
965 VOID
967  _In_ PUNICODE_STRING UnicodeString,
968  _Out_ PPH_STRINGREF String
969  )
970 {
971  String->Length = UnicodeString->Length;
972  String->Buffer = UnicodeString->Buffer;
973 }
974 
975 PHLIBAPI
976 LONG
977 NTAPI
979  _In_ PPH_STRINGREF String1,
980  _In_ PPH_STRINGREF String2,
981  _In_ BOOLEAN IgnoreCase
982  );
983 
984 PHLIBAPI
985 BOOLEAN
986 NTAPI
988  _In_ PPH_STRINGREF String1,
989  _In_ PPH_STRINGREF String2,
990  _In_ BOOLEAN IgnoreCase
991  );
992 
993 PHLIBAPI
994 ULONG_PTR
995 NTAPI
997  _In_ PPH_STRINGREF String,
998  _In_ WCHAR Character,
999  _In_ BOOLEAN IgnoreCase
1000  );
1001 
1002 PHLIBAPI
1003 ULONG_PTR
1004 NTAPI
1006  _In_ PPH_STRINGREF String,
1007  _In_ WCHAR Character,
1008  _In_ BOOLEAN IgnoreCase
1009  );
1010 
1011 PHLIBAPI
1012 ULONG_PTR
1013 NTAPI
1015  _In_ PPH_STRINGREF String,
1016  _In_ PPH_STRINGREF SubString,
1017  _In_ BOOLEAN IgnoreCase
1018  );
1019 
1020 PHLIBAPI
1021 BOOLEAN
1022 NTAPI
1024  _In_ PPH_STRINGREF Input,
1025  _In_ WCHAR Separator,
1026  _Out_ PPH_STRINGREF FirstPart,
1027  _Out_ PPH_STRINGREF SecondPart
1028  );
1029 
1030 PHLIBAPI
1031 BOOLEAN
1032 NTAPI
1034  _In_ PPH_STRINGREF Input,
1035  _In_ WCHAR Separator,
1036  _Out_ PPH_STRINGREF FirstPart,
1037  _Out_ PPH_STRINGREF SecondPart
1038  );
1039 
1040 PHLIBAPI
1041 BOOLEAN
1042 NTAPI
1044  _In_ PPH_STRINGREF Input,
1045  _In_ PPH_STRINGREF Separator,
1046  _In_ BOOLEAN IgnoreCase,
1047  _Out_ PPH_STRINGREF FirstPart,
1048  _Out_ PPH_STRINGREF SecondPart
1049  );
1050 
1051 #define PH_SPLIT_AT_CHAR_SET 0x0 // default
1052 #define PH_SPLIT_AT_STRING 0x1
1053 #define PH_SPLIT_AT_RANGE 0x2
1054 #define PH_SPLIT_CASE_INSENSITIVE 0x1000
1055 #define PH_SPLIT_COMPLEMENT_CHAR_SET 0x2000
1056 #define PH_SPLIT_START_AT_END 0x4000
1057 #define PH_SPLIT_CHAR_SET_IS_UPPERCASE 0x8000
1058 
1059 PHLIBAPI
1060 BOOLEAN
1061 NTAPI
1063  _In_ PPH_STRINGREF Input,
1064  _In_ PPH_STRINGREF Separator,
1065  _In_ ULONG Flags,
1066  _Out_ PPH_STRINGREF FirstPart,
1067  _Out_ PPH_STRINGREF SecondPart,
1068  _Out_opt_ PPH_STRINGREF SeparatorPart
1069  );
1070 
1071 #define PH_TRIM_START_ONLY 0x1
1072 #define PH_TRIM_END_ONLY 0x2
1073 
1074 PHLIBAPI
1075 VOID
1076 NTAPI
1078  _Inout_ PPH_STRINGREF String,
1079  _In_ PPH_STRINGREF CharSet,
1080  _In_ ULONG Flags
1081  );
1082 
1083 FORCEINLINE
1084 LONG
1086  _In_ PPH_STRINGREF String1,
1087  _In_ PWSTR String2,
1088  _In_ BOOLEAN IgnoreCase
1089  )
1090 {
1091  PH_STRINGREF sr2;
1092 
1093  PhInitializeStringRef(&sr2, String2);
1094 
1095  return PhCompareStringRef(String1, &sr2, IgnoreCase);
1096 }
1097 
1098 FORCEINLINE
1099 BOOLEAN
1101  _In_ PPH_STRINGREF String1,
1102  _In_ PWSTR String2,
1103  _In_ BOOLEAN IgnoreCase
1104  )
1105 {
1106  PH_STRINGREF sr2;
1107 
1108  PhInitializeStringRef(&sr2, String2);
1109 
1110  return PhEqualStringRef(String1, &sr2, IgnoreCase);
1111 }
1112 
1113 FORCEINLINE
1114 BOOLEAN
1116  _In_ PPH_STRINGREF String,
1117  _In_ PPH_STRINGREF Prefix,
1118  _In_ BOOLEAN IgnoreCase
1119  )
1120 {
1121  PH_STRINGREF sr;
1122 
1123  sr.Buffer = String->Buffer;
1124  sr.Length = Prefix->Length;
1125 
1126  if (String->Length < sr.Length)
1127  return FALSE;
1128 
1129  return PhEqualStringRef(&sr, Prefix, IgnoreCase);
1130 }
1131 
1132 FORCEINLINE
1133 BOOLEAN
1135  _In_ PPH_STRINGREF String,
1136  _In_ PWSTR Prefix,
1137  _In_ BOOLEAN IgnoreCase
1138  )
1139 {
1140  PH_STRINGREF prefix;
1141 
1142  PhInitializeStringRef(&prefix, Prefix);
1143 
1144  return PhStartsWithStringRef(String, &prefix, IgnoreCase);
1145 }
1146 
1147 FORCEINLINE
1148 BOOLEAN
1150  _In_ PPH_STRINGREF String,
1151  _In_ PPH_STRINGREF Suffix,
1152  _In_ BOOLEAN IgnoreCase
1153  )
1154 {
1155  PH_STRINGREF sr;
1156 
1157  if (Suffix->Length > String->Length)
1158  return FALSE;
1159 
1160  sr.Buffer = (PWCHAR)((PCHAR)String->Buffer + String->Length - Suffix->Length);
1161  sr.Length = Suffix->Length;
1162 
1163  return PhEqualStringRef(&sr, Suffix, IgnoreCase);
1164 }
1165 
1166 FORCEINLINE
1167 BOOLEAN
1169  _In_ PPH_STRINGREF String,
1170  _In_ PWSTR Suffix,
1171  _In_ BOOLEAN IgnoreCase
1172  )
1173 {
1174  PH_STRINGREF suffix;
1175 
1176  PhInitializeStringRef(&suffix, Suffix);
1177 
1178  return PhEndsWithStringRef(String, &suffix, IgnoreCase);
1179 }
1180 
1181 FORCEINLINE
1182 VOID
1184  _Inout_ PPH_STRINGREF String,
1185  _In_ LONG_PTR Length
1186  )
1187 {
1188  String->Buffer = (PWCH)((PCHAR)String->Buffer + Length);
1189  String->Length -= Length;
1190 }
1191 
1192 FORCEINLINE
1193 VOID
1195  _In_ PPH_STRINGREF String
1196  )
1197 {
1198  SIZE_T i;
1199  SIZE_T j;
1200  WCHAR t;
1201 
1202  for (i = 0, j = String->Length / sizeof(WCHAR) - 1; i <= j; i++, j--)
1203  {
1204  t = String->Buffer[i];
1205  String->Buffer[i] = String->Buffer[j];
1206  String->Buffer[j] = t;
1207  }
1208 }
1209 
1210 extern PPH_OBJECT_TYPE PhStringType;
1211 
1220 typedef struct _PH_STRING
1221 {
1222  // Header
1223  union
1224  {
1226  struct
1227  {
1229  SIZE_T Length;
1231  PWCH Buffer;
1232  };
1233  };
1234 
1235  // Data
1236  union
1237  {
1238  WCHAR Data[1];
1239  struct
1240  {
1244  PVOID Allocation;
1245  };
1246  };
1247 } PH_STRING, *PPH_STRING;
1248 
1249 PHLIBAPI
1250 PPH_STRING
1251 NTAPI
1253  _In_ PWSTR Buffer
1254  );
1255 
1256 PHLIBAPI
1257 PPH_STRING
1258 NTAPI
1260  _In_opt_ PWCHAR Buffer,
1261  _In_ SIZE_T Length
1262  );
1263 
1264 FORCEINLINE
1265 PPH_STRING
1267  _In_ PPH_STRINGREF String
1268  )
1269 {
1270  return PhCreateStringEx(String->Buffer, String->Length);
1271 }
1272 
1273 FORCEINLINE
1274 PPH_STRING
1276  _In_ PUNICODE_STRING UnicodeString
1277  )
1278 {
1279  return PhCreateStringEx(UnicodeString->Buffer, UnicodeString->Length);
1280 }
1281 
1282 PHLIBAPI
1283 PPH_STRING
1284 NTAPI
1286  VOID
1287  );
1288 
1289 PHLIBAPI
1290 PPH_STRING
1291 NTAPI
1293  _In_ ULONG Count,
1294  ...
1295  );
1296 
1297 #define PH_CONCAT_STRINGS_LENGTH_CACHE_SIZE 16
1298 
1299 PHLIBAPI
1300 PPH_STRING
1301 NTAPI
1303  _In_ ULONG Count,
1304  _In_ va_list ArgPtr
1305  );
1306 
1307 PHLIBAPI
1308 PPH_STRING
1309 NTAPI
1311  _In_ PWSTR String1,
1312  _In_ PWSTR String2
1313  );
1314 
1315 PHLIBAPI
1316 PPH_STRING
1317 NTAPI
1319  _In_ PPH_STRINGREF String1,
1320  _In_ PPH_STRINGREF String2
1321  );
1322 
1323 PPH_STRING
1324 NTAPI
1326  _In_ PPH_STRINGREF String1,
1327  _In_ PPH_STRINGREF String2,
1328  _In_ PPH_STRINGREF String3
1329  );
1330 
1331 PHLIBAPI
1332 PPH_STRING
1333 NTAPI
1335  _In_ _Printf_format_string_ PWSTR Format,
1336  ...
1337  );
1338 
1339 PHLIBAPI
1340 PPH_STRING
1341 NTAPI
1343  _In_ _Printf_format_string_ PWSTR Format,
1344  _In_ va_list ArgPtr
1345  );
1346 
1357 FORCEINLINE
1358 PWSTR
1360  _In_opt_ PPH_STRING String
1361  )
1362 {
1363  if (String)
1364  return String->Buffer;
1365  else
1366  return NULL;
1367 }
1368 
1369 FORCEINLINE
1372  _In_opt_ PPH_STRING String
1373  )
1374 {
1375  PH_STRINGREF sr;
1376 
1377  if (String)
1378  sr = String->sr;
1379  else
1381 
1382  return sr;
1383 }
1384 
1395 FORCEINLINE
1396 PWSTR
1398  _In_opt_ PPH_STRING String
1399  )
1400 {
1401  if (String)
1402  return String->Buffer;
1403  else
1404  return L"";
1405 }
1406 
1418 FORCEINLINE
1419 PWSTR
1421  _In_opt_ PPH_STRING String,
1422  _In_ PWSTR DefaultString
1423  )
1424 {
1425  if (String)
1426  return String->Buffer;
1427  else
1428  return DefaultString;
1429 }
1430 
1436 FORCEINLINE
1437 BOOLEAN
1439  _In_opt_ PPH_STRING String
1440  )
1441 {
1442  return !String || String->Length == 0;
1443 }
1444 
1450 FORCEINLINE
1451 PPH_STRING
1453  _In_ PPH_STRING String
1454  )
1455 {
1456  return PhCreateStringEx(String->Buffer, String->Length);
1457 }
1458 
1466 FORCEINLINE
1467 LONG
1469  _In_ PPH_STRING String1,
1470  _In_ PPH_STRING String2,
1471  _In_ BOOLEAN IgnoreCase
1472  )
1473 {
1474  if (!IgnoreCase)
1475  return wcscmp(String1->Buffer, String2->Buffer);
1476  else
1477  return PhCompareStringRef(&String1->sr, &String2->sr, IgnoreCase); // faster than wcsicmp
1478 }
1479 
1487 FORCEINLINE
1488 LONG
1490  _In_ PPH_STRING String1,
1491  _In_ PWSTR String2,
1492  _In_ BOOLEAN IgnoreCase
1493  )
1494 {
1495  if (!IgnoreCase)
1496  {
1497  return wcscmp(String1->Buffer, String2);
1498  }
1499  else
1500  {
1501  return PhCompareStringRef2(&String1->sr, String2, IgnoreCase);
1502  }
1503 }
1504 
1512 FORCEINLINE
1513 LONG
1515  _In_opt_ PPH_STRING String1,
1516  _In_opt_ PPH_STRING String2,
1517  _In_ BOOLEAN IgnoreCase
1518  )
1519 {
1520  if (String1 && String2)
1521  {
1522  return PhCompareString(String1, String2, IgnoreCase);
1523  }
1524  else if (!String1)
1525  {
1526  return !String2 ? 0 : -1;
1527  }
1528  else
1529  {
1530  return 1;
1531  }
1532 }
1533 
1541 FORCEINLINE
1542 BOOLEAN
1544  _In_ PPH_STRING String1,
1545  _In_ PPH_STRING String2,
1546  _In_ BOOLEAN IgnoreCase
1547  )
1548 {
1549  return PhEqualStringRef(&String1->sr, &String2->sr, IgnoreCase);
1550 }
1551 
1559 FORCEINLINE
1560 BOOLEAN
1562  _In_ PPH_STRING String1,
1563  _In_ PWSTR String2,
1564  _In_ BOOLEAN IgnoreCase
1565  )
1566 {
1567  if (!IgnoreCase)
1568  {
1569  return wcscmp(String1->Buffer, String2) == 0;
1570  }
1571  else
1572  {
1573  return PhEqualStringRef2(&String1->sr, String2, IgnoreCase);
1574  }
1575 }
1576 
1586 FORCEINLINE
1587 BOOLEAN
1589  _In_ PPH_STRING String,
1590  _In_ PPH_STRING Prefix,
1591  _In_ BOOLEAN IgnoreCase
1592  )
1593 {
1594  return PhStartsWithStringRef(&String->sr, &Prefix->sr, IgnoreCase);
1595 }
1596 
1606 FORCEINLINE
1607 BOOLEAN
1609  _In_ PPH_STRING String,
1610  _In_ PWSTR Prefix,
1611  _In_ BOOLEAN IgnoreCase
1612  )
1613 {
1614  PH_STRINGREF prefix;
1615 
1616  PhInitializeStringRef(&prefix, Prefix);
1617 
1618  return PhStartsWithStringRef(&String->sr, &prefix, IgnoreCase);
1619 }
1620 
1630 FORCEINLINE
1631 BOOLEAN
1633  _In_ PPH_STRING String,
1634  _In_ PPH_STRING Suffix,
1635  _In_ BOOLEAN IgnoreCase
1636  )
1637 {
1638  return PhEndsWithStringRef(&String->sr, &Suffix->sr, IgnoreCase);
1639 }
1640 
1650 FORCEINLINE
1651 BOOLEAN
1653  _In_ PPH_STRING String,
1654  _In_ PWSTR Suffix,
1655  _In_ BOOLEAN IgnoreCase
1656  )
1657 {
1658  PH_STRINGREF suffix;
1659 
1660  PhInitializeStringRef(&suffix, Suffix);
1661 
1662  return PhEndsWithStringRef(&String->sr, &suffix, IgnoreCase);
1663 }
1664 
1676 FORCEINLINE
1677 ULONG_PTR
1679  _In_ PPH_STRING String,
1680  _In_ SIZE_T StartIndex,
1681  _In_ WCHAR Char
1682  )
1683 {
1684  if (StartIndex != 0)
1685  {
1686  ULONG_PTR r;
1687  PH_STRINGREF sr;
1688 
1689  sr = String->sr;
1690  PhSkipStringRef(&sr, StartIndex * sizeof(WCHAR));
1691  r = PhFindCharInStringRef(&sr, Char, FALSE);
1692 
1693  if (r != -1)
1694  return r + StartIndex;
1695  else
1696  return -1;
1697  }
1698  else
1699  {
1700  return PhFindCharInStringRef(&String->sr, Char, FALSE);
1701  }
1702 }
1703 
1715 FORCEINLINE
1716 ULONG_PTR
1718  _In_ PPH_STRING String,
1719  _In_ SIZE_T StartIndex,
1720  _In_ WCHAR Char
1721  )
1722 {
1723  if (StartIndex != 0)
1724  {
1725  ULONG_PTR r;
1726  PH_STRINGREF sr;
1727 
1728  sr = String->sr;
1729  PhSkipStringRef(&sr, StartIndex * sizeof(WCHAR));
1730  r = PhFindLastCharInStringRef(&sr, Char, FALSE);
1731 
1732  if (r != -1)
1733  return r + StartIndex;
1734  else
1735  return -1;
1736  }
1737  else
1738  {
1739  return PhFindLastCharInStringRef(&String->sr, Char, FALSE);
1740  }
1741 }
1742 
1754 FORCEINLINE
1755 ULONG_PTR
1757  _In_ PPH_STRING String,
1758  _In_ SIZE_T StartIndex,
1759  _In_ PWSTR SubString
1760  )
1761 {
1762  PH_STRINGREF sr2;
1763 
1764  PhInitializeStringRef(&sr2, SubString);
1765 
1766  if (StartIndex != 0)
1767  {
1768  ULONG_PTR r;
1769  PH_STRINGREF sr1;
1770 
1771  sr1 = String->sr;
1772  PhSkipStringRef(&sr1, StartIndex * sizeof(WCHAR));
1773  r = PhFindStringInStringRef(&sr1, &sr2, FALSE);
1774 
1775  if (r != -1)
1776  return r + StartIndex;
1777  else
1778  return -1;
1779  }
1780  else
1781  {
1782  return PhFindStringInStringRef(&String->sr, &sr2, FALSE);
1783  }
1784 }
1785 
1793 FORCEINLINE
1794 PPH_STRING
1796  _In_ PPH_STRING String,
1797  _In_ SIZE_T StartIndex,
1798  _In_ SIZE_T Count
1799  )
1800 {
1801  return PhCreateStringEx(&String->Buffer[StartIndex], Count * sizeof(WCHAR));
1802 }
1803 
1809 FORCEINLINE
1810 VOID
1812  _Inout_ PPH_STRING String
1813  )
1814 {
1815  _wcslwr(String->Buffer);
1816 }
1817 
1823 FORCEINLINE
1824 VOID
1826  _Inout_ PPH_STRING String
1827  )
1828 {
1829  _wcsupr(String->Buffer);
1830 }
1831 
1842 FORCEINLINE
1843 VOID
1845  _Inout_ PPH_STRING String
1846  )
1847 {
1848  String->Length = PhCountStringZ(String->Buffer) * sizeof(WCHAR);
1849 }
1850 
1851 // byte string
1852 
1853 extern PPH_OBJECT_TYPE PhBytesType;
1854 
1859 typedef struct _PH_BYTES
1860 {
1861  // Header
1862  union
1863  {
1865  struct
1866  {
1868  SIZE_T Length;
1870  PCH Buffer;
1871  };
1872  };
1873 
1874  // Data
1875  union
1876  {
1877  CHAR Data[1];
1878  struct
1879  {
1883  PVOID Allocation;
1884  };
1885  };
1886 } PH_BYTES, *PPH_BYTES;
1887 
1888 PHLIBAPI
1889 PPH_BYTES
1890 NTAPI
1892  _In_ PSTR Buffer
1893  );
1894 
1895 PHLIBAPI
1896 PPH_BYTES
1897 NTAPI
1899  _In_opt_ PCHAR Buffer,
1900  _In_ SIZE_T Length
1901  );
1902 
1903 FORCEINLINE
1904 PPH_BYTES
1906  _In_ PPH_BYTESREF Bytes
1907  )
1908 {
1909  return PhCreateBytesEx(Bytes->Buffer, Bytes->Length);
1910 }
1911 
1912 // Unicode
1913 
1914 #define PH_UNICODE_BYTE_ORDER_MARK 0xfeff
1915 #define PH_UNICODE_MAX_CODE_POINT 0x10ffff
1916 
1917 #define PH_UNICODE_UTF16_TO_HIGH_SURROGATE(CodePoint) ((USHORT)((CodePoint) >> 10) + 0xd7c0)
1918 #define PH_UNICODE_UTF16_TO_LOW_SURROGATE(CodePoint) ((USHORT)((CodePoint) & 0x3ff) + 0xdc00)
1919 #define PH_UNICODE_UTF16_IS_HIGH_SURROGATE(CodeUnit) ((CodeUnit) >= 0xd800 && (CodeUnit) <= 0xdbff)
1920 #define PH_UNICODE_UTF16_IS_LOW_SURROGATE(CodeUnit) ((CodeUnit) >= 0xdc00 && (CodeUnit) <= 0xdfff)
1921 #define PH_UNICODE_UTF16_TO_CODE_POINT(HighSurrogate, LowSurrogate) (((ULONG)(HighSurrogate) << 10) + (ULONG)(LowSurrogate) - 0x35fdc00)
1922 
1923 #define PH_UNICODE_UTF8 0
1924 #define PH_UNICODE_UTF16 1
1925 #define PH_UNICODE_UTF32 2
1926 
1927 typedef struct _PH_UNICODE_DECODER
1928 {
1929  UCHAR Encoding; // PH_UNICODE_*
1930  UCHAR State;
1931  UCHAR InputCount;
1932  UCHAR Reserved;
1933  union
1934  {
1935  UCHAR Utf8[4];
1936  USHORT Utf16[2];
1937  ULONG Utf32;
1938  } Input;
1939  union
1940  {
1941  struct
1942  {
1943  UCHAR Input[4];
1944  UCHAR CodeUnit1;
1945  UCHAR CodeUnit2;
1946  UCHAR CodeUnit3;
1947  UCHAR CodeUnit4;
1948  } Utf8;
1949  struct
1950  {
1951  USHORT Input[2];
1952  USHORT CodeUnit;
1953  } Utf16;
1954  struct
1955  {
1956  ULONG Input;
1957  } Utf32;
1958  } u;
1960 
1961 FORCEINLINE
1962 VOID
1964  _Out_ PPH_UNICODE_DECODER Decoder,
1965  _In_ UCHAR Encoding
1966  )
1967 {
1968  memset(Decoder, 0, sizeof(PH_UNICODE_DECODER));
1969  Decoder->Encoding = Encoding;
1970 }
1971 
1972 PHLIBAPI
1973 BOOLEAN
1974 NTAPI
1976  _Inout_ PPH_UNICODE_DECODER Decoder,
1977  _In_ ULONG CodeUnit
1978  );
1979 
1980 PHLIBAPI
1981 BOOLEAN
1982 NTAPI
1984  _Inout_ PPH_UNICODE_DECODER Decoder,
1985  _Out_ PULONG CodePoint
1986  );
1987 
1988 PHLIBAPI
1989 BOOLEAN
1990 NTAPI
1992  _In_ UCHAR Encoding,
1993  _In_ ULONG CodePoint,
1994  _Out_opt_ PVOID CodeUnits,
1995  _Out_ PULONG NumberOfCodeUnits
1996  );
1997 
1998 // 8-bit to UTF-16
1999 
2000 PHLIBAPI
2001 VOID
2002 NTAPI
2004  _In_reads_bytes_(InputLength) PCH Input,
2005  _In_ SIZE_T InputLength,
2006  _Out_writes_bytes_(InputLength * sizeof(WCHAR)) PWCH Output
2007  );
2008 
2009 PHLIBAPI
2010 PPH_STRING
2011 NTAPI
2013  _In_reads_bytes_(InputLength) PCH Input,
2014  _In_ SIZE_T InputLength
2015  );
2016 
2017 FORCEINLINE
2018 PPH_STRING
2020  _In_ PSTR Input
2021  )
2022 {
2023  return PhZeroExtendToUtf16Ex(Input, strlen(Input));
2024 }
2025 
2026 // UTF-16 to ASCII
2027 
2028 PHLIBAPI
2029 PPH_BYTES
2030 NTAPI
2032  _In_ PWCH Buffer,
2033  _In_ SIZE_T Length,
2034  _In_opt_ CHAR Replacement
2035  );
2036 
2037 FORCEINLINE
2038 PPH_BYTES
2040  _In_ PWSTR Buffer,
2041  _In_opt_ CHAR Replacement
2042  )
2043 {
2044  return PhConvertUtf16ToAsciiEx(Buffer, PhCountStringZ(Buffer) * sizeof(WCHAR), Replacement);
2045 }
2046 
2047 // Multi-byte to UTF-16
2048 // In-place: RtlMultiByteToUnicodeN, RtlMultiByteToUnicodeSize
2049 
2050 PHLIBAPI
2051 PPH_STRING
2052 NTAPI
2054  _In_ PSTR Buffer
2055  );
2056 
2057 PHLIBAPI
2058 PPH_STRING
2059 NTAPI
2061  _In_ PCHAR Buffer,
2062  _In_ SIZE_T Length
2063  );
2064 
2065 // UTF-16 to multi-byte
2066 // In-place: RtlUnicodeToMultiByteN, RtlUnicodeToMultiByteSize
2067 
2068 PHLIBAPI
2069 PPH_BYTES
2070 NTAPI
2072  _In_ PWSTR Buffer
2073  );
2074 
2075 PHLIBAPI
2076 PPH_BYTES
2077 NTAPI
2079  _In_ PWCHAR Buffer,
2080  _In_ SIZE_T Length
2081  );
2082 
2083 // UTF-8 to UTF-16
2084 
2085 PHLIBAPI
2086 BOOLEAN
2087 NTAPI
2089  _Out_ PSIZE_T BytesInUtf16String,
2090  _In_reads_bytes_(BytesInUtf8String) PCH Utf8String,
2091  _In_ SIZE_T BytesInUtf8String
2092  );
2093 
2094 PHLIBAPI
2095 BOOLEAN
2096 NTAPI
2098  _Out_writes_bytes_to_(MaxBytesInUtf16String, *BytesInUtf16String) PWCH Utf16String,
2099  _In_ SIZE_T MaxBytesInUtf16String,
2100  _Out_opt_ PSIZE_T BytesInUtf16String,
2101  _In_reads_bytes_(BytesInUtf8String) PCH Utf8String,
2102  _In_ SIZE_T BytesInUtf8String
2103  );
2104 
2105 PHLIBAPI
2106 PPH_STRING
2107 NTAPI
2109  _In_ PSTR Buffer
2110  );
2111 
2112 PHLIBAPI
2113 PPH_STRING
2114 NTAPI
2116  _In_ PCHAR Buffer,
2117  _In_ SIZE_T Length
2118  );
2119 
2120 // UTF-16 to UTF-8
2121 
2122 PHLIBAPI
2123 BOOLEAN
2124 NTAPI
2126  _Out_ PSIZE_T BytesInUtf8String,
2127  _In_reads_bytes_(BytesInUtf16String) PWCH Utf16String,
2128  _In_ SIZE_T BytesInUtf16String
2129  );
2130 
2131 PHLIBAPI
2132 BOOLEAN
2133 NTAPI
2135  _Out_writes_bytes_to_(MaxBytesInUtf8String, *BytesInUtf8String) PCH Utf8String,
2136  _In_ SIZE_T MaxBytesInUtf8String,
2137  _Out_opt_ PSIZE_T BytesInUtf8String,
2138  _In_reads_bytes_(BytesInUtf16String) PWCH Utf16String,
2139  _In_ SIZE_T BytesInUtf16String
2140  );
2141 
2142 PHLIBAPI
2143 PPH_BYTES
2144 NTAPI
2146  _In_ PWSTR Buffer
2147  );
2148 
2149 PHLIBAPI
2150 PPH_BYTES
2151 NTAPI
2153  _In_ PWCHAR Buffer,
2154  _In_ SIZE_T Length
2155  );
2156 
2157 // String builder
2158 
2164 typedef struct _PH_STRING_BUILDER
2165 {
2173  PPH_STRING String;
2175 
2176 PHLIBAPI
2177 VOID
2178 NTAPI
2180  _Out_ PPH_STRING_BUILDER StringBuilder,
2181  _In_ SIZE_T InitialCapacity
2182  );
2183 
2184 PHLIBAPI
2185 VOID
2186 NTAPI
2188  _Inout_ PPH_STRING_BUILDER StringBuilder
2189  );
2190 
2191 PHLIBAPI
2192 PPH_STRING
2193 NTAPI
2195  _Inout_ PPH_STRING_BUILDER StringBuilder
2196  );
2197 
2198 PHLIBAPI
2199 VOID
2200 NTAPI
2202  _Inout_ PPH_STRING_BUILDER StringBuilder,
2203  _In_ PPH_STRINGREF String
2204  );
2205 
2206 PHLIBAPI
2207 VOID
2208 NTAPI
2210  _Inout_ PPH_STRING_BUILDER StringBuilder,
2211  _In_ PWSTR String
2212  );
2213 
2214 PHLIBAPI
2215 VOID
2216 NTAPI
2218  _Inout_ PPH_STRING_BUILDER StringBuilder,
2219  _In_opt_ PWCHAR String,
2220  _In_ SIZE_T Length
2221  );
2222 
2223 PHLIBAPI
2224 VOID
2225 NTAPI
2227  _Inout_ PPH_STRING_BUILDER StringBuilder,
2228  _In_ WCHAR Character
2229  );
2230 
2231 PHLIBAPI
2232 VOID
2233 NTAPI
2235  _Inout_ PPH_STRING_BUILDER StringBuilder,
2236  _In_ WCHAR Character,
2237  _In_ SIZE_T Count
2238  );
2239 
2240 PHLIBAPI
2241 VOID
2242 NTAPI
2244  _Inout_ PPH_STRING_BUILDER StringBuilder,
2245  _In_ _Printf_format_string_ PWSTR Format,
2246  ...
2247  );
2248 
2249 VOID
2250 NTAPI
2252  _Inout_ PPH_STRING_BUILDER StringBuilder,
2253  _In_ _Printf_format_string_ PWSTR Format,
2254  _In_ va_list ArgPtr
2255  );
2256 
2257 PHLIBAPI
2258 VOID
2259 NTAPI
2261  _Inout_ PPH_STRING_BUILDER StringBuilder,
2262  _In_ SIZE_T Index,
2263  _In_ PPH_STRINGREF String
2264  );
2265 
2266 PHLIBAPI
2267 VOID
2268 NTAPI
2270  _Inout_ PPH_STRING_BUILDER StringBuilder,
2271  _In_ SIZE_T Index,
2272  _In_ PWSTR String
2273  );
2274 
2275 PHLIBAPI
2276 VOID
2277 NTAPI
2279  _Inout_ PPH_STRING_BUILDER StringBuilder,
2280  _In_ SIZE_T Index,
2281  _In_opt_ PWCHAR String,
2282  _In_ SIZE_T Length
2283  );
2284 
2285 PHLIBAPI
2286 VOID
2287 NTAPI
2289  _Inout_ PPH_STRING_BUILDER StringBuilder,
2290  _In_ SIZE_T StartIndex,
2291  _In_ SIZE_T Count
2292  );
2293 
2294 FORCEINLINE
2295 VOID
2297  _Inout_ PPH_STRING_BUILDER StringBuilder,
2298  _In_ SIZE_T Count
2299  )
2300 {
2302  StringBuilder,
2303  StringBuilder->String->Length / sizeof(WCHAR) - Count,
2304  Count
2305  );
2306 }
2307 
2308 // Byte string builder
2309 
2314 typedef struct _PH_BYTES_BUILDER
2315 {
2323  PPH_BYTES Bytes;
2325 
2326 PHLIBAPI
2327 VOID
2328 NTAPI
2330  _Out_ PPH_BYTES_BUILDER BytesBuilder,
2331  _In_ SIZE_T InitialCapacity
2332  );
2333 
2334 PHLIBAPI
2335 VOID
2336 NTAPI
2338  _Inout_ PPH_BYTES_BUILDER BytesBuilder
2339  );
2340 
2341 PHLIBAPI
2342 PPH_BYTES
2343 NTAPI
2345  _Inout_ PPH_BYTES_BUILDER BytesBuilder
2346  );
2347 
2348 FORCEINLINE
2349 PVOID
2351  _In_ PPH_BYTES_BUILDER BytesBuilder,
2352  _In_ SIZE_T Offset
2353  )
2354 {
2355  return BytesBuilder->Bytes->Buffer + Offset;
2356 }
2357 
2358 PHLIBAPI
2359 VOID
2360 NTAPI
2362  _Inout_ PPH_BYTES_BUILDER BytesBuilder,
2363  _In_ PPH_BYTESREF Bytes
2364  );
2365 
2366 PHLIBAPI
2367 VOID
2368 NTAPI
2370  _Inout_ PPH_BYTES_BUILDER BytesBuilder,
2371  _In_ PCHAR Bytes
2372  );
2373 
2374 PHLIBAPI
2375 PVOID
2376 NTAPI
2378  _Inout_ PPH_BYTES_BUILDER BytesBuilder,
2379  _In_opt_ PVOID Buffer,
2380  _In_ SIZE_T Length,
2381  _In_opt_ SIZE_T Alignment,
2382  _Out_opt_ PSIZE_T Offset
2383  );
2384 
2385 // List
2386 
2387 extern PPH_OBJECT_TYPE PhListType;
2388 
2394 typedef struct _PH_LIST
2395 {
2397  ULONG Count;
2401  PVOID *Items;
2402 } PH_LIST, *PPH_LIST;
2403 
2404 PHLIBAPI
2405 PPH_LIST
2406 NTAPI
2407 PhCreateList(
2408  _In_ ULONG InitialCapacity
2409  );
2410 
2411 PHLIBAPI
2412 VOID
2413 NTAPI
2414 PhResizeList(
2415  _Inout_ PPH_LIST List,
2416  _In_ ULONG NewCapacity
2417  );
2418 
2419 PHLIBAPI
2420 VOID
2421 NTAPI
2423  _Inout_ PPH_LIST List,
2424  _In_ PVOID Item
2425  );
2426 
2427 PHLIBAPI
2428 VOID
2429 NTAPI
2431  _Inout_ PPH_LIST List,
2432  _In_ PVOID *Items,
2433  _In_ ULONG Count
2434  );
2435 
2436 PHLIBAPI
2437 VOID
2438 NTAPI
2439 PhClearList(
2440  _Inout_ PPH_LIST List
2441  );
2442 
2443 _Success_(return != -1)
2444 PHLIBAPI
2445 ULONG
2446 NTAPI
2447 PhFindItemList(
2448  _In_ PPH_LIST List,
2449  _In_ PVOID Item
2450  );
2451 
2452 PHLIBAPI
2453 VOID
2454 NTAPI
2456  _Inout_ PPH_LIST List,
2457  _In_ ULONG Index,
2458  _In_ PVOID Item
2459  );
2460 
2461 PHLIBAPI
2462 VOID
2463 NTAPI
2465  _Inout_ PPH_LIST List,
2466  _In_ ULONG Index,
2467  _In_ PVOID *Items,
2468  _In_ ULONG Count
2469  );
2470 
2471 PHLIBAPI
2472 VOID
2473 NTAPI
2475  _Inout_ PPH_LIST List,
2476  _In_ ULONG Index
2477  );
2478 
2479 PHLIBAPI
2480 VOID
2481 NTAPI
2483  _Inout_ PPH_LIST List,
2484  _In_ ULONG StartIndex,
2485  _In_ ULONG Count
2486  );
2487 
2500 typedef LONG (NTAPI *PPH_COMPARE_FUNCTION)(
2501  _In_ PVOID Item1,
2502  _In_ PVOID Item2,
2503  _In_opt_ PVOID Context
2504  );
2505 
2506 // Pointer list
2507 
2508 extern PPH_OBJECT_TYPE PhPointerListType;
2509 
2516 typedef struct _PH_POINTER_LIST
2517 {
2519  ULONG Count;
2523  ULONG FreeEntry;
2525  ULONG NextEntry;
2527  PVOID *Items;
2529 
2530 #define PH_IS_LIST_POINTER_VALID(Pointer) (!((ULONG_PTR)(Pointer) & 0x1))
2531 
2532 PHLIBAPI
2533 PPH_POINTER_LIST
2534 NTAPI
2536  _In_ ULONG InitialCapacity
2537  );
2538 
2539 PHLIBAPI
2540 HANDLE
2541 NTAPI
2543  _Inout_ PPH_POINTER_LIST PointerList,
2544  _In_ PVOID Pointer
2545  );
2546 
2547 PHLIBAPI
2548 BOOLEAN
2549 NTAPI
2551  _In_ PPH_POINTER_LIST PointerList,
2552  _Inout_ PULONG EnumerationKey,
2553  _Out_ PVOID *Pointer,
2554  _Out_ PHANDLE PointerHandle
2555  );
2556 
2557 PHLIBAPI
2558 HANDLE
2559 NTAPI
2561  _In_ PPH_POINTER_LIST PointerList,
2562  _In_ PVOID Pointer
2563  );
2564 
2565 PHLIBAPI
2566 VOID
2567 NTAPI
2569  _Inout_ PPH_POINTER_LIST PointerList,
2570  _In_ HANDLE PointerHandle
2571  );
2572 
2573 FORCEINLINE
2574 BOOLEAN
2576  _In_ PPH_POINTER_LIST PointerList,
2577  _Inout_ PULONG EnumerationKey,
2578  _Out_ PVOID *Pointer
2579  )
2580 {
2581  while (*EnumerationKey < PointerList->NextEntry)
2582  {
2583  PVOID pointer = PointerList->Items[*EnumerationKey];
2584 
2585  (*EnumerationKey)++;
2586 
2587  if (PH_IS_LIST_POINTER_VALID(pointer))
2588  {
2589  *Pointer = pointer;
2590  return TRUE;
2591  }
2592  }
2593 
2594  return FALSE;
2595 }
2596 
2597 // Hash
2598 
2599 typedef struct _PH_HASH_ENTRY
2600 {
2602  ULONG Hash;
2604 
2605 #define PH_HASH_SET_INIT { 0 }
2606 #define PH_HASH_SET_SIZE(Buckets) (sizeof(Buckets) / sizeof(PPH_HASH_ENTRY))
2607 
2614 FORCEINLINE
2615 VOID
2617  _Out_ PPH_HASH_ENTRY *Buckets,
2618  _In_ ULONG NumberOfBuckets
2619  )
2620 {
2621  memset(Buckets, 0, sizeof(PPH_HASH_ENTRY) * NumberOfBuckets);
2622 }
2623 
2632 FORCEINLINE
2633 PPH_HASH_ENTRY *
2635  _In_ ULONG NumberOfBuckets
2636  )
2637 {
2638  PPH_HASH_ENTRY *buckets;
2639 
2640  buckets = (PPH_HASH_ENTRY *)PhAllocate(sizeof(PPH_HASH_ENTRY) * NumberOfBuckets);
2641  PhInitializeHashSet(buckets, NumberOfBuckets);
2642 
2643  return buckets;
2644 }
2645 
2654 FORCEINLINE
2655 ULONG
2657  _In_ PPH_HASH_ENTRY *Buckets,
2658  _In_ ULONG NumberOfBuckets
2659  )
2660 {
2661  ULONG i;
2662  PPH_HASH_ENTRY entry;
2663  ULONG count;
2664 
2665  count = 0;
2666 
2667  for (i = 0; i < NumberOfBuckets; i++)
2668  {
2669  for (entry = Buckets[i]; entry; entry = entry->Next)
2670  count++;
2671  }
2672 
2673  return count;
2674 }
2675 
2686 FORCEINLINE
2687 VOID
2689  _Inout_ PPH_HASH_ENTRY *NewBuckets,
2690  _In_ ULONG NumberOfNewBuckets,
2691  _In_ PPH_HASH_ENTRY *OldBuckets,
2692  _In_ ULONG NumberOfOldBuckets
2693  )
2694 {
2695  ULONG i;
2696  PPH_HASH_ENTRY entry;
2697  PPH_HASH_ENTRY nextEntry;
2698  ULONG index;
2699 
2700  for (i = 0; i < NumberOfOldBuckets; i++)
2701  {
2702  entry = OldBuckets[i];
2703 
2704  while (entry)
2705  {
2706  nextEntry = entry->Next;
2707 
2708  index = entry->Hash & (NumberOfNewBuckets - 1);
2709  entry->Next = NewBuckets[index];
2710  NewBuckets[index] = entry;
2711 
2712  entry = nextEntry;
2713  }
2714  }
2715 }
2716 
2727 FORCEINLINE
2728 VOID
2730  _Inout_ PPH_HASH_ENTRY *Buckets,
2731  _In_ ULONG NumberOfBuckets,
2732  _Out_ PPH_HASH_ENTRY Entry,
2733  _In_ ULONG Hash
2734  )
2735 {
2736  ULONG index;
2737 
2738  index = Hash & (NumberOfBuckets - 1);
2739 
2740  Entry->Hash = Hash;
2741  Entry->Next = Buckets[index];
2742  Buckets[index] = Entry;
2743 }
2744 
2757 FORCEINLINE
2758 PPH_HASH_ENTRY
2760  _In_ PPH_HASH_ENTRY *Buckets,
2761  _In_ ULONG NumberOfBuckets,
2762  _In_ ULONG Hash
2763  )
2764 {
2765  return Buckets[Hash & (NumberOfBuckets - 1)];
2766 }
2767 
2775 FORCEINLINE
2776 VOID
2778  _Inout_ PPH_HASH_ENTRY *Buckets,
2779  _In_ ULONG NumberOfBuckets,
2780  _Inout_ PPH_HASH_ENTRY Entry
2781  )
2782 {
2783  ULONG index;
2784  PPH_HASH_ENTRY entry;
2785  PPH_HASH_ENTRY previousEntry;
2786 
2787  index = Entry->Hash & (NumberOfBuckets - 1);
2788  previousEntry = NULL;
2789 
2790  entry = Buckets[index];
2791 
2792  do
2793  {
2794  if (entry == Entry)
2795  {
2796  if (!previousEntry)
2797  Buckets[index] = entry->Next;
2798  else
2799  previousEntry->Next = entry->Next;
2800 
2801  return;
2802  }
2803 
2804  previousEntry = entry;
2805  entry = entry->Next;
2806  } while (entry);
2807 
2808  // Entry doesn't actually exist in the set. This is a fatal logic error.
2809  PhRaiseStatus(STATUS_INTERNAL_ERROR);
2810 }
2811 
2821 FORCEINLINE
2822 VOID
2824  _Inout_ PPH_HASH_ENTRY **Buckets,
2825  _Inout_ PULONG NumberOfBuckets,
2826  _In_ ULONG NewNumberOfBuckets
2827  )
2828 {
2829  PPH_HASH_ENTRY *newBuckets;
2830 
2831  newBuckets = PhCreateHashSet(NewNumberOfBuckets);
2832  PhDistributeHashSet(newBuckets, NewNumberOfBuckets, *Buckets, *NumberOfBuckets);
2833 
2834  PhFree(*Buckets);
2835  *Buckets = newBuckets;
2836  *NumberOfBuckets = NewNumberOfBuckets;
2837 }
2838 
2839 // Hashtable
2840 
2841 extern PPH_OBJECT_TYPE PhHashtableType;
2842 
2843 typedef struct _PH_HASHTABLE_ENTRY
2844 {
2846  ULONG HashCode;
2850  ULONG Next;
2854 
2864 typedef BOOLEAN (NTAPI *PPH_HASHTABLE_COMPARE_FUNCTION)(
2865  _In_ PVOID Entry1,
2866  _In_ PVOID Entry2
2867  );
2868 
2883 typedef ULONG (NTAPI *PPH_HASHTABLE_HASH_FUNCTION)(
2884  _In_ PVOID Entry
2885  );
2886 
2887 // Use power-of-two sizes instead of primes
2888 #define PH_HASHTABLE_POWER_OF_TWO_SIZE
2889 
2890 // Enables 2^32-1 possible hash codes instead of only 2^31
2891 //#define PH_HASHTABLE_FULL_HASH
2892 
2896 typedef struct _PH_HASHTABLE
2897 {
2899  ULONG EntrySize;
2904 
2908  PULONG Buckets;
2912  PVOID Entries;
2913 
2915  ULONG Count;
2917  ULONG FreeEntry;
2921  ULONG NextEntry;
2923 
2924 #define PH_HASHTABLE_ENTRY_SIZE(InnerSize) (FIELD_OFFSET(PH_HASHTABLE_ENTRY, Body) + (InnerSize))
2925 #define PH_HASHTABLE_GET_ENTRY(Hashtable, Index) \
2926  ((PPH_HASHTABLE_ENTRY)PTR_ADD_OFFSET((Hashtable)->Entries, \
2927  PH_HASHTABLE_ENTRY_SIZE((Hashtable)->EntrySize) * (Index)))
2928 #define PH_HASHTABLE_GET_ENTRY_INDEX(Hashtable, Entry) \
2929  ((ULONG)(PTR_ADD_OFFSET(Entry, -(Hashtable)->Entries) / \
2930  PH_HASHTABLE_ENTRY_SIZE((Hashtable)->EntrySize)))
2931 
2932 PHLIBAPI
2933 PPH_HASHTABLE
2934 NTAPI
2936  _In_ ULONG EntrySize,
2937  _In_ PPH_HASHTABLE_COMPARE_FUNCTION CompareFunction,
2938  _In_ PPH_HASHTABLE_HASH_FUNCTION HashFunction,
2939  _In_ ULONG InitialCapacity
2940  );
2941 
2942 PHLIBAPI
2943 PVOID
2944 NTAPI
2946  _Inout_ PPH_HASHTABLE Hashtable,
2947  _In_ PVOID Entry
2948  );
2949 
2950 PHLIBAPI
2951 PVOID
2952 NTAPI
2954  _Inout_ PPH_HASHTABLE Hashtable,
2955  _In_ PVOID Entry,
2956  _Out_opt_ PBOOLEAN Added
2957  );
2958 
2959 PHLIBAPI
2960 VOID
2961 NTAPI
2963  _Inout_ PPH_HASHTABLE Hashtable
2964  );
2965 
2966 PHLIBAPI
2967 BOOLEAN
2968 NTAPI
2970  _In_ PPH_HASHTABLE Hashtable,
2971  _Out_ PVOID *Entry,
2972  _Inout_ PULONG EnumerationKey
2973  );
2974 
2975 PHLIBAPI
2976 PVOID
2977 NTAPI
2979  _In_ PPH_HASHTABLE Hashtable,
2980  _In_ PVOID Entry
2981  );
2982 
2983 PHLIBAPI
2984 BOOLEAN
2985 NTAPI
2987  _Inout_ PPH_HASHTABLE Hashtable,
2988  _In_ PVOID Entry
2989  );
2990 
2991 // New faster enumeration method
2992 
2994 {
2995  ULONG_PTR Current;
2996  ULONG_PTR End;
2997  ULONG_PTR Step;
2999 
3000 FORCEINLINE
3001 VOID
3003  _In_ PPH_HASHTABLE Hashtable,
3004  _Out_ PPH_HASHTABLE_ENUM_CONTEXT Context
3005  )
3006 {
3007  Context->Current = (ULONG_PTR)Hashtable->Entries;
3008  Context->Step = PH_HASHTABLE_ENTRY_SIZE(Hashtable->EntrySize);
3009  Context->End = Context->Current + (ULONG_PTR)Hashtable->NextEntry * Context->Step;
3010 }
3011 
3012 FORCEINLINE
3013 PVOID
3015  _Inout_ PPH_HASHTABLE_ENUM_CONTEXT Context
3016  )
3017 {
3018  PPH_HASHTABLE_ENTRY entry;
3019 
3020  while (Context->Current != Context->End)
3021  {
3022  entry = (PPH_HASHTABLE_ENTRY)Context->Current;
3023  Context->Current += Context->Step;
3024 
3025  if (entry->HashCode != -1)
3026  return &entry->Body;
3027  }
3028 
3029  return NULL;
3030 }
3031 
3032 PHLIBAPI
3033 ULONG
3034 NTAPI
3035 PhHashBytes(
3036  _In_reads_(Length) PUCHAR Bytes,
3037  _In_ SIZE_T Length
3038  );
3039 
3040 PHLIBAPI
3041 ULONG
3042 NTAPI
3044  _In_ PPH_STRINGREF String,
3045  _In_ BOOLEAN IgnoreCase
3046  );
3047 
3048 FORCEINLINE
3049 ULONG
3051  _In_ ULONG Value
3052  )
3053 {
3054  // Java style.
3055  Value ^= (Value >> 20) ^ (Value >> 12);
3056  return Value ^ (Value >> 7) ^ (Value >> 4);
3057 }
3058 
3059 FORCEINLINE
3060 ULONG
3062  _In_ ULONG64 Value
3063  )
3064 {
3065  // http://www.concentric.net/~Ttwang/tech/inthash.htm
3066 
3067  Value = ~Value + (Value << 18);
3068  Value ^= Value >> 31;
3069  Value *= 21;
3070  Value ^= Value >> 11;
3071  Value += Value << 6;
3072  Value ^= Value >> 22;
3073 
3074  return (ULONG)Value;
3075 }
3076 
3077 FORCEINLINE
3078 ULONG
3080  _In_ ULONG_PTR Value
3081  )
3082 {
3083 #ifdef _WIN64
3084  return PhHashInt64(Value);
3085 #else
3086  return PhHashInt32(Value);
3087 #endif
3088 }
3089 
3090 // Simple hashtable
3091 
3092 typedef struct _PH_KEY_VALUE_PAIR
3093 {
3094  PVOID Key;
3095  PVOID Value;
3097 
3098 PHLIBAPI
3099 PPH_HASHTABLE
3100 NTAPI
3102  _In_ ULONG InitialCapacity
3103  );
3104 
3105 PHLIBAPI
3106 PVOID
3107 NTAPI
3109  _Inout_ PPH_HASHTABLE SimpleHashtable,
3110  _In_opt_ PVOID Key,
3111  _In_opt_ PVOID Value
3112  );
3113 
3114 PHLIBAPI
3115 PVOID *
3116 NTAPI
3118  _In_ PPH_HASHTABLE SimpleHashtable,
3119  _In_opt_ PVOID Key
3120  );
3121 
3122 FORCEINLINE
3123 PVOID
3124 NTAPI
3126  _In_ PPH_HASHTABLE SimpleHashtable,
3127  _In_opt_ PVOID Key
3128  )
3129 {
3130  PVOID *item;
3131 
3132  item = PhFindItemSimpleHashtable(SimpleHashtable, Key);
3133 
3134  if (item)
3135  return *item;
3136  else
3137  return NULL;
3138 }
3139 
3140 PHLIBAPI
3141 BOOLEAN
3142 NTAPI
3144  _Inout_ PPH_HASHTABLE SimpleHashtable,
3145  _In_opt_ PVOID Key
3146  );
3147 
3148 // Free list
3149 
3150 typedef struct _PH_FREE_LIST
3151 {
3152  SLIST_HEADER ListHead;
3153 
3154  ULONG Count;
3156  SIZE_T Size;
3158 
3159 typedef struct _PH_FREE_LIST_ENTRY
3160 {
3161  SLIST_ENTRY ListEntry;
3164 
3165 #ifdef _WIN64
3166 C_ASSERT(FIELD_OFFSET(PH_FREE_LIST_ENTRY, ListEntry) == 0x0);
3167 C_ASSERT(FIELD_OFFSET(PH_FREE_LIST_ENTRY, Body) == 0x10);
3168 #else
3169 C_ASSERT(FIELD_OFFSET(PH_FREE_LIST_ENTRY, ListEntry) == 0x0);
3170 C_ASSERT(FIELD_OFFSET(PH_FREE_LIST_ENTRY, Body) == 0x8);
3171 #endif
3172 
3173 PHLIBAPI
3174 VOID
3175 NTAPI
3177  _Out_ PPH_FREE_LIST FreeList,
3178  _In_ SIZE_T Size,
3179  _In_ ULONG MaximumCount
3180  );
3181 
3182 PHLIBAPI
3183 VOID
3184 NTAPI
3186  _Inout_ PPH_FREE_LIST FreeList
3187  );
3188 
3189 PHLIBAPI
3190 PVOID
3191 NTAPI
3193  _Inout_ PPH_FREE_LIST FreeList
3194  );
3195 
3196 PHLIBAPI
3197 VOID
3198 NTAPI
3200  _Inout_ PPH_FREE_LIST FreeList,
3201  _In_ PVOID Memory
3202  );
3203 
3204 // Callback
3205 
3214 typedef VOID (NTAPI *PPH_CALLBACK_FUNCTION)(
3215  _In_opt_ PVOID Parameter,
3216  _In_opt_ PVOID Context
3217  );
3218 
3223 {
3225  LIST_ENTRY ListEntry;
3230  PVOID Context;
3236  BOOLEAN Unregistering;
3237  BOOLEAN Reserved;
3239  USHORT Flags;
3241 
3248 typedef struct _PH_CALLBACK
3249 {
3251  LIST_ENTRY ListHead;
3257 
3258 #define PH_CALLBACK_DECLARE(Name) PH_CALLBACK Name = { &Name.ListHead, &Name.ListHead, PH_QUEUED_LOCK_INIT, PH_QUEUED_LOCK_INIT }
3259 
3260 PHLIBAPI
3261 VOID
3262 NTAPI
3264  _Out_ PPH_CALLBACK Callback
3265  );
3266 
3267 PHLIBAPI
3268 VOID
3269 NTAPI
3271  _Inout_ PPH_CALLBACK Callback
3272  );
3273 
3274 PHLIBAPI
3275 VOID
3276 NTAPI
3278  _Inout_ PPH_CALLBACK Callback,
3279  _In_ PPH_CALLBACK_FUNCTION Function,
3280  _In_opt_ PVOID Context,
3281  _Out_ PPH_CALLBACK_REGISTRATION Registration
3282  );
3283 
3284 PHLIBAPI
3285 VOID
3286 NTAPI
3288  _Inout_ PPH_CALLBACK Callback,
3289  _In_ PPH_CALLBACK_FUNCTION Function,
3290  _In_opt_ PVOID Context,
3291  _In_ USHORT Flags,
3292  _Out_ PPH_CALLBACK_REGISTRATION Registration
3293  );
3294 
3295 PHLIBAPI
3296 VOID
3297 NTAPI
3299  _Inout_ PPH_CALLBACK Callback,
3300  _Inout_ PPH_CALLBACK_REGISTRATION Registration
3301  );
3302 
3303 PHLIBAPI
3304 VOID
3305 NTAPI
3307  _In_ PPH_CALLBACK Callback,
3308  _In_opt_ PVOID Parameter
3309  );
3310 
3311 // General
3312 
3313 PHLIBAPI
3314 ULONG
3315 NTAPI
3317  _In_ ULONG Minimum
3318  );
3319 
3320 PHLIBAPI
3321 ULONG
3322 NTAPI
3324  _In_ ULONG Number
3325  );
3326 
3327 PHLIBAPI
3328 ULONG
3329 NTAPI
3331  _In_ ULONG Base,
3332  _In_ ULONG Exponent
3333  );
3334 
3335 PHLIBAPI
3336 ULONG64
3337 NTAPI
3339  _In_ ULONG64 Base,
3340  _In_ ULONG Exponent
3341  );
3342 
3343 PHLIBAPI
3344 BOOLEAN
3345 NTAPI
3347  _In_ PPH_STRINGREF String,
3348  _Out_writes_bytes_(String->Length / sizeof(WCHAR) / 2) PUCHAR Buffer
3349  );
3350 
3351 PHLIBAPI
3352 PPH_STRING
3353 NTAPI
3355  _In_reads_bytes_(Length) PUCHAR Buffer,
3356  _In_ ULONG Length
3357  );
3358 
3359 PPH_STRING
3360 NTAPI
3362  _In_reads_bytes_(Length) PUCHAR Buffer,
3363  _In_ ULONG Length,
3364  _In_ BOOLEAN UpperCase
3365  );
3366 
3367 PHLIBAPI
3368 BOOLEAN
3369 NTAPI
3371  _In_ PPH_STRINGREF String,
3372  _In_opt_ ULONG Base,
3373  _Out_opt_ PLONG64 Integer
3374  );
3375 
3376 PHLIBAPI
3377 PPH_STRING
3378 NTAPI
3380  _In_ LONG64 Integer,
3381  _In_opt_ ULONG Base,
3382  _In_ BOOLEAN Signed
3383  );
3384 
3385 #define PH_TIMESPAN_STR_LEN 30
3386 #define PH_TIMESPAN_STR_LEN_1 (PH_TIMESPAN_STR_LEN + 1)
3387 
3388 #define PH_TIMESPAN_HMS 0
3389 #define PH_TIMESPAN_HMSM 1
3390 #define PH_TIMESPAN_DHMS 2
3391 
3392 PHLIBAPI
3393 VOID
3394 NTAPI
3396  _Out_writes_(PH_TIMESPAN_STR_LEN_1) PWSTR Destination,
3397  _In_ ULONG64 Ticks,
3398  _In_opt_ ULONG Mode
3399  );
3400 
3401 PHLIBAPI
3402 VOID
3403 NTAPI
3405  _Inout_updates_(Count) _Needs_align_(4) PULONG Memory,
3406  _In_ ULONG Value,
3407  _In_ SIZE_T Count
3408  );
3409 
3411 PHLIBAPI VOID FASTCALL PhxfFillMemoryUlong(PULONG Memory, ULONG Value, ULONG Count);
3412 
3413 PHLIBAPI
3414 VOID
3415 NTAPI
3417  _Inout_updates_(Count) PFLOAT A,
3418  _In_ FLOAT B,
3419  _In_ SIZE_T Count
3420  );
3421 
3423 PHLIBAPI VOID FASTCALL PhxfDivideSingle2U(PFLOAT A, FLOAT B, ULONG Count);
3424 
3425 // Format
3426 
3427 typedef enum _PH_FORMAT_TYPE
3428 {
3443 
3452 
3453  // Floating-point flags
3462 
3463  // Floating-point and integer flags
3467  FormatPrefixSign = 0x20000,
3471  FormatPadZeros = 0x40000,
3472 
3473  // General flags
3475  FormatLeftAlign = 0x80000000,
3477  FormatRightAlign = 0x40000000,
3479  FormatUpperCase = 0x20000000
3480 } PH_FORMAT_TYPE;
3481 
3485 typedef struct _PH_FORMAT
3486 {
3492  USHORT Precision;
3496  USHORT Width;
3498  WCHAR Pad;
3502  UCHAR Radix;
3505  UCHAR Parameter;
3506  union
3507  {
3508  WCHAR Char;
3510  PWSTR StringZ;
3514  LONG64 Int64;
3515  LONG_PTR IntPtr;
3516  ULONG UInt32;
3517  ULONG64 UInt64;
3518  ULONG_PTR UIntPtr;
3519  DOUBLE Double;
3520 
3521  ULONG64 Size;
3522  } u;
3523 } PH_FORMAT, *PPH_FORMAT;
3524 
3525 // Convenience macros
3526 #define PhInitFormatC(f, v) do { (f)->Type = CharFormatType; (f)->u.Char = (v); } while (0)
3527 #define PhInitFormatS(f, v) do { (f)->Type = StringFormatType; PhInitializeStringRef(&(f)->u.String, (v)); } while (0)
3528 #define PhInitFormatSR(f, v) do { (f)->Type = StringFormatType; (f)->u.String = (v); } while (0)
3529 #define PhInitFormatMultiByteS(f, v) do { (f)->Type = MultiByteStringFormatType; PhInitializeBytesRef(&(f)->u.MultiByteString, (v)); } while (0)
3530 #define PhInitFormatD(f, v) do { (f)->Type = Int32FormatType; (f)->u.Int32 = (v); } while (0)
3531 #define PhInitFormatU(f, v) do { (f)->Type = UInt32FormatType; (f)->u.UInt32 = (v); } while (0)
3532 #define PhInitFormatX(f, v) do { (f)->Type = UInt32FormatType | FormatUseRadix; (f)->u.UInt32 = (v); (f)->Radix = 16; } while (0)
3533 #define PhInitFormatI64D(f, v) do { (f)->Type = Int64FormatType; (f)->u.Int64 = (v); } while (0)
3534 #define PhInitFormatI64U(f, v) do { (f)->Type = UInt64FormatType; (f)->u.UInt64 = (v); } while (0)
3535 #define PhInitFormatI64X(f, v) do { (f)->Type = UInt64FormatType | FormatUseRadix; (f)->u.UInt64 = (v); (f)->Radix = 16; } while (0)
3536 #define PhInitFormatIU(f, v) do { (f)->Type = UIntPtrFormatType; (f)->u.UIntPtr = (v); } while (0)
3537 #define PhInitFormatIX(f, v) do { (f)->Type = UIntPtrFormatType | FormatUseRadix; (f)->u.UIntPtr = (v); (f)->Radix = 16; } while (0)
3538 #define PhInitFormatF(f, v, p) do { (f)->Type = DoubleFormatType | FormatUsePrecision; (f)->u.Double = (v); (f)->Precision = (p); } while (0)
3539 #define PhInitFormatE(f, v, p) do { (f)->Type = DoubleFormatType | FormatStandardForm | FormatUsePrecision; (f)->u.Double = (v); (f)->Precision = (p); } while (0)
3540 #define PhInitFormatA(f, v, p) do { (f)->Type = DoubleFormatType | FormatHexadecimalForm | FormatUsePrecision; (f)->u.Double = (v); (f)->Precision = (p); } while (0)
3541 #define PhInitFormatSize(f, v) do { (f)->Type = SizeFormatType; (f)->u.Size = (v); } while (0)
3542 
3543 PHLIBAPI
3544 PPH_STRING
3545 NTAPI
3546 PhFormat(
3547  _In_reads_(Count) PPH_FORMAT Format,
3548  _In_ ULONG Count,
3549  _In_opt_ SIZE_T InitialCapacity
3550  );
3551 
3552 PHLIBAPI
3553 BOOLEAN
3554 NTAPI
3556  _In_reads_(Count) PPH_FORMAT Format,
3557  _In_ ULONG Count,
3558  _Out_writes_bytes_opt_(BufferLength) PWSTR Buffer,
3559  _In_opt_ SIZE_T BufferLength,
3560  _Out_opt_ PSIZE_T ReturnLength
3561  );
3562 
3563 // basesupa
3564 
3565 PHLIBAPI
3566 PPH_STRING
3567 NTAPI
3569  _In_ PWSTR Buffer
3570  );
3571 
3572 PHLIBAPI
3573 PPH_STRING
3574 NTAPI
3576  _In_opt_ PWSTR Buffer,
3577  _In_ SIZE_T Length
3578  );
3579 
3580 PHLIBAPI
3581 PPH_STRING
3582 NTAPI
3584  _In_ PPH_STRING String
3585  );
3586 
3587 PHLIBAPI
3588 PPH_STRING
3589 NTAPI
3591  _In_ ULONG Count,
3592  ...
3593  );
3594 
3595 PHLIBAPI
3596 PPH_STRING
3597 NTAPI
3599  _In_ PWSTR String1,
3600  _In_ PWSTR String2
3601  );
3602 
3603 PHLIBAPI
3604 PPH_STRING
3605 NTAPI
3607  _In_ _Printf_format_string_ PWSTR Format,
3608  ...
3609  );
3610 
3611 PHLIBAPI
3612 PPH_STRING
3613 NTAPI
3615  _In_ PPH_STRING String
3616  );
3617 
3618 PHLIBAPI
3619 PPH_STRING
3620 NTAPI
3622  _In_ PPH_STRING String
3623  );
3624 
3625 PHLIBAPI
3626 PPH_STRING
3627 NTAPI
3628 PhaSubstring(
3629  _In_ PPH_STRING String,
3630  _In_ SIZE_T StartIndex,
3631  _In_ SIZE_T Count
3632  );
3633 
3634 // error
3635 
3636 PHLIBAPI
3637 ULONG
3638 NTAPI
3640  _In_ NTSTATUS Status
3641  );
3642 
3643 PHLIBAPI
3644 NTSTATUS
3645 NTAPI
3647  _In_ ULONG DosError
3648  );
3649 
3650 PHLIBAPI
3651 BOOLEAN
3652 NTAPI
3654  _In_ NTSTATUS Status
3655  );
3656 
3657 // collect
3658 
3659 // Generic tree definitions
3660 
3662 {
3666 
3667 #define PhIsLeftChildElement(Links) ((Links)->Parent->Left == (Links))
3668 #define PhIsRightChildElement(Links) ((Links)->Parent->Right == (Links))
3669 
3670 // AVL trees
3671 
3672 typedef struct _PH_AVL_LINKS
3673 {
3679 
3680 struct _PH_AVL_TREE;
3681 
3682 typedef LONG (NTAPI *PPH_AVL_TREE_COMPARE_FUNCTION)(
3683  _In_ PPH_AVL_LINKS Links1,
3684  _In_ PPH_AVL_LINKS Links2
3685  );
3686 
3687 typedef struct _PH_AVL_TREE
3688 {
3689  PH_AVL_LINKS Root; // Right contains real root
3690  ULONG Count;
3691 
3692  PPH_AVL_TREE_COMPARE_FUNCTION CompareFunction;
3694 
3695 #define PH_AVL_TREE_INIT(CompareFunction) { { NULL, NULL, NULL, 0 }, 0, CompareFunction }
3696 
3697 #define PhRootElementAvlTree(Tree) ((Tree)->Root.Right)
3698 
3699 PHLIBAPI
3700 VOID
3701 NTAPI
3703  _Out_ PPH_AVL_TREE Tree,
3704  _In_ PPH_AVL_TREE_COMPARE_FUNCTION CompareFunction
3705  );
3706 
3707 PHLIBAPI
3708 PPH_AVL_LINKS
3709 NTAPI
3711  _Inout_ PPH_AVL_TREE Tree,
3712  _Out_ PPH_AVL_LINKS Element
3713  );
3714 
3715 PHLIBAPI
3716 VOID
3717 NTAPI
3719  _Inout_ PPH_AVL_TREE Tree,
3720  _Inout_ PPH_AVL_LINKS Element
3721  );
3722 
3723 PHLIBAPI
3724 PPH_AVL_LINKS
3725 NTAPI
3727  _In_ PPH_AVL_TREE Tree,
3728  _In_ PPH_AVL_LINKS Element
3729  );
3730 
3731 PHLIBAPI
3732 PPH_AVL_LINKS
3733 NTAPI
3735  _In_ PPH_AVL_TREE Tree,
3736  _In_ PPH_AVL_LINKS Element,
3737  _Out_ PLONG Result
3738  );
3739 
3740 PHLIBAPI
3741 PPH_AVL_LINKS
3742 NTAPI
3744  _In_ PPH_AVL_TREE Tree
3745  );
3746 
3747 PHLIBAPI
3748 PPH_AVL_LINKS
3749 NTAPI
3751  _In_ PPH_AVL_TREE Tree
3752  );
3753 
3754 PHLIBAPI
3755 PPH_AVL_LINKS
3756 NTAPI
3758  _In_ PPH_AVL_LINKS Element
3759  );
3760 
3761 PHLIBAPI
3762 PPH_AVL_LINKS
3763 NTAPI
3765  _In_ PPH_AVL_LINKS Element
3766  );
3767 
3768 typedef BOOLEAN (NTAPI *PPH_ENUM_AVL_TREE_CALLBACK)(
3769  _In_ PPH_AVL_TREE Tree,
3770  _In_ PPH_AVL_LINKS Element,
3771  _In_opt_ PVOID Context
3772  );
3773 
3774 PHLIBAPI
3775 VOID
3776 NTAPI
3778  _In_ PPH_AVL_TREE Tree,
3779  _In_ PH_TREE_ENUMERATION_ORDER Order,
3780  _In_ PPH_ENUM_AVL_TREE_CALLBACK Callback,
3781  _In_opt_ PVOID Context
3782  );
3783 
3784 // handle
3785 
3786 struct _PH_HANDLE_TABLE;
3788 
3790 {
3791  union
3792  {
3793  PVOID Object;
3794  ULONG_PTR Value;
3795  struct
3796  {
3800  ULONG_PTR Type : 1;
3804  ULONG_PTR Locked : 1;
3805  ULONG_PTR Value : sizeof(ULONG_PTR) * 8 - 2;
3806  } TypeAndValue;
3807  };
3808  union
3809  {
3810  ACCESS_MASK GrantedAccess;
3812  ULONG_PTR Value2;
3813  };
3815 
3816 #define PH_HANDLE_TABLE_SAFE
3817 #define PH_HANDLE_TABLE_FREE_COUNT 64
3818 
3819 #define PH_HANDLE_TABLE_STRICT_FIFO 0x1
3820 #define PH_HANDLE_TABLE_VALID_FLAGS 0x1
3821 
3822 VOID
3824  VOID
3825  );
3826 
3827 PPH_HANDLE_TABLE
3828 NTAPI
3830  VOID
3831  );
3832 
3833 VOID
3834 NTAPI
3836  _In_ _Post_invalid_ PPH_HANDLE_TABLE HandleTable
3837  );
3838 
3839 BOOLEAN
3840 NTAPI
3842  _Inout_ PPH_HANDLE_TABLE HandleTable,
3843  _Inout_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
3844  );
3845 
3846 VOID
3847 NTAPI
3849  _Inout_ PPH_HANDLE_TABLE HandleTable,
3850  _Inout_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
3851  );
3852 
3853 HANDLE
3854 NTAPI
3856  _Inout_ PPH_HANDLE_TABLE HandleTable,
3857  _In_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
3858  );
3859 
3860 BOOLEAN
3861 NTAPI
3863  _Inout_ PPH_HANDLE_TABLE HandleTable,
3864  _In_ HANDLE Handle,
3865  _In_opt_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
3866  );
3867 
3868 PPH_HANDLE_TABLE_ENTRY
3869 NTAPI
3871  _In_ PPH_HANDLE_TABLE HandleTable,
3872  _In_ HANDLE Handle
3873  );
3874 
3875 typedef BOOLEAN (NTAPI *PPH_ENUM_HANDLE_TABLE_CALLBACK)(
3876  _In_ PPH_HANDLE_TABLE HandleTable,
3877  _In_ HANDLE Handle,
3878  _In_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry,
3879  _In_opt_ PVOID Context
3880  );
3881 
3882 VOID
3883 NTAPI
3885  _In_ PPH_HANDLE_TABLE HandleTable,
3886  _In_ PPH_ENUM_HANDLE_TABLE_CALLBACK Callback,
3887  _In_opt_ PVOID Context
3888  );
3889 
3890 VOID
3891 NTAPI
3893  _In_ PPH_HANDLE_TABLE HandleTable,
3894  _In_ PPH_ENUM_HANDLE_TABLE_CALLBACK Callback,
3895  _In_opt_ PVOID Context
3896  );
3897 
3899 {
3904 
3906 {
3907  ULONG Count;
3908  ULONG Flags;
3909  ULONG TableLevel;
3911 
3913 {
3914  ULONG Flags;
3916 
3917 NTSTATUS
3918 NTAPI
3920  _In_ PPH_HANDLE_TABLE HandleTable,
3921  _In_ PH_HANDLE_TABLE_INFORMATION_CLASS InformationClass,
3922  _Out_writes_bytes_opt_(BufferLength) PVOID Buffer,
3923  _In_ ULONG BufferLength,
3924  _Out_opt_ PULONG ReturnLength
3925  );
3926 
3927 NTSTATUS
3928 NTAPI
3930  _Inout_ PPH_HANDLE_TABLE HandleTable,
3931  _In_ PH_HANDLE_TABLE_INFORMATION_CLASS InformationClass,
3932  _In_reads_bytes_(BufferLength) PVOID Buffer,
3933  _In_ ULONG BufferLength
3934  );
3935 
3936 // workqueue
3937 
3938 #if !defined(_PH_WORKQUEUE_PRIVATE) && defined(DEBUG)
3939 extern PPH_LIST PhDbgWorkQueueList;
3940 extern PH_QUEUED_LOCK PhDbgWorkQueueListLock;
3941 #endif
3942 
3943 typedef struct _PH_WORK_QUEUE
3944 {
3946  BOOLEAN Terminating;
3947 
3948  LIST_ENTRY QueueListHead;
3951 
3955 
3959  ULONG BusyCount;
3961 
3963  _In_ PUSER_THREAD_START_ROUTINE Function,
3964  _In_ PVOID Context
3965  );
3966 
3967 typedef struct _PH_WORK_QUEUE_ITEM
3968 {
3969  LIST_ENTRY ListEntry;
3971  PVOID Context;
3974 
3975 VOID
3977  VOID
3978  );
3979 
3980 PHLIBAPI
3981 VOID
3982 NTAPI
3984  _Out_ PPH_WORK_QUEUE WorkQueue,
3985  _In_ ULONG MinimumThreads,
3986  _In_ ULONG MaximumThreads,
3987  _In_ ULONG NoWorkTimeout
3988  );
3989 
3990 PHLIBAPI
3991 VOID
3992 NTAPI
3994  _Inout_ PPH_WORK_QUEUE WorkQueue
3995  );
3996 
3997 PHLIBAPI
3998 VOID
3999 NTAPI
4001  _Inout_ PPH_WORK_QUEUE WorkQueue
4002  );
4003 
4004 PHLIBAPI
4005 VOID
4006 NTAPI
4008  _Inout_ PPH_WORK_QUEUE WorkQueue,
4009  _In_ PUSER_THREAD_START_ROUTINE Function,
4010  _In_opt_ PVOID Context
4011  );
4012 
4013 VOID
4015  _Inout_ PPH_WORK_QUEUE WorkQueue,
4016  _In_ PUSER_THREAD_START_ROUTINE Function,
4017  _In_opt_ PVOID Context,
4018  _In_opt_ PPH_WORK_QUEUE_ITEM_DELETE_FUNCTION DeleteFunction
4019  );
4020 
4021 PHLIBAPI
4022 VOID
4023 NTAPI
4025  _In_ PUSER_THREAD_START_ROUTINE Function,
4026  _In_opt_ PVOID Context
4027  );
4028 
4029 // data
4030 
4031 // SIDs
4032 
4033 extern SID PhSeNobodySid;
4034 
4035 extern SID PhSeEveryoneSid;
4036 
4037 extern SID PhSeLocalSid;
4038 
4039 extern SID PhSeCreatorOwnerSid;
4040 extern SID PhSeCreatorGroupSid;
4041 
4042 extern SID PhSeDialupSid;
4043 extern SID PhSeNetworkSid;
4044 extern SID PhSeBatchSid;
4045 extern SID PhSeInteractiveSid;
4046 extern SID PhSeServiceSid;
4047 extern SID PhSeAnonymousLogonSid;
4048 extern SID PhSeProxySid;
4049 extern SID PhSeAuthenticatedUserSid;
4050 extern SID PhSeRestrictedCodeSid;
4051 extern SID PhSeTerminalServerUserSid;
4053 extern SID PhSeLocalSystemSid;
4054 extern SID PhSeLocalServiceSid;
4055 extern SID PhSeNetworkServiceSid;
4056 
4057 // Unicode
4058 
4060 
4061 // Characters
4062 
4063 extern BOOLEAN PhCharIsPrintable[256];
4064 extern ULONG PhCharToInteger[256];
4065 extern CHAR PhIntegerToChar[69];
4066 extern CHAR PhIntegerToCharUpper[69];
4067 
4068 // CRC32
4069 
4070 extern ULONG PhCrc32Table[256];
4071 
4072 // Enums
4073 
4076 extern WCHAR *PhKWaitReasonNames[MaximumWaitReason];
4077 
4078 #ifdef __cplusplus
4079 }
4080 #endif
4081 
4082 #endif