1 #ifndef INCLUDE_REACTOS_CAPTURE_H
2 #define INCLUDE_REACTOS_CAPTURE_H
4 #if ! defined(_NTOSKRNL_) && ! defined(_WIN32K_)
5 #error Header intended for use by NTOSKRNL/WIN32K only!
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};
14 static const LARGE_STRING __emptyLargeString
= {0, 0, 0, NULL
};
19 * NOTE: NTOSKRNL unfortunately doesn't export RtlRaiseStatus!
21 VOID NTAPI
W32kRaiseStatus(NTSTATUS Status
);
22 #define RtlRaiseStatus W32kRaiseStatus
26 * NOTE: Alignment of the pointers is not verified!
28 #define ProbeForWriteGenericType(Ptr, Type) \
30 if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
31 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
32 RtlRaiseStatus (STATUS_ACCESS_VIOLATION); \
34 *(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \
37 #define ProbeForWriteBoolean(Ptr) ProbeForWriteGenericType(Ptr, BOOLEAN)
38 #define ProbeForWriteUchar(Ptr) ProbeForWriteGenericType(Ptr, UCHAR)
39 #define ProbeForWriteChar(Ptr) ProbeForWriteGenericType(Ptr, CHAR)
40 #define ProbeForWriteUshort(Ptr) ProbeForWriteGenericType(Ptr, USHORT)
41 #define ProbeForWriteShort(Ptr) ProbeForWriteGenericType(Ptr, SHORT)
42 #define ProbeForWriteUlong(Ptr) ProbeForWriteGenericType(Ptr, ULONG)
43 #define ProbeForWriteLong(Ptr) ProbeForWriteGenericType(Ptr, LONG)
44 #define ProbeForWriteUint(Ptr) ProbeForWriteGenericType(Ptr, UINT)
45 #define ProbeForWriteInt(Ptr) ProbeForWriteGenericType(Ptr, INT)
46 #define ProbeForWriteUlonglong(Ptr) ProbeForWriteGenericType(Ptr, ULONGLONG)
47 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG)
48 #define ProbeForWritePointer(Ptr) ProbeForWriteGenericType(Ptr, PVOID)
49 #define ProbeForWriteHandle(Ptr) ProbeForWriteGenericType(Ptr, HANDLE)
50 #define ProbeForWriteLangid(Ptr) ProbeForWriteGenericType(Ptr, LANGID)
51 #define ProbeForWriteSize_t(Ptr) ProbeForWriteGenericType(Ptr, SIZE_T)
52 #define ProbeForWriteLargeInteger(Ptr) ProbeForWriteGenericType(&((PLARGE_INTEGER)Ptr)->QuadPart, LONGLONG)
53 #define ProbeForWriteUlargeInteger(Ptr) ProbeForWriteGenericType(&((PULARGE_INTEGER)Ptr)->QuadPart, ULONGLONG)
54 #define ProbeForWriteUnicodeString(Ptr) ProbeForWriteGenericType((PUNICODE_STRING)Ptr, UNICODE_STRING)
56 #define ProbeForWriteLargeString(Ptr) ProbeForWriteGenericType((PLARGE_STRING)Ptr, LARGE_STRING)
58 #define ProbeForWriteIoStatusBlock(Ptr) ProbeForWriteGenericType((PIO_STATUS_BLOCK)Ptr, IO_STATUS_BLOCK)
60 #define ProbeForReadGenericType(Ptr, Type, Default) \
61 (((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \
62 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) ? \
63 ExRaiseStatus (STATUS_ACCESS_VIOLATION), Default : \
64 *(const volatile Type *)(Ptr))
66 #define ProbeForReadBoolean(Ptr) ProbeForReadGenericType(Ptr, BOOLEAN, FALSE)
67 #define ProbeForReadUchar(Ptr) ProbeForReadGenericType(Ptr, UCHAR, 0)
68 #define ProbeForReadChar(Ptr) ProbeForReadGenericType(Ptr, CHAR, 0)
69 #define ProbeForReadUshort(Ptr) ProbeForReadGenericType(Ptr, USHORT, 0)
70 #define ProbeForReadShort(Ptr) ProbeForReadGenericType(Ptr, SHORT, 0)
71 #define ProbeForReadUlong(Ptr) ProbeForReadGenericType(Ptr, ULONG, 0)
72 #define ProbeForReadLong(Ptr) ProbeForReadGenericType(Ptr, LONG, 0)
73 #define ProbeForReadUint(Ptr) ProbeForReadGenericType(Ptr, UINT, 0)
74 #define ProbeForReadInt(Ptr) ProbeForReadGenericType(Ptr, INT, 0)
75 #define ProbeForReadUlonglong(Ptr) ProbeForReadGenericType(Ptr, ULONGLONG, 0)
76 #define ProbeForReadLonglong(Ptr) ProbeForReadGenericType(Ptr, LONGLONG, 0)
77 #define ProbeForReadPointer(Ptr) ProbeForReadGenericType(Ptr, PVOID, NULL)
78 #define ProbeForReadHandle(Ptr) ProbeForReadGenericType(Ptr, HANDLE, NULL)
79 #define ProbeForReadLangid(Ptr) ProbeForReadGenericType(Ptr, LANGID, 0)
80 #define ProbeForReadSize_t(Ptr) ProbeForReadGenericType(Ptr, SIZE_T, 0)
81 #define ProbeForReadLargeInteger(Ptr) ProbeForReadGenericType((const LARGE_INTEGER *)(Ptr), LARGE_INTEGER, __emptyLargeInteger)
82 #define ProbeForReadUlargeInteger(Ptr) ProbeForReadGenericType((const ULARGE_INTEGER *)(Ptr), ULARGE_INTEGER, __emptyULargeInteger)
83 #define ProbeForReadUnicodeString(Ptr) ProbeForReadGenericType((const UNICODE_STRING *)(Ptr), UNICODE_STRING, __emptyUnicodeString)
85 #define ProbeForReadLargeString(Ptr) ProbeForReadGenericType((const LARGE_STRING *)(Ptr), LARGE_STRING, __emptyLargeString)
87 #define ProbeForReadIoStatusBlock(Ptr) ProbeForReadGenericType((const IO_STATUS_BLOCK *)(Ptr), IO_STATUS_BLOCK, __emptyIoStatusBlock)
89 #define ProbeAndZeroHandle(Ptr) \
91 if ((ULONG_PTR)(Ptr) + sizeof(HANDLE) - 1 < (ULONG_PTR)(Ptr) || \
92 (ULONG_PTR)(Ptr) + sizeof(HANDLE) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \
93 RtlRaiseStatus (STATUS_ACCESS_VIOLATION); \
95 *(volatile HANDLE *)(Ptr) = NULL; \
99 * Inlined Probing Macros
102 #if defined(_WIN32K_)
105 ProbeArrayForRead(IN
const VOID
*ArrayPtr
,
112 /* Check for integer overflow */
113 ArraySize
= ItemSize
* ItemCount
;
114 if (ArraySize
/ ItemSize
!= ItemCount
)
116 RtlRaiseStatus (STATUS_INVALID_PARAMETER
);
119 /* Probe the array */
120 ProbeForRead(ArrayPtr
,
127 ProbeArrayForWrite(IN OUT PVOID ArrayPtr
,
134 /* Check for integer overflow */
135 ArraySize
= ItemSize
* ItemCount
;
136 if (ArraySize
/ ItemSize
!= ItemCount
)
138 RtlRaiseStatus (STATUS_INVALID_PARAMETER
);
141 /* Probe the array */
142 ProbeForWrite(ArrayPtr
,
146 #endif /* _WIN32K_ */
150 ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest
,
151 IN KPROCESSOR_MODE CurrentMode
,
152 IN
const UNICODE_STRING
*UnsafeSrc
)
154 NTSTATUS Status
= STATUS_SUCCESS
;
155 WCHAR
*Buffer
= NULL
;
156 ASSERT(Dest
!= NULL
);
158 /* Probe the structure and buffer*/
159 if(CurrentMode
!= KernelMode
)
163 *Dest
= ProbeForReadUnicodeString(UnsafeSrc
);
164 if(Dest
->Buffer
!= NULL
)
166 if (Dest
->Length
!= 0)
168 ProbeForRead(Dest
->Buffer
,
172 /* Allocate space for the buffer */
173 Buffer
= ExAllocatePoolWithTag(PagedPool
,
174 Dest
->Length
+ sizeof(WCHAR
),
175 TAG('U', 'S', 'T', 'R'));
178 Status
= STATUS_INSUFFICIENT_RESOURCES
;
183 RtlCopyMemory(Buffer
, Dest
->Buffer
, Dest
->Length
);
184 Buffer
[Dest
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
186 /* Set it as the buffer */
187 Dest
->Buffer
= Buffer
;
188 Dest
->MaximumLength
= Dest
->Length
+ sizeof(WCHAR
);
192 /* sanitize structure */
193 Dest
->MaximumLength
= 0;
199 /* sanitize structure */
201 Dest
->MaximumLength
= 0;
204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
206 /* Free allocated resources and zero the destination string */
212 Dest
->MaximumLength
= 0;
215 /* Return the error code */
216 Status
= _SEH2_GetExceptionCode();
222 /* Just copy the UNICODE_STRING structure, don't allocate new memory!
223 We trust the caller to supply valid pointers and data. */
233 ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString
,
234 IN KPROCESSOR_MODE CurrentMode
)
236 if(CurrentMode
!= KernelMode
&& CapturedString
->Buffer
!= NULL
)
238 ExFreePool(CapturedString
->Buffer
);
242 #endif /* INCLUDE_REACTOS_CAPTURE_H */