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