Fixed ProbeForRead* macros: make sure the data always is read while probing it
[reactos.git] / reactos / ntoskrnl / include / internal / ntoskrnl.h
1 #ifndef __INCLUDE_INTERNAL_NTOSKRNL_H
2 #define __INCLUDE_INTERNAL_NTOSKRNL_H
3
4 /*
5 * Use these to place a function in a specific section of the executable
6 */
7 #define PLACE_IN_SECTION(s) __attribute__((section (s)))
8 #define INIT_FUNCTION PLACE_IN_SECTION("init")
9 #define PAGE_LOCKED_FUNCTION PLACE_IN_SECTION("pagelk")
10 #define PAGE_UNLOCKED_FUNCTION PLACE_IN_SECTION("pagepo")
11
12 #ifdef _NTOSKRNL_
13
14 #include "ke.h"
15 #include "i386/mm.h"
16 #include "i386/fpu.h"
17 #include "ob.h"
18 #include "mm.h"
19 #include "ps.h"
20 #include "cc.h"
21 #include "io.h"
22 #include "po.h"
23 #include "se.h"
24 #include "ldr.h"
25 #include "kd.h"
26 #include "ex.h"
27 #include "fsrtl.h"
28 #include "lpc.h"
29 #include "rtl.h"
30 #ifdef KDBG
31 #include "../kdbg/kdb.h"
32 #endif
33 #include "dbgk.h"
34 #include "tag.h"
35 #include "test.h"
36 #include "inbv.h"
37
38 #include <pshpack1.h>
39 /*
40 * Defines a descriptor as it appears in the processor tables
41 */
42 typedef struct __DESCRIPTOR
43 {
44 ULONG a;
45 ULONG b;
46 } IDT_DESCRIPTOR, GDT_DESCRIPTOR;
47
48 #include <poppack.h>
49
50 extern IDT_DESCRIPTOR KiIdt[256];
51 //extern GDT_DESCRIPTOR KiGdt[256];
52
53 /*
54 * Initalization functions (called once by main())
55 */
56 VOID MmInitSystem(ULONG Phase, PLOADER_PARAMETER_BLOCK LoaderBlock, ULONG LastKernelAddress);
57 VOID IoInit(VOID);
58 VOID IoInit2(BOOLEAN BootLog);
59 VOID STDCALL IoInit3(VOID);
60 VOID ObInit(VOID);
61 VOID PsInit(VOID);
62 VOID CmInitializeRegistry(VOID);
63 VOID STDCALL CmInitHives(BOOLEAN SetupBoot);
64 VOID CmInit2(PCHAR CommandLine);
65 VOID CmShutdownRegistry(VOID);
66 BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
67 BOOLEAN CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize);
68 VOID KdInitSystem(ULONG Reserved, PLOADER_PARAMETER_BLOCK LoaderBlock);
69
70 /* FIXME - RtlpCreateUnicodeString is obsolete and should be removed ASAP! */
71 BOOLEAN FASTCALL
72 RtlpCreateUnicodeString(
73 IN OUT PUNICODE_STRING UniDest,
74 IN PCWSTR Source,
75 IN POOL_TYPE PoolType);
76
77 VOID
78 NTAPI
79 RtlpLogException(IN PEXCEPTION_RECORD ExceptionRecord,
80 IN PCONTEXT ContextRecord,
81 IN PVOID ContextData,
82 IN ULONG Size);
83
84 #define ExRaiseStatus RtlRaiseStatus
85
86 /*
87 * Inlined Probing Macros
88 */
89 static __inline
90 NTSTATUS
91 NTAPI
92 ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest,
93 IN KPROCESSOR_MODE CurrentMode,
94 IN PUNICODE_STRING UnsafeSrc)
95 {
96 NTSTATUS Status = STATUS_SUCCESS;
97 WCHAR *Buffer;
98 ASSERT(Dest != NULL);
99
100 /* Probe the structure and buffer*/
101 if(CurrentMode != KernelMode)
102 {
103 _SEH_TRY
104 {
105 ProbeForRead(UnsafeSrc,
106 sizeof(UNICODE_STRING),
107 sizeof(ULONG));
108 *Dest = *UnsafeSrc;
109 if(Dest->Buffer != NULL)
110 {
111 if (Dest->Length != 0)
112 {
113 ProbeForRead(Dest->Buffer,
114 Dest->Length,
115 sizeof(WCHAR));
116
117 /* Allocate space for the buffer */
118 Buffer = ExAllocatePoolWithTag(PagedPool,
119 Dest->Length + sizeof(WCHAR),
120 TAG('U', 'S', 'T', 'R'));
121 if (Buffer == NULL)
122 {
123 Status = STATUS_INSUFFICIENT_RESOURCES;
124 _SEH_LEAVE;
125 }
126
127 /* Copy it */
128 RtlCopyMemory(Buffer, Dest->Buffer, Dest->Length);
129 Buffer[Dest->Length / sizeof(WCHAR)] = UNICODE_NULL;
130
131 /* Set it as the buffer */
132 Dest->Buffer = Buffer;
133 }
134 else
135 {
136 /* sanitize structure */
137 Dest->MaximumLength = 0;
138 Dest->Buffer = NULL;
139 }
140 }
141 else
142 {
143 /* sanitize structure */
144 Dest->Length = 0;
145 Dest->MaximumLength = 0;
146 }
147 }
148 _SEH_HANDLE
149 {
150 Status = _SEH_GetExceptionCode();
151 }
152 _SEH_END;
153 }
154 else
155 {
156 /* Just copy the UNICODE_STRING structure, don't allocate new memory!
157 We trust the caller to supply valid pointers and data. */
158 *Dest = *UnsafeSrc;
159 }
160
161 /* Return */
162 return Status;
163 }
164
165 static __inline
166 VOID
167 NTAPI
168 ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString,
169 IN KPROCESSOR_MODE CurrentMode)
170 {
171 if(CurrentMode != KernelMode && CapturedString->Buffer != NULL)
172 {
173 ExFreePool(CapturedString->Buffer);
174 }
175 }
176
177 /*
178 * NOTE: Alignment of the pointers is not verified!
179 */
180 #define ProbeForWriteGenericType(Ptr, Type) \
181 do { \
182 if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
183 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
184 RtlRaiseStatus (STATUS_ACCESS_VIOLATION); \
185 } \
186 *(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \
187 } while (0)
188
189 #define ProbeForWriteBoolean(Ptr) ProbeForWriteGenericType(Ptr, BOOLEAN)
190 #define ProbeForWriteUchar(Ptr) ProbeForWriteGenericType(Ptr, UCHAR)
191 #define ProbeForWriteChar(Ptr) ProbeForWriteGenericType(Ptr, Char)
192 #define ProbeForWriteUshort(Ptr) ProbeForWriteGenericType(Ptr, USHORT)
193 #define ProbeForWriteShort(Ptr) ProbeForWriteGenericType(Ptr, SHORT)
194 #define ProbeForWriteUlong(Ptr) ProbeForWriteGenericType(Ptr, ULONG)
195 #define ProbeForWriteLong(Ptr) ProbeForWriteGenericType(Ptr, LONG)
196 #define ProbeForWriteUint(Ptr) ProbeForWriteGenericType(Ptr, UINT)
197 #define ProbeForWriteInt(Ptr) ProbeForWriteGenericType(Ptr, INT)
198 #define ProbeForWriteUlonglong(Ptr) ProbeForWriteGenericType(Ptr, ULONGLONG)
199 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG)
200 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG)
201 #define ProbeForWritePointer(Ptr) ProbeForWriteGenericType(Ptr, PVOID)
202 #define ProbeForWriteHandle(Ptr) ProbeForWriteGenericType(Ptr, HANDLE)
203 #define ProbeForWriteLangid(Ptr) ProbeForWriteGenericType(Ptr, LANGID)
204 #define ProbeForWriteLargeInteger(Ptr) ProbeForWriteGenericType(&(Ptr)->QuadPart, LONGLONG)
205 #define ProbeForWriteUlargeInteger(Ptr) ProbeForWriteGenericType(&(Ptr)->QuadPart, ULONGLONG)
206
207 #define ProbeForReadGenericType(Ptr, Type, Default) \
208 (((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
209 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) ? \
210 ExRaiseStatus (STATUS_ACCESS_VIOLATION), Default : \
211 *(volatile Type *)(Ptr))
212
213 #define ProbeForReadBoolean(Ptr) ProbeForReadGenericType(Ptr, BOOLEAN, FALSE)
214 #define ProbeForReadUchar(Ptr) ProbeForReadGenericType(Ptr, UCHAR, 0)
215 #define ProbeForReadChar(Ptr) ProbeForReadGenericType(Ptr, CHAR, 0)
216 #define ProbeForReadUshort(Ptr) ProbeForReadGenericType(Ptr, USHORT, 0)
217 #define ProbeForReadShort(Ptr) ProbeForReadGenericType(Ptr, SHORT, 0)
218 #define ProbeForReadUlong(Ptr) ProbeForReadGenericType(Ptr, ULONG, 0)
219 #define ProbeForReadLong(Ptr) ProbeForReadGenericType(Ptr, LONG, 0)
220 #define ProbeForReadUint(Ptr) ProbeForReadGenericType(Ptr, UINT, 0)
221 #define ProbeForReadInt(Ptr) ProbeForReadGenericType(Ptr, INT, 0)
222 #define ProbeForReadUlonglong(Ptr) ProbeForReadGenericType(Ptr, ULONGLONG, 0)
223 #define ProbeForReadLonglong(Ptr) ProbeForReadGenericType(Ptr, LONGLONG, 0)
224 #define ProbeForReadPointer(Ptr) ProbeForReadGenericType(Ptr, PVOID, NULL)
225 #define ProbeForReadHandle(Ptr) ProbeForReadGenericType(Ptr, HANDLE, NULL)
226 #define ProbeForReadLangid(Ptr) ProbeForReadGenericType(Ptr, LANGID, 0)
227 #define ProbeForReadLargeInteger(Ptr) ((LARGE_INTEGER)ProbeForReadGenericType(&(Ptr)->QuadPart, LONGLONG, 0))
228 #define ProbeForReadUlargeInteger(Ptr) ((ULARGE_INTEGER)ProbeForReadGenericType(&(Ptr)->QuadPart, ULONGLONG, 0))
229
230 /*
231 * generic information class probing code
232 */
233
234 #define ICIF_QUERY 0x1
235 #define ICIF_SET 0x2
236 #define ICIF_QUERY_SIZE_VARIABLE 0x4
237 #define ICIF_SET_SIZE_VARIABLE 0x8
238 #define ICIF_SIZE_VARIABLE (ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE)
239
240 typedef struct _INFORMATION_CLASS_INFO
241 {
242 ULONG RequiredSizeQUERY;
243 ULONG RequiredSizeSET;
244 ULONG AlignmentSET;
245 ULONG AlignmentQUERY;
246 ULONG Flags;
247 } INFORMATION_CLASS_INFO, *PINFORMATION_CLASS_INFO;
248
249 #define ICI_SQ_SAME(Size, Alignment, Flags) \
250 { Size, Size, Alignment, Alignment, Flags }
251
252 #define ICI_SQ(SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags) \
253 { SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags }
254
255 static inline NTSTATUS
256 DefaultSetInfoBufferCheck(UINT Class,
257 const INFORMATION_CLASS_INFO *ClassList,
258 UINT ClassListEntries,
259 PVOID Buffer,
260 ULONG BufferLength,
261 KPROCESSOR_MODE PreviousMode)
262 {
263 NTSTATUS Status = STATUS_SUCCESS;
264
265 if (Class >= 0 && Class < ClassListEntries)
266 {
267 if (!(ClassList[Class].Flags & ICIF_SET))
268 {
269 Status = STATUS_INVALID_INFO_CLASS;
270 }
271 else if (ClassList[Class].RequiredSizeSET > 0 &&
272 BufferLength != ClassList[Class].RequiredSizeSET)
273 {
274 if (!(ClassList[Class].Flags & ICIF_SET_SIZE_VARIABLE))
275 {
276 Status = STATUS_INFO_LENGTH_MISMATCH;
277 }
278 }
279
280 if (NT_SUCCESS(Status))
281 {
282 if (PreviousMode != KernelMode)
283 {
284 _SEH_TRY
285 {
286 ProbeForRead(Buffer,
287 BufferLength,
288 ClassList[Class].AlignmentSET);
289 }
290 _SEH_HANDLE
291 {
292 Status = _SEH_GetExceptionCode();
293 }
294 _SEH_END;
295 }
296 }
297 }
298 else
299 Status = STATUS_INVALID_INFO_CLASS;
300
301 return Status;
302 }
303
304 static inline NTSTATUS
305 DefaultQueryInfoBufferCheck(UINT Class,
306 const INFORMATION_CLASS_INFO *ClassList,
307 UINT ClassListEntries,
308 PVOID Buffer,
309 ULONG BufferLength,
310 PULONG ReturnLength,
311 KPROCESSOR_MODE PreviousMode)
312 {
313 NTSTATUS Status = STATUS_SUCCESS;
314
315 if (Class >= 0 && Class < ClassListEntries)
316 {
317 if (!(ClassList[Class].Flags & ICIF_QUERY))
318 {
319 Status = STATUS_INVALID_INFO_CLASS;
320 }
321 else if (ClassList[Class].RequiredSizeQUERY > 0 &&
322 BufferLength != ClassList[Class].RequiredSizeQUERY)
323 {
324 if (!(ClassList[Class].Flags & ICIF_QUERY_SIZE_VARIABLE))
325 {
326 Status = STATUS_INFO_LENGTH_MISMATCH;
327 }
328 }
329
330 if (NT_SUCCESS(Status))
331 {
332 if (PreviousMode != KernelMode)
333 {
334 _SEH_TRY
335 {
336 if (Buffer != NULL)
337 {
338 ProbeForWrite(Buffer,
339 BufferLength,
340 ClassList[Class].AlignmentQUERY);
341 }
342
343 if (ReturnLength != NULL)
344 {
345 ProbeForWriteUlong(ReturnLength);
346 }
347 }
348 _SEH_HANDLE
349 {
350 Status = _SEH_GetExceptionCode();
351 }
352 _SEH_END;
353 }
354 }
355 }
356 else
357 Status = STATUS_INVALID_INFO_CLASS;
358
359 return Status;
360 }
361
362 /*
363 * Use IsPointerOffset to test whether a pointer should be interpreted as an offset
364 * or as a pointer
365 */
366 #if defined(_X86_) || defined(_M_AMD64)
367
368 /* for x86 and x86-64 the MSB is 1 so we can simply test on that */
369 #define IsPointerOffset(Ptr) ((LONG_PTR)(Ptr) >= 0)
370
371 #elif defined(_IA64_)
372
373 /* on Itanium if the 24 most significant bits are set, we're not dealing with
374 offsets anymore. */
375 #define IsPointerOffset(Ptr) (((ULONG_PTR)(Ptr) & 0xFFFFFF0000000000ULL) == 0)
376
377 #else
378 #error IsPointerOffset() needs to be defined for this architecture
379 #endif
380
381 #endif
382 /*
383 *
384 */
385 #define MM_STACK_SIZE (3*4096)
386
387 #endif /* INCLUDE_INTERNAL_NTOSKRNL_H */