- Add msvc compatible version of ProveForRead(U)LargeInteger
[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 static const UNICODE_STRING __emptyUnicodeString = {0};
87
88 /*
89 * NOTE: Alignment of the pointers is not verified!
90 */
91 #define ProbeForWriteGenericType(Ptr, Type) \
92 do { \
93 if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
94 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
95 RtlRaiseStatus (STATUS_ACCESS_VIOLATION); \
96 } \
97 *(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \
98 } while (0)
99
100 #define ProbeForWriteBoolean(Ptr) ProbeForWriteGenericType(Ptr, BOOLEAN)
101 #define ProbeForWriteUchar(Ptr) ProbeForWriteGenericType(Ptr, UCHAR)
102 #define ProbeForWriteChar(Ptr) ProbeForWriteGenericType(Ptr, Char)
103 #define ProbeForWriteUshort(Ptr) ProbeForWriteGenericType(Ptr, USHORT)
104 #define ProbeForWriteShort(Ptr) ProbeForWriteGenericType(Ptr, SHORT)
105 #define ProbeForWriteUlong(Ptr) ProbeForWriteGenericType(Ptr, ULONG)
106 #define ProbeForWriteLong(Ptr) ProbeForWriteGenericType(Ptr, LONG)
107 #define ProbeForWriteUint(Ptr) ProbeForWriteGenericType(Ptr, UINT)
108 #define ProbeForWriteInt(Ptr) ProbeForWriteGenericType(Ptr, INT)
109 #define ProbeForWriteUlonglong(Ptr) ProbeForWriteGenericType(Ptr, ULONGLONG)
110 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG)
111 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG)
112 #define ProbeForWritePointer(Ptr) ProbeForWriteGenericType(Ptr, PVOID)
113 #define ProbeForWriteHandle(Ptr) ProbeForWriteGenericType(Ptr, HANDLE)
114 #define ProbeForWriteLangid(Ptr) ProbeForWriteGenericType(Ptr, LANGID)
115 #define ProbeForWriteLargeInteger(Ptr) ProbeForWriteGenericType(&(Ptr)->QuadPart, LONGLONG)
116 #define ProbeForWriteUlargeInteger(Ptr) ProbeForWriteGenericType(&(Ptr)->QuadPart, ULONGLONG)
117 #define ProbeForWriteUnicodeString(Ptr) ProbeForWriteGenericType(Ptr, UNICODE_STRING)
118
119 #define ProbeForReadGenericType(Ptr, Type, Default) \
120 (((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
121 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) ? \
122 ExRaiseStatus (STATUS_ACCESS_VIOLATION), Default : \
123 *(volatile Type *)(Ptr))
124
125 #define ProbeForReadBoolean(Ptr) ProbeForReadGenericType(Ptr, BOOLEAN, FALSE)
126 #define ProbeForReadUchar(Ptr) ProbeForReadGenericType(Ptr, UCHAR, 0)
127 #define ProbeForReadChar(Ptr) ProbeForReadGenericType(Ptr, CHAR, 0)
128 #define ProbeForReadUshort(Ptr) ProbeForReadGenericType(Ptr, USHORT, 0)
129 #define ProbeForReadShort(Ptr) ProbeForReadGenericType(Ptr, SHORT, 0)
130 #define ProbeForReadUlong(Ptr) ProbeForReadGenericType(Ptr, ULONG, 0)
131 #define ProbeForReadLong(Ptr) ProbeForReadGenericType(Ptr, LONG, 0)
132 #define ProbeForReadUint(Ptr) ProbeForReadGenericType(Ptr, UINT, 0)
133 #define ProbeForReadInt(Ptr) ProbeForReadGenericType(Ptr, INT, 0)
134 #define ProbeForReadUlonglong(Ptr) ProbeForReadGenericType(Ptr, ULONGLONG, 0)
135 #define ProbeForReadLonglong(Ptr) ProbeForReadGenericType(Ptr, LONGLONG, 0)
136 #define ProbeForReadPointer(Ptr) ProbeForReadGenericType(Ptr, PVOID, NULL)
137 #define ProbeForReadHandle(Ptr) ProbeForReadGenericType(Ptr, HANDLE, NULL)
138 #define ProbeForReadLangid(Ptr) ProbeForReadGenericType(Ptr, LANGID, 0)
139 #ifdef _MSC_VER
140 #define ProbeForReadLargeInteger(Ptr) (*(volatile LARGE_INTEGER*)ProbeForReadGenericType(&(Ptr)->QuadPart, LONGLONG, 0))
141 #define ProbeForReadUlargeInteger(Ptr) (*(volatile ULARGE_INTEGER*)ProbeForReadGenericType(&(Ptr)->QuadPart, ULONGLONG, 0))
142 #else
143 #define ProbeForReadLargeInteger(Ptr) ((LARGE_INTEGER)ProbeForReadGenericType(&(Ptr)->QuadPart, LONGLONG, 0))
144 #define ProbeForReadUlargeInteger(Ptr) ((ULARGE_INTEGER)ProbeForReadGenericType(&(Ptr)->QuadPart, ULONGLONG, 0))
145 #endif
146 #define ProbeForReadUnicodeString(Ptr) ProbeForReadGenericType(Ptr, UNICODE_STRING, __emptyUnicodeString)
147
148 /*
149 * Inlined Probing Macros
150 */
151 static __inline
152 NTSTATUS
153 NTAPI
154 ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest,
155 IN KPROCESSOR_MODE CurrentMode,
156 IN PUNICODE_STRING UnsafeSrc)
157 {
158 NTSTATUS Status = STATUS_SUCCESS;
159 WCHAR *Buffer;
160 ASSERT(Dest != NULL);
161
162 /* Probe the structure and buffer*/
163 if(CurrentMode != KernelMode)
164 {
165 _SEH_TRY
166 {
167 *Dest = ProbeForReadUnicodeString(UnsafeSrc);
168 if(Dest->Buffer != NULL)
169 {
170 if (Dest->Length != 0)
171 {
172 ProbeForRead(Dest->Buffer,
173 Dest->Length,
174 sizeof(WCHAR));
175
176 /* Allocate space for the buffer */
177 Buffer = ExAllocatePoolWithTag(PagedPool,
178 Dest->Length + sizeof(WCHAR),
179 TAG('U', 'S', 'T', 'R'));
180 if (Buffer == NULL)
181 {
182 Status = STATUS_INSUFFICIENT_RESOURCES;
183 _SEH_LEAVE;
184 }
185
186 /* Copy it */
187 RtlCopyMemory(Buffer, Dest->Buffer, Dest->Length);
188 Buffer[Dest->Length / sizeof(WCHAR)] = UNICODE_NULL;
189
190 /* Set it as the buffer */
191 Dest->Buffer = Buffer;
192 }
193 else
194 {
195 /* sanitize structure */
196 Dest->MaximumLength = 0;
197 Dest->Buffer = NULL;
198 }
199 }
200 else
201 {
202 /* sanitize structure */
203 Dest->Length = 0;
204 Dest->MaximumLength = 0;
205 }
206 }
207 _SEH_HANDLE
208 {
209 Status = _SEH_GetExceptionCode();
210 }
211 _SEH_END;
212 }
213 else
214 {
215 /* Just copy the UNICODE_STRING structure, don't allocate new memory!
216 We trust the caller to supply valid pointers and data. */
217 *Dest = *UnsafeSrc;
218 }
219
220 /* Return */
221 return Status;
222 }
223
224 static __inline
225 VOID
226 NTAPI
227 ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString,
228 IN KPROCESSOR_MODE CurrentMode)
229 {
230 if(CurrentMode != KernelMode && CapturedString->Buffer != NULL)
231 {
232 ExFreePool(CapturedString->Buffer);
233 }
234 }
235
236 /*
237 * generic information class probing code
238 */
239
240 #define ICIF_QUERY 0x1
241 #define ICIF_SET 0x2
242 #define ICIF_QUERY_SIZE_VARIABLE 0x4
243 #define ICIF_SET_SIZE_VARIABLE 0x8
244 #define ICIF_SIZE_VARIABLE (ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE)
245
246 typedef struct _INFORMATION_CLASS_INFO
247 {
248 ULONG RequiredSizeQUERY;
249 ULONG RequiredSizeSET;
250 ULONG AlignmentSET;
251 ULONG AlignmentQUERY;
252 ULONG Flags;
253 } INFORMATION_CLASS_INFO, *PINFORMATION_CLASS_INFO;
254
255 #define ICI_SQ_SAME(Size, Alignment, Flags) \
256 { Size, Size, Alignment, Alignment, Flags }
257
258 #define ICI_SQ(SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags) \
259 { SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags }
260
261 static inline NTSTATUS
262 DefaultSetInfoBufferCheck(UINT Class,
263 const INFORMATION_CLASS_INFO *ClassList,
264 UINT ClassListEntries,
265 PVOID Buffer,
266 ULONG BufferLength,
267 KPROCESSOR_MODE PreviousMode)
268 {
269 NTSTATUS Status = STATUS_SUCCESS;
270
271 if (Class >= 0 && Class < ClassListEntries)
272 {
273 if (!(ClassList[Class].Flags & ICIF_SET))
274 {
275 Status = STATUS_INVALID_INFO_CLASS;
276 }
277 else if (ClassList[Class].RequiredSizeSET > 0 &&
278 BufferLength != ClassList[Class].RequiredSizeSET)
279 {
280 if (!(ClassList[Class].Flags & ICIF_SET_SIZE_VARIABLE))
281 {
282 Status = STATUS_INFO_LENGTH_MISMATCH;
283 }
284 }
285
286 if (NT_SUCCESS(Status))
287 {
288 if (PreviousMode != KernelMode)
289 {
290 _SEH_TRY
291 {
292 ProbeForRead(Buffer,
293 BufferLength,
294 ClassList[Class].AlignmentSET);
295 }
296 _SEH_HANDLE
297 {
298 Status = _SEH_GetExceptionCode();
299 }
300 _SEH_END;
301 }
302 }
303 }
304 else
305 Status = STATUS_INVALID_INFO_CLASS;
306
307 return Status;
308 }
309
310 static inline NTSTATUS
311 DefaultQueryInfoBufferCheck(UINT Class,
312 const INFORMATION_CLASS_INFO *ClassList,
313 UINT ClassListEntries,
314 PVOID Buffer,
315 ULONG BufferLength,
316 PULONG ReturnLength,
317 KPROCESSOR_MODE PreviousMode)
318 {
319 NTSTATUS Status = STATUS_SUCCESS;
320
321 if (Class >= 0 && Class < ClassListEntries)
322 {
323 if (!(ClassList[Class].Flags & ICIF_QUERY))
324 {
325 Status = STATUS_INVALID_INFO_CLASS;
326 }
327 else if (ClassList[Class].RequiredSizeQUERY > 0 &&
328 BufferLength != ClassList[Class].RequiredSizeQUERY)
329 {
330 if (!(ClassList[Class].Flags & ICIF_QUERY_SIZE_VARIABLE))
331 {
332 Status = STATUS_INFO_LENGTH_MISMATCH;
333 }
334 }
335
336 if (NT_SUCCESS(Status))
337 {
338 if (PreviousMode != KernelMode)
339 {
340 _SEH_TRY
341 {
342 if (Buffer != NULL)
343 {
344 ProbeForWrite(Buffer,
345 BufferLength,
346 ClassList[Class].AlignmentQUERY);
347 }
348
349 if (ReturnLength != NULL)
350 {
351 ProbeForWriteUlong(ReturnLength);
352 }
353 }
354 _SEH_HANDLE
355 {
356 Status = _SEH_GetExceptionCode();
357 }
358 _SEH_END;
359 }
360 }
361 }
362 else
363 Status = STATUS_INVALID_INFO_CLASS;
364
365 return Status;
366 }
367
368 /*
369 * Use IsPointerOffset to test whether a pointer should be interpreted as an offset
370 * or as a pointer
371 */
372 #if defined(_X86_) || defined(_M_AMD64)
373
374 /* for x86 and x86-64 the MSB is 1 so we can simply test on that */
375 #define IsPointerOffset(Ptr) ((LONG_PTR)(Ptr) >= 0)
376
377 #elif defined(_IA64_)
378
379 /* on Itanium if the 24 most significant bits are set, we're not dealing with
380 offsets anymore. */
381 #define IsPointerOffset(Ptr) (((ULONG_PTR)(Ptr) & 0xFFFFFF0000000000ULL) == 0)
382
383 #else
384 #error IsPointerOffset() needs to be defined for this architecture
385 #endif
386
387 #endif
388 /*
389 *
390 */
391 #define MM_STACK_SIZE (3*4096)
392
393 #endif /* INCLUDE_INTERNAL_NTOSKRNL_H */