1 /* 2 * PROJECT: ReactOS API tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Test for NtReadFile 5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org> 6 */ 7 8 #include "precomp.h" 9 10 static 11 BOOL 12 Is64BitSystem(VOID) 13 { 14 #ifdef _WIN64 15 return TRUE; 16 #else 17 NTSTATUS Status; 18 ULONG_PTR IsWow64; 19 20 Status = NtQueryInformationProcess(NtCurrentProcess(), 21 ProcessWow64Information, 22 &IsWow64, 23 sizeof(IsWow64), 24 NULL); 25 if (NT_SUCCESS(Status)) 26 { 27 return IsWow64 != 0; 28 } 29 30 return FALSE; 31 #endif 32 } 33 34 static 35 ULONG 36 SizeOfMdl(VOID) 37 { 38 return Is64BitSystem() ? 48 : 28; 39 } 40 41 START_TEST(NtReadFile) 42 { 43 NTSTATUS Status; 44 HANDLE FileHandle; 45 UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\ntdll-apitest-NtReadFile-test.bin"); 46 PVOID Buffer; 47 SIZE_T BufferSize; 48 LARGE_INTEGER ByteOffset; 49 OBJECT_ATTRIBUTES ObjectAttributes; 50 IO_STATUS_BLOCK IoStatus; 51 FILE_DISPOSITION_INFORMATION DispositionInfo; 52 ULONG TooLargeDataSize = (MAXUSHORT + 1 - SizeOfMdl()) / sizeof(ULONG_PTR) * PAGE_SIZE; // 0x3FF9000 on x86 53 ULONG LargeMdlMaxDataSize = TooLargeDataSize - PAGE_SIZE; 54 55 trace("System is %d bits, Size of MDL: %lu\n", Is64BitSystem() ? 64 : 32, SizeOfMdl()); 56 trace("Max MDL data size: 0x%lx bytes\n", LargeMdlMaxDataSize); 57 58 ByteOffset.QuadPart = 0; 59 60 Buffer = NULL; 61 BufferSize = TooLargeDataSize; 62 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 63 &Buffer, 64 0, 65 &BufferSize, 66 MEM_RESERVE | MEM_COMMIT, 67 PAGE_READWRITE); 68 if (!NT_SUCCESS(Status)) 69 { 70 skip("Failed to allocate memory, status %lx\n", Status); 71 return; 72 } 73 74 InitializeObjectAttributes(&ObjectAttributes, 75 &FileName, 76 OBJ_CASE_INSENSITIVE, 77 NULL, 78 NULL); 79 Status = NtCreateFile(&FileHandle, 80 FILE_READ_DATA | FILE_WRITE_DATA | DELETE | SYNCHRONIZE, 81 &ObjectAttributes, 82 &IoStatus, 83 NULL, 84 0, 85 0, 86 FILE_SUPERSEDE, 87 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | 88 FILE_NO_INTERMEDIATE_BUFFERING, 89 NULL, 90 0); 91 ok_hex(Status, STATUS_SUCCESS); 92 93 ByteOffset.QuadPart = 0x10000; 94 Status = NtWriteFile(FileHandle, 95 NULL, 96 NULL, 97 NULL, 98 &IoStatus, 99 Buffer, 100 BufferSize - 0x10000, 101 &ByteOffset, 102 NULL); 103 ok_hex(Status, STATUS_SUCCESS); 104 ByteOffset.QuadPart = 0; 105 106 /* non-cached, max size -- succeeds */ 107 Status = NtReadFile(FileHandle, 108 NULL, 109 NULL, 110 NULL, 111 &IoStatus, 112 Buffer, 113 LargeMdlMaxDataSize - PAGE_SIZE, 114 &ByteOffset, 115 NULL); 116 ok_hex(Status, STATUS_SUCCESS); 117 118 /* non-cached, max size -- succeeds */ 119 Status = NtReadFile(FileHandle, 120 NULL, 121 NULL, 122 NULL, 123 &IoStatus, 124 Buffer, 125 LargeMdlMaxDataSize, 126 &ByteOffset, 127 NULL); 128 ok_hex(Status, STATUS_SUCCESS); 129 130 /* non-cached, too large -- fails to allocate MDL 131 * Note: this returns STATUS_SUCCESS on Win7 -- higher MDL size limit */ 132 Status = NtReadFile(FileHandle, 133 NULL, 134 NULL, 135 NULL, 136 &IoStatus, 137 Buffer, 138 LargeMdlMaxDataSize + PAGE_SIZE, 139 &ByteOffset, 140 NULL); 141 ok_hex(Status, STATUS_INSUFFICIENT_RESOURCES); 142 143 /* non-cached, unaligned -- fails with invalid parameter */ 144 Status = NtReadFile(FileHandle, 145 NULL, 146 NULL, 147 NULL, 148 &IoStatus, 149 Buffer, 150 LargeMdlMaxDataSize + 1, 151 &ByteOffset, 152 NULL); 153 ok_hex(Status, STATUS_INVALID_PARAMETER); 154 155 DispositionInfo.DeleteFile = TRUE; 156 Status = NtSetInformationFile(FileHandle, 157 &IoStatus, 158 &DispositionInfo, 159 sizeof(DispositionInfo), 160 FileDispositionInformation); 161 ok_hex(Status, STATUS_SUCCESS); 162 Status = NtClose(FileHandle); 163 ok_hex(Status, STATUS_SUCCESS); 164 165 Status = NtCreateFile(&FileHandle, 166 FILE_READ_DATA | FILE_WRITE_DATA | DELETE | SYNCHRONIZE, 167 &ObjectAttributes, 168 &IoStatus, 169 NULL, 170 0, 171 0, 172 FILE_SUPERSEDE, 173 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 174 NULL, 175 0); 176 ok_hex(Status, STATUS_SUCCESS); 177 178 ByteOffset.QuadPart = 0x10000; 179 Status = NtWriteFile(FileHandle, 180 NULL, 181 NULL, 182 NULL, 183 &IoStatus, 184 Buffer, 185 BufferSize - 0x10000, 186 &ByteOffset, 187 NULL); 188 ok_hex(Status, STATUS_SUCCESS); 189 ByteOffset.QuadPart = 0; 190 191 /* cached: succeeds with arbitrary length */ 192 Status = NtReadFile(FileHandle, 193 NULL, 194 NULL, 195 NULL, 196 &IoStatus, 197 Buffer, 198 LargeMdlMaxDataSize, 199 &ByteOffset, 200 NULL); 201 ok_hex(Status, STATUS_SUCCESS); 202 203 Status = NtReadFile(FileHandle, 204 NULL, 205 NULL, 206 NULL, 207 &IoStatus, 208 Buffer, 209 LargeMdlMaxDataSize + 1, 210 &ByteOffset, 211 NULL); 212 ok_hex(Status, STATUS_SUCCESS); 213 214 Status = NtReadFile(FileHandle, 215 NULL, 216 NULL, 217 NULL, 218 &IoStatus, 219 Buffer, 220 TooLargeDataSize, 221 &ByteOffset, 222 NULL); 223 ok_hex(Status, STATUS_SUCCESS); 224 225 DispositionInfo.DeleteFile = TRUE; 226 Status = NtSetInformationFile(FileHandle, 227 &IoStatus, 228 &DispositionInfo, 229 sizeof(DispositionInfo), 230 FileDispositionInformation); 231 ok_hex(Status, STATUS_SUCCESS); 232 Status = NtClose(FileHandle); 233 ok_hex(Status, STATUS_SUCCESS); 234 235 Status = NtFreeVirtualMemory(NtCurrentProcess(), 236 &Buffer, 237 &BufferSize, 238 MEM_RELEASE); 239 ok_hex(Status, STATUS_SUCCESS); 240 } 241