ReactOS  0.4.15-dev-1070-ge1a01de
probe.h
Go to the documentation of this file.
1 #ifndef INCLUDE_REACTOS_CAPTURE_H
2 #define INCLUDE_REACTOS_CAPTURE_H
3 
4 #include <suppress.h>
5 
6 #if ! defined(_NTOSKRNL_) && ! defined(_WIN32K_)
7 #error Header intended for use by NTOSKRNL/WIN32K only!
8 #endif
9 
10 static const UNICODE_STRING __emptyUnicodeString = {0, 0, NULL};
11 static const LARGE_INTEGER __emptyLargeInteger = {{0, 0}};
12 static const ULARGE_INTEGER __emptyULargeInteger = {{0, 0}};
13 static const IO_STATUS_BLOCK __emptyIoStatusBlock = {{0}, 0};
14 
15 #if defined(_WIN32K_) && !defined(__cplusplus)
16 static const LARGE_STRING __emptyLargeString = {0, 0, 0, NULL};
17 #endif
18 
19 /*
20  * NOTE: Alignment of the pointers is not verified!
21  */
22 #define ProbeForWriteGenericType(Ptr, Type) \
23  do { \
24  if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
25  (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
26  ExRaiseAccessViolation(); \
27  } \
28  *(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \
29  } while (0)
30 
31 #define ProbeForWriteBoolean(Ptr) ProbeForWriteGenericType(Ptr, BOOLEAN)
32 #define ProbeForWriteUchar(Ptr) ProbeForWriteGenericType(Ptr, UCHAR)
33 #define ProbeForWriteChar(Ptr) ProbeForWriteGenericType(Ptr, CHAR)
34 #define ProbeForWriteUshort(Ptr) ProbeForWriteGenericType(Ptr, USHORT)
35 #define ProbeForWriteShort(Ptr) ProbeForWriteGenericType(Ptr, SHORT)
36 #define ProbeForWriteUlong(Ptr) ProbeForWriteGenericType(Ptr, ULONG)
37 #define ProbeForWriteLong(Ptr) ProbeForWriteGenericType(Ptr, LONG)
38 #define ProbeForWriteUint(Ptr) ProbeForWriteGenericType(Ptr, UINT)
39 #define ProbeForWriteInt(Ptr) ProbeForWriteGenericType(Ptr, INT)
40 #define ProbeForWriteUlonglong(Ptr) ProbeForWriteGenericType(Ptr, ULONGLONG)
41 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG)
42 #define ProbeForWritePointer(Ptr) ProbeForWriteGenericType(Ptr, PVOID)
43 #define ProbeForWriteHandle(Ptr) ProbeForWriteGenericType(Ptr, HANDLE)
44 #define ProbeForWriteLangid(Ptr) ProbeForWriteGenericType(Ptr, LANGID)
45 #define ProbeForWriteSize_t(Ptr) ProbeForWriteGenericType(Ptr, SIZE_T)
46 #define ProbeForWriteLargeInteger(Ptr) ProbeForWriteGenericType(&((PLARGE_INTEGER)Ptr)->QuadPart, LONGLONG)
47 #define ProbeForWriteUlargeInteger(Ptr) ProbeForWriteGenericType(&((PULARGE_INTEGER)Ptr)->QuadPart, ULONGLONG)
48 #define ProbeForWriteUnicodeString(Ptr) ProbeForWriteGenericType((PUNICODE_STRING)Ptr, UNICODE_STRING)
49 #if defined(_WIN32K_)
50 #define ProbeForWriteLargeString(Ptr) ProbeForWriteGenericType((PLARGE_STRING)Ptr, LARGE_STRING)
51 #endif
52 #define ProbeForWriteIoStatusBlock(Ptr) ProbeForWriteGenericType((PIO_STATUS_BLOCK)Ptr, IO_STATUS_BLOCK)
53 
54 #define ProbeForReadGenericType(Ptr, Type, Default) \
55  (((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
56  (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) ? \
57  ExRaiseAccessViolation(), Default : \
58  *(const volatile Type *)(Ptr))
59 
60 #define ProbeForReadBoolean(Ptr) ProbeForReadGenericType(Ptr, BOOLEAN, FALSE)
61 #define ProbeForReadUchar(Ptr) ProbeForReadGenericType(Ptr, UCHAR, 0)
62 #define ProbeForReadChar(Ptr) ProbeForReadGenericType(Ptr, CHAR, 0)
63 #define ProbeForReadUshort(Ptr) ProbeForReadGenericType(Ptr, USHORT, 0)
64 #define ProbeForReadShort(Ptr) ProbeForReadGenericType(Ptr, SHORT, 0)
65 #define ProbeForReadUlong(Ptr) ProbeForReadGenericType(Ptr, ULONG, 0)
66 #define ProbeForReadLong(Ptr) ProbeForReadGenericType(Ptr, LONG, 0)
67 #define ProbeForReadUint(Ptr) ProbeForReadGenericType(Ptr, UINT, 0)
68 #define ProbeForReadInt(Ptr) ProbeForReadGenericType(Ptr, INT, 0)
69 #define ProbeForReadUlonglong(Ptr) ProbeForReadGenericType(Ptr, ULONGLONG, 0)
70 #define ProbeForReadLonglong(Ptr) ProbeForReadGenericType(Ptr, LONGLONG, 0)
71 #define ProbeForReadPointer(Ptr) ProbeForReadGenericType(Ptr, PVOID, NULL)
72 #define ProbeForReadHandle(Ptr) ProbeForReadGenericType(Ptr, HANDLE, NULL)
73 #define ProbeForReadLangid(Ptr) ProbeForReadGenericType(Ptr, LANGID, 0)
74 #define ProbeForReadSize_t(Ptr) ProbeForReadGenericType(Ptr, SIZE_T, 0)
75 #define ProbeForReadLargeInteger(Ptr) ProbeForReadGenericType((const LARGE_INTEGER *)(Ptr), LARGE_INTEGER, __emptyLargeInteger)
76 #define ProbeForReadUlargeInteger(Ptr) ProbeForReadGenericType((const ULARGE_INTEGER *)(Ptr), ULARGE_INTEGER, __emptyULargeInteger)
77 #define ProbeForReadUnicodeString(Ptr) ProbeForReadGenericType((const UNICODE_STRING *)(Ptr), UNICODE_STRING, __emptyUnicodeString)
78 #if defined(_WIN32K_)
79 #define ProbeForReadLargeString(Ptr) ProbeForReadGenericType((const LARGE_STRING *)(Ptr), LARGE_STRING, __emptyLargeString)
80 #endif
81 #define ProbeForReadIoStatusBlock(Ptr) ProbeForReadGenericType((const IO_STATUS_BLOCK *)(Ptr), IO_STATUS_BLOCK, __emptyIoStatusBlock)
82 
83 #define ProbeAndZeroHandle(Ptr) \
84  do { \
85  if ((ULONG_PTR)(Ptr) + sizeof(HANDLE) - 1 < (ULONG_PTR)(Ptr) || \
86  (ULONG_PTR)(Ptr) + sizeof(HANDLE) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
87  ExRaiseAccessViolation(); \
88  } \
89  *(volatile HANDLE *)(Ptr) = NULL; \
90  } while (0)
91 
92 /*
93  * Inlined Probing Macros
94  */
95 
96 #if defined(_WIN32K_)
97 static __inline
98 VOID
99 ProbeArrayForRead(IN const VOID *ArrayPtr,
100  IN ULONG ItemSize,
101  IN ULONG ItemCount,
103 {
104  ULONG ArraySize;
105 
106  /* Check for integer overflow */
107  ArraySize = ItemSize * ItemCount;
108  if (ArraySize / ItemSize != ItemCount)
109  {
111  }
112 
113  /* Probe the array */
114  _PRAGMA_WARNING_SUPPRESS(__WARNING_PROBE_NO_TRY) /* Must be inside __try / __except block */
115  ProbeForRead(ArrayPtr, ArraySize, Alignment);
116 }
117 
118 static __inline
119 VOID
120 ProbeArrayForWrite(IN OUT PVOID ArrayPtr,
121  IN ULONG ItemSize,
122  IN ULONG ItemCount,
124 {
125  ULONG ArraySize;
126 
127  /* Check for integer overflow */
128  ArraySize = ItemSize * ItemCount;
129  if (ArraySize / ItemSize != ItemCount)
130  {
132  }
133 
134  /* Probe the array */
135  _PRAGMA_WARNING_SUPPRESS(__WARNING_PROBE_NO_TRY) /* Must be inside __try / __except block */
136  ProbeForWrite(ArrayPtr, ArraySize, Alignment);
137 }
138 #endif /* _WIN32K_ */
139 
140 static __inline
141 NTSTATUS
143  IN KPROCESSOR_MODE CurrentMode,
144  IN const UNICODE_STRING *UnsafeSrc)
145 {
147  PWCHAR Buffer = NULL;
148  ASSERT(Dest != NULL);
149 
150  /* Probe the structure and buffer*/
151  if(CurrentMode != KernelMode)
152  {
153  _SEH2_TRY
154  {
155 #ifdef __cplusplus
156  ProbeForRead(UnsafeSrc, sizeof(*UnsafeSrc), 1);
157  RtlCopyMemory(Dest, UnsafeSrc, sizeof(*UnsafeSrc));
158 #else
159  *Dest = ProbeForReadUnicodeString(UnsafeSrc);
160 #endif
161  if(Dest->Buffer != NULL)
162  {
163  if (Dest->Length != 0)
164  {
165  ProbeForRead(Dest->Buffer, Dest->Length, sizeof(WCHAR));
166 
167  /* Allocate space for the buffer */
169  Dest->Length + sizeof(WCHAR),
170  'RTSU');
171  if (Buffer == NULL)
172  {
174  _SEH2_LEAVE;
175  }
176 
177  /* Copy it */
178  RtlCopyMemory(Buffer, Dest->Buffer, Dest->Length);
179  Buffer[Dest->Length / sizeof(WCHAR)] = UNICODE_NULL;
180 
181  /* Set it as the buffer */
182  Dest->Buffer = Buffer;
183  if (Dest->Length % sizeof(WCHAR))
184  {
185  Dest->Length--;
186  }
187  if (Dest->Length >= UNICODE_STRING_MAX_BYTES)
188  {
189  Dest->MaximumLength = Dest->Length;
190  }
191  else
192  {
193  Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
194  }
195  }
196  else
197  {
198  /* Sanitize structure */
199  Dest->MaximumLength = 0;
200  Dest->Buffer = NULL;
201  }
202  }
203  else
204  {
205  /* Sanitize structure */
206  Dest->Length = 0;
207  Dest->MaximumLength = 0;
208  }
209  }
211  {
212  /* Free allocated resources and zero the destination string */
213  if (Buffer != NULL)
214  {
215  ExFreePoolWithTag(Buffer, 'RTSU');
216  }
217  Dest->Length = 0;
218  Dest->MaximumLength = 0;
219  Dest->Buffer = NULL;
220 
221  /* Return the error code */
223  }
224  _SEH2_END;
225  }
226  else
227  {
228  /* Just copy the UNICODE_STRING structure, don't allocate new memory!
229  We trust the caller to supply valid pointers and data. */
230  *Dest = *UnsafeSrc;
231  }
232 
233  /* Return */
234  return Status;
235 }
236 
237 static __inline
238 VOID
240  IN KPROCESSOR_MODE CurrentMode)
241 {
242  if(CurrentMode != KernelMode && CapturedString->Buffer != NULL)
243  {
244  ExFreePoolWithTag(CapturedString->Buffer, 'RTSU');
245  }
246 
247  CapturedString->Length = 0;
248  CapturedString->MaximumLength = 0;
249  CapturedString->Buffer = NULL;
250 }
251 
252 #endif /* INCLUDE_REACTOS_CAPTURE_H */
static __inline NTSTATUS ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest, IN KPROCESSOR_MODE CurrentMode, IN const UNICODE_STRING *UnsafeSrc)
Definition: probe.h:142
#define IN
Definition: typedefs.h:39
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
static const IO_STATUS_BLOCK __emptyIoStatusBlock
Definition: probe.h:13
#define ExRaiseStatus
Definition: ntoskrnl.h:96
uint16_t * PWCHAR
Definition: typedefs.h:56
#define UNICODE_STRING_MAX_BYTES
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
_SEH2_TRY
Definition: create.c:4226
#define UNICODE_NULL
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
static const UNICODE_STRING __emptyUnicodeString
Definition: probe.h:10
Definition: bufpool.h:45
static __inline VOID ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, IN KPROCESSOR_MODE CurrentMode)
Definition: probe.h:239
__wchar_t WCHAR
Definition: xmlstorage.h:180
static const LARGE_INTEGER __emptyLargeInteger
Definition: probe.h:11
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static const ULARGE_INTEGER __emptyULargeInteger
Definition: probe.h:12
static UCHAR ItemSize[4]
Definition: parser.c:16
_SEH2_END
Definition: create.c:4400
#define ProbeForReadUnicodeString(Ptr)
Definition: probe.h:77
#define __WARNING_PROBE_NO_TRY
Definition: suppress.h:538
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define _SEH2_LEAVE
Definition: filesup.c:20
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define _PRAGMA_WARNING_SUPPRESS(x)
Definition: suppress.h:28