Factor out probe and capture code from private ntoskrnl header and put it in
[reactos.git] / reactos / include / reactos / probe.h
1 #ifndef INCLUDE_REACTOS_CAPTURE_H
2 #define INCLUDE_REACTOS_CAPTURE_H
3
4 static const UNICODE_STRING __emptyUnicodeString = {0};
5 static const LARGE_INTEGER __emptyLargeInteger = {{0, 0}};
6 static const ULARGE_INTEGER __emptyULargeInteger = {{0, 0}};
7
8 /*
9 * NOTE: Alignment of the pointers is not verified!
10 */
11 #define ProbeForWriteGenericType(Ptr, Type) \
12 do { \
13 if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
14 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
15 RtlRaiseStatus (STATUS_ACCESS_VIOLATION); \
16 } \
17 *(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \
18 } while (0)
19
20 #define ProbeForWriteBoolean(Ptr) ProbeForWriteGenericType(Ptr, BOOLEAN)
21 #define ProbeForWriteUchar(Ptr) ProbeForWriteGenericType(Ptr, UCHAR)
22 #define ProbeForWriteChar(Ptr) ProbeForWriteGenericType(Ptr, Char)
23 #define ProbeForWriteUshort(Ptr) ProbeForWriteGenericType(Ptr, USHORT)
24 #define ProbeForWriteShort(Ptr) ProbeForWriteGenericType(Ptr, SHORT)
25 #define ProbeForWriteUlong(Ptr) ProbeForWriteGenericType(Ptr, ULONG)
26 #define ProbeForWriteLong(Ptr) ProbeForWriteGenericType(Ptr, LONG)
27 #define ProbeForWriteUint(Ptr) ProbeForWriteGenericType(Ptr, UINT)
28 #define ProbeForWriteInt(Ptr) ProbeForWriteGenericType(Ptr, INT)
29 #define ProbeForWriteUlonglong(Ptr) ProbeForWriteGenericType(Ptr, ULONGLONG)
30 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG)
31 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG)
32 #define ProbeForWritePointer(Ptr) ProbeForWriteGenericType(Ptr, PVOID)
33 #define ProbeForWriteHandle(Ptr) ProbeForWriteGenericType(Ptr, HANDLE)
34 #define ProbeForWriteLangid(Ptr) ProbeForWriteGenericType(Ptr, LANGID)
35 #define ProbeForWriteSize_t(Ptr) ProbeForWriteGenericType(Ptr, SIZE_T)
36 #define ProbeForWriteLargeInteger(Ptr) ProbeForWriteGenericType(&(Ptr)->QuadPart, LONGLONG)
37 #define ProbeForWriteUlargeInteger(Ptr) ProbeForWriteGenericType(&(Ptr)->QuadPart, ULONGLONG)
38 #define ProbeForWriteUnicodeString(Ptr) ProbeForWriteGenericType(Ptr, UNICODE_STRING)
39
40 #define ProbeForReadGenericType(Ptr, Type, Default) \
41 (((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
42 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) ? \
43 ExRaiseStatus (STATUS_ACCESS_VIOLATION), Default : \
44 *(Type *)(Ptr))
45
46 #define ProbeForReadBoolean(Ptr) ProbeForReadGenericType(Ptr, BOOLEAN, FALSE)
47 #define ProbeForReadUchar(Ptr) ProbeForReadGenericType(Ptr, UCHAR, 0)
48 #define ProbeForReadChar(Ptr) ProbeForReadGenericType(Ptr, CHAR, 0)
49 #define ProbeForReadUshort(Ptr) ProbeForReadGenericType(Ptr, USHORT, 0)
50 #define ProbeForReadShort(Ptr) ProbeForReadGenericType(Ptr, SHORT, 0)
51 #define ProbeForReadUlong(Ptr) ProbeForReadGenericType(Ptr, ULONG, 0)
52 #define ProbeForReadLong(Ptr) ProbeForReadGenericType(Ptr, LONG, 0)
53 #define ProbeForReadUint(Ptr) ProbeForReadGenericType(Ptr, UINT, 0)
54 #define ProbeForReadInt(Ptr) ProbeForReadGenericType(Ptr, INT, 0)
55 #define ProbeForReadUlonglong(Ptr) ProbeForReadGenericType(Ptr, ULONGLONG, 0)
56 #define ProbeForReadLonglong(Ptr) ProbeForReadGenericType(Ptr, LONGLONG, 0)
57 #define ProbeForReadPointer(Ptr) ProbeForReadGenericType(Ptr, PVOID, NULL)
58 #define ProbeForReadHandle(Ptr) ProbeForReadGenericType(Ptr, HANDLE, NULL)
59 #define ProbeForReadLangid(Ptr) ProbeForReadGenericType(Ptr, LANGID, 0)
60 #define ProbeForReadSize_t(Ptr) ProbeForReadGenericType(Ptr, SIZE_T, 0)
61 #define ProbeForReadLargeInteger(Ptr) ProbeForReadGenericType(Ptr, LARGE_INTEGER, __emptyLargeInteger)
62 #define ProbeForReadUlargeInteger(Ptr) ProbeForReadGenericType(Ptr, ULARGE_INTEGER, __emptyULargeInteger)
63 #define ProbeForReadUnicodeString(Ptr) ProbeForReadGenericType(Ptr, UNICODE_STRING, __emptyUnicodeString)
64
65 /*
66 * Inlined Probing Macros
67 */
68 static __inline
69 NTSTATUS
70 NTAPI
71 ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest,
72 IN KPROCESSOR_MODE CurrentMode,
73 IN PUNICODE_STRING UnsafeSrc)
74 {
75 NTSTATUS Status = STATUS_SUCCESS;
76 WCHAR *Buffer;
77 ASSERT(Dest != NULL);
78
79 /* Probe the structure and buffer*/
80 if(CurrentMode != KernelMode)
81 {
82 _SEH_TRY
83 {
84 *Dest = ProbeForReadUnicodeString(UnsafeSrc);
85 if(Dest->Buffer != NULL)
86 {
87 if (Dest->Length != 0)
88 {
89 ProbeForRead(Dest->Buffer,
90 Dest->Length,
91 sizeof(WCHAR));
92
93 /* Allocate space for the buffer */
94 Buffer = ExAllocatePoolWithTag(PagedPool,
95 Dest->Length + sizeof(WCHAR),
96 TAG('U', 'S', 'T', 'R'));
97 if (Buffer == NULL)
98 {
99 Status = STATUS_INSUFFICIENT_RESOURCES;
100 _SEH_LEAVE;
101 }
102
103 /* Copy it */
104 RtlCopyMemory(Buffer, Dest->Buffer, Dest->Length);
105 Buffer[Dest->Length / sizeof(WCHAR)] = UNICODE_NULL;
106
107 /* Set it as the buffer */
108 Dest->Buffer = Buffer;
109 Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
110 }
111 else
112 {
113 /* sanitize structure */
114 Dest->MaximumLength = 0;
115 Dest->Buffer = NULL;
116 }
117 }
118 else
119 {
120 /* sanitize structure */
121 Dest->Length = 0;
122 Dest->MaximumLength = 0;
123 }
124 }
125 _SEH_HANDLE
126 {
127 Status = _SEH_GetExceptionCode();
128 }
129 _SEH_END;
130 }
131 else
132 {
133 /* Just copy the UNICODE_STRING structure, don't allocate new memory!
134 We trust the caller to supply valid pointers and data. */
135 *Dest = *UnsafeSrc;
136 }
137
138 /* Return */
139 return Status;
140 }
141
142 static __inline
143 VOID
144 NTAPI
145 ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString,
146 IN KPROCESSOR_MODE CurrentMode)
147 {
148 if(CurrentMode != KernelMode && CapturedString->Buffer != NULL)
149 {
150 ExFreePool(CapturedString->Buffer);
151 }
152 }
153
154 #endif /* INCLUDE_REACTOS_CAPTURE_H */