1 #ifndef INCLUDE_REACTOS_CAPTURE_H 2 #define INCLUDE_REACTOS_CAPTURE_H 3 4 #include <suppress.h> 5 6 #if ! defined(_NTOSKRNL_) && ! defined(_WIN32K_) 7 #error Header intended for use by NTOSKRNL/WIN32K only! 8 #endif 9 10 static const UNICODE_STRING __emptyUnicodeString = {0, 0, NULL}; 11 static const LARGE_INTEGER __emptyLargeInteger = {{0, 0}}; 12 static const ULARGE_INTEGER __emptyULargeInteger = {{0, 0}}; 13 static const IO_STATUS_BLOCK __emptyIoStatusBlock = {{0}, 0}; 14 15 #if defined(_WIN32K_) && !defined(__cplusplus) 16 static const LARGE_STRING __emptyLargeString = {0, 0, 0, NULL}; 17 #endif 18 19 /* 20 * NOTE: Alignment of the pointers is not verified! 21 */ 22 #define ProbeForWriteGenericType(Ptr, Type) \ 23 do { \ 24 if ((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \ 25 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \ 26 ExRaiseAccessViolation(); \ 27 } \ 28 *(volatile Type *)(Ptr) = *(volatile Type *)(Ptr); \ 29 } while (0) 30 31 #define ProbeForWriteBoolean(Ptr) ProbeForWriteGenericType(Ptr, BOOLEAN) 32 #define ProbeForWriteUchar(Ptr) ProbeForWriteGenericType(Ptr, UCHAR) 33 #define ProbeForWriteChar(Ptr) ProbeForWriteGenericType(Ptr, CHAR) 34 #define ProbeForWriteUshort(Ptr) ProbeForWriteGenericType(Ptr, USHORT) 35 #define ProbeForWriteShort(Ptr) ProbeForWriteGenericType(Ptr, SHORT) 36 #define ProbeForWriteUlong(Ptr) ProbeForWriteGenericType(Ptr, ULONG) 37 #define ProbeForWriteLong(Ptr) ProbeForWriteGenericType(Ptr, LONG) 38 #define ProbeForWriteUint(Ptr) ProbeForWriteGenericType(Ptr, UINT) 39 #define ProbeForWriteInt(Ptr) ProbeForWriteGenericType(Ptr, INT) 40 #define ProbeForWriteUlonglong(Ptr) ProbeForWriteGenericType(Ptr, ULONGLONG) 41 #define ProbeForWriteLonglong(Ptr) ProbeForWriteGenericType(Ptr, LONGLONG) 42 #define ProbeForWritePointer(Ptr) ProbeForWriteGenericType(Ptr, PVOID) 43 #define ProbeForWriteHandle(Ptr) ProbeForWriteGenericType(Ptr, HANDLE) 44 #define ProbeForWriteLangId(Ptr) ProbeForWriteGenericType(Ptr, LANGID) 45 #define ProbeForWriteSize_t(Ptr) ProbeForWriteGenericType(Ptr, SIZE_T) 46 #define ProbeForWriteLargeInteger(Ptr) ProbeForWriteGenericType(&((PLARGE_INTEGER)Ptr)->QuadPart, LONGLONG) 47 #define ProbeForWriteUlargeInteger(Ptr) ProbeForWriteGenericType(&((PULARGE_INTEGER)Ptr)->QuadPart, ULONGLONG) 48 #define ProbeForWriteUnicodeString(Ptr) ProbeForWriteGenericType((PUNICODE_STRING)Ptr, UNICODE_STRING) 49 #if defined(_WIN32K_) 50 #define ProbeForWriteLargeString(Ptr) ProbeForWriteGenericType((PLARGE_STRING)Ptr, LARGE_STRING) 51 #endif 52 #define ProbeForWriteIoStatusBlock(Ptr) ProbeForWriteGenericType((PIO_STATUS_BLOCK)Ptr, IO_STATUS_BLOCK) 53 54 #define ProbeForReadGenericType(Ptr, Type, Default) \ 55 (((ULONG_PTR)(Ptr) + sizeof(Type) - 1 < (ULONG_PTR)(Ptr) || \ 56 (ULONG_PTR)(Ptr) + sizeof(Type) - 1 >= (ULONG_PTR)MmUserProbeAddress) ? \ 57 ExRaiseAccessViolation(), Default : \ 58 *(const volatile Type *)(Ptr)) 59 60 #define ProbeForReadBoolean(Ptr) ProbeForReadGenericType(Ptr, BOOLEAN, FALSE) 61 #define ProbeForReadUchar(Ptr) ProbeForReadGenericType(Ptr, UCHAR, 0) 62 #define ProbeForReadChar(Ptr) ProbeForReadGenericType(Ptr, CHAR, 0) 63 #define ProbeForReadUshort(Ptr) ProbeForReadGenericType(Ptr, USHORT, 0) 64 #define ProbeForReadShort(Ptr) ProbeForReadGenericType(Ptr, SHORT, 0) 65 #define ProbeForReadUlong(Ptr) ProbeForReadGenericType(Ptr, ULONG, 0) 66 #define ProbeForReadLong(Ptr) ProbeForReadGenericType(Ptr, LONG, 0) 67 #define ProbeForReadUint(Ptr) ProbeForReadGenericType(Ptr, UINT, 0) 68 #define ProbeForReadInt(Ptr) ProbeForReadGenericType(Ptr, INT, 0) 69 #define ProbeForReadUlonglong(Ptr) ProbeForReadGenericType(Ptr, ULONGLONG, 0) 70 #define ProbeForReadLonglong(Ptr) ProbeForReadGenericType(Ptr, LONGLONG, 0) 71 #define ProbeForReadPointer(Ptr) ProbeForReadGenericType(Ptr, PVOID, NULL) 72 #define ProbeForReadHandle(Ptr) ProbeForReadGenericType(Ptr, HANDLE, NULL) 73 #define ProbeForReadLangId(Ptr) ProbeForReadGenericType(Ptr, LANGID, 0) 74 #define ProbeForReadSize_t(Ptr) ProbeForReadGenericType(Ptr, SIZE_T, 0) 75 #define ProbeForReadLargeInteger(Ptr) ProbeForReadGenericType((const LARGE_INTEGER *)(Ptr), LARGE_INTEGER, __emptyLargeInteger) 76 #define ProbeForReadUlargeInteger(Ptr) ProbeForReadGenericType((const ULARGE_INTEGER *)(Ptr), ULARGE_INTEGER, __emptyULargeInteger) 77 #define ProbeForReadUnicodeString(Ptr) ProbeForReadGenericType((const UNICODE_STRING *)(Ptr), UNICODE_STRING, __emptyUnicodeString) 78 #if defined(_WIN32K_) 79 #define ProbeForReadLargeString(Ptr) ProbeForReadGenericType((const LARGE_STRING *)(Ptr), LARGE_STRING, __emptyLargeString) 80 #endif 81 #define ProbeForReadIoStatusBlock(Ptr) ProbeForReadGenericType((const IO_STATUS_BLOCK *)(Ptr), IO_STATUS_BLOCK, __emptyIoStatusBlock) 82 83 #define ProbeAndZeroHandle(Ptr) \ 84 do { \ 85 if ((ULONG_PTR)(Ptr) + sizeof(HANDLE) - 1 < (ULONG_PTR)(Ptr) || \ 86 (ULONG_PTR)(Ptr) + sizeof(HANDLE) - 1 >= (ULONG_PTR)MmUserProbeAddress) { \ 87 ExRaiseAccessViolation(); \ 88 } \ 89 *(volatile HANDLE *)(Ptr) = NULL; \ 90 } while (0) 91 92 /* 93 * Inlined Probing Macros 94 */ 95 96 #if defined(_WIN32K_) 97 static __inline 98 VOID 99 ProbeArrayForRead(IN const VOID *ArrayPtr, 100 IN ULONG ItemSize, 101 IN ULONG ItemCount, 102 IN ULONG Alignment) 103 { 104 ULONG ArraySize; 105 106 /* Check for integer overflow */ 107 ArraySize = ItemSize * ItemCount; 108 if (ArraySize / ItemSize != ItemCount) 109 { 110 ExRaiseStatus(STATUS_INVALID_PARAMETER); 111 } 112 113 /* Probe the array */ 114 _PRAGMA_WARNING_SUPPRESS(__WARNING_PROBE_NO_TRY) /* Must be inside __try / __except block */ 115 ProbeForRead(ArrayPtr, ArraySize, Alignment); 116 } 117 118 static __inline 119 VOID 120 ProbeArrayForWrite(IN OUT PVOID ArrayPtr, 121 IN ULONG ItemSize, 122 IN ULONG ItemCount, 123 IN ULONG Alignment) 124 { 125 ULONG ArraySize; 126 127 /* Check for integer overflow */ 128 ArraySize = ItemSize * ItemCount; 129 if (ArraySize / ItemSize != ItemCount) 130 { 131 ExRaiseStatus(STATUS_INVALID_PARAMETER); 132 } 133 134 /* Probe the array */ 135 _PRAGMA_WARNING_SUPPRESS(__WARNING_PROBE_NO_TRY) /* Must be inside __try / __except block */ 136 ProbeForWrite(ArrayPtr, ArraySize, Alignment); 137 } 138 #endif /* _WIN32K_ */ 139 140 static __inline 141 NTSTATUS 142 ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest, 143 IN KPROCESSOR_MODE CurrentMode, 144 IN const UNICODE_STRING *UnsafeSrc) 145 { 146 NTSTATUS Status = STATUS_SUCCESS; 147 PWCHAR Buffer = NULL; 148 ASSERT(Dest != NULL); 149 150 /* Probe the structure and buffer*/ 151 if(CurrentMode != KernelMode) 152 { 153 _SEH2_TRY 154 { 155 #ifdef __cplusplus 156 ProbeForRead(UnsafeSrc, sizeof(*UnsafeSrc), 1); 157 RtlCopyMemory(Dest, UnsafeSrc, sizeof(*UnsafeSrc)); 158 #else 159 *Dest = ProbeForReadUnicodeString(UnsafeSrc); 160 #endif 161 if(Dest->Buffer != NULL) 162 { 163 if (Dest->Length != 0) 164 { 165 ProbeForRead(Dest->Buffer, Dest->Length, sizeof(WCHAR)); 166 167 /* Allocate space for the buffer */ 168 Buffer = (PWCHAR)ExAllocatePoolWithTag(PagedPool, 169 Dest->Length + sizeof(WCHAR), 170 'RTSU'); 171 if (Buffer == NULL) 172 { 173 Status = STATUS_INSUFFICIENT_RESOURCES; 174 _SEH2_LEAVE; 175 } 176 177 /* Copy it */ 178 RtlCopyMemory(Buffer, Dest->Buffer, Dest->Length); 179 Buffer[Dest->Length / sizeof(WCHAR)] = UNICODE_NULL; 180 181 /* Set it as the buffer */ 182 Dest->Buffer = Buffer; 183 if (Dest->Length % sizeof(WCHAR)) 184 { 185 Dest->Length--; 186 } 187 if (Dest->Length >= UNICODE_STRING_MAX_BYTES) 188 { 189 Dest->MaximumLength = Dest->Length; 190 } 191 else 192 { 193 Dest->MaximumLength = Dest->Length + sizeof(WCHAR); 194 } 195 } 196 else 197 { 198 /* Sanitize structure */ 199 Dest->MaximumLength = 0; 200 Dest->Buffer = NULL; 201 } 202 } 203 else 204 { 205 /* Sanitize structure */ 206 Dest->Length = 0; 207 Dest->MaximumLength = 0; 208 } 209 } 210 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 211 { 212 /* Free allocated resources and zero the destination string */ 213 if (Buffer != NULL) 214 { 215 ExFreePoolWithTag(Buffer, 'RTSU'); 216 } 217 Dest->Length = 0; 218 Dest->MaximumLength = 0; 219 Dest->Buffer = NULL; 220 221 /* Return the error code */ 222 Status = _SEH2_GetExceptionCode(); 223 } 224 _SEH2_END; 225 } 226 else 227 { 228 /* Just copy the UNICODE_STRING structure, don't allocate new memory! 229 We trust the caller to supply valid pointers and data. */ 230 *Dest = *UnsafeSrc; 231 } 232 233 /* Return */ 234 return Status; 235 } 236 237 static __inline 238 VOID 239 ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, 240 IN KPROCESSOR_MODE CurrentMode) 241 { 242 if(CurrentMode != KernelMode && CapturedString->Buffer != NULL) 243 { 244 ExFreePoolWithTag(CapturedString->Buffer, 'RTSU'); 245 } 246 247 CapturedString->Length = 0; 248 CapturedString->MaximumLength = 0; 249 CapturedString->Buffer = NULL; 250 } 251 252 #endif /* INCLUDE_REACTOS_CAPTURE_H */ 253