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