1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Kernel-Mode Test Suite MmMapLockedPagesSpecifyCache test user-mode part 5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 #include <ndk/exfuncs.h> 10 11 #include "MmMapLockedPagesSpecifyCache.h" 12 13 #define ALIGN_DOWN_BY(size, align) \ 14 ((ULONG_PTR)(size) & ~((ULONG_PTR)(align) - 1)) 15 16 #define SET_BUFFER_LENGTH(Var, Length) \ 17 { \ 18 C_ASSERT(((Length) % sizeof(ULONG)) == 0); \ 19 Var = (Length); \ 20 } 21 22 #define FILL_QUERY_BUFFER(QueryBuffer, BufferLength, UseCache) \ 23 { \ 24 QueryBuffer.Length = BufferLength; \ 25 QueryBuffer.Buffer = NULL; \ 26 QueryBuffer.Cached = UseCache; \ 27 QueryBuffer.Status = STATUS_SUCCESS; \ 28 } 29 30 #define FILL_READ_BUFFER(QueryBuffer, ReadBuffer) \ 31 { \ 32 PULONG Buffer; \ 33 ReadBuffer.Buffer = QueryBuffer.Buffer; \ 34 if (!skip(QueryBuffer.Buffer != NULL, "Buffer is NULL\n")) \ 35 { \ 36 ReadBuffer.Pattern = WRITE_PATTERN; \ 37 ReadBuffer.Length = QueryBuffer.Length; \ 38 Buffer = QueryBuffer.Buffer; \ 39 for (i = 0; i < ReadBuffer.Length / sizeof(ULONG); ++i) \ 40 { \ 41 Buffer[i] = ReadBuffer.Pattern; \ 42 } \ 43 } \ 44 } 45 46 #define CHECK_ALLOC(MappedBuffer, BufferLength) \ 47 { \ 48 NTSTATUS Status; \ 49 PVOID BaseAddress; \ 50 SIZE_T Size; \ 51 BaseAddress = MappedBuffer; \ 52 Size = BufferLength; \ 53 Status = NtAllocateVirtualMemory(NtCurrentProcess(), \ 54 &BaseAddress, \ 55 0, \ 56 &Size, \ 57 MEM_RESERVE, \ 58 PAGE_READWRITE); \ 59 ok_eq_hex(Status, STATUS_CONFLICTING_ADDRESSES); \ 60 BaseAddress = MappedBuffer; \ 61 Size = 0; \ 62 Status = NtFreeVirtualMemory(NtCurrentProcess(), \ 63 &BaseAddress, \ 64 &Size, \ 65 MEM_DECOMMIT); \ 66 ok_eq_hex(Status, STATUS_UNABLE_TO_DELETE_SECTION); \ 67 BaseAddress = MappedBuffer; \ 68 Size = 0; \ 69 Status = NtFreeVirtualMemory(NtCurrentProcess(), \ 70 &BaseAddress, \ 71 &Size, \ 72 MEM_RELEASE); \ 73 ok_eq_hex(Status, STATUS_UNABLE_TO_DELETE_SECTION); \ 74 Status = NtUnmapViewOfSection(NtCurrentProcess(), \ 75 MappedBuffer); \ 76 ok_eq_hex(Status, STATUS_NOT_MAPPED_VIEW); \ 77 } 78 79 START_TEST(MmMapLockedPagesSpecifyCache) 80 { 81 QUERY_BUFFER QueryBuffer; 82 READ_BUFFER ReadBuffer; 83 DWORD Length; 84 USHORT i; 85 USHORT BufferLength; 86 SYSTEM_BASIC_INFORMATION BasicInfo; 87 NTSTATUS Status; 88 ULONG_PTR HighestAddress; 89 DWORD Error; 90 91 Error = KmtLoadAndOpenDriver(L"MmMapLockedPagesSpecifyCache", FALSE); 92 ok_eq_int(Error, ERROR_SUCCESS); 93 if (Error) 94 return; 95 96 // Less than a page 97 SET_BUFFER_LENGTH(BufferLength, 2048); 98 Length = sizeof(QUERY_BUFFER); 99 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 100 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 101 ok_eq_int(QueryBuffer.Length, BufferLength); 102 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 103 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 104 105 Length = 0; 106 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 107 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 108 109 Length = sizeof(QUERY_BUFFER); 110 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, TRUE); 111 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 112 ok_eq_int(QueryBuffer.Length, BufferLength); 113 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 114 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 115 116 Length = 0; 117 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 118 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 119 120 // 1 page 121 SET_BUFFER_LENGTH(BufferLength, 4096); 122 Length = sizeof(QUERY_BUFFER); 123 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 124 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 125 ok_eq_int(QueryBuffer.Length, BufferLength); 126 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 127 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 128 129 Length = 0; 130 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 131 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 132 133 Length = sizeof(QUERY_BUFFER); 134 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, TRUE); 135 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 136 ok_eq_int(QueryBuffer.Length, BufferLength); 137 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 138 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 139 140 Length = 0; 141 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 142 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 143 144 // more than 1 page 145 SET_BUFFER_LENGTH(BufferLength, 4096 + 2048); 146 Length = sizeof(QUERY_BUFFER); 147 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 148 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 149 ok_eq_int(QueryBuffer.Length, BufferLength); 150 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 151 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 152 153 Length = 0; 154 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 155 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 156 157 Length = sizeof(QUERY_BUFFER); 158 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, TRUE); 159 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 160 ok_eq_int(QueryBuffer.Length, BufferLength); 161 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 162 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 163 164 Length = 0; 165 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 166 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 167 168 // 2 pages 169 SET_BUFFER_LENGTH(BufferLength, 2 * 4096); 170 Length = sizeof(QUERY_BUFFER); 171 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 172 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 173 ok_eq_int(QueryBuffer.Length, BufferLength); 174 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 175 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 176 177 Length = 0; 178 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 179 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 180 181 Length = sizeof(QUERY_BUFFER); 182 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, TRUE); 183 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 184 ok_eq_int(QueryBuffer.Length, BufferLength); 185 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 186 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 187 188 Length = 0; 189 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 190 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 191 192 // more than 2 pages 193 SET_BUFFER_LENGTH(BufferLength, 2 * 4096 + 2048); 194 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 195 Length = sizeof(QUERY_BUFFER); 196 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 197 ok_eq_int(QueryBuffer.Length, BufferLength); 198 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 199 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 200 201 Length = 0; 202 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 203 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 204 205 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, TRUE); 206 Length = sizeof(QUERY_BUFFER); 207 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 208 ok_eq_int(QueryBuffer.Length, BufferLength); 209 ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"); 210 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 211 212 Length = 0; 213 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 214 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 215 216 // ask for a specific address (we know that ReadBuffer.Buffer is free) 217 SET_BUFFER_LENGTH(BufferLength, 4096); 218 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 219 QueryBuffer.Buffer = ReadBuffer.Buffer; 220 Length = sizeof(QUERY_BUFFER); 221 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 222 ok_eq_int(QueryBuffer.Length, BufferLength); 223 ok(QueryBuffer.Buffer == ReadBuffer.Buffer, "Buffer is NULL\n"); 224 CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); 225 226 Length = 0; 227 FILL_READ_BUFFER(QueryBuffer, ReadBuffer); 228 ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 229 230 // ask for an unaligned address 231 SET_BUFFER_LENGTH(BufferLength, 4096); 232 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 233 QueryBuffer.Buffer = (PVOID)((ULONG_PTR)ReadBuffer.Buffer + 2048); 234 QueryBuffer.Status = STATUS_INVALID_ADDRESS; 235 Length = sizeof(QUERY_BUFFER); 236 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 237 ok_eq_int(QueryBuffer.Length, BufferLength); 238 ok(QueryBuffer.Buffer == NULL, "Buffer is %p\n", QueryBuffer.Buffer); 239 240 Length = 0; 241 ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n"); 242 243 // get system info for MmHighestUserAddress 244 Status = NtQuerySystemInformation(SystemBasicInformation, 245 &BasicInfo, 246 sizeof(BasicInfo), 247 NULL); 248 ok_eq_hex(Status, STATUS_SUCCESS); 249 trace("MaximumUserModeAddress: %lx\n", BasicInfo.MaximumUserModeAddress); 250 HighestAddress = ALIGN_DOWN_BY(BasicInfo.MaximumUserModeAddress, PAGE_SIZE); 251 252 // near MmHighestUserAddress 253 SET_BUFFER_LENGTH(BufferLength, 4096); 254 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 255 QueryBuffer.Buffer = (PVOID)(HighestAddress - 15 * PAGE_SIZE); // 7ffe0000 256 QueryBuffer.Status = STATUS_INVALID_ADDRESS; 257 trace("QueryBuffer.Buffer %p\n", QueryBuffer.Buffer); 258 Length = sizeof(QUERY_BUFFER); 259 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 260 ok_eq_int(QueryBuffer.Length, BufferLength); 261 ok(QueryBuffer.Buffer == NULL, "Buffer is %p\n", QueryBuffer.Buffer); 262 263 Length = 0; 264 ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n"); 265 266 // far enough away from MmHighestUserAddress 267 SET_BUFFER_LENGTH(BufferLength, 4096); 268 FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); 269 QueryBuffer.Buffer = (PVOID)(HighestAddress - 16 * PAGE_SIZE); // 7ffdf000 270 QueryBuffer.Status = -1; 271 trace("QueryBuffer.Buffer %p\n", QueryBuffer.Buffer); 272 Length = sizeof(QUERY_BUFFER); 273 ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); 274 ok_eq_int(QueryBuffer.Length, BufferLength); 275 ok(QueryBuffer.Status == STATUS_SUCCESS || 276 QueryBuffer.Status == STATUS_CONFLICTING_ADDRESSES, "Status = %lx\n", QueryBuffer.Status); 277 278 Length = 0; 279 ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n"); 280 281 KmtCloseDriver(); 282 KmtUnloadDriver(); 283 } 284